На самом деле это может стать чрезвычайно трудной проблемой, если вы хотите или должны сгруппировать строки по одинаковым именам магазинов без экзогенного указания количества реальных магазинов или их официальных названий. Это связано с тем, что вы неизбежно столкнетесь с нечетко перекрывающимися кластерами и нарушениями транзитивности при любом заданном пороговом расстоянии или минимизации расстояния между строками. A будет ближе всего к B, B будет ближе к C, а C будет не ближе к A, и что тогда? A и B не могут быть одним и тем же магазином, в то время как C является тем же магазином, что и B, но не A!
Если вы можете указать вектор канонических названий магазинов, тогда я рекомендую следующее, которое просто находитканоническое имя магазина, которое ближе к названию в каждой строке и создает новый столбец из этих ближайших канонических имен. Затем вы можете сгруппировать по значениям этого нового столбца и свернуть идентификаторы хранилища в векторы, разделенные запятыми, или что-то еще.
library(future)
library(stringdist)
library(tidyverse)
library(magrittr)
#>
#> Attaching package: 'magrittr'
#> The following object is masked from 'package:purrr':
#>
#> set_names
#> The following object is masked from 'package:tidyr':
#>
#> extract
data <- tribble(
~PairID, ~`Store name`,
1, "Quick Stop",
2, "TD's Food Shop",
2, "TD's Food Shops",
3, "TD's Food Shops",
3, "TD's Food Shop 1",
4, "TD's Food Shop",
4, "TD's Food Shop 1"
)
standard_names <- c("Quick Stop", "TD's Food Shop")
plan(multiprocess)
data %<>% mutate(
closest_name =
stringdistmatrix(`Store name`, standard_names, method = "jw") %>%
apply(1, function(x) which(x == min(x))) %>%
extract(standard_names, .)
)
data
#> # A tibble: 7 x 3
#> PairID `Store name` closest_name
#> <dbl> <chr> <chr>
#> 1 1 Quick Stop Quick Stop
#> 2 2 TD's Food Shop TD's Food Shop
#> 3 2 TD's Food Shops TD's Food Shop
#> 4 3 TD's Food Shops TD's Food Shop
#> 5 3 TD's Food Shop 1 TD's Food Shop
#> 6 4 TD's Food Shop TD's Food Shop
#> 7 4 TD's Food Shop 1 TD's Food Shop
combined_pairIDs <-
data %>%
group_by(closest_name) %>%
summarize_at("PairID", ~ toString(order(unique(.x)))) %>%
ungroup()
combined_pairIDs
#> # A tibble: 2 x 2
#> closest_name PairID
#> <chr> <chr>
#> 1 Quick Stop 1
#> 2 TD's Food Shop 1, 2, 3
Создано в 2019-10-19 с помощью пакета представить (v0.3.0)
Обратите внимание, что здесь есть вероятность ошибки, которую я намеренно оставляю. Что делать, если одна из строк имеет имя, которое одинаково близко к двум илибольше канонических имен? Он попытается извлечь более одного значения из standard_names
, что недопустимо. Если такие связи случаются, вам нужно решить, как вы хотите их разорвать и что они могут указывать на характер данных.