ifelse 使因子 'forget' 成为其水平顺序

ifelse makes factor 'forget' its levels order

我有一个包含两个因素的数据框,例如:

data <- data.frame(
  x = factor(rep(letters[1:3], 2)),
  y = factor(rep(c('z','x','y'), each=2), c('z','x','y'))
)

 data
  x y
1 a z
2 b z
3 c x
4 a x
5 b y
6 c y

我想将 xa 的所有 y 转换为 NA。所以我尝试:

factor(ifelse(data$x=='a', NA, as.character(data$y)))
<NA> z    x    <NA> y    y   
Levels: x y z

获得与原始数据不同的级别顺序,即:

data$y
z z x x y y
Levels: z x y

除了像这样的蛮力之外,你能建议任何保持原始顺序的方法吗:

factor(ifelse(data$x=='a', NA, as.character(data$y)), c('z','x','y'))
<NA> z    x    <NA> y    y   
Levels: z x y

根据 Roland 的评论,这是一个很好的解决方案,我提出了 tidyverse 解决方案:

library(tidyverse)
library(magrittr)

data %>% 
  mutate(y = y %>% inset(x=='a', value=NA)) %>% 
  pull(y)

<NA> z    x    <NA> y    y   
Levels: z x y 

也许对某人有用:)

另一种选择,感谢 Darren Tsai:

data %>% 
  mutate(y = y %>% replace(x=='a', NA)) %>% 
  pull(y)

<NA> z    x    <NA> y    y   
Levels: z x y 

您还可以使用 [] 来保留因子属性:

data$y[] <- ifelse(data$x=='a', NA, as.character(data$y)) 
str(data$y)
# Factor w/ 3 levels "z","x","y": NA 1 2 NA 3 3

你的方法看起来不错。如果您不想手动设置新级别,可以参考data$y的级别。

factor(ifelse(data$x == 'a', NA, as.character(data$y)), levels(data$y))

# [1] <NA> z    x    <NA> y    y   
# Levels: z x y

您也可以使用 replace(),它不会重置关卡。

replace(data$y, data$x == 'a', NA)

# [1] <NA> z    x    <NA> y    y   
# Levels: z x y