0

data.frames を何らかの条件でサブセット化する場合、データ フレームに NA が含まれていると、条件の結果として NA 値が得られることがあります。次に、data.frame のサブセット化で問題が発生します。

# data generation
set.seed(123)
df <- data.frame(a = 1:100, b = sample(c("moon", "venus"), 100, replace = TRUE), c = sample(c('a', 'b', NA), 100, replace = TRUE))

# indexing
with(df, df[a < 30 & b == "moon" & c == "a",])

あなたは得る:

      a    b    c
NA   NA <NA> <NA>
10   10 moon    a
12   12 moon    a
NA.1 NA <NA> <NA>
NA.2 NA <NA> <NA>
29   29 moon    a

これは、条件が NA を含むベクトルになり、これらの NA がデータ フレームのインデックス作成で上記の結果を生成するために発生します。

解決策の 1 つは、次の修正のいずれかです。

with(df, df[a < 30 & b == "moon" & (c == "a" & !is.na(c)),])  # exclude NAs
with(df, df[a < 30 & b == "moon" & (c == "a" | is.na(c)),])  # include NAs

しかし、これらはかなり不器用です - のような長い条件が df[A == x1 & B == x2 & C == x3 & D == x4,]あり、各要素をこのようにラップする必要があると想像してください - df[(A == x1 | is.na(A)) & (B == x2 | is.na(B)) ...,]

データフレームを検査しようとするだけで、コンソールにこれらの大量のコードを書く必要のない、この問題に対するエレガントな解決策はありますか?

4

3 に答える 3

5

行を省略したい場合、NA手っ取り早くハックな解決策の 1 つは、次のようにラップすることですwhich

> with(df, df[a < 30 & b == "moon" & c == "a",])
      a    b    c
NA   NA <NA> <NA>
10   10 moon    a
12   12 moon    a
NA.1 NA <NA> <NA>
NA.2 NA <NA> <NA>
29   29 moon    a
> with(df, df[which(a < 30 & b == "moon" & c == "a"),])
    a    b c
10 10 moon a
12 12 moon a
29 29 moon a

編集時: このような状況での別のオプションは、眉をひそめる人もいるかもしれませんが、個人的には非常に便利だと思うのは、括弧内にローカル変数を定義することです:

> with(df, df[{i<-a < 30 & b == "moon" & c == "a"; i | is.na(i)},])
    a    b    c
6   6 moon <NA>
10 10 moon    a
12 12 moon    a
15 15 moon <NA>
18 18 moon <NA>
29 29 moon    a
> with(df, df[{i<-a < 30 & b == "moon" & c == "a"; i & !is.na(i)},])
    a    b c
10 10 moon a
12 12 moon a
29 29 moon a

これは、特別な関数を記述したり、別の行でインデックスを定義したりするよりも簡潔であり、必要なことを正確に実行する R 関数がない多くの状況に適用できます。

于 2013-10-17T15:40:18.677 に答える
1

data.tableパッケージを使用できます。すべてを a に含める必要はなく、with(df, ...)NA を FALSE として扱うため、これによりコードが簡素化されます。

require(data.table)
dt <- data.table(df)
dt[a < 30 & b == "moon" & c == "a",] # exclude NAs
dt[a < 30 & b == "moon" & (c == "a"|is.na(c)),] # include NAs
于 2013-10-17T15:40:29.197 に答える
1
clean <- function(x, include = FALSE){
    x[is.na(x)] <- include
    x
}

# Original output
with(df, df[a < 30 & b == "moon" & c == "a",])
# Clean it up and remove NAs
with(df, df[clean(a < 30 & b == "moon" & c == "a"),])
# Clean it up but include NAs
with(df, df[clean(a < 30 & b == "moon" & c == "a", include = TRUE),])

を与える

> with(df, df[a < 30 & b == "moon" & c == "a",])
      a    b    c
NA   NA <NA> <NA>
10   10 moon    a
12   12 moon    a
NA.1 NA <NA> <NA>
NA.2 NA <NA> <NA>
29   29 moon    a
> 
> with(df, df[clean(a < 30 & b == "moon" & c == "a"),])
    a    b c
10 10 moon a
12 12 moon a
29 29 moon a
> with(df, df[clean(a < 30 & b == "moon" & c == "a", include = TRUE),])
    a    b    c
6   6 moon <NA>
10 10 moon    a
12 12 moon    a
15 15 moon <NA>
18 18 moon <NA>
29 29 moon    a

を使用whichすることもできますが、デフォルトで値を除外することしかできません

于 2013-10-17T15:41:12.683 に答える