Заменить строки в переменной, используя вектор поиска - PullRequest
0 голосов
/ 07 октября 2018

У меня есть датафрейм 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, чтобы «A» в df заменялось на «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 голосов
/ 08 октября 2018

Не ясно, что результат должен быть без учета регистра.

По моему мнению, операции замены (обновления), которые включают неопределенное количество изменений, лучше всего выполнять с помощью JOIN.В этом случае это также укрепляет хорошую практику отслеживания ваших изменений в отдельном фрейме данных.

К сожалению, у тидиверса нет функции «обновить фрейм данных» .... пропущено явное .Это означает, что тидиверсы должны использовать обходной путь, 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    
0 голосов
/ 07 октября 2018

Мы можем использовать 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)]]
0 голосов
/ 07 октября 2018

Правильный способ сделать это с помощью stringr - str_replace_all:

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

(спасибо, @Moody_Mudskipper!)

0 голосов
/ 07 октября 2018

Вы можете использовать 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))
...