18

sを持つ列を持つdata.tableがありますNA。その列が特定の値を取る行を削除したい (たまたま"")。ただし、私の最初の試みでは、NAs でも行が失われました。

> a = c(1,"",NA)
> x <- data.table(a);x
    a
1:  1
2:   
3: NA
> y <- x[a!=""];y
   a
1: 1

を見た後?`!=`、動作するワンライナーを見つけましたが、それは苦痛です:

> z <- x[!sapply(a,function(x)identical(x,""))]; z
    a
1:  1
2: NA

これを行うためのより良い方法があるかどうか疑問に思っていますか?NAまた、複数の非値を除外するためにこれを拡張する良い方法がわかりません。悪い方法は次のとおりです。

>     drop_these <- function(these,where){
+         argh <- !sapply(where,
+             function(x)unlist(lapply(as.list(these),function(this)identical(x,this)))
+         )
+         if (is.matrix(argh)){argh <- apply(argh,2,all)}
+         return(argh)
+     }
>     x[drop_these("",a)]
    a
1:  1
2: NA
>     x[drop_these(c(1,""),a)]
    a
1: NA

サブセット化するときに sを保持して、動作が異なるように見える data.frameを調べて?J試してみました。NA

> w <- data.frame(a,stringsAsFactors=F); w
     a
1    1
2     
3 <NA>
> d <- w[a!="",,drop=F]; d
      a
1     1
NA <NA>
4

3 に答える 3

4

マシューからの背景回答:

!=この質問で強調されているonの動作はNA、考えてみれば意図したものではありませんでした。[.data.frame当初の意図は、実際にはwrt==とは異なるものにNAすることでした。誰もがそれに満足していると思います。たとえば、FAQ 2.17 には次のように記載されています。

DT[ColA==ColB]よりも簡単ですDF[!is.na(ColA) & !is.na(ColB) & ColA==ColB,]

その便利さは次のように実現されます。

DT[c(TRUE,NA,FALSE)]NAをとして扱いますFALSEが、それぞれの行をDF[c(TRUE,NA,FALSE)] 返しますNANA

動機は利便性だけでなく速度です。なぜなら!、 、is.na&および==はそれぞれ、それぞれの結果に関連付けられたメモリ割り当てを持つベクトル スキャンだからです (イントロ ビネットで説明されています)。したがってx[is.na(a) | a!=""]、実用的なソリューションですが、data.tableで必要としないようにしようとしていたタイプのロジックです。x[!a %in% ""]少し良いです。つまり、 3 回 (%in%と)では!なく2 回 (と) スキャンします。しかし、実際 には、1 回のスキャンでFrank が期待したこと ( を含む) を実行する必要があります。is.na|!=x[a != ""]NA

この質問にリンクする新しい機能リクエストが提出されました:

DT[col!=""] には NA を含める必要があります

Frank、Eddi、Arun に感謝します。正しく理解していない場合は、お気軽に修正してください。そうしないと、最終的に変更が行われます。複合式を考慮した方法で行う必要があります。たとえば、in を含む行DT[colA=="foo" & colB!="bar"]を除外し、 is 以外でisの行を含める必要があります。同様に、colA または colB のいずれかであるが両方ではない行を含める必要があります。そしておそらく、 との両方が含まれる行を含める必要があります(現在は含まれていないと思います)。NAcolAcolANAcolBNADT[colA!=colB]NADT[colA==colB]colAcolBNA

于 2013-06-09T10:52:16.470 に答える
3

お察しのとおり、これが理由です。

a != ""
#[1]  TRUE    NA FALSE

すでに考え出したことを実行できます。つまり、次のことをx[is.na(a) | a != ""]実行できます。setkeya

setkey(x, a)
x[!J("")]
于 2013-04-25T18:25:46.773 に答える