我正在处理一个大数据。并使用'by'来'分组'3个变量。
我的data.table是d
并且键为“ma”(10位整数,但我在下面缩短了它。)
但是设置by="ma,year,month"
(对我而言,更直观的分组语句)并没有给出我想要的东西。例如,ma = 284有2011年11月的3个条目,或ma = 672有2011年12月的2个条目。
> d[,list(n=length(trx_num)),by=list(ma,year,month)]
ma year month n
1: 284 2011 12 3
2: 284 2012 1 1
3: 284 2011 11 5
4: 284 2011 11 1
5: 284 2011 11 2
---
5782971: 672 2012 7 1
5782972: 672 2011 12 1
5782973: 672 2012 2 1
5782974: 672 2011 12 1
5782975: 672 2012 1 1
然而,反转'by'顺序会产生所需的结果。
> d[,list(n=length(trx_num)),by=list(month,year,ma)]
month year ma n
1: 12 2011 284 3
2: 1 2012 284 1
3: 11 2011 284 8
4: 5 2012 543 7
5: 7 2012 543 3
---
1214686: 5 2012 672 28
1214687: 4 2012 672 13
1214688: 12 2011 672 11
1214689: 7 2012 672 9
1214690: 9 2012 672 11
我在这里缺少什么?提前致谢。
编辑:
str()给出错误结果的数据
> str(d)
Classes âdata.tableâ and 'data.frame': 14688135 obs. of 3 variables:
$ ma : num 3e+10 3e+10 3e+10 3e+10 3e+10 ...
$ year : int 2011 2012 2011 2011 2011 2011 2011 2011 2011 2011 ...
$ month: int 12 1 11 12 11 11 11 11 11 11 ...
- attr(*, ".internal.selfref")=<externalptr>
- attr(*, "sorted")= chr "ma"
错误结果的str():
> str(d[,.N,by=list(ma,year,month)])
Classes âdata.tableâ and 'data.frame': 5782975 obs. of 4 variables:
$ ma : num 3e+10 3e+10 3e+10 3e+10 3e+10 ...
$ year : int 2011 2012 2011 2011 2011 2012 2012 2012 2012 2012 ...
$ month: int 12 1 11 11 11 5 7 6 9 8 ...
$ N : int 3 1 5 1 2 1 1 1 1 1 ...
- attr(*, ".internal.selfref")=<externalptr>
正确结果的str():
> str(d[,.N,by=list(month,year,ma)])
Classes âdata.tableâ and 'data.frame': 1214690 obs. of 4 variables:
$ month: int 12 1 11 5 7 6 9 8 11 12 ...
$ year : int 2011 2012 2011 2012 2012 2012 2012 2012 2011 2011 ...
$ ma : num 3e+10 3e+10 3e+10 3e+10 3e+10 ...
$ N : int 3 1 8 7 3 12 15 3 6 6 ...
- attr(*, ".internal.selfref")=<externalptr>
答案 0 :(得分:7)
要结束评论跟踪,ma
列的类型为numeric
并包含精确不同但非常接近的值,几乎在机器容差范围内但不完全相同。换句话说,这种情况:
x < y < z
(y-x) just less than machine tolerance so considered equal
(z-y) just less than machine tolerance so considered equal
(z-x) just over machine tolerance so considered not equal
当这样的列与另外两列(即by=
3列)分组时,这些列的顺序(如果其中一列具有上述值)可以更改这些值是否被视为相等(和/或在同一组)。
解决方案是不要为此类数据使用类型numeric
(double
是另一个名称)。使用integer
,或者在这种情况下,整数大于2 ^ 31(导致强制到double
并且失去准确性,iiuc),character
。 data.table
快速排序integer
和character
。无论如何,它在排序double
方面的速度并不快。
我们会尝试向warning
添加新的data.table
:
答案 1 :(得分:1)
我构建了一个小测试用例,在这个对话框中的一个点我认为表现出了意想不到的行为,(但我正在阅读错误的对象以进行比较):
d <- structure(list(ma = c(284L, 284L, 284L, 284L, 284L, 284L, 284L,
284L, 284L, 284L, 284L, 284L, 672L, 672L, 672L, 672L, 672L),
year = c(2011L, 2011L, 2011L, 2012L, 2011L, 2011L, 2011L,
2011L, 2011L, 2011L, 2011L, 2011L, 2012L, 2011L, 2012L, 2011L,
2012L), month = c(12L, 12L, 12L, 1L, 11L, 11L, 11L, 11L,
11L, 11L, 11L, 11L, 7L, 12L, 2L, 12L, 1L), trx_num = c(4L,
9L, 8L, 4L, 4L, 6L, 3L, 8L, 2L, 2L, 8L, 9L, 8L, 6L, 10L,
6L, 10L)), .Names = c("ma", "year", "month", "trx_num"), row.names = c(NA,
-17L), class = c("data.table", "data.frame"), .internal.selfref = <pointer: 0x105afb0>, sorted = "ma")
构建它:
dat <- read.table(text=" ma year month n
284 2011 12 3
284 2012 1 1
284 2011 11 5
284 2011 11 1
284 2011 11 2
672 2012 7 1
672 2011 12 1
672 2012 2 1
672 2011 12 1
672 2012 1 1", header=TRUE)
require(data.table)
d <- data.table( data.frame(dat[rep(rownames(dat), times=dat$n), 1:3], trx_num=unlist(sapply(dat$n, sample, x=1:10)) ) )
setkey(d, ma)
d[,list(n=length(trx_num)),by=list(ma,year,month)]
d[,list(n=length(trx_num)),by=list(month,year,ma)]
此时很明显BlueMagister的解决方案是正确的:
d[,.N, by=list(month,year,ma)]
d[,.N, by=list(ma,year,month)] # same result modulo row order