【问题标题】:Rank periods with different conditions in the same dataframe在同一数据框中对具有不同条件的时段进行排名
【发布时间】:2015-05-26 15:22:54
【问题描述】:

我想根据某些条件对具有不同标准的数据框的行进行排名。

我有一个包含以下数据的数据框:采样日期、采样日期的月份、种群中繁殖个体的百分比和公历天数。

如果行在超过 20% 的人口正在繁殖的时期(繁殖期)之内或之外,我想以不同的方式对这些行进行排名。 我有这个信息好几个月了,但在这里我只写了两个:

    mydf <- read.table(text="sampling_date - month - breeder - gregorian_days
    1/1/00-1-0-1
    5/1/00-1-10-5
    9/1/00-1-50-9
    13/1/00-1-100-13
    17/1/00-1-30-17
    21/1/00-1-20-21
    25/1/00-1-12-25
    29/1/00-1-3-29
    1/2/00-2-10-33
    5/2/00-2-20-37
    9/2/00-2-50-41
    13/2/00-2-80-45
    17/2/00-2-50-49
    21/2/00-2-51-53
    25/2/00-2-30-57
    28/2/00-2-10-61"
    , sep="-", header=TRUE)
mydf

我想对每个月的行进行排名:

(1)在值小于20的第一行之前写A

(2) 从第一个大于 20 的值开始,开始排名,但每 3 个真实天对行进行排名(例如,排名 1 = 第 5、6、7 天;排名 2 = 第 8、9、10 天...) .因此,繁殖期内的所有行不必是连续的。有可能第一个月的某些等级不会被添加为 4。

这样做直到最后一行的值大于 20

(3) 在最后一行后面的值大于 20 放 B

下面我添加了我想要得到的结果

   sampling_date month breeder gregorian_days rank
1         1/1/00     1       0              1    A
2         5/1/00     1      10              5    A
3         9/1/00     1      50              9    1
4        13/1/00     1     100             13    2
5        17/1/00     1      30             17    3
6        21/1/00     1      20             21    5
7        25/1/00     1      12             25    B
8        29/1/00     1       3             29    B
9         1/2/00     2      10             33    A
10        5/2/00     2      20             37    1
11        9/2/00     2      50             41    2
12       13/2/00     2      80             45    3
13       17/2/00     2      50             49    5
14       21/2/00     2      51             53    6
15       25/2/00     2      30             57    7
16       28/2/00     2      10             61    B

开始排名的阈值可以是基于数据框一列的值的标准,或者我可以得到确切的日期来定义周期繁殖期内外的不同行为。

例如阈值

    Start<- c("9/1/00", "5/2/00")
    End <- c("21/1/00", "25/2/00")

我所要做的就是使用函数if 为每个月创建一个循环以将值更改为更高和更低的 20,但我不知道如何在繁殖期内进行排名。

你能帮帮我吗?

提前致谢

【问题讨论】:

  • 我刚刚更正了对象mydf。现在它应该可以完美运行了。非常感谢

标签: r rank


【解决方案1】:
df <- data.frame(sampling_date=c('1/1/00','5/1/00','9/1/00','13/1/00','17/1/00',
                                 '21/1/00','25/1/00','29/1/00','1/2/00','5/2/00',
                                 '9/2/00','13/2/00','17/2/00','21/2/00','25/2/00','28/2/00'), 
                                  month=c(1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2),
                                  breeder=c(0,10,50,100,30,20,12,3,10,20,50,80,50,51,30,10), 
                                  gregorian_days=c(1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61))

df$sampling_date <- as.Date(df$sampling_date,'%d/%m/%y')

df$rank <- do.call(c, by(df, df$month, function(x) { 
                      breeding <- x$breeder>=20 
                      first <- which(breeding)[1] 
                      start <- x$sampling_date[first]
                      ifelse(breeding,
                             as.integer(x$sampling_date-start)%/%3+1,
                             c('A','B')[(1:nrow(x)>=first)+1])
                      }))
df
##    sampling_date month breeder gregorian_days rank
## 1     2000-01-01     1       0              1    A
## 2     2000-01-05     1      10              5    A
## 3     2000-01-09     1      50              9    1
## 4     2000-01-13     1     100             13    2
## 5     2000-01-17     1      30             17    3
## 6     2000-01-21     1      20             21    5
## 7     2000-01-25     1      12             25    B
## 8     2000-01-29     1       3             29    B
## 9     2000-02-01     2      10             33    A
## 10    2000-02-05     2      20             37    1
## 11    2000-02-09     2      50             41    2
## 12    2000-02-13     2      80             45    3
## 13    2000-02-17     2      50             49    5
## 14    2000-02-21     2      51             53    6
## 15    2000-02-25     2      30             57    7
## 16    2000-02-28     2      10             61    B

注意事项:

  • 我已使用 as.Date(...,'%d/%m/%y'); 将您的日期强制转换为 Date 课程,以准备按日期计算。
  • 我利用by() 函数进行分组逻辑。我选择了by() 而不是aggregate()ave(),因为后两者一次只能处理一列,但逻辑需要多列(特别是sampling_datebreeder),by() 支持。还有,aggregate()总是将聚合后的数据和输入的data.frame按列组合,强制每组为一行,所以一般不适合多元素返回值; ave()by() 是必需的。
  • 在我的解决方案中,我预先计算 (1) 一个逻辑向量,表示哪些行是“繁殖日”,哪些不是 (breeding),(2) 第一个繁殖日行索引 (first),以及 ( 3)第一个繁殖日Date值(start)。然后我用ifelse(breeding,...)在繁殖期分支。
  • 对于繁殖日,我将每一天减去开始日期,然后使用整数除以 3(加 1)得到排名值。
  • 对于非繁殖日,我根据非繁殖日是在start 之前还是之后,对c('A','B') 进行索引。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-26
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多