替换因子列中的<na>

时间:2016-08-24 14:46:30

标签: r dataframe replace 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不是该因素中的有效等级,对吧?所以我必须告诉因素栏还有另一个级别?

6 个答案:

答案 0 :(得分:27)

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

答案 1 :(得分: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"

答案 2 :(得分:3)

因子变量的基本概念是它只能采用特定值,即levels。不在levels中的值无效。

您有两种可能性:

如果您有一个遵循此概念的变量,请确保在创建时定义所有级别,即使是那些没有相应值的级别。

或者让变量成为一个字符变量并使用它。

PS:这些问题通常来自数据导入。例如,你在那里展示的东西看起来应该是一个数字变量,而不是一个因子变量。

答案 3 :(得分:3)

问题在于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 :(得分:3)

我遇到了类似的问题,我想补充一下我认为最实用(也是最整洁)的解决方案:

将列转换为character列,使用mutate和简单的ifelse语句将NA的值更改为您想要的因子水平(我选择了“无”),将其转换回factor列:

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

干净而轻松,因为当NA列中出现factor值时,您实际上不必花时间。您绕过了怪异之处,最后得到了一个干净的factor变量。

答案 5 :(得分:0)

通过使用factor函数,我的方式会有点传统:

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

您可以将“ None”替换为所需的适当替换(例如0L)