当我通过引用分配所有列时,为什么data.table会自动转换

sta*_*ant 6 r data.table

这是我不理解的东西data.table 如果我选择一行,我尝试将此行的所有值设置NA为新行 - data.table被转换为逻辑

#Here is a sample table
DT <- data.table(a=rep(1L,3),b=rep(1.1,3),d=rep('aa',3))
DT
   a   b  d
1: 1 1.1 aa
2: 1 1.1 aa
3: 1 1.1 aa

#Here I extract a line, all the column types are kept... good
str(DT[1])
Classes ‘data.table’ and 'data.frame':  1 obs. of  3 variables:
 $ a: int 1
 $ b: num 1.1
 $ d: chr "aa"
 - attr(*, ".internal.selfref")=<externalptr> 

#Now here I want to set them all to NA...they all become logicals => WHY IS THAT ?
str(DT[1][,colnames(DT):=NA])
Classes ‘data.table’ and 'data.frame':  1 obs. of  3 variables:
 $ a: logi NA
 $ b: logi NA
 $ d: logi NA
 - attr(*, ".internal.selfref")=<externalptr> 
Run Code Online (Sandbox Code Playgroud)

编辑:我认为这是一个错误

R) str(DT[1][,a:=NA])
Classes ‘data.table’ and 'data.frame':  1 obs. of  3 variables:
 $ a: logi NA
 $ b: num 1.1
 $ d: chr "aa"
 - attr(*, ".internal.selfref")=<externalptr> 
R) str(DT[1:2][,a:=NA])
Classes ‘data.table’ and 'data.frame':  2 obs. of  3 variables:
 $ a: int  NA NA
 $ b: num  1.1 1.1
 $ d: chr  "aa" "aa"
 - attr(*, ".internal.selfref")=<externalptr> 
Run Code Online (Sandbox Code Playgroud)

Mat*_*wle 9

提供答案,来自?":=":

与< - for data.frame不同,(可能很大的)LHS不会被强制匹配(通常很小的)RHS的类型.相反,如有必要,RHS会被强制匹配LHS的类型.如果这涉及将双精度值强制转换为整数列,则会给出警告(是否截断了小数数据).这样做的动机是效率.最好让前面的列类型正确并坚持下去.更改列类型是可能的,但故意更难:提供整列作为RHS.然后将此RHS加入到该列槽中,我们称之为plonk语法,或者如果您愿意,则替换列语法.通过需要构造新类型的全长向量,您可以更好地了解正在发生的事情,并且您确实打算更改列类型的代码的读者更清楚.

当然,所有这一切的动机都是大表(比如RAM中的10GB).不是1或2行表.

把它更简单:如果长度(RHS)== nrow(DT),那么RHS(和无论其类型)砰的一声扔到到该列槽.即使这些长度为1.如果长度(RHS)<nrow(DT),列的内存(及其类型)保持不变,但RHS被强制并循环使用以替换其中的(子集)项目柱.

如果我需要在大表中更改列的类型,我写道:

DT[, col := as.numeric(col)]
Run Code Online (Sandbox Code Playgroud)

这里<-分配一个新的向量,将col强制转换为新的内存,然后将其插入到列槽中.它尽可能高效.这是一个plonk的原因是因为长度(RHS)== nrow(DT).

如果要覆盖包含某个默认值的其他类型的列:

DT[, col := rep(21.5, nrow(DT))]    # i.e., deliberately harder
Run Code Online (Sandbox Code Playgroud)

如果col之前是整数类型,那么它将改为键入包含每行21.5的数字.否则只会data.frame导致21.5被强制为21的警告(除非DT只有1行!)