【问题标题】:Complicated subtraction in RR中的复杂减法
【发布时间】:2015-07-08 19:03:31
【问题描述】:

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

这是一个示例数据集:

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 等之间的差异。

我怎样才能做到最好?

【问题讨论】:

  • 我投票结束这个问题,因为它是关于如何在没有可重现示例的情况下使用 R。
  • 不是一个真正的统计问题。数据是长格式还是宽格式。您应该看到?diff?rowSums
  • 试试library(data.table);setDT(dat)[, Sum:= sum(abs(diff(Score)))/.N, ID]
  • 谢谢@akrun。但是 R 给了我一个错误。错误:找不到函数“setDT”
  • 你有哪个版本?我有 data.table 的开发版本,但 setDT 也应该适用于 1.9.4 CRAN 版本

标签: r aggregate cumulative-sum split-apply-combine


【解决方案1】:

它是 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) 然后迭代那些1:S,这是一个强烈的代码味道,你正在做一个group_by(ID),即拆分-应用-组合,通常用于聚合。
  • 然后切片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 并除以尝试次数。
  • 注意在组内使用 dplyr 的 first(Var), last(Var), n()
  • 最后,dplyr::summarize 允许您直接命名摘要列,因此您不需要colnames(mat) &lt;- c('ppt', 'AvDiff')。当您执行summarize 操作时,您得到的结果是一个仅包含用于分组的列(ID)和汇总列(avdiff)的df;其他变量 Time, Score 会自动删除。

阅读拆分-应用-组合、聚合、dplyr 或 data.table 教程,并尝试一下。

【讨论】:

    猜你喜欢
    • 2015-06-24
    • 1970-01-01
    • 2018-11-21
    • 2013-04-09
    • 1970-01-01
    • 2019-04-21
    • 1970-01-01
    • 2021-04-12
    • 1970-01-01
    相关资源
    最近更新 更多