【问题标题】:Data.Table rolling join by groupData.Table 按组滚动连接
【发布时间】:2016-04-18 18:43:14
【问题描述】:

如何找到每个(loc.xloc.y)对的最后值,test.day之前

dt <- data.table( 
  loc.x = as.integer(c(1, 1, 3, 1, 3, 1)),
  loc.y = as.integer(c(1, 2, 1, 2, 1, 2)),
  time = as.IDate(c("2015-03-11", "2015-05-10", "2015-09-27",
                    "2015-11-25", "2014-09-13", "2015-08-19")), 
  value = letters[1:6]
)

setkey(dt, loc.x, loc.y, time)
test.day <- as.IDate("2015-10-01")

需要的输出:

   loc.x loc.y value
1:     1     1     a
2:     1     2     f
3:     3     1     c

【问题讨论】:

    标签: r join data.table


    【解决方案1】:

    另一种选择是使用last 函数:

    dt[, last(value[time < test.day]), by = .(loc.x, loc.y)]
    

    给出:

       loc.x loc.y V1
    1:     1     1  a
    2:     1     2  f
    3:     3     1  c
    

    【讨论】:

    • 我认为dt[time &lt; test.day, last(value), by = .(loc.x, loc.y)] 会更有效率,因为它不会按组重新计算time &lt; test.day,但这至少与我的另一个答案几乎相同。
    【解决方案2】:

    您可以首先将time &lt; test.day 所在的行进行子集化(这应该非常有效,因为它不是按组完成的),然后选择每个组的最后一个value。为此,您可以使用 tail(value, 1L) 或按照 Floo0 的建议使用 value[.N],结果是:

    dt[time < test.day, tail(value, 1L), by = .(loc.x, loc.y)]
    #   loc.x loc.y V1
    #1:     1     1  a
    #2:     1     2  f
    #3:     3     1  c
    

    dt[time < test.day, value[.N], by = .(loc.x, loc.y)]
    

    请注意,这是有效的,因为数据是根据setkey(dt, loc.x, loc.y, time) 排序的。

    【讨论】:

    • 如果tail(value, 1L),你可以使用value[.N]
    • @Floo0,当然,这是另一种选择。
    【解决方案3】:

    这是另一个在创建查找表后使用滚动联接的选项

    indx <- data.table(unique(dt[ ,.(loc.x, loc.y)]), time = test.day)  
    dt[indx, roll = TRUE, on = names(indx)]
    #    loc.x loc.y       time value
    # 1:     1     1 2015-10-01     a
    # 2:     1     2 2015-10-01     f
    # 3:     3     1 2015-10-01     c
    

    或@eddi 建议的非常相似的选项

    dt[dt[, .(time = test.day), by = .(loc.x, loc.y)], roll = T, on = c('loc.x', 'loc.y', 'time')]
    

    或者一个效率较低的班轮,因为它会按组调用[.data.table

    dt[, 
        .SD[data.table(test.day), value, roll = TRUE, on = c(time = "test.day")], 
        by = .(loc.x, loc.y)
      ]
    #    loc.x loc.y V1
    # 1:     1     1  a
    # 2:     1     2  f
    # 3:     3     1  c
    

    【讨论】:

    • 嗯,用dt[dt[, .(time = test.day), by = .(loc.x, loc.y)], roll = T, on = c('loc.x', 'loc.y', 'time')] 来避免循环中的[.data.table 怎么样?
    • 是的,实际上我的想法是indx &lt;- data.table(unique(dt[ ,.(loc.x, loc.y)]), time = test.day) ; dt[indx, roll = TRUE, on = names(indx)],但这一切似乎太过分了,我正要删除它。
    • @eddi 我将两者都添加到了答案中。我想现在这将更具竞争力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 2016-01-25
    • 2023-03-11
    • 2016-08-08
    • 1970-01-01
    • 2019-09-22
    相关资源
    最近更新 更多