在R中为数据框按herd分组标记测试次数(首次/二次)
为分组内的测试次数生成连续编号
我有一个动物测试数据集,动物按herd分组,每个herd可进行多次测试。需要新增testing列,标记该herd本次是第几次测试(同一测试日期的所有动物对应同一个测试次数编号)。
示例数据集
df <- data.frame( animal = c("Animal1", "Animal2", "Animal3", "Animal1", "Animal2", "Animal3", "Animal4", "Animal5", "Animal6", "Animal4", "Animal5", "Animal6"), herd = c("Herd1","Herd1","Herd1", "Herd1","Herd1","Herd1","Herd2","Herd2", "Herd2","Herd2","Herd2","Herd2"), date = c("2017-01-01", "2017-01-01", "2017-01-01", "2018-07-01" , "2018-07-01", "2018-07-01", "2017-05-01", "2017-05-01", "2017-05-01", "2019-07-01", "2019-07-01", "2019-07-01"))
期望结果
animal herd date testing 1 Animal1 Herd1 2017-01-01 1 2 Animal2 Herd1 2017-01-01 1 3 Animal3 Herd1 2017-01-01 1 4 Animal1 Herd1 2018-07-01 2 5 Animal2 Herd1 2018-07-01 2 6 Animal3 Herd1 2018-07-01 2 7 Animal4 Herd2 2017-05-01 1 8 Animal5 Herd2 2017-05-01 1 9 Animal6 Herd2 2017-05-01 1 10 Animal4 Herd2 2019-07-01 2 11 Animal5 Herd2 2019-07-01 2 12 Animal6 Herd2 2019-07-01 2
原代码问题分析
使用rank(date)时,默认采用平均排名方式:当同一组内有多个相同日期时,会计算这些行的平均位置作为排名,导致编号不连续(比如Herd1中2017-01-01的平均位置是2,2018-07-01的平均位置是5),完全不符合需求。
解决方案
方法1:使用dplyr的dense_rank()
dense_rank()会为每个不同的日期分配连续的整数序号,相同日期对应同一个编号,完美匹配需求:
library(dplyr) df <- df %>% group_by(herd) %>% mutate(testing = dense_rank(date)) %>% ungroup()
方法2:先转换日期类型再编号(更稳妥)
如果你的date列是字符类型,建议先转换为Date类型,避免字符排序可能出现的问题:
df <- df %>% mutate(date = as.Date(date)) %>% group_by(herd) %>% mutate(testing = dense_rank(date)) %>% ungroup()
方法3:Base R实现
无需加载dplyr,使用ave()函数结合match()和unique()实现:
# 先转换日期类型 df$date <- as.Date(df$date) # 按herd分组,为每个日期分配连续编号 df$testing <- ave(as.integer(df$date), df$herd, FUN = function(x) match(x, unique(sort(x))))
以上三种方法都能得到你期望的testing列编号,同一herd内的相同测试日期对应同一个连续的测试次数编号。
内容的提问来源于stack exchange,提问作者Gómez-Buendía A.
相关产品推荐
相关产品推荐

