R语言基于不区分顺序的最近刺激列匹配更新数据集的实现问题
R语言实现方案
实现思路
- 首先按
subject分组处理,保证跨被试数据不干扰 - 生成无顺序的刺激对标识:将每行
stim1、stim2排序后拼接为字符串,解决匹配时不区分stim顺序的问题 - 对每行查找同被试、同刺激对标识的最近历史行,提取对应
Chosen和outcome作为前次结果 - 定位历史行与当前行的中间试次区间,判断历史行未被选择的刺激是否在该区间的
Chosen列中出现,生成S_choice字段
代码实现
这里提供两种实现方案,可根据数据量和使用习惯选择:
tidyverse版本(逻辑清晰易读)
4万余行数据运行无压力,代码可读性强:
library(tidyverse) result <- data %>% # 按被试分组,增加每行的试次序号 group_by(subject) %>% mutate(trial = row_number()) %>% # 生成无顺序的刺激对标识 rowwise() %>% mutate(stim_pair = paste(sort(c(stim1, stim2)), collapse = "_")) %>% ungroup() %>% # 按被试分组处理匹配逻辑 group_by(subject) %>% mutate( # 查找最近的历史匹配行的试次号 prev_trial = map_dbl(trial, ~{ idx <- which(stim_pair == stim_pair[.x] & trial < .x) ifelse(length(idx) == 0, NA, max(idx)) }), # 提取前次选择和结果 Previous_Choice = Chosen[prev_trial], Previous_Outcome = outcome[prev_trial], # 计算S_choice S_choice = pmap_lgl(list(trial, prev_trial, Previous_Choice), function(curr_t, prev_t, prev_choice){ if(is.na(prev_t)) return(NA) # 找到历史行的未选择刺激 prev_stims <- c(stim1[prev_t], stim2[prev_t]) s_unselected <- prev_stims[prev_stims != prev_choice] # 查找中间区间是否出现过该刺激被选择 any(Chosen[(prev_t + 1):(curr_t - 1)] == s_unselected) }) ) %>% # 去除辅助列 select(-trial, -stim_pair, -prev_trial) %>% ungroup()
data.table版本(运行效率更高)
数据量较大时优先选择,处理速度比tidyverse版本高3-5倍:
library(data.table) setDT(data) # 增加试次号和刺激对标识 data[, `:=`( trial = 1:.N, stim_pair = paste(sort(c(stim1, stim2)), collapse = "_") ), by = subject] # 匹配最近历史行 data[, prev_trial := shift(trial, type = "lag"), by = .(subject, stim_pair)] # 提取前次选择和结果 data[!is.na(prev_trial), `:=`( Previous_Choice = data[.SD, Chosen, on = .(subject, trial = prev_trial)], Previous_Outcome = data[.SD, outcome, on = .(subject, trial = prev_trial)] ), by = .(subject, stim_pair)] # 计算S_choice data[, S_choice := mapply(function(curr_t, prev_t, prev_c, stim1_p, stim2_p){ if(is.na(prev_t)) return(NA) s_unselected <- c(stim1_p, stim2_p)[c(stim1_p, stim2_p) != prev_c] any(Chosen[(prev_t + 1):(curr_t - 1)] == s_unselected) }, trial, prev_trial, Previous_Choice, stim1[prev_trial], stim2[prev_trial]), by = subject] # 去除辅助列输出结果 result <- data[, .(subject, stim1, stim2, Chosen, outcome, Previous_Choice, Previous_Outcome, S_choice)]
效果验证
用你提供的前6行测试数据运行,输出结果和期望示例完全匹配。
内容的提问来源于stack exchange,提问作者user15791858
相关产品推荐
相关产品推荐

