根据另外两列中的共享值对一列的行进行求和

时间:2017-04-24 20:19:22

标签: r data.table

我的问题类似于其他问题,例如:Sum of rows based on column-value

在R中使用data.table,如果我想根据另一列中的唯一值对列中的值求和,我可以执行以下操作:

mre = data.table(
    ref=rep(LETTERS[1:5],3),
    qual=c('B','C','D','E','A','C','D','E','A','B','D','E','A','B','C'),
    score=10:24
    )

mre[,team_score:=sum(score),by=ref]

或者:

mre[,team_val:=sum(score),by=qual]

但我怎样才能同时做到这两件事呢?也就是说,添加mre[,score]mre[,ref]mre[,qual]等于五个唯一值(A到E)之一的所有元素。因此,对于A,新列中的元素将是分数中所有行的总和,其中A出现在mre[,ref]mre[,qual](1,5,6,9,11,13)中。

我能做到:

mre[ref=="A"|qual=="A",team_val:=sum(score)]

但这非常低效。当然有更好/更聪明的data.table方式来做到这一点?

编辑:澄清所需的输出,更好的例子

我可以这样做,而不是创建一个新列并通过引用计算总和,这会导致涉及refqual列中多个值的并发症,我可以这样做:

test=
  merge(setkey(setnames(mre[,sum(score),by=ref],"ref","test_val"),test_val),
        setkey(setnames(mre[,sum(score),by=qual],"qual","test_val"),test_val),
        all=T)[,team_val:=rowSums(.SD,na.rm=T),.SDcols=c("V1.x","V1.y")]

产生:

> test
   test_val V1.x V1.y team_val
1:        A   45   54       99
2:        B   48   52      100
3:        C   51   50      101
4:        D   54   48      102
5:        E   57   51      108

我希望以一种不需要合并的方式来做这件事。我只需要team_val列,我立即在一个乘法表达式中使用另一个data.table的列(所以我可以这样做:

team_val =
  merge(setkey(setnames(mre[,sum(score),by=ref],"ref","test_val"),test_val),
        setkey(setnames(mre[,sum(score),by=qual],"qual","test_val"),test_val),
        all=T)[,rowSums(.SD,na.rm=T),.SDcols=c("V1.x","V1.y")]

得到:

> team_val
[1]  99 100 101 102 108

但仍需要合并)。我正在努力加入链接(即Section 2b)。

1 个答案:

答案 0 :(得分:1)

我认为这就是你想要的......

sapply(unique(c(mre$ref, mre$qual)), function(x) sum(mre$score[mre$ref == x | mre$qual == x]))

 A   B   C   D   E 
99 100 101 102 108 

使用1.5m行的data.frame /表,只需2秒钟。

如果你能明确指定等级,它会快一点。

sapply(LETTERS[1:5], function(x) sum(mre$score[mre$ref == x | mre$qual == x]))

1.5米行的时间不到1.5秒。