簡體   English   中英

代替<NA>在因子列中

[英]Replace <NA> in a factor column

我想用有效值替換因子列中的<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不是該因子的有效水平,對嗎? 所以我必須告訴因子列還有另一個級別?

1) addNA如果fac是一個因子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)這可以寫成一行,如下所示:

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

2) factor也可以在一行中使用factor的各種參數來完成,如下所示:

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)

3) 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)。

另一種方法是:

#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"

因子變量的基本概念是它只能取特定值,即levels 不在levels值無效。

你有兩種可能:

如果您有一個遵循此概念的變量,請確保在創建它時定義所有級別,即使是那些沒有相應值的級別。

或者使變量成為字符變量並使用它。

PS:這些問題通常是由數據導入引起的。 例如,您在那里顯示的內容看起來應該是數字變量而不是因子變量。

我有類似的問題,我想添加我認為最實用(也最整潔)的解決方案:

將列轉換為character列,使用mutate和簡單的ifelse語句將NA值更改為您想要的因子級別(我選擇了“無”),將其轉換回factor列:

df %>% mutate(
a = as.character(a),
a = ifelse(is.na(a), "None", a),
a = as.factor(a)
)

干凈且輕松,因為當它們出現在factor列中時,您實際上不必涉足NA值。 您繞過了怪異並最終得到了一個干凈的factor變量。

此外,為了回應下面關於多列的評論:您可以將語句包裝在一個函數中並使用mutate_if來選擇所有因子變量,或者,如果您知道相關列的名稱,則使用mutate_at來應用該函數:

replace_factor_na <- function(x){
  x <- as.character(x)
  x <- if_else(is.na(x), "None", x)
  x <- as.factor(x)
}

df <- df %>%
  mutate_if(is.factor, replace_factor_na)

問題是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"

通過使用factor函數,我的方法會有點傳統:

a <- factor(a, 
            exclude = NULL, 
            levels = c(levels(a), NA),
            labels = c(levels(a), "None"))

您可以用您想要的適當替換替換“無”(例如 0L)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM