2013-01-24 71 views
3

后创造新的专栏中,我有两个data.tables,mainmetrics,都是由cid 我要添加到表main平均每个位于度量几个值的键。连接两个data.tables

但是,我想筛选code,只对metrics中的那些行与给定的code进行平均。

> metrics 
    cid code DZ value1 value2 
1: 1001 A 101  8  21 
2: 1001 B 102  11  26 
3: 1001 A 103  17  25 
4: 1002 A 104  25  39 
5: 1002 B 105  6  30 
6: 1002 A 106  23  40 
7: 1003 A 107  27  32 
8: 1003 B 108  16  37 
9: 1003 A 109  14  42 

# DESIRED OUTPUT 
> main 
    cid A.avg.val1 A.avg.val2 B.avg.val1  B.avg.val2  
1: 1001 12.5   23.0   11    26      
2: 1002 24.0   39.5    6    30    
3: 1003 20.5   37.0   16    37    



# SAMPLE DATA 
set.seed(1) 
main <- data.table(cid=1e3+1:3, key="cid") 
metrics <- data.table(cid=rep(1e3+1:3, each=3), code=rep(c("A", "B", "A"), 3), DZ=101:109, value1=sample(30, 9), value2=sample(20:50, 9), key="cid") 
code.filters <- c("A", "B") 

这些行可以获得所需的输出,但我很难将新列分配到main中。 (另外,以编程方式进行则是首选)。

main[metrics[code==code.filters[[1]]]][, list(mean(c(value1))), by=cid] 
main[metrics[code==code.filters[[1]]]][, list(mean(c(value2))), by=cid] 
main[metrics[code==code.filters[[2]]]][, list(mean(c(value1))), by=cid] 
main[metrics[code==code.filters[[1]]]][, list(mean(c(value2))), by=cid] 

此外,有人可以解释为什么下面的行只取每个组的最后一个值?

main[metrics[ code=="A"], A.avg.val1 := mean(c(value1))] 
+0

其实它不是在数据库中存储计算值一个很好的做法。这些应该在输出数据时完成。 – N1tr0

+0

也许,'不是一个好习惯'是错误的术语。也许,'有什么意义'更好? :-)计算值的一个主要方面是它们发生了变化,为什么要在运行中计算并始终准确时存储该数据?如果你存储它并去调用它,它可能已经过时并且不正确。 – N1tr0

+0

@ N1tr0,我想你可能误解了这个问题:我没有将值存储回数据库,我将它存储在data.table中,即存储器中。 –

回答

2

关闭工作@阿伦的回答,下面得到期望的结果:

invisible( 
sapply(code.filters, function(cf) 
    main[metrics[code==cf, list(avgv1 = mean(value1), avgv2 = mean(value2)), by=cid], 
     paste0(cf, c(".avg.val1", ".avg.val2")) :=list(avgv1, avgv2)] 
)) 

> main 
    cid A.avg.val1 A.avg.val2 B.avg.val1 B.avg.val2 
1: 1001  12.5  23.0   11   26 
2: 1002  24.0  39.5   6   30 
3: 1003  20.5  37.0   16   37 
3

您不需要main。可以按如下方式从metrics直接得到它:

> tmp.dt <- metrics[, list(A.avg.val1 = mean(value1[code=="A"]), 
       A.avg.val2 = mean(value2[code=="A"]), 
       B.avg.val1 = mean(value1[code == "B"]), 
       B.avg.val2 = mean(value2[code == "B"])), by=cid] 

#  cid A.avg.val1 A.avg.val2 B.avg.val1 B.avg.val2 
# 1: 1001  12.5  23.0   11   26 
# 2: 1002  24.0  39.5   6   30 
# 3: 1003  20.5  37.0   16   37 

如果你仍然想main于子集只是做:

main <- data.table(cid = c(1001:1002)) 
> tmp.dt[main] 

#  cid A.avg.val1 A.avg.val2 B.avg.val1 B.avg.val2 
# 1: 1001  12.5  23.0   11   26 
# 2: 1002  24.0  39.5   6   30 
+0

主要是比上面示例中的数据表大得多。我需要它回到主要的进一步计算。但是,谢谢你的建议!我想我可以从这里开始工作! –

+0

谢谢Arun,我不认为'tmp.dt'是必需的,因为我可以直接在'main [...]'中包装你的建议。请参阅下面 –

+0

感谢您的指导;) –

2

我将分两个步骤来完成此。首先,让你的手段,那么reshape数据

foo <- main[metrics] 
bar <- foo[, list(val1 = mean(value1), 
        val2 = mean(value2)), 
      by=c('cid', 'code')] 

library(reshape2) 
bar.melt <- melt(bar, id.var=c('cid', 'code')) 
dcast(data=bar.melt, 
     cid ~ code + variable) 

不过说真的,我可能会离开这个数据在“长”格式,因为我觉得它更容易的工作!

+0

谢谢@Justin。我希望能够以“data.table-esque”的方式做到这一点,因为我希望获得它提供的内存效率。 –