13

私は大きな data.table で作業しており、「by」を使用して 3 つの変数を「グループ化」しています。

私のdata.tableにはdキー「ma」があります(10桁の整数ですが、以下で短縮しました)。

しかし、設定by="ma,year,month"(私にとってはより直感的な group by ステートメント) では、私が望むものは得られません。たとえば、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>
4

2 に答える 2

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

このような列が他の 2 つの列 (つまりby=3 つの列) と一緒にグループ化されている場合、これらの 3 つの列の順序は、それらの列の 1 つに上記のような値がある場合、それらの値が等しい (同じグループ内にある) と見なされるかどうかを変更できます。 .

解決策は、そのようなデータに type numeric( doubleis another name) を使用しないことです。代わりintegerに、または整数が 2^31 より大きい場合 ( doubleiiuc への強制と精度の損失を引き起こします) をcharacter使用してください。 data.tableはソートが速くintegercharacter. とにかく、ソートはまだそれほど速くdoubleありません。

warningに新しいものを追加してみますdata.table:

FR#2469値が近いがマシンの許容範囲内にない場合tolerance.warningに検出して発行する新しいオプションを追加warningnumeric

于 2013-01-11T17:28:10.203 に答える
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
于 2013-01-10T20:47:42.637 に答える