替换因子列中的<NA>

buh*_*htz 17 replace r dataframe 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)
Run Code Online (Sandbox Code Playgroud)

可能看起来像这样

      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
Run Code Online (Sandbox Code Playgroud)

现在我想<NA>用数字替换值.

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

我想我错过了关于因素的基本R概念.我呢?我无法理解为什么它不起作用.我想,invalid factor level意味着88不是这个因素的有效电平,对不对?所以我必须告诉因素栏还有另一个级别?

G. *_*eck 30

1)addNA如果fac是一个因子addNA(fac)是相同的因素但是添加了NA作为一个级别.看到?addNA

要强制NA级别为88:

facna <- addNA(fac)
levels(facna) <- c(levels(fac), 88)
Run Code Online (Sandbox Code Playgroud)

赠送:

> facna
 [1] 1  2  3  3  4  88 2  4  88 3 
Levels: 1 2 3 4 88
Run Code Online (Sandbox Code Playgroud)

1a) 这可以写成一行如下:

`levels<-`(addNA(fac), c(levels(fac), 88))
Run Code Online (Sandbox Code Playgroud)

2)因子它也可以使用如下的各种参数在一行中完成factor:

factor(fac, levels = levels(addNA(fac)), labels = c(levels(fac), 88), exclude = NULL)
Run Code Online (Sandbox Code Playgroud)

2a)或等效地:

factor(fac, levels = c(levels(fac), NA), labels = c(levels(fac), 88), exclude = NULL)
Run Code Online (Sandbox Code Playgroud)

3)ifelse另一种方法是:

factor(ifelse(is.na(fac), 88, paste(fac)), levels = c(levels(fac), 88))
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

注意:我们使用以下输入fac

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

更新:已改进(1)并添加(1a).后来加了(4).


Bri*_*ran 6

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

a <- factor(a, 
            exclude = NULL, 
            levels = c(levels(a), NA),
            labels = c(levels(a), "None"))
Run Code Online (Sandbox Code Playgroud)

您可以将“无”替换为您想要的适当替换(例如 0L)


Rol*_*and 5

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

你有两种可能:

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

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

PS:这些问题通常是由数据导入引起的。例如,您在那里显示的内容看起来应该是数字变量而不是因子变量。


小智 5

其他方法是:

#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"
Run Code Online (Sandbox Code Playgroud)


Mat*_*ius 5

我遇到了类似的问题,我想添加我认为最务实(而且也整洁)的解决方案:

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

df %>% mutate(
a = as.character(a),
a = ifelse(is.na(a), "None", a),
a = as.factor(a)
)
Run Code Online (Sandbox Code Playgroud)

NA干净且无痛,因为当值出现在列中时,您实际上不必涉足这些值factor。你绕过了奇怪的地方并最终得到一个干净的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)
Run Code Online (Sandbox Code Playgroud)