web-dev-qa-db-ja.com

因子列の<NA>を置換

ファクター列の<NA>値を有効な値に置き換えたい。しかし、私は方法を見つけることができません。この例はデモ用です。元のデータは、対処しなければならない外部のcsvファイルから取得されます。

df <- data.frame(a=sample(0:10, size=10, replace=TRUE),
                 b=sample(20:30, size=10, replace=TRUE))
df[df$a==0,'a'] <- NA
df$a <- as.factor(df$a)

こんな感じ

      a  b
1     1 29
2     2 23
3     3 23
4     3 22
5     4 28
6  <NA> 24
7     2 21
8     4 25
9  <NA> 29
10    3 24

ここで、<NA>値を数値に置き換えます。

df[is.na(df$a), 'a'] <- 88
In `[<-.factor`(`*tmp*`, iseq, value = c(88, 88)) :
  invalid factor level, NA generated

因子に関する基本的なRコンセプトを見逃したと思います。私ですか?なぜ機能しないのか理解できません。 invalid factor levelは、88がその要素の有効なレベルではないことを意味すると思いますか?だから私は別のレベルがあることを因子列に伝えなければなりませんか?

17
buhtz

1)addNAfacが因子である場合addNA(fac)は同じ因子ですが、NAがレベルとして追加されます。見る ?addNA

NAレベルを強制的に88にするには:

facna <- addNA(fac)
levels(facna) <- c(levels(fac), 88)

与える:

> facna
 [1] 1  2  3  3  4  88 2  4  88 3 
Levels: 1 2 3 4 88

1a)これは、次のように1行で記述できます。

`levels<-`(addNA(fac), c(levels(fac), 88))

2)factorfactorのさまざまな引数を使用して、次のように1行で実行することもできます。

factor(fac, levels = levels(addNA(fac)), labels = c(levels(fac), 88), exclude = NULL)

2a)または同等:

factor(fac, levels = c(levels(fac), NA), labels = c(levels(fac), 88), exclude = NULL)

)ifelse別のアプローチ:

factor(ifelse(is.na(fac), 88, paste(fac)), levels = c(levels(fac), 88))

4)forcats forcatsパッケージには次の機能があります。

library(forcats)

fct_explicit_na(fac, "88")
## [1] 1  2  3  3  4  88 2  4  88 3 
## Levels: 1 2 3 4 88

注:入力に以下を使用しましたfac

fac <- structure(c(1L, 2L, 3L, 3L, 4L, NA, 2L, 4L, NA, 3L), .Label = c("1", 
"2", "3", "4"), class = "factor")

更新:改善(1)および追加(1a)しました。後で追加(4)。

29
G. Grothendieck

問題は、NAがその要素のレベルではないことです:

> levels(df$a)
[1] "2"  "4"  "5"  "9"  "10"

すぐに変更することはできませんが、次の方法でうまくいきます。

df$a <- as.numeric(as.character(df$a))
df[is.na(df$a),1] <- 88
df$a <- as.factor(df$a)
> df$a
 [1] 9  88 3  9  5  9  88 8  3  9 
Levels: 3 5 8 9 88
> levels(df$a)
[1] "3"  "5"  "8"  "9"  "88"
4
000andy8484

他の方法は次のとおりです。

#check levels
levels(df$a)
#[1] "3"  "4"  "7"  "9"  "10"

#add new factor level. i.e 88 in our example
df$a = factor(df$a, levels=c(levels(df$a), 88))

#convert all NA's to 88
df$a[is.na(df$a)] = 88

#check levels again
levels(df$a)
#[1] "3"  "4"  "7"  "9"  "10" "88"
4
Karim Kanatov

因子変数の基本的な概念は、特定の値、つまりlevelsのみを取ることができるということです。 levelsにない値は無効です。

次の2つの可能性があります。

この概念に従う変数がある場合は、対応する値がないものも含めて、作成するときにすべてのレベルを必ず定義してください。

または、変数を文字変数にして、それを使用します。

PS:多くの場合、これらの問題はデータのインポートに起因します。たとえば、そこに表示されるものは、因子変数ではなく数値変数であるように見えます。

3
Roland