我在改变 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/