R 连接两个data.tables后创建新列

R 连接两个data.tables后创建新列,r,join,data.table,R,Join,Data.table,我有两个data.tables,main和metrics,都由cid 我想在表main中添加度量中几个值的平均值 但是,我想按code进行过滤,仅用给定的code对metrics中的行求平均值 > 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

我有两个data.tables,
main
metrics
,都由
cid
我想在表
main
中添加度量中几个值的平均值

但是,我想按
code
进行过滤,仅用给定的
code
metrics
中的行求平均值

> 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[metrics[ code=="A"],  A.avg.val1 := mean(c(value1))]

您不需要
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

我会分两步来做。首先,获取您的平均值,然后对数据进行重塑

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)

foo根据@Arun的答案,以下内容得到了期望的结果:

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

实际上,在数据库中存储计算值不是一个好的做法。这些都应该在输出数据时进行。也许“不好的做法”是错误的术语。也许,“重点是什么”更好一些?:-)计算值的一个主要方面是它们会发生变化,所以当数据可以动态计算且始终准确时,为什么要存储这些数据呢。如果您存储并调用它,它可能已经过时且不正确。@N1tr0,我想您可能误解了这个问题:我没有将值存储回数据库,而是将其存储在data.table(即内存)中。啊,好的。这就是我在一个我不属于的地方所得到的我有更多的数据库和脚本编写经验。不是编程。我会回去玩我的沙箱。main的数据表比上面示例中的数据表大得多。我需要它返回main进行进一步计算。但是谢谢你的建议!!我想我可以在这里工作!谢谢Arun,我不认为需要
tmp.dt
,因为我可以直接将您的建议包装在
main[…]
中。请看下面的Hanks@Justin。我希望以一种“数据表式”的方式完成它,因为我希望获得它提供的内存效率。
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)
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