【问题标题】:creating new column after joining two data.tables加入两个 data.tables 后创建新列
【发布时间】:2013-01-24 20:40:20
【问题描述】:

我有两个 data.tables,mainmetrics,均由 cid 键入 我想将位于指标中的几个值的平均值添加到表main

但是,我想按code 进行过滤,只用给定的codemetrics 中的那些行进行平均。

> 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")

这些行获得了所需的输出,但我很难将新的 col 分配回 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))]

【问题讨论】:

  • 实际上将计算值存储在数据库中并不是一个好习惯。这些应该在输出数据时完成。
  • 也许,“不是一个好的做法”是错误的术语。也许,“有什么意义”更好? :-) 计算值的一个主要方面是它们会发生变化,所以当它可以动态计算并且始终准确时,为什么要存储该数据。如果您存储它并去召回它,它可能已经过时且不正确。
  • @N1tr0,我想你可能误解了这个问题:我没有将值存储回我的数据库中,我将它存储在 data.table 中,即内存中。
  • 啊,好的。这就是我在一个我不属于的领域所得到的。 :) 我有更多的数据库和脚本经验。不是编程。我会回去玩我的沙盒。大声笑。

标签: r join data.table


【解决方案1】:

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

【讨论】:

  • main 的数据表比上面的示例大得多。我需要它返回到 main 以进行进一步的计算。不过谢谢你的建议!!我想我可以从这里开始工作!
  • 谢谢 Arun,我认为 tmp.dt 不是必需的,因为我可以将您的建议直接包含在 main[...] 中。请看下面
【解决方案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)

但实际上,我可能会将数据保留为“长”格式,因为我发现它更容易处理!

【讨论】:

  • 谢谢@贾斯汀。我希望以“data.table-esque”的方式来做,因为我希望获得它提供的内存效率。
【解决方案3】:

根据@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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-07
    • 1970-01-01
    • 2016-03-24
    • 2019-02-13
    • 1970-01-01
    • 1970-01-01
    • 2020-11-23
    • 1970-01-01
    相关资源
    最近更新 更多