Tidyverse: замена целых строк на основе частичных совпадений - PullRequest
1 голос
/ 21 мая 2019

Я хочу заменить целые строковые записи в данных на основе частичных совпадений, используя функции из пакета stringr.

Единственный метод, который я пробовал, - это замена точных совпадений с помощью str_replace_all(), но это становится утомительным и громоздким, когда есть десятки вариантов, которые нужно исправить.Я ищу заменить на основе частичных совпадений.В моем следующем разделе я заменяю варианты «испанец» и «колумбиец» по прямой спецификации.Тем не менее, я хотел бы выполнить эти замены на основе чего-то вроде выполнения условия, что в словах есть «Spa» или «Col».

library(tidyverse)
library(stringr)

data <- c(
  "Spanish",
  "SPANIARD",
  "Spainiard",
  "Colombian",
  "Columbian",
  "Ecuador",
  "Equador",
  "Ecuadorian",
  "VENEZUELAN"
)

str_replace_all(data,
                c(
                  "Spanish" = "Spaniard",
                  "SPANIARD" = "Spaniard",
                  "Spainiard" = "Spaniard",
                  "Columbian" = "Colombian"
                ))
#> [1] "Spaniard"   "Spaniard"   "Spaniard"   "Colombian"  "Colombian" 
#> [6] "Ecuador"    "Equador"    "Ecuadorian" "VENEZUELAN"

Создано в 2019-05-21 представьте пакет (v0.2.1)

Так что str_replace_all() работает как рекламируется, но я ищу способ упростить этот процесс в Tidyverse.Любая помощь очень ценится.

Ответы [ 2 ]

1 голос
/ 21 мая 2019

Я предпочитаю использовать меру расстояния (например, расстояние Яро-Винклера или другую меру расстояния), но у них есть свои недостатки. Будьте устали от того, что вы могли бы изменить с частичным соответствием. Если вы делаете частичное сопоставление, было бы разумно увидеть, каковы возможности. Но вы можете сделать то, что вы обрисовали в общих чертах, используя case_when с startsWith или grepl:

tibble(data = data) %>%
  mutate(
    v1 = tolower(data),
    new_name = case_when(
      startsWith(v1, "spa") ~ "Spanaird",
      startsWith(v1, "col") ~ "Colombian",
      startsWith(v1, "eq") | startsWith(v1, "ec") ~ "Equadorian",
      startsWith(v1, "ven") ~ "Venezuelan",
      TRUE ~ as.character(data)))

# A tibble: 9 x 3
  data       v1         new_name  
  <chr>      <chr>      <chr>     
1 Spanish    spanish    Spanaird  
2 SPANIARD   spaniard   Spanaird  
3 Spainiard  spainiard  Spanaird  
4 Colombian  colombian  Colombian 
5 Columbian  columbian  Colombian 
6 Ecuador    ecuador    Equadorian
7 Equador    equador    Equadorian
8 Ecuadorian ecuadorian Equadorian
9 VENEZUELAN venezuelan Venezuelan

Чтобы увидеть возможности, которые вы можете сделать это (или несколько других вещей):

tibble(data = data) %>%
  arrange(data) %>%
  count(tolower(data)) 
1 голос
/ 21 мая 2019

Можно использовать метод расстояния для частичного совпадения

vals <- c("Spaniard", "Equador", "Colombian", "Venezuelan")
library(stringdist)
vals[amatch(tolower(data), tolower(vals),maxDist=5)]
#[1] "Spaniard"   "Spaniard"   "Spaniard"   "Colombian"  "Colombian"  
#[6] "Equador"    "Equador"    "Equador"    "Venezuelan"

Он может быть передан по трубопроводу tidyverse

library(tidyverse)
tibble(v1 = data) %>%
    mutate(v1 = vals[amatch(tolower(v1), tolower(vals), maxDist = 5)])
...