使用聚合操作时如何避免在 data.table 中创建重复项
Posted
技术标签:
【中文标题】使用聚合操作时如何避免在 data.table 中创建重复项【英文标题】:How to avoid creation of duplicates in data.table when using aggregation operations 【发布时间】:2020-05-31 18:26:40 【问题描述】:我正在使用data.table
对象来加快一些聚合操作。我的数据集的实际大小超过 1 亿行,因此我为这个问题包含了虚拟数据。我的data.table
对象是Sample3
(我在最后一侧添加了dput()
版本),它由5 个变量组成:Date
、Id
、Value
、Week
和Day
。我想通过Id
和Week
执行聚合任务,以计算Number
:行数,Sum
:值的总和,Avg
:值的平均值和Diff
:之间的差异Day
和最大 Date
。我为该任务使用了下一个代码:
library(data.table)
#Compute
Summary <- Sample3[,.(Number=.N,Sum=sum(Value),Avg=mean(Value),
Diff=Day-max(Date)),by = .(Id,Week)]
计算是正确的,但是有一个问题,Summary
有重复的行,而根据Id
和Week
,所需的输出应该只有 1 个观察值。此外,Sample3
有 11 行,Summary
有相同的行数。我没有使用:=
运算符。这是我得到的输出:
Id Week Number Sum Avg Diff
1: 923996 48-2014 5 21.690579 4.338116 5 days
2: 923996 48-2014 5 21.690579 4.338116 5 days
3: 923996 48-2014 5 21.690579 4.338116 5 days
4: 923996 48-2014 5 21.690579 4.338116 5 days
5: 923996 48-2014 5 21.690579 4.338116 5 days
6: 923996 49-2014 3 22.115795 7.371932 2 days
7: 923996 49-2014 3 22.115795 7.371932 2 days
8: 923996 49-2014 3 22.115795 7.371932 2 days
9: 923996 50-2014 1 5.101146 5.101146 3 days
10: 923996 51-2014 2 6.086128 3.043064 1 days
11: 923996 51-2014 2 6.086128 3.043064 1 days
Summary
的正确输出应如下所示:
Id Week Number Sum Avg Diff
1: 923996 48-2014 5 21.690579 4.338116 5 days
2: 923996 49-2014 3 22.115795 7.371932 2 days
3: 923996 50-2014 1 5.101146 5.101146 3 days
4: 923996 51-2014 2 6.086128 3.043064 1 days
我不知道为什么在这个单一操作中会发生这种行为,并且在大数据集中有重复的行可能会导致删除它们的任务需要更多时间。就像每一行都在更新。下一个是Sample3
的dput()
版本:
Sample3 <- structure(list(Date = structure(c(16405, 16405, 16406, 16406,
16406, 16407, 16409, 16409, 16415, 16421, 16424), class = "Date"),
Id = c(923996L, 923996L, 923996L, 923996L, 923996L, 923996L,
923996L, 923996L, 923996L, 923996L, 923996L), Value = c(5.69822266467209,
3.11110428877822, 4.74334486914574, 2.17729208527479, 5.96061541361928,
7.60801375507644, 4.3689394081637, 10.1388420642027, 5.10114642099159,
0.022944125999933, 6.06318436387287), Week = c("48-2014",
"48-2014", "48-2014", "48-2014", "48-2014", "49-2014", "49-2014",
"49-2014", "50-2014", "51-2014", "51-2014"), Day = structure(c(16411,
16411, 16411, 16411, 16411, 16411, 16411, 16411, 16418, 16425,
16425), class = "Date")), row.names = c(NA, -11L), class = c("data.table",
"data.frame"), .internal.selfref = <pointer: 0x0000000000311ef0>)
我是使用data.table
的新手,也许这是一个非常简单的解决方案,但我已经搜索了其他帖子,但没有找到修改这种情况的方法。感谢您的帮助。
【问题讨论】:
【参考方案1】:您获得多行的原因是因为此代码生成一个向量而不是单个值:
Diff=Day-max(Date)
您只需要[1]
(或min
)
library(data.table)
Sample3[,.(Number=.N,Sum=sum(Value),Avg=mean(Value),
Diff=Day[1]-max(Date)),by = .(Id,Week)]
# Id Week Number Sum Avg Diff
#1: 923996 48-2014 5 21.690579 4.338116 5 days
#2: 923996 49-2014 3 22.115795 7.371932 2 days
#3: 923996 50-2014 1 5.101146 5.101146 3 days
#4: 923996 51-2014 2 6.086128 3.043064 1 days
正如@Uwe 所说,data.table
中有一些函数可以帮助优化代码的速度,例如 first
和 last
如果您的数据已经按日期排列。
【讨论】:
或许,您可以添加data.table
具有first()
和last()
功能?以上是关于使用聚合操作时如何避免在 data.table 中创建重复项的主要内容,如果未能解决你的问题,请参考以下文章
r data.table 围绕 ad-hoc 连接的函数包装器(在链中聚合)