6

这是我不明白的事情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> 

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

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> 

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> 
4

1 回答 1

10

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

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

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

更简单地说:如果然后将RHSlength(RHS) == nrow(DT)(以及任何类型)插入该列槽。即使这些长度为 1。如果,列(及其类型)的内存保持在原位,但 RHS 被强制并回收以替换该列中的项目(子集)。length(RHS) < nrow(DT)

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

DT[, col := as.numeric(col)]

这里as.numeric分配一个新向量,将“col”强制到那个新内存中,然后将其插入列槽中。它尽可能高效。这是一个笨拙的原因是因为length(RHS) == nrow(DT)

如果你想用包含一些默认值的不同类型覆盖列:

DT[, col := rep(21.5, nrow(DT))]    # i.e., deliberately harder

如果“col”之前是整数类型,那么它将更改为每行包含 21.5 的数字类型。否则只会DT[, col := 21.5]导致关于 21.5 被强制为 21 的警告(除非 DT 只有 1 行!)

于 2013-09-04T11:03:15.220 回答