r - 为什么我的 ifelse 语句将因子转换为数字?

标签 r dataframe dplyr filter data-wrangling

我在改变 dplyr 中的变量时遇到了一个奇怪的问题。如果我运行这段代码:

diamonds %>% 
  select(cut) %>% 
  table()

我在 R 中的 diamonds 数据集中看到了这个因素列表:

cut
     Fair      Good Very Good   Premium     Ideal 
     1610      4906     12082     13791     21551 

但是,如果我尝试更改其中一个名称并保留其余名称:

diamonds %>% 
  mutate(cut.fix = ifelse(cut == "Fair",
                          "Not Fair at All",
                          cut)) %>% 
  select(cut.fix) %>% 
  table()

它只会更改“固定”值,其他所有内容都会变成数值:

cut.fix
              2               3               4               5 
           4906           12082           13791           21551 
Not Fair at All 
           1610 

这是什么原因以及如何解决?

最佳答案

if_else() 的警告在这种情况下信息更丰富:

library(tidyverse)

diamonds %>% 
  select(cut) %>% 
  table()
#> .
#>      Fair      Good Very Good   Premium     Ideal 
#>      1610      4906     12082     13791     21551

diamonds %>% 
  mutate(cut.fix = if_else(cut == "Fair",
                           "Not Fair at All",
                           cut)) %>% 
  select(cut.fix) %>% 
  table()
#> Error in `mutate()`:
#> ! Problem while computing `cut.fix = if_else(cut == "Fair", "Not Fair at
#>   All", cut)`.
#> Caused by error in `if_else()`:
#> ! `false` must be a character vector, not a `ordered/factor` object.

ifelse()函数不是“类型安全”,它可以以灾难性的方式转换/强制值。使用 dplyr if_else()功能更安全(在这些情况下会出错),您可以进行相应调整,例如您可以将“cut”转换为字符,而不是有序因子(“cut”):

diamonds %>% 
  mutate(cut.fix = if_else(cut == "Fair",
                           "Not Fair at All",
                           as.character(cut))) %>% 
  select(cut.fix) %>% 
  table()
#> .
#>            Good           Ideal Not Fair at All         Premium       Very Good 
#>            4906           21551            1610           13791           12082

这“有效”,但正如 @RitchieSacramento 指出的那样,更好的解决方案是重新编码“cut”变量并保留因子级别信息,例如使用dplyr::recode() :

diamonds %>% 
  mutate(cut.fix = recode(cut, "Fair" = "Not Fair at All")) %>% 
  select(cut.fix) %>% 
  table()
#> .
#> Not Fair at All            Good       Very Good         Premium           Ideal 
#>            1610            4906           12082           13791           21551

或者,上面 @RitchieSacramento 评论中的解决方案,使用 forcats::fct_recode() :


diamonds %>%
  mutate(cut.fix = fct_recode(cut, "Not fair at All" = "Fair" )) %>%
  select(cut.fix) %>% 
  table()
#> .
#> Not fair at All            Good       Very Good         Premium           Ideal 
#>            1610            4906           12082           13791           21551

reprex package 于 2022 年 9 月 27 日创建(v2.0.1)

关于r - 为什么我的 ifelse 语句将因子转换为数字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73862874/

相关文章:

r - 删除R中具有聚合组的重复项

r - rename.sf(.tbl, !!!syms) 错误 : internal error: can't find `agr` columns

r - 在 Shiny 的 R 应用程序中显示欧元符号

r - 更改Wordcloud包R中的字体

r - 我如何每秒运行一个函数

c - 通过 C+GSL 模拟与通过 R 并行模拟

r - 需要数据框中高级分组和数据操作的帮助

python - 如何从系列中获取数据帧索引?

r - add_column 不向数据框添加列

r - 将 df 中的值更改为 0 = FALSE、1 = TRUE、2 = TRUE