使用查找向量替换变量中的字符串

时间:2018-10-07 19:14:05

标签: r dplyr tidyverse stringr

我有一个数据帧df,其中包含一个字符变量以及fromvec和tovec。

df <- tibble(var = c("A", "B", "C", "a", "E", "D", "b"))

fromvec <- c("A", "B", "C")

tovec <- c("X", "Y", "Z")

在fromvec中使用字符串,在df中对其进行检查,然后将其替换为tovec中的相应字符串,以便将df中的“ A”替换为“ X”,将“ B”替换为“ Y”,依此类推,以获取所需的df 。

desired_df <- tibble(var = c("X", "Y", "Z", "X", "E", "D", "Y"))

我尝试了以下操作,但未获得期望的结果!

from_vec <- paste(fromvec, collapse="|") 
to_vec <- paste(tovec, collapse="|") 

undesired_df <- df %>% 
  mutate(var = str_replace(str_to_upper(var), from_vec, to_vec))

tibble(var = c("X|Y|Z", "X|Y|Z", "X|Y|Z", "X|Y|Z", "E", "D", "X|Y|Z"))

请帮助我获取所需的_df。

4 个答案:

答案 0 :(得分:5)

您可以使用chartr

df$var <- chartr(paste(fromvec,collapse=""),
                 paste(tovec,collapse=""),
                 toupper(df$var))
# # A tibble: 7 x 1
#   var  
#   <chr>
# 1 X    
# 2 Y    
# 3 Z    
# 4 X    
# 5 E    
# 6 D    
# 7 Y    

或者我们可以使用recode

library(dplyr)
df$var <- recode(toupper(df$var), !!!setNames(tovec,fromvec))

如果您真的想使用str_replace,可以这样做:

library(purrr)
library(stringr)
df$var <- reduce2(fromvec, tovec, str_replace, .init=toupper(df$var))

答案 1 :(得分:3)

使用stringr执行此操作的正确方法是使用str_replace_all

mutate(df,str_replace_all(str_to_upper(var),setNames(tovec, fromvec)))

(感谢@Moody_Mudskipper!)

答案 2 :(得分:2)

我们可以使用base R

with(df, ifelse(toupper(var) %in% fromvec, 
           setNames(tovec, fromvec)[toupper(var)], var))
#[1] "X" "Y" "Z" "X" "E" "D" "Y"

也可以通过创建逻辑条件将其写成两行

i1 <- toupper(df$var) %in% fromvec
df$var[i1] <- setNames(tovec, fromvec)[toupper(df$var)[i1]]

或使用data.table

library(data.table)
setDT(df)[toupper(var) %in% fromvec, var := setNames(tovec, fromvec)[toupper(var)]]

答案 3 :(得分:0)

目前尚不清楚结果是否区分大小写。

在我看来,涉及不确定数量的更改的替换(更新)操作最好使用JOIN来完成。在这种情况下,它还巩固了在单独的数据框中跟踪更改的良好做法。

不幸的是,tidyverse没有“更新数据框”功能。...缺少明显。这意味着收卷者必须使用变通方法coalesce

#JOIN Operation
tibble(fromvec, tovec) %>%                       #< dataframe of changes
  right_join(df, by = c("fromvec" = "var")) %>%  #< join operation
  transmute(var = coalesce(tovec, fromvec))      #< coalesce work-around

# A tibble: 7 x 1
  var  
  <chr>
1 X    
2 Y    
3 Z    
4 a    
5 E    
6 D    
7 b    

如果首选不区分大小写的操作,请考虑在管道中插入str_to_upper

tibble(fromvec, tovec) %>% 
  right_join(df %>% mutate(var = (str_to_upper(var))),  #<modify case 
             by = c("fromvec" = "var")) %>% 
  transmute(var = coalesce(tovec, fromvec))

# A tibble: 7 x 1
  var  
  <chr>
1 X    
2 Y    
3 Z    
4 X    
5 E    
6 D    
7 Y