基于前一行列值修改R数据框Shift列值的技术问询
解决方案
思路拆解
要实现需求,核心是标记CorrAns的类型并引用前一行的类型值,结合分组内的行位置判断规则。具体步骤:
- 为每个CorrAns标记类型(颜色类/形状类),简化前后行的类型比较;
- 按Subject分组后,仅针对原Shift值为2的行,根据规则更新Shift:
- 分组首行直接设为7;
- 非首行对比当前行与前一行的类型,相同设7,不同设8;
- 原Shift不为2的行保持原值。
完整代码
library(dplyr) # 加载示例数据(如果未加载) exampledata <- structure(list(Subject = c(500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502), Block = c(4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 10L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), Colour = c("GREEN", "RED", "RED", "GREEN", "RED", "GREEN", "RED", "RED", "GREEN", "GREEN", "RED", "GREEN", "GREEN", "RED", "RED", "RED", "GREEN", "GREEN", "GREEN", "RED", "GREEN", "GREEN", "RED", "RED", "GREEN", "RED", "GREEN", "RED", "RED", "GREEN", "GREEN", "RED", "GREEN", "GREEN", "RED", "GREEN", "RED", "RED", "GREEN", "GREEN", "GREEN", "RED", "GREEN", "RED", "RED", "RED", "RED"), Cong = c(21L, 21L, 22L, 22L, 21L, 22L, 21L, 22L, 22L, 21L, 21L, 22L, 21L, 22L, 21L, 22L, 21L, 22L, 21L, 22L, 22L, 21L, 21L, 22L, 22L, 21L, 22L, 21L, 22L, 22L, 21L, 21L, 22L, 21L, 21L, 22L, 22L, 21L, 22L, 22L, 21L, 22L, 21L, 21L, 22L, 22L, 21L ), CorrAns = c("GREEN", "RED", "circle", "triangle", "triangle", "GREEN", "triangle", "RED", "GREEN", "GREEN", "triangle", "GREEN", "GREEN", "RED", "triangle", "circle", "GREEN", "GREEN", "GREEN", "circle", "GREEN", "GREEN", "RED", "circle", "triangle", "triangle", "GREEN", "triangle", "RED", "GREEN", "GREEN", "triangle", "GREEN", "circle", "triangle", "GREEN", "RED", "triangle", "triangle", "GREEN", "GREEN", "RED", "GREEN", "triangle", "RED", "circle", "triangle"), CorrResp = c(4L, 3L, 4L, 3L, 3L, 4L, 3L, 3L, 4L, 4L, 3L, 4L, 4L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 3L, 4L, 3L, 3L, 4L, 3L, 3L, 4L, 4L, 3L, 4L, 4L, 3L, 4L, 3L, 3L, 3L, 4L, 4L, 3L, 4L, 3L, 3L, 4L, 3L), Jitter1 = c(646L, 1294L, 639L, 1194L, 758L, 1205L, 942L, 542L, 1256L, 1250L, 1031L, 1486L, 1426L, 1123L, 1306L, 1426L, 1037L, 1208L, 1201L, 842L, 646L, 646L, 1294L, 639L, 1194L, 758L, 1205L, 942L, 542L, 1256L, 1250L, 1031L, 1486L, 1342L, 822L, 741L, 589L, 1025L, 914L, 1382L, 1384L, 875L, 615L, 922L, 1296L, 923L, 595L), Jitter2 = c(1146L, 1794L, 1139L, 1694L, 1258L, 1705L, 1442L, 1042L, 1756L, 1750L, 1531L, 1986L, 1926L, 1623L, 1806L, 1926L, 1537L, 1708L, 1701L, 1342L, 1146L, 1146L, 1794L, 1139L, 1694L, 1258L, 1705L, 1442L, 1042L, 1756L, 1750L, 1531L, 1986L, 1842L, 1322L, 1241L, 1089L, 1525L, 1414L, 1882L, 1884L, 1375L, 1115L, 1422L, 1796L, 1423L, 1095L), Procedure.Trial. = c("TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc5", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc2", "TrialProc5", "TrialProc5", "TrialProc5", "TrialProc5", "TrialProc5", "TrialProc5", "TrialProc5", "TrialProc5", "TrialProc5", "TrialProc5", "TrialProc5", "TrialProc5", "TrialProc5", "TrialProc5"), Shape = c("circle", "triangle", "circle", "triangle", "triangle", "triangle", "triangle", "circle", "triangle", "circle", "triangle", "triangle", "circle", "circle", "triangle", "circle", "circle", "triangle", "circle", "circle", "triangle", "circle", "triangle", "circle", "triangle", "triangle", "triangle", "triangle", "circle", "triangle", "circle", "triangle", "triangle", "circle", "triangle", "triangle", "circle", "triangle", "triangle", "triangle", "circle", "circle", "circle", "triangle", "circle", "circle", "triangle"), Shift = c(2L, 2L, 2L, 2L, 7L, 8L, 8L, 8L, 7L, 7L, 8L, 8L, 7L, 7L, 8L, 7L, 8L, 7L, 7L, 8L, 8L, 2L, 2L, 2L, 2L, 7L, 8L, 8L, 8L, 7L, 7L, 8L, 8L, 2L, 2L, 2L, 2L, 8L, 7L, 8L, 7L, 7L, 7L, 8L, 8L, 8L, 7L)), row.names = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 208L, 209L, 210L, 211L, 212L, 213L, 214L, 215L, 216L, 217L, 218L, 219L, 220L, 417L, 418L, 419L, 420L, 421L, 422L, 423L, 424L, 425L, 426L, 427L, 428L, 429L, 430L), class = "data.frame") # 处理数据 processed_data <- exampledata %>% group_by(Subject) %>% # 标记CorrAns的类型:颜色类为color,形状类为shape mutate(ans_type = ifelse(CorrAns %in% c("RED", "GREEN"), "color", "shape")) %>% # 更新Shift列 mutate(Shift = case_when( # 规则1:原Shift为2且是分组首行,设为7 Shift == 2 & row_number() == 1 ~ 7L, # 规则2:原Shift为2,且当前行与前一行类型相同,设为7 Shift == 2 & ans_type == lag(ans_type) ~ 7L, # 规则3:原Shift为2,且当前行与前一行类型不同,设为8 Shift == 2 & ans_type != lag(ans_type) ~ 8L, # 其他情况保持原Shift值 TRUE ~ Shift )) %>% # 移除临时的ans_type列(可选) select(-ans_type) %>% ungroup() # 查看结果 head(processed_data, 10)
代码说明
ans_type列:用ifelse快速标记每个CorrAns的类型,避免重复判断字符串是否属于颜色/形状类;lag(ans_type):dplyr的lag()函数用于获取分组内前一行的ans_type值,这是解决“引用前一行数据”问题的核心;row_number():用于判断是否为分组内的首行,对应规则1;case_when的顺序:按规则优先级排列,确保首行判断优先于前后行类型对比;- 类型一致性:用
7L/8L确保输出为整数类型,和原Shift列类型保持一致。
兼容性说明
代码兼容R 4.0.3及以上版本,依赖的dplyr版本需支持group_by()、mutate()、lag()和row_number(),这些函数在dplyr 1.0.0及以上版本中均可用,若版本过低可通过install.packages("dplyr")更新。
内容的提问来源于stack exchange,提问作者Orestes_Fox
相关产品推荐
相关产品推荐

