11

2つに分割したいdata.tableがあります。私はこれを次のように行います:

dt <- data.table(a=c(1,2,3,3),b=c(1,1,2,2))
sdt <- split(dt,dt$b==2)

しかし、次のステップとしてこのようなことをしたい場合

sdt[[1]][,c:=.N,by=a]

次の警告メッセージが表示されます。

警告メッセージ:In [.data.table(sdt [[1]] :=、、(c、.N)、by = a):無効な.internal.selfrefが検出され、テーブル全体のコピーを取得して修正されたため、:=でこの新しいメッセージを追加できます参照による列。以前の時点で、このdata.tableはRによってコピーされています。現在(そして奇妙なことに)Rでdata.table全体をコピーする可能性のあるkey <-、names <-、attr<-は避けてください。コピーを避けるために、代わりにset *構文を使用してください:setkey()、setnames()およびsetattr()。また、list(DT1、DT2)はDT1とDT2全体をコピーします(Rのlist()は名前付きオブジェクトをコピーします)。必要に応じて(実装するために)代わりにreflist()を使用します。このメッセージが役に立たない場合は、datatable-helpに報告して、根本的な原因を修正できるようにしてください。

より効率的になるように(そしてこのメ​​ッセージを受け取らないように)テーブルを分割するより良い方法があるかどうか疑問に思っていますか?

4

3 に答える 3

11

これはv1.8.7で機能します(v1.8.6でも機能する可能性があります):

> sdt = lapply(split(1:nrow(dt), dt$b==2), function(x)dt[x])
> sdt
$`FALSE`
   a b
1: 1 1
2: 2 1

$`TRUE`
   a b
1: 3 2
2: 3 2

> sdt[[1]][,c:=.N,by=a]     # now no warning
> sdt
$`FALSE`
   a b c
1: 1 1 1
2: 2 1 1

$`TRUE`
   a b
1: 3 2
2: 3 2

しかし、@ mnelが言ったように、それは非効率的です。可能であれば分割は避けてください。

于 2013-02-20T11:25:09.003 に答える
4

data.tableを分割する方法を探していたところ、この古い質問に出くわしました。

分割が必要な場合があり、data.tableの「by」アプローチは便利ではありません。

実際には、data.tableのみの命令を使用して手動で簡単に分割を行うことができ、非常に効率的に機能します。

SplitDataTable <- function(dt,attr) {
  boundaries=c(0,which(head(dt[[attr]],-1)!=tail(dt[[attr]],-1)),nrow(dt))
  return(
    mapply(
      function(start,end) {dt[start:end,]},
      head(boundaries,-1)+1,
      tail(boundaries,-1),
      SIMPLIFY=F))
}
于 2015-07-06T12:52:12.837 に答える
3

上で述べたように(@jangorecki)、パッケージにdata.tableはすでに分割のための独自の機能があります。その単純化されたケースでは、次を使用できます。

> dt <- data.table(a = c(1, 2, 3, 3), b = c(1, 1, 2, 2))
> split(dt, by = "b")
$`1`
   a b
1: 1 1
2: 2 1

$`2`
   a b
1: 3 2
2: 3 2

より困難な/具体的なケースでは、参照関数を使用してdata.tableに新しい変数を作成する:=set、関数を呼び出すことをお勧めしますsplitdt[, SplitCriteria := (...)]パフォーマンスを気にする場合は、分割変数を外部で計算するのではなく、常にdata.table環境にとどまるようにしてください。

于 2019-08-30T13:13:24.770 に答える