在R中按姓名分组将Workout列值转移至下一个对应日期行
按Name分组将Workout值转移到下一个对应Date行的解决方案
先来看你提供的原始数据:
df <- data.frame(id = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10'), Date = c("01-Feb-17", "05-Feb-17", "01-May-17", "03-May-17","24-May-17", "05-Oct-17", "20-Oct-17", "25-Oct-17", "01-Dec-17", "12-Dec-17"), Name=c("John", "Jack", "Jack", "John", "John", "Jack", "John", "Jack", "John", "Jack"), Workout=c('150', '130', '140', '160', '150', '130', '140', '160', '150', '130'))
你的需求很明确:针对每个Name分组,把当前行的Workout数值转移到该Name对应的下一个Date所在的行。比如John在01-Feb-17的150要移到他的下一个日期03-May-17的行,Jack同理。
实现步骤
这里我用dplyr包来处理,它的分组和窗口函数非常适合这类需求:
- 先把
Date列转换成日期格式(确保后续排序是按时间顺序,避免原始数据顺序打乱逻辑),同时把Workout转成数值型; - 按
Name分组后,每组内按Date排序; - 使用
lead()函数将当前行的Workout值映射到下一行,最后一组的最后一行没有下一个日期,会自动生成NA,这符合逻辑。
完整代码如下:
library(dplyr) df_processed <- df %>% # 转换数据类型,确保日期和数值可操作 mutate(Date = as.Date(Date, format = "%d-%b-%y"), Workout = as.numeric(Workout)) %>% # 按Name分组,每组内严格按日期排序 group_by(Name) %>% arrange(Date, .by_group = TRUE) %>% # 将当前Workout值转移到下一行,自定义列名为Previous_Workout mutate(Previous_Workout = lead(Workout)) %>% # 取消分组恢复常规数据框格式 ungroup() %>% # 可选:把Date转回原来的字符串格式(如果需要和原始格式一致) mutate(Date = format(Date, "%d-%b-%y")) # 查看处理后的结果 print(df_processed)
结果说明
运行后你会看到:
- John的
01-Feb-17行的Previous_Workout为NA(这是他的第一行,没有前序值需要转移),而03-May-17行的Previous_Workout是150(来自01-Feb-17的Workout); - Jack的
05-Feb-17行的Previous_Workout为NA,01-May-17行的Previous_Workout是130(来自05-Feb-17的Workout); - 每个Name的最后一行
Previous_Workout都是NA,因为没有下一个日期的行可以承接这个值。
如果你不需要保留原始的Workout列,可以在mutate步骤后加上select(-Workout)来移除它。
内容的提问来源于stack exchange,提问作者Denis
相关产品推荐
相关产品推荐

