我有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
上。
答案 0 :(得分:14)
来自?NA
NA是长度为1的逻辑常量,包含缺失值指示符。除了原始NA之外,NA可以被强制转换为任何其他矢量类型。还有其他原子向量类型的常量NA_integer_,NA_real_,NA_complex_和NA_character_支持缺失值:所有这些都是R语言中的保留字。
您必须为您的功能指定正确的类型 -
您可以在函数中强制匹配x
的类型(请注意,我们需要any
才能适用于子集中包含多行的情况!
f <- function(x) {if any((x==9)) {return(as(NA, class(x)))} else { return(x)}}
使用set
(或:=
)来设置/替换引用可能会产生更多数据。表示意义。
set(dtb, i = which(dtb[,a]==9), j = 'a', value=NA_integer_)
使用[{1}} 的矢量扫描,:=
或[
内的a==9
dtb[a == 9, a := NA_integer_]
或:=
以及二进制搜索
setkeyv(dtb, 'a')
dtb[J(9), a := NA_integer_]
如果您使用:=
或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)
[.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
不出所料,二进制搜索方法是最快的
答案 1 :(得分: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
希望这有帮助。
答案 2 :(得分:-1)
如果要为多个变量分配NAs,可以使用approach suggested here:
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))]
}