我想确定一个大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“与= FALSE”总是导致data.table。
快速和非常脏的方法是:
DT1 <- DT[1, ]
colClasses <- sapply(DT1, FUN=function(x)class(x)[1])
什么是最高贵和有效的方式来做到这一点?
有简要的调查,它看起来像一个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
或lapply
正在做的拷贝(我不认为他们做了,因为R是擅长写入时复制,而那些不写),而是as.list
在lapply
(其分派给as.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除去as.list.data.table
方法,因为data.table
is()
已经是一个list
,太。 这可能会加速其实不少成语,如lapply(.SD,...)
[编辑:这是固定在V1.8.1]。
谢谢你提出这个问题!
我看不出有什么错在这样的方法
colClasses <- sapply(head(DT1,1), FUN=class)
它基本上是你的quick'n'dirty解决方案,但也许有点更清晰(即使没有这么多)...