R:data.table中的循环列

R:data.table中的循环列,r,data.table,sapply,R,Data.table,Sapply,我想确定大型data.table的列类 colClasses <- sapply(DT, FUN=function(x)class(x)[1]) colClasses memory.size() [1] 687.59 >colClasses memory.size() [1] 1346.21 循环似乎不可能,因为data.table“with=FALSE”总是导致data.table colClasses <- sapply(DT, FUN=function(x)class(x)

我想确定大型data.table的列类

colClasses <- sapply(DT, FUN=function(x)class(x)[1])
colClasses memory.size()
[1] 687.59
>colClasses memory.size()
[1] 1346.21
循环似乎不可能,因为data.table“with=FALSE”总是导致data.table

colClasses <- sapply(DT, FUN=function(x)class(x)[1])
一种快速且非常脏的方法是:

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

DT1我认为这样的方法没有任何错误

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

colClasses已经进行了简要的调查,它看起来像一个
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" 
因此,将
看作.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>
> 
所以,是的,非常好

我提出删除
as.list.data.table
方法,因为
data.table
也是()。这实际上可能会加快很多习惯用法的速度,例如
lappy(.SD,…)
。[编辑:这已在v1.8.1中修复]


谢谢你问这个问题

我不太明白。为什么不干脆
sapply(DT,class)
?文本中添加了计时above@MatthewDowle:我认为OP意味着sapply使用data.table的子集创建临时变量,以便为每列传递给FUN。因为它的data.table非常大,并且有很多列,所以效率不高。出于这个原因,他的解决方法是先将data.table减少到一行,然后调用sapply…@digEmAll-Ahah,我现在明白了,谢谢。这篇文章内容丰富。感谢您展示了调试这个的步骤。这确实是一个很好的解决方案,但并不像我希望的那样优雅。
> 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" 
>