Data.table: 按同一列进行汇总和分组时总计不正确?

创建于 2018-10-10  ·  4评论  ·  资料来源: Rdatatable/data.table

您好。 当我在同一列上进行汇总和分组时,我对data.table的行为感到困惑。 似乎对分组数据而不是未分组数据执行汇总(例如,求和)。 我并不一定要说这是错误的-但这与其他工具不同,我想知道其解释是什么,或者我是否做错了什么(或者可能是错误)。 我包括了与dplyr的比较,它的性能比我期望的还要好(和SQL一样)。 注意:我已经尝试根据请求搜索问题,堆栈溢出等,但是这种情况的性质(对同一列进行分组和聚合)有点独特,而且我没有找到任何匹配项。

# Minimal reproducible example

请比较下面两个示例中的总计列。 例如,存在三行,其值为3,因此我希望合计为9,而不是3。

数据表

library(data.table)
df <- data.frame(SomeNumber=c(1,2,3,1,2,3,1,2,3))
dt <- data.table(df)
r <- dt[, .(.N, Total=sum(SomeNumber)), by=SomeNumber]

结果(r):

   SomeNumber N Total
1:          1 3     1
2:          2 3     2
3:          3 3     3

dplyr

library(dplyr)
df <- data.frame(SomeNumber=c(1,2,3,1,2,3,1,2,3))
r <- df %>% group_by(SomeNumber) %>% 
  summarise(N=n(), Total=sum(SomeNumber)) %>%
  ungroup()

结果(r):

   SomeNumber N Total
1:          1 3     3
2:          2 3     6
3:          3 3     9

# Output of sessionInfo()
R版本3.5.1(2018-07-02)
平台:x86_64-w64-mingw32 / x64(64位)
运行于:Windows> = 8 x64(内部版本9200)

矩阵产品:默认

地区:
[1] LC_COLLATE =英语_United Kingdom.1252 LC_CTYPE =英语_United Kingdom.1252 LC_MONETARY =英语_United Kingdom.1252
[4] LC_NUMERIC = C LC_TIME = English_United Kingdom.1252

附加基本软件包:
[1]统计图形grDevices utils数据集方法库

其他附件包:
[1] dplyr_0.7.6 data.table_1.11.8 openxlsx_4.1.0 bindrcpp_0.2.2ivottabler_0.4.0.9000

通过名称空间(未附加)加载:
[1] Rcpp_0.12.19 rstudioapi_0.8 bindr_0.1.1 magrittr_1.5 tidyselect_0.2.4 R6_2.3.0 rlang_0.2.2 fani_0.3.0 tools_3.5.1
[10] utf8_1.1.4 cli_1.0.1 htmltools_0.3.6 yaml_2.2.0断言_0.2.0摘要_0.6.17 tibble_1.4.2蜡笔_1.3.4 zip_1.0.0
[19] purrr_0.2.5 htmlwidgets_1.3胶水_1.3.0编译器_3.5.1支柱_1.3.0 jsonlite_1.5 pkgconfig_2.0.2

bug question

最有用的评论

感谢@ franknarf1@jangorecki的答复和指向FAQ的指针。
阅读FAQ答案并进行了更多测试之后,似乎您必须非常小心如何使用分组变量,因为在具有相同数据的不同列上进行聚合会导致不同的结果,具体取决于用于分组的内容。 我仍然觉得这很奇怪,有点尴尬,但是也许这只是我需要习惯的东西。

例子:

library(data.table)
df <- data.frame(SomeNumberA=c(1,1,1),SomeNumberB=c(1,1,1))
dt <- data.table(df)
r <- dt[, .(.N, TotalA=sum(SomeNumberA)), by=SomeNumberA]

以上结果: TotalA = 1

library(data.table)
df <- data.frame(SomeNumberA=c(1,1,1),SomeNumberB=c(1,1,1))
dt <- data.table(df)
r <- dt[, .(.N, TotalB=sum(SomeNumberB)), by=SomeNumberA]

以上结果: TotalB = 3

library(data.table)
df <- data.frame(SomeNumberA=c(1,1,1),SomeNumberB=c(1,1,1))
dt <- data.table(df)
r <- dt[, .(.N, TotalA=sum(SomeNumberA), TotalB=sum(SomeNumberB)), by=SomeNumberA]

没有结果,执行失败并显示以下错误:
gsum(SomeNumberA)中的错误:找不到对象'SomeNumberA'

所有4条评论

它与其他工具不同,我想知道其解释是什么,或者我做错了什么(或者可能是错误)。 我包括了与dplyr的比较,它的执行效果与我期望的一样(并且更像SQL)

里面jDT[, j, by] ,在列by有长度为1。你能做到这一点的计算像.N*SomeNumber ,但:

dt[, .(.N, Total=.N*SomeNumber), by=SomeNumber]
# or, for efficiency with GForce...
dt[, .(.N), by=SomeNumber][, Total := N*SomeNumber][]

有关原理,请参阅问题“在每个组中,为什么组变量的长度为1?” 常见问题解答中的vignette("datatable-faq")https://github.com/Rdatatable/data.table/wiki/入门

感谢@ franknarf1@jangorecki的答复和指向FAQ的指针。
阅读FAQ答案并进行了更多测试之后,似乎您必须非常小心如何使用分组变量,因为在具有相同数据的不同列上进行聚合会导致不同的结果,具体取决于用于分组的内容。 我仍然觉得这很奇怪,有点尴尬,但是也许这只是我需要习惯的东西。

例子:

library(data.table)
df <- data.frame(SomeNumberA=c(1,1,1),SomeNumberB=c(1,1,1))
dt <- data.table(df)
r <- dt[, .(.N, TotalA=sum(SomeNumberA)), by=SomeNumberA]

以上结果: TotalA = 1

library(data.table)
df <- data.frame(SomeNumberA=c(1,1,1),SomeNumberB=c(1,1,1))
dt <- data.table(df)
r <- dt[, .(.N, TotalB=sum(SomeNumberB)), by=SomeNumberA]

以上结果: TotalB = 3

library(data.table)
df <- data.frame(SomeNumberA=c(1,1,1),SomeNumberB=c(1,1,1))
dt <- data.table(df)
r <- dt[, .(.N, TotalA=sum(SomeNumberA), TotalB=sum(SomeNumberB)), by=SomeNumberA]

没有结果,执行失败并显示以下错误:
gsum(SomeNumberA)中的错误:找不到对象'SomeNumberA'

最后一个是一个错误...

不确定这是否是data.table分组/聚合方法的细微差别,但是当按单个变量进行分组和聚合时data.table不会“分解”分组调用。

聚合后,它将每个数字作为自己的组进行计数,因此在您的情况下,您只剩下3个SomeNumber变量求和,而不是原始的9。

快速简便的修复方法是确保分解在初始分组调用中进行。

library(data.table)

df <- data.frame(SomeNumber=c(1, 2, 3, 1, 2, 3, 1, 2, 3))

dt <- data.table(df)

r <- dt[, .(.N, Total = sum(SomeNumber)), by = as.factor(SomeNumber)]

   as.factor N Total
1:         1 3     3
2:         2 3     6
3:         3 3     9
此页面是否有帮助?
0 / 5 - 0 等级