如何在R中按组识别非连续Trial_Nr数值及中断位置
问题描述
我有一个长格式数据集,不同受试者由subj_id(示例中为Crowdsourcing_SubjId)标识,参与的刺激由连续变量Trial_Nr标记。需要识别Trial_Nr序列中断的受试者及中断位置。
最小可复现示例(MWE):
df <- structure(list(Crowdsourcing_SubjId = c("5e42fc295135b5000cd20d0b", "5e42fc295135b5000cd20d0b", "5e42fc295135b5000cd20d0b", "5e42fc295135b5000cd20d0b", "5e42fc295135b5000cd20d0b", "5e42fc295135b5000cd20d0b", "63bd9ac0dc52225142c5b1d4", "63bd9ac0dc52225142c5b1d4", "63bd9ac0dc52225142c5b1d4", "63bd9ac0dc52225142c5b1d4" ), Trial_Nr = c(1:6, 1, 2, 5, 6)), row.names = c(NA, 10L), class = "data.frame")
尝试使用diff()但无法按组实现正确计算,代码如下:
library(tidyverse) df %>% group_by(Crowsourcing_SubjId) %>% summarise(flag = diff(Trial_Nr))
这段代码既没有按组正确计算差异,也无法定位中断位置。期望输出如下:
Crowdsourcing_SubjId flag disruption 5e42fc295135b5000cd20d0b 1 NA 63bd9ac0dc52225142c5b1d4 3 2
解决方案
通过dplyr的分组计算,结合diff()和辅助函数可以实现需求。核心逻辑是按受试者分组后,计算相邻试次的差值,定位差值异常的位置,再整理成期望的输出格式。
完整代码:
library(tidyverse) df %>% group_by(Crowdsourcing_SubjId) %>% # 计算相邻Trial_Nr的差值,标记中断位置 mutate(flag = c(NA, diff(Trial_Nr)), disruption = ifelse(flag > 1, lag(Trial_Nr), NA)) %>% # 保留每组最后一行(无中断组)或中断所在行(有中断组) slice_max(row_number(), n = 1) %>% # 无中断组默认flag为1 mutate(flag = ifelse(is.na(flag), 1, flag)) %>% select(Crowdsourcing_SubjId, flag, disruption) %>% ungroup()
代码说明:
mutate(flag = c(NA, diff(Trial_Nr))):给每个受试者的试次序列计算相邻差值,第一个试次无前置值,差值设为NA。disruption = ifelse(flag > 1, lag(Trial_Nr), NA):当差值大于1时,记录中断前的试次编号;无中断则为NA。slice_max(row_number(), n = 1):每个组保留最后一行,这样无中断的组会保留最终的连续状态,有中断的组会保留包含中断信息的记录。mutate(flag = ifelse(is.na(flag), 1, flag)):无中断的组将flag统一设为1,匹配期望输出格式。
执行后输出结果与期望一致:
# A tibble: 2 × 3 Crowdsourcing_SubjId flag disruption <chr> <dbl> <int> 1 5e42fc295135b5000cd20d0b 1 NA 2 63bd9ac0dc52225142c5b1d4 3 2
内容的提问来源于stack exchange,提问作者RobertP.
相关产品推荐
相关产品推荐

