在同一数据框中对具有不同条件的时间段进行排名
Rank periods with different conditions in the same dataframe
我想根据某些条件用不同的标准对数据框的行进行排名。
我有一个包含以下数据的数据框:采样日期、采样日期的月份、种群中繁殖个体的百分比和公历天数。
如果行在超过 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,但我不知道如何在育种期内进行排名.
你能帮帮我吗?
提前致谢
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
class 以准备按日期计算。
- 我已将
by()
函数用于分组逻辑。我选择 by()
而不是 aggregate()
和 ave()
因为后两者一次只能在一列上工作,但逻辑需要多列(具体来说 sampling_date
和 breeder
),by()
支持。此外,aggregate()
总是将聚合数据与输入 data.frame 按列组合,迫使每组成一行,因此它通常不适用于多元素 return 值; ave()
和 by()
是必需的。
- 在我的解决方案中,我预先计算 (1) 一个逻辑向量,表示哪些行是 "breeding days" 哪些行不是 (
breeding
),(2) 第一个繁殖日行索引 (first
),以及(3)第一个繁殖日Date
值(start
)。然后我在繁殖期分支 ifelse(breeding,...)
.
- 对于育种日,我按日期减去每一天减去开始日,并使用整数除以 3(加 1)得到排名值。
- 对于非繁殖日,我根据非繁殖日是在
start
之前还是之后索引c('A','B')
。
我想根据某些条件用不同的标准对数据框的行进行排名。
我有一个包含以下数据的数据框:采样日期、采样日期的月份、种群中繁殖个体的百分比和公历天数。
如果行在超过 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,但我不知道如何在育种期内进行排名.
你能帮帮我吗?
提前致谢
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
class 以准备按日期计算。 - 我已将
by()
函数用于分组逻辑。我选择by()
而不是aggregate()
和ave()
因为后两者一次只能在一列上工作,但逻辑需要多列(具体来说sampling_date
和breeder
),by()
支持。此外,aggregate()
总是将聚合数据与输入 data.frame 按列组合,迫使每组成一行,因此它通常不适用于多元素 return 值;ave()
和by()
是必需的。 - 在我的解决方案中,我预先计算 (1) 一个逻辑向量,表示哪些行是 "breeding days" 哪些行不是 (
breeding
),(2) 第一个繁殖日行索引 (first
),以及(3)第一个繁殖日Date
值(start
)。然后我在繁殖期分支ifelse(breeding,...)
. - 对于育种日,我按日期减去每一天减去开始日,并使用整数除以 3(加 1)得到排名值。
- 对于非繁殖日,我根据非繁殖日是在
start
之前还是之后索引c('A','B')
。