【问题标题】:data.table join using two columns from one table and one column from otherdata.table 使用一个表中的两列和另一个表中的一列连接
【发布时间】:2013-07-25 19:54:41
【问题描述】:

我有两个数据表,我们称它们为 weightsvalues
weights 表有 5 列如下:

first POSIXct
late POSIXct
nodeid integer
aggid integer
weight numeric

values 表有这些列

nodeid integer
Date POSIXct
hour integer
value decimal

我们的想法是生成一个新表,在该表中,它将根据权重将节点的加权平均值转换为聚合节点。但是,权重会随着时间而变化,需要根据第一个和最晚的日期进行匹配。执行此操作的 SQL 语法如下所示

select v.Date, v.hour, w.aggid, sum(v.value*w.weight) as aggvalue
from values v inner join weights w
on v.nodeid=w.nodeid and v.date between w.first and w.late
group by aggid, date, hour

鉴于 SQL 语法中的 between 逻辑,我不确定从哪里开始。这在 data.table 语法中是否可行,或者我需要将weights 表转换为每天都有一行而不是使用范围?

这是一些示例数据(抱歉,它太长了)...

values<-data.table(nodeid = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
2L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 
6L, 6L, 6L, 6L, 6L), Date = c("2013-07-02", "2013-07-02", "2013-07-05", 
"2013-07-08", "2013-07-10", "2013-07-02", "2013-07-02", "2013-07-05", 
"2013-07-08", "2013-07-10", "2013-07-02", "2013-07-02", "2013-07-05", 
"2013-07-08", "2013-07-10", "2013-07-02", "2013-07-02", "2013-07-05", 
"2013-07-08", "2013-07-10", "2013-07-02", "2013-07-02", "2013-07-05", 
"2013-07-08", "2013-07-10", "2013-07-02", "2013-07-02", "2013-07-05", 
"2013-07-08", "2013-07-10"), hour = c(1L, 2L, 23L, 2L, 2L, 1L, 
2L, 23L, 2L, 2L, 1L, 2L, 23L, 2L, 2L, 1L, 2L, 23L, 2L, 2L, 1L, 
2L, 23L, 2L, 2L, 1L, 2L, 23L, 2L, 2L), value = c(8.234, 3.218, 
0.787, 8.689, 6.218, 6.89, 1.914, 2.459, 6.683, 8.122, 0.281, 
1.136, 1.993, 7.27, 9.582, 5.777, 1.375, 9.204, 7.862, 0.633, 
2.433, 1.842, 7.178, 10.692, 1.417, 1.259, 2.619, 0.031, 6.744, 
5.941))

weights<-data.table(first = c("2013-07-01", "2013-07-01", "2013-07-01", 
"2013-07-01", "2013-07-01", "2013-07-01", "2013-07-08", "2013-07-08", 
"2013-07-08", "2013-07-08", "2013-07-08", "2013-07-08"), late = c("2013-07-07", 
"2013-07-07", "2013-07-07", "2013-07-07", "2013-07-07", "2013-07-07", 
"2013-07-20", "2013-07-20", "2013-07-20", "2013-07-20", "2013-07-20", 
"2013-07-20"), nodeid = c(1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 
4L, 5L, 6L), aggid = c(1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 
2L, 2L), weight = c(0.5, 0.25, 0.25, 0.3, 0.5, 0.2, 0.6, 0.2, 
0.2, 0.4, 0.45, 0.15))

exresults<-data.table(aggid = c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 
2L), Date = c("2013-07-02", "2013-07-02", "2013-07-02", "2013-07-02", 
"2013-07-05", "2013-07-05", "2013-07-08", "2013-07-08", "2013-07-10", 
"2013-07-10"), hour = c(1L, 1L, 2L, 2L, 23L, 23L, 2L, 2L, 2L, 
2L), aggvalue = c(5.90975, 3.2014, 2.3715, 1.8573, 1.5065, 6.3564, 
8.004, 8.9678, 7.2716, 1.782))

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    使用data.tableroll 参数加入:

    setkey(values, nodeid, Date)
    setkey(weights, nodeid, late)
    
    weights[values, roll = -Inf][, list(aggvalue = sum(weight*value)),
                                   by = list(aggid, Date = late, hour)]
    #    aggid       Date hour aggvalue
    # 1:     1 2013-07-02    1  5.90975
    # 2:     1 2013-07-02    2  2.37150
    # 3:     1 2013-07-05   23  1.50650
    # 4:     1 2013-07-08    2  8.00400
    # 5:     1 2013-07-10    2  7.27160
    # 6:     2 2013-07-02    1  3.20140
    # 7:     2 2013-07-02    2  1.85730
    # 8:     2 2013-07-05   23  6.35640
    # 9:     2 2013-07-08    2  8.96780
    #10:     2 2013-07-10    2  1.78200
    

    注意:如果不存在正确的范围,我会小心 - 我没有测试那个边缘情况。

    【讨论】:

    • 我看到你不需要first 列,我承认我需要在roll 上做更多的阅读,但是有没有办法使用first 而不是late。我的真实数据的来源方式,我只有first 日期,我必须创建late 列来创建范围。如果有一种语法允许我只使用first 列,那么我可以完全跳过创建late 列。这是可能的还是必要的步骤?
    • 我将weights 上的密钥更改为first 而不是late,并将roll=-Inf 更改为roll=Inf,这似乎有效。
    • @DeanMacGregor 是的,就是这样
    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 2020-06-23
    • 2018-06-09
    • 2021-09-22
    • 1970-01-01
    • 2014-09-25
    • 2021-11-28
    • 2015-05-15
    相关资源
    最近更新 更多