将函数应用于数据表子集,不包括嵌套的值

时间:2013-09-21 20:01:23

标签: r data.table

我有一个与此相关的问题,我之前曾问过:Assignment of a value from a foreach loop。我发现尽管友好用户提供的解决方案指向了正确的方向,但它们并没有解决我的实际问题。这里是样本数据集:

td <- data.table(date=c(rep(1,10),rep(2,10)),var=c(rep(1,4),2,rep(1,5)),id=rep(1:10,2))

它与以前相同,但它更好地反映了我的真实数据我想用文字做什么:对于每个id,我想在一定时期内得到所有其他id的均值(例如mean(td [date = =“2004-01-01”&amp; id!= 1] $ var)但是适用于所有期间和所有ID)。所以它是某种嵌套操作。我尝试过类似的东西:

td[,.SD[,mean(.SD$var[-.I]),by=id],by=date]

但这并没有给出正确的结果。

2 个答案:

答案 0 :(得分:5)

更新

 Josh very intelligently suggested to use `.BY ` instead of `.GRP`

td[, td[!.BY, mean(var), by=date], by=id]

原始答案:

如果您按id键入,则可以通过以下方式使用.GRP

setkey(td, id)

## grab all the unique IDs. Only necessary if not all ids are 
##     represented in all dates
uid <- unique(td$id)

td[, td[!.(uid[.GRP]), mean(var), by=date] , by=id]


    id date       V1
 1:  1    1 1.111111
 2:  1    2 1.111111
 3:  2    1 1.111111
 4:  2    2 1.111111
 5:  3    1 1.111111
 6:  3    2 1.111111
 7:  4    1 1.111111
 8:  4    2 1.111111
 9:  5    1 1.000000
10:  5    2 1.000000
11:  6    1 1.111111
12:  6    2 1.111111
13:  7    1 1.111111
14:  7    2 1.111111
15:  8    1 1.111111
16:  8    2 1.111111
17:  9    1 1.111111
18:  9    2 1.111111
19: 10    1 1.111111
20: 10    2 1.111111

答案 1 :(得分:3)

这样做吗?

DT[,{
    vbar <- mean(var)
    n <- .N
    .SD[,(n*vbar-sum(var))/(n-.N),by=id]
},by='date']

编辑(回复@ Arun的评论):中间的神秘表达是(伪代码)的解决方案

mean(everything) = weight(this)*mean(this) + weight(others)*mean(others)

EDIT2(基准测试):我更喜欢Josh / Richardo的答案,但这一代代数减少了计算次数,因为重要的是:

require(microbenchmark)
setkey(DT,id)
microbenchmark(
    algebra=DT[,{
        vbar <- mean(var)
        n <- .N
        .SD[,(n*vbar-sum(var))/(n-.N),by=id]
    },by='date'],
    bybyby=DT[, DT[!.BY, mean(var), by=date], by=id]
)
# Unit: milliseconds
#     expr       min        lq    median       uq       max neval
#  algebra  6.448764  6.920922  7.083707  7.38093  64.36238   100
#   bybyby 37.778504 39.425788 41.628918 44.26533 130.85040   100

用户可能已经将他们的DT锁定了,但如果没有,我猜这也会带来轻微的成本。