Замена строк с помощью fuzzywuzzyR - PullRequest
0 голосов
/ 01 марта 2019

У меня большой набор данных с названиями городов.Многие из имен не согласованы.

Пример:

vec = c("New York", "New York City", "new York CIty", "NY", "Berlin", "BERLIn", "BERLIN", "London", "LONDEN", "Lond", "LONDON")

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

Этот пакет предоставляет возможность обнаруживать дубликаты следующим образом:

library(fuzzywuzzyR)

init_proc = FuzzUtils$new() 
PROC = init_proc$Full_process   
init_scor = FuzzMatcher$new()    
SCOR = init_scor$WRATIO         
init = FuzzExtract$new()

init$Dedupe(contains_dupes = vec, threshold = 70L, scorer = SCOR)

dict_keys(['New York City', 'NY', 'BERLIN', 'LONDEN'])

Или я могу установить «мастер-значение», например:

master = "London"

init$Extract(string = master, sequence_strings = vec, processor = PROC, scorer = SCOR)

[[1]]
[[1]][[1]]
[1] "London"

[[1]][[2]]
[1] 100


[[2]]
[[2]][[1]]
[1] "LONDON"

[[2]][[2]]
[1] 100


[[3]]
[[3]][[1]]
[1] "Lond"

[[3]][[2]]
[1] 90


[[4]]
[[4]][[1]]
[1] "LONDEN"

[[4]][[2]]
[1] 83


[[5]]
[[5]][[1]]
[1] "NY"

[[5]][[2]]
[1] 45

Мой вопросКак я могу использовать это, чтобы заменить все совпадения в списке с тем же значением, то есть я хотел бы заменить все значения, которые соответствуют основному значению, с "Лондон".Тем не менее, у меня нет основных ценностей.Итак, мне нужно иметь список совпадений и заменить значения.В этом случае это будет «Нью-Йорк», «Лондон», «Берлин».После процесса vec должен выглядеть следующим образом.

new_vec = c("New York", "New York", "New York", "New York", "Berlin", "Berlin", "Berlin", "London", "London", "London", "London")

Обновление

@ Камилла пришла в голову идея использовать world.cities из mapsпакет.Я нашел эту запись с использованием fuzzyjoin, имеющую дело с аналогичной проблемой.

Чтобы использовать это, я конвертирую vec во фрейм данных.

vec = as.data.frame(vec, stringsAsFactors = F) 
colnames(vec) = c("City")

Затем с помощьюпакет fuzzyjoin вместе с world.cities пакета maps.

library(maps)
library(fuzzyjoin)

vec %>%
  stringdist_left_join(world.cities, by = c(City = "name"), distance_col = "d") %>%
  group_by(City) %>%
  top_n(1)

Вывод выглядит так:

# A tibble: 50 x 3
# Groups:   City [5]
   City     name         d
   <chr>    <chr>    <dbl>
 1 New York New York     0
 2 NY       Ae           2
 3 NY       Al           2
 4 NY       As           2
 5 NY       As           2
 6 NY       As           2
 7 NY       Au           2
 8 NY       Ba           2
 9 NY       Bo           2
10 NY       Bo           2
# ... with 40 more rows

Проблема в том, что я понятия не имею, какиспользовать расстояние между ´name and City`, чтобы изменить значения с ошибками на правильные для всех городов.В теории корретное значение должно быть наиболее близким.Но то есть для Нью-Йорка это не так.

...