R:为什么"ifelse"将因子强制转换为整数?

lil*_*ets 8 r

我试图将变量的值更改为NA值,如果它们不在向量中:

sample <- factor(c('01', '014', '1', '14', '24'))
df <- data.frame(var1 = 1:6, var2 = factor(c('01', '24', 'none', '1', 'unknown', '24')))
df$var2 <- ifelse(df$var2 %in% sample, df$var2, NA)
Run Code Online (Sandbox Code Playgroud)

由于某种原因,R不保留因子变量的原始值,而是将它们转换为数字序列:

> sample <- factor(c('01', '014', '1', '14', '24'))
> df <- data.frame(var1 = 1:6, 
                   var2 = factor(c('01', '24', 'none', '1', 'unknown', '24')))
> class(df$var2)
[1] "factor"
> df
  var1    var2
1    1      01
2    2      24
3    3    none
4    4       1
5    5 unknown
6    6      24
> df$var2 <- ifelse(df$var2 %in% sample, df$var2, NA)
> class(df$var2)
[1] "integer"
> df
  var1 var2
1    1    1
2    2    3
3    3   NA
4    4    2
5    5   NA
6    6    3
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况,以及实现我在这里尝试的正确方法是什么?

(我需要使用因子而不是整数,以免混淆"01"和"1",我的原始数据集很大,所以使用因子而不是字符应该可以节省一些内存)

Use*_*321 2

我认为实现您想要做的事情的一种方法是改变您的因素水平:

levels(df$var2)[!levels(df$var2) %in% sample] <- NA
Run Code Online (Sandbox Code Playgroud)

通过更改级别,所有与这些级别不匹配的值都将转换为因子 NA,结果将是:

df
  var1 var2
1    1   01
2    2   24
3    3 <NA>
4    4    1
5    5 <NA>
6    6   24

> df$var2
[1] 01   24   <NA> 1    <NA> 24  
Levels: 01 1 24
Run Code Online (Sandbox Code Playgroud)

未知值和无值不再位于因子水平中。或者,如果您想在您的价值观中保留未知和无,您可以尝试以下操作:

df$var2[!df$var2 %in% sample] <- NA

> df
  var1 var2
1    1   01
2    2   24
3    3 <NA>
4    4    1
5    5 <NA>
6    6   24


> df$var2
[1] 01   24   <NA> 1    <NA> 24  
Levels: 01 1 24 none unknown
Run Code Online (Sandbox Code Playgroud)

ifelse 更改数据类的原因是 ifelse 不维护类。在这里阅读第二个答案:如何防止 ifelse() 将 Date 对象转换为数字对象

@tchakravarty 在评论中提到的最后一种方法是使用 dplyr 中的 if_else!