You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言中为数据框生成前次试验分数列时循环报错的解决方案

问题描述

我有如下结构的dataframe:

subjectID(受试者ID)Trial(试验次数)Score(分数)
1116
1116
1116
128
128
128
1312
1312
1312
219
219
219
2210
2210
2210

需要新增一列Previous_Trial_Score,存储每个受试者上一次试验的分数,效果如下:

subjectID(受试者ID)Trial(试验次数)Score(分数)Previous_Trial_Score(前次试验分数)
1116NA
1116NA
1116NA
12816
12816
12816
13128
13128
13128
219NA
219NA
219NA
22109
22109
22109

每个受试者的Trial 1对应的Previous_Trial_Score为NA。我写了如下循环代码:

for (myperson in unique(data$subjectID)){
  for (mytrial in unique(data$Trial[data$Trial>1])){

    #Specify the trial and person
    Prev_Score=as.numeric(unique(data[data$subjectID==myperson & data$Trial==mytrial-1, "Score"]))
    

    #Save it to the dataframe
    data[data$subjectID==myperson & data$Trial==mytrial,"Prev_Score"]=Prev_Score
    
    
  }
}

运行时出现错误:

Error: Assigned data `value` must be compatible with existing data.
i Error occurred for column `Prev_Score`.
x Can't convert from <double> to <logical> due to loss of precision.
* Locations: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 3...
解决方案

修复原有循环的方法

错误原因是赋值前未初始化Prev_Score列,R会默认将其创建为逻辑型,后续赋值数值型数据时就会报错。只需提前初始化该列为数值型即可:

# 先初始化列为数值型,默认填充NA
data$Prev_Score <- NA_real_

for (myperson in unique(data$subjectID)){
  # 仅遍历当前受试者存在的、大于1的试验次数
  mytrials <- unique(data$Trial[data$subjectID == myperson & data$Trial > 1])
  for (mytrial in mytrials){
    # 获取前一次试验的分数
    Prev_Score <- as.numeric(unique(data[data$subjectID == myperson & data$Trial == mytrial - 1, "Score"]))
    # 赋值到对应行
    data[data$subjectID == myperson & data$Trial == mytrial, "Prev_Score"] <- Prev_Score
  }
}

tidyverse/dplyr 替代方案

用dplyr的分组和窗口函数更简洁高效,无需手动写循环:

library(dplyr)

data <- data %>%
  # 按受试者分组
  group_by(subjectID) %>%
  # 按试验次数排序,确保顺序正确
  arrange(Trial, .by_group = TRUE) %>%
  # 提取每个试验组的首个分数作为基准,向前偏移得到前次试验分数后填充同组所有行
  mutate(
    trial_score = first(Score),
    Previous_Trial_Score = lag(trial_score)
  ) %>%
  # 移除临时列
  select(-trial_score) %>%
  ungroup()

也可以先提取受试者-试验的分数映射表,再合并回原数据:

library(dplyr)

# 创建每个受试者-试验的分数映射表,生成前次试验分数
trial_scores <- data %>%
  distinct(subjectID, Trial, .keep_all = TRUE) %>%
  group_by(subjectID) %>%
  mutate(Previous_Trial_Score = lag(Score)) %>%
  ungroup()

# 合并回原数据框
data <- data %>%
  left_join(trial_scores, by = c("subjectID", "Trial", "Score"))

内容的提问来源于stack exchange,提问作者Paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 13:48:22