10

大きなdata.tableの列クラスを決定したいと思います。

colClasses <- sapply(DT, FUN=function(x)class(x)[1])

動作しますが、明らかにローカルコピーがメモリに保存されます。

> memory.size()
[1] 687.59
> colClasses <- sapply(DT, class)
> memory.size()
[1] 1346.21

data.table "with = FALSE"は常にdata.tableになるため、ループは不可能のようです。

迅速で非常に汚い方法は次のとおりです。

DT1 <- DT[1, ]
colClasses <- sapply(DT1, FUN=function(x)class(x)[1])

これを行うための最も効率的で効率的な方法は何ですか?

4

2 に答える 2

11

簡単に調べてみましたが、data.tableバグのようです。

> DT = data.table(a=1:1e6,b=1:1e6,c=1:1e6,d=1:1e6)
> Rprofmem()
> sapply(DT,class)
        a         b         c         d 
"integer" "integer" "integer" "integer" 
> Rprofmem(NULL)
> noquote(readLines("Rprofmem.out"))
[1] 4000040 :"as.list.data.table" "as.list" "lapply" "sapply"       
[2] 4000040 :"as.list.data.table" "as.list" "lapply" "sapply" 
[3] 4000040 :"as.list.data.table" "as.list" "lapply" "sapply"   
[4] 4000040 :"as.list.data.table" "as.list" "lapply" "sapply" 

> tracemem(DT)
> sapply(DT,class)
tracemem[000000000431A290 -> 00000000065D70D8]: as.list.data.table as.list lapply sapply 
        a         b         c         d 
"integer" "integer" "integer" "integer" 

だから、見てas.list.data.table

> data.table:::as.list.data.table
function (x, ...) 
{
    ans <- unclass(x)
    setattr(ans, "row.names", NULL)
    setattr(ans, "sorted", NULL)
    setattr(ans, ".internal.selfref", NULL)
    ans
}
<environment: namespace:data.table>
> 

unclass最初の行の厄介なことに注意してください。?unclass引数の深いコピーを取ることを確認します。このクイックルックからは、コピーを行っているようには見えませんsapply(Rlapplyはコピーオンライトが得意であり、書き込みを行っていないため、コピーを行っているとは思いませんでした)as.list。)。lapplyas.list.data.table

したがって、を回避するunclassと、速度が上がるはずです。やってみよう:

> DT = data.table(a=1:1e7,b=1:1e7,c=1:1e7,d=1:1e7)
> system.time(sapply(DT,class))
   user  system elapsed 
   0.28    0.06    0.35 
> system.time(sapply(DT,class))  # repeat timing a few times and take minimum
   user  system elapsed 
   0.17    0.00    0.17 
> system.time(sapply(DT,class))
   user  system elapsed 
   0.13    0.04    0.18 
> system.time(sapply(DT,class))
   user  system elapsed 
   0.14    0.03    0.17 
> assignInNamespace("as.list.data.table",function(x)x,"data.table")
> data.table:::as.list.data.table
function(x)x
> system.time(sapply(DT,class))
   user  system elapsed 
      0       0       0 
> system.time(sapply(DT,class))
   user  system elapsed 
   0.01    0.00    0.02 
> system.time(sapply(DT,class))
   user  system elapsed 
      0       0       0 
> sapply(DT,class)
        a         b         c         d 
"integer" "integer" "integer" "integer" 
> 

だから、はい、無限に良いです。

すでに、メソッドも削除するために、バグレポート#2000を作成しました。これにより、実際には、などのかなりの数のイディオムが高速化される可能性があります。[編集:これはv1.8.1で修正されました]。as.list.data.tabledata.table is()listlapply(.SD,...)

この質問をしてくれてありがとう!

于 2012-05-14T18:07:33.873 に答える
2

このようなアプローチでは何も問題はありません

colClasses <- sapply(head(DT1,1), FUN=class)

それは基本的にあなたの迅速な「汚い」解決策ですが、おそらく少し明確です(それほど多くはありませんが)...

于 2012-05-14T14:55:01.987 に答える