0

我正在研究一个需要我从列中减去信息的数据集。这是一个重复测量数据集,其中一个人最多被测试六次,最少两次。数据为长格式

这是一个示例数据集:

ID=c('X1', 'X1', 'X1', 'X1', 'X2', 'X2', 'X2', 'X3', 'X3', 'X3', 'X3')
Time=c(1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 4)
Score=c(10, 9, 8, 6, 10, 8, 4, 9, 8, 6, 4)
dat=data.frame(ID, Time, Score)

在最简单的形式中,我的数据包含以下变量:

  • Participant ID- 唯一的字母数字代码
  • Time- 从 1 到 6 不等
  • Score- 测试 1 的分数从 1 到 10 不等。重复测试后分数可能保持不变或下降。

我想计算测试会话中连续分数之间的差异,将它们相加,然后除以每个参与者的分数。以更简单的形式,我希望它如下所示:

Sum of [(time1-time2 score) + (time2-time3 score) + (time3-time4 score)]/N (Scores for participant)  

分母必须考虑每个参与者的不同重复测量次数。

早些时候,我的代码是这样的:

S = length(unique(dat$ID))     
dat$ppt = as.numeric(factor(dat$ID, labels = 1:S))     
mat = matrix(nrow = S, ncol = 2) # empty matrix 

for (s in 1:S) { # for each subject 
  scores = dat[dat$ID == s, 'Score'] # get scores for participant s 
  scores = na.omit(scores) 
  avCumDiff = sum(diff(scores))/length(scores) # average cumulative difference 
  mat[s,] = c(s, avCumDiff) # add to matrix
}     
colnames(mat) <- c('ppt', 'AvDiff') 

这段代码的问题在于它会累积地相互减去分数。我希望它添加分数 1&2、2&3、3&4 等之间的差异。

我怎样才能做到最好?

4

1 回答 1

2

它是 dplyr(或 data.table)中的一个单行代码。这是 dplyr 版本(akrun 已经给了你 data.table 版本):

require(dplyr)
dat %>% group_by(ID) %>% summarize(avdiff = (last(Score)-first(Score)) / n() )

  ID  avdiff
1 X1 -1.00
2 X2 -2.00
3 X3 -1.25

或者如果你想要 absdiff,做avdiff = abs(last(Score)-first(Score) / n()

您的大部分代码都是多余的,可以删除:

  • 每当您看到length(unique(dat$ID)then 遍历这些1:S时,这就是您正在执行group_by(ID)ie split-apply-combine 的强烈代码气味,通常用于聚合。
  • 然后切片scores = dat[dat$ID == s, 'Score']正是那个 group_by 操作。(顺便说一句,你的意思总是空的[dat$ppt == s, 'Score']
  • 将 ID 转换为因子dat$ppt = as.numeric(factor(dat$ID...是完全没有必要的。group_by(ID)这样做。您的组名或矩阵行不是整数是可以的。
  • 声明一个空结果mat = matrix(...)是不必要的,就像手动插入它一样mat[s,] = c(s, avCumDiff)
  • scores = na.omit(scores)是不必要的;大多数 sum、cumsum、absdiff 等函数默认排除 NA,R 函数中的“house style”是感知 NA 并在 NA 存在的情况下做聪明的事情。
  • 因此,您想汇总分数的 absdiff 并除以尝试次数。
  • first(Var), last(Var), n()注意在组内使用 dplyr
  • 最后,dplyr::summarize允许您直接命名摘要列,因此您不需要colnames(mat) <- c('ppt', 'AvDiff'). 当您进行summarize操作时,您得到的结果是一个 df,其中仅包含用于分组的列(ID)和汇总列(avdiff);其他变量Time, Score会自动删除。

阅读 split-apply-combine、aggregation、dplyr 或 data.table 教程,并尝试一下。

于 2015-07-09T20:02:20.407 回答