如何使用 Data.Tables 按附近值分组

how to group by nearby values using data.tables

提问人:yingw 提问时间:6/18/2016 最后编辑:yingw 更新时间:6/18/2016 访问量:81

问:

我的数据如下所示:

    ID1     ID2     Time            diff
1:  1958616 P209576 4/15/2016 7:46  NA mins
2:  1958493 P209580 3/23/2016 9:41  -33005.16793 mins
3:  1958493 P209580 3/25/2016 15:41 3240.09742 mins
4:  1958493 P209580 3/30/2016 10:22 6880.65360 mins
5:  1958492 P209580 3/30/2016 11:31 69.00078 mins
6:  1958493 P209580 4/11/2016 10:07 17196.62313 mins

我想做的是对 8 小时时间窗口内出现的所有 ID 进行分组,并在分组后返回不同 ID1 的数量。在上面的示例中,第 4 行和第 5 行将分组,因为 .abs(diff) < 60*8

我曾经生成 diff 列。data[, diff := TIME - shift(TIME)]

我理想的输出是这样的

    num_of_unique_id1   ID2     Initial_time
1:  1                   P209576 4/15/2016 7:46
2:  1                   P209580 3/23/2016 9:41
3:  1                   P209580 3/25/2016 15:41
4:  2                   P209580 3/30/2016 10:22
5:  1                   P209580 4/11/2016 10:07

我认为可以使用但不确定如何为参数创建列来创建。num_of_unique_id1.SDlength(unique(ID1))by =

我知道还会出现边界问题(A 在 B 的 8 小时内,B 在 C 的 8 小时内,但 A 和 C 相隔 8 小时以上),在这些情况下,我想我想把它们都归为一行。

输出dput(data)

structure(list(ID1 = c("1958616", "1958493", "1958493", "1958493",
"1958492", "1958493"), ID2 = c("P209576", "P209580", "P209580",
"P209580", "P209580", "P209580"), Time = structure(c(1460706387.438,
1458726077.362, 1458920483.207, 1459333322.423, 1459337462.47,
1460369259.858), class = c("POSIXct", "POSIXt"), tzone = "GMT"),
    diff = structure(c(NA, -33005.1679333329, 3240.09741666714,
    6880.65360000133, 69.0007833321889, 17196.6231333335), units = "mins", class = "difftime")), .Names = c("ID1",
"ID2", "Time", "diff"), class = c("data.table", "data.frame"), row.names = c(NA,
-6L), .internal.selfref = <pointer: 0x1ce9a28>)
R Data.Table 时间序列

评论

0赞 alexperrone 6/18/2016
您能否使用数据来提供可重复的数据?看这里dputhead
0赞 alexperrone 6/18/2016
“我想做的是将 8 小时内出现的所有 ID 分组”......您想在上一个(及时)条目的 8 小时时间窗口内?为什么不先按时间对数据进行排序?
0赞 alexperrone 6/18/2016
或者,数据是否需要保持其来历的顺序?
0赞 yingw 6/18/2016
我先按 ID2 排序,然后按时间排序。是的,假设 ID2 相同,则按上一个时间条目分组。数据不需要保持其来历的顺序。

答:

4赞 alexperrone 6/18/2016 #1

如果数据按时间排序,我们可以计算差异并使用 分配唯一组。cumsum

data <- data[order(Time)]
data[ , diff := NULL]  # we will re-compute diff in hours
data[ , diff_hours := as.numeric(c(0, diff(Time)))]
##        ID1     ID2                Time diff_hours
## 1: 1958493 P209580 2016-03-23 09:41:17   0.000000
## 2: 1958493 P209580 2016-03-25 15:41:23  54.001624
## 3: 1958493 P209580 2016-03-30 10:22:02 114.677560
## 4: 1958492 P209580 2016-03-30 11:31:02   1.150013
## 5: 1958493 P209580 2016-04-11 10:07:39 286.610386
## 6: 1958616 P209576 2016-04-15 07:46:27  93.646550

window <- 8  # the time window in hours
data[ , group := cumsum(diff_hours > window) + 1]
data[ , num_of_unique_id1 := uniqueN(ID1), by = group]
##        ID1     ID2                Time diff_hours group num_of_unique_id1
## 1: 1958493 P209580 2016-03-23 09:41:17   0.000000     1                 1
## 2: 1958493 P209580 2016-03-25 15:41:23  54.001624     2                 1
## 3: 1958493 P209580 2016-03-30 10:22:02 114.677560     3                 2
## 4: 1958492 P209580 2016-03-30 11:31:02   1.150013     3                 2
## 5: 1958493 P209580 2016-04-11 10:07:39 286.610386     4                 1
## 6: 1958616 P209576 2016-04-15 07:46:27  93.646550     5                 1

请注意,大约一小时内的两个数据点被分配相同,并且(每组)为 2,而所有其他数据点都在它们自己的组中。2016-03-30groupnum_of_unique_id1