10

我有一个data.table包含一些组的。我对每个组进行操作,一些组返回数字,其他组返回NA。出于某种原因data.table,很难将所有内容重新组合在一起。这是一个错误还是我误解了?这是一个例子:

dtb <- data.table(a=1:10)
f <- function(x) {if (x==9) {return(NA)} else { return(x)}}
dtb[,f(a),by=a]

Error in `[.data.table`(dtb, , f(a), by = a) : 
  columns of j don't evaluate to consistent types for each group: result for group 9 has     column 1 type 'logical' but expecting type 'integer'

我的理解是这NA与 R 中的数字兼容,因为显然我们可以拥有一个data.table具有值的NA值。我意识到我可以回来NULL,这会很好,但问题在于NA.

4

3 回答 3

14

?NA

NA 是长度为 1 的逻辑常数,其中包含缺失值指示符。NA 可以强制转换为除 raw 之外的任何其他向量类型。还有其他支持缺失值的原子向量类型的常量 NA_integer_、NA_real_、NA_complex_ 和 NA_character_:所有这些都是 R 语言中的保留字。

您必须指定正确的类型才能使您的功能正常工作 -

您可以在函数内强制以匹配的类型x(请注意,我们需要让它any适用于子集中超过 1 行的情况!

f <- function(x) {if any((x==9)) {return(as(NA, class(x)))} else { return(x)}}

更多 data.table*ish* 方法

set使用(或:=)通过引用设置/替换可能更有意义。

set(dtb, i = which(dtb[,a]==9), j = 'a', value=NA_integer_)

或者:=[使用矢量扫描a==9

dtb[a == 9, a := NA_integer_]

:=与二进制搜索一起

setkeyv(dtb, 'a')
dtb[J(9), a := NA_integer_] 

有用的注意事项

如果您使用:=orset方法,您似乎不需要指定NA类型

以下两个都可以

dtb <- data.table(a=1:10)
setkeyv(dtb,'a')
dtb[a==9,a := NA]

dtb <- data.table(a=1:10)
setkeyv(dtb,'a')
set(dtb, which(dtb[,a] == 9), 'a', NA)

这会给出一个非常有用的错误消息,让您知道原因和解决方案:

( DTc [.data.table, J(9), :=(a, NA)) 中的错误:RHS 的类型(“逻辑”)必须与 LHS(“整数”)匹配。对于最快的情况,检查和强制会影响性能。要么更改目标列的类型,要么自己强制 := 的 RHS(例如,使用 1L 而不是 1)


哪个最快

具有合理的大数据集,a在原位被替换

就地更换

library(data.table)

set.seed(1)
n <- 1e+07
DT <- data.table(a = sample(15, n, T))
setkeyv(DT, "a")
DTa <- copy(DT)
DTb <- copy(DT)
DTc <- copy(DT)
DTd <- copy(DT)
DTe <- copy(DT)

f <- function(x) {
    if (any(x == 9)) {
        return(as(NA, class(x)))
    } else {
        return(x)
    }
}

system.time({DT[a == 9, `:=`(a, NA_integer_)]})
##    user  system elapsed 
##    0.95    0.24    1.20 
system.time({DTa[a == 9, `:=`(a, NA)]})
##    user  system elapsed 
##    0.74    0.17    1.00 
system.time({DTb[J(9), `:=`(a, NA_integer_)]})
##    user  system elapsed 
##    0.02    0.00    0.02 
system.time({set(DTc, which(DTc[, a] == 9), j = "a", value = NA)})
##    user  system elapsed 
##    0.49    0.22    0.67 
system.time({set(DTc, which(DTd[, a] == 9), j = "a", value = NA_integer_)})
##    user  system elapsed 
##    0.54    0.06    0.58 
system.time({DTe[, `:=`(a, f(a)), by = a]})
##    user  system elapsed 
##    0.53    0.12    0.66 
# The are all the same!
all(identical(DT, DTa), identical(DT, DTb), identical(DT, DTc), identical(DT, 
    DTd), identical(DT, DTe))
## [1] TRUE

不出所料,二分搜索方法是最快的

于 2012-09-13T04:55:16.887 回答
0

你也可以这样做:

dtb <- data.table(a=1:10)

mat <- ifelse(dtb == 9,NA,dtb$a)

上面的命令会给你矩阵,但你可以把它改回 data.table

new.dtb <- data.table(mat)
new.dtb
     a
 1:   1
 2:   2
 3:   3
 4:   4
 5:   5
 6:   6
 7:   7
 8:   8
 9:  NA
10:  10

希望这可以帮助。

于 2012-09-13T05:20:30.417 回答
-1

如果要将 NA 分配给许多变量,可以使用此处建议的方法

v_1  <- c(0,0,1,2,3,4,4,99)
v_2  <- c(1,2,2,2,3,99,1,0)
dat  <-  data.table(v_1,v_2)

for(n in 1:2) {
  chari <-  paste0(sprintf('v_%s' ,n), ' %in% c(0,99)')
  charj <- sprintf('v_%s := NA_integer_', n)
  dat[eval(parse(text=chari)), eval(parse(text=charj))]
}
于 2012-12-06T02:14:06.657 回答