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.tableNANULLNA

4

3 に答える 3

14

から?NA

NAは、長さ1の論理定数であり、欠落値インジケーターが含まれています。NAは、rawを除く他の任意のベクトルタイプに強制変換できます。欠測値をサポートする他のアトミックベクトルタイプの定数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)}}

より多くのdata.table*ish*アプローチ

参照によって設定/置換するためにset(または)を使用する方が、data.tableの意味を理解できる場合があります。:=

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_] 

注意するのに便利

:=またはアプローチを使用する場合、タイプ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を強制します(たとえば、1の代わりに1Lを使用して)


どちらが一番速いですか

aその場で置き換えられる妥当な大きなdata.setを使用

その場で交換

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 に答える