数据表中的NA

Ale*_*lex 10 r na data.table

我有一个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'
Run Code Online (Sandbox Code Playgroud)

我的理解是NA与R中的数字兼容,因为显然我们可以拥有data.table具有NA价值的数字.我意识到我可以返回NULL,这将工作正常,但问题是NA.

mne*_*nel 14

?NA

NA是长度为1的逻辑常量,其包含缺失值指示符.除了原始NA之外,NA可以被强制转换为任何其他矢量类型.还存在支持缺失值的其他原子向量类型的常量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)}}
Run Code Online (Sandbox Code Playgroud)

更多data.table*ish*方法

它可能会产生更多数据.使用set(或:=)通过引用设置/替换的意义.

set(dtb, i = which(dtb[,a]==9), j = 'a', value=NA_integer_)
Run Code Online (Sandbox Code Playgroud)

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

dtb[a == 9, a := NA_integer_]
Run Code Online (Sandbox Code Playgroud)

或者 :=二进制搜索

setkeyv(dtb, 'a')
dtb[J(9), a := NA_integer_] 
Run Code Online (Sandbox Code Playgroud)

有用的注意

如果使用:=set方法,则似乎不需要指定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)
Run Code Online (Sandbox Code Playgroud)

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

误差在[.data.table(DTC,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
Run Code Online (Sandbox Code Playgroud)

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

  • @mnel,因为你在`a`上键入`DT`,这个简单例子的最大速度似乎是用DT [J(9),a:= NA_integer_]`来实现的?不过,考虑到OP之前的评论,也许这是一个有争议的问题. (2认同)