我可以使用因子作为搜索并替换 mutate 中的值吗?

Can I use factors as search and replace values in mutate?

我有一个值列表,我想用另一个列表中的值替换它们,无论它们出现在哪里。因此,例如,凡是“白色”作为头发颜色出现的地方,我都想使用“浅色”;无论“auburn”出现在哪里,我都想使用“brown”。我可以通过以下方式实现:

find_text = c("white", "auburn", "none")
replace_text = c("light", "brown", "bald")

starwars %>%
  filter(gender == "feminine") %>% 
  select(c("name", "hair_color", "species")) %>%
  mutate(hair_color = str_replace(hair_color, find_text[1], replace_text[1]),
         hair_color = str_replace(hair_color, find_text[2], replace_text[2]),
         hair_color = str_replace(hair_color, find_text[3], replace_text[3]),
         )

我想我可以使用 fct_recode() 但这似乎也需要一个命名字符串。 有没有更简洁的方法来解决这个问题?

我们可以使用命名向量来替换str_replace。这里假设我们要替换子串即匹配替换一个子串而不是固定的字符串替换

library(dplyr)
library(stringr)
starwars %>%
   filter(gender == "feminine") %>% 
   select(c("name", "hair_color", "species")) %>%
   mutate(hair_color_new = str_replace_all(hair_color, 
          set_names(replace_text, find_text)))
# A tibble: 17 x 4
#   name               hair_color species    hair_color_new
#   <chr>              <chr>      <chr>      <chr>         
# 1 Leia Organa        brown      Human      brown         
# 2 Beru Whitesun lars brown      Human      brown         
# 3 Mon Mothma         auburn     Human      brown         
# 4 Shmi Skywalker     black      Human      black         
# 5 Ayla Secura        none       Twi'lek    bald          
# 6 Adi Gallia         none       Tholothian bald          
# 7 Cordé              brown      Human      brown         
# 8 Luminara Unduli    black      Mirialan   black         
# 9 Barriss Offee      black      Mirialan   black         
#10 Dormé              brown      Human      brown         
#11 Zam Wesell         blonde     Clawdite   blonde        
#12 Taun We            none       Kaminoan   bald          
#13 Jocasta Nu         white      Human      light         
#14 R4-P17             none       Droid      bald          
#15 Shaak Ti           none       Togruta    bald          
#16 Rey                brown      Human      brown         
#17 Padmé Amidala      brown      Human      brown    

如果我们想要固定匹配,那么recode也有用

starwars %>%
    filter(gender == "feminine") %>% 
    select(c("name", "hair_color", "species"))  %>% 
    mutate(hair_color_new = recode(hair_color, !!! set_names(replace_text, find_text)))
# A tibble: 17 x 4
#   name               hair_color species    hair_color_new
#   <chr>              <chr>      <chr>      <chr>         
# 1 Leia Organa        brown      Human      brown         
# 2 Beru Whitesun lars brown      Human      brown         
# 3 Mon Mothma         auburn     Human      brown         
# 4 Shmi Skywalker     black      Human      black         
# 5 Ayla Secura        none       Twi'lek    bald          
# 6 Adi Gallia         none       Tholothian bald          
# 7 Cordé              brown      Human      brown         
# 8 Luminara Unduli    black      Mirialan   black         
# 9 Barriss Offee      black      Mirialan   black         
#10 Dormé              brown      Human      brown         
#11 Zam Wesell         blonde     Clawdite   blonde        
#12 Taun We            none       Kaminoan   bald          
#13 Jocasta Nu         white      Human      light         
#14 R4-P17             none       Droid      bald          
#15 Shaak Ti           none       Togruta    bald          
#16 Rey                brown      Human      brown         
#17 Padmé Amidala      brown      Human      brown      

这是一个使用 join 的选项。

library(tidyverse)

replacetext <- data.frame(
  find_text = c("white", "auburn", "none"), 
  replace_text = c("light", "brown", "bald"), 
  stringsAsFactors = F)

starwars %>%
  filter(gender == "female") %>% 
  select(c("name", "hair_color", "species")) %>% 
  left_join(replacetext, by = c("hair_color" = "find_text")) %>% 
  mutate(replace_text = coalesce(replace_text, hair_color)) %>% 
  select(-hair_color) %>% 
  rename(hair_color = replace_text)