Haben kurz untersucht, und es sieht aus wie ein data.table
Bug.
> 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"
Also, suchen Sie in 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>
>
Notiere die nervtötende unclass
in der ersten Zeile. ?unclass
bestätigt, dass es eine tiefe Kopie seines Arguments braucht. Von diesem schnellen Aussehen scheint es nicht oder lapply
sind das Kopieren (ich glaube nicht, dass sie getan haben, da R ist gut in Copy-on-Write, und diese sind nicht schriftlich), sondern die as.list
in lapply
(die an as.list.data.table
versendet).
Also, wenn wir die unclass
vermeiden, sollte es beschleunigen. Lassen Sie uns versuchen:
> 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"
>
Also, ja, unendlich besser.
Ich habe bug report #2000 hob die as.list.data.table
Methode, da ein data.table
is()
bereits ein list
auch zu entfernen. Dies könnte einige Idiome tatsächlich beschleunigen, wie lapply(.SD,...)
. [BEARBEITEN: Dies wurde in Version 1.8.1 behoben].
Danke für das Stellen dieser Frage !!
Nicht sicher, ich folge. Warum nicht einfach 'sapply (DT, Klasse)'? –
Timings im obigen Text hinzugefügt –
@MatthewDowle: Ich denke, das OP bedeutet, dass Sapply temporäre Variablen mit den Teilmengen der data.tabelle erstellt, um für jede Spalte zu FUN übergeben. Da seine data.table wirklich groß ist und viele Spalten hat, ist das nicht effizient. Aus diesem Grund ist seine Problemumgehung, die data.table zuerst auf eine Zeile zu reduzieren und dann sapply aufzurufen ... – digEmAll