Существует ли эффективная стратегия нечеткого объединения данных клиента для определения единого идентификатора клиента в R? - PullRequest
1 голос
/ 20 июня 2019

Я хочу выполнить «нечеткую дедупликацию» для данных моего клиента, чтобы получить уникальный идентификатор для каждого клиента, где в исходных данных для одного и того же клиента могли быть введены несколько идентификаторов.

У меня есть данныекадр в R, который содержит список клиентов.У каждого клиента есть идентификатор, имя, фамилия, адрес электронной почты и номер телефона.

Многие клиенты были введены несколько раз для разных покупок.Иногда старая запись (с тем же идентификатором) используется повторно, в других случаях выдается новая запись и новый идентификатор.

Какова подходящая стратегия для дедупликации этих данных, когда я не могу рассчитывать на точное совпадение во всех полях - например,неправильное написание имени или только начального имени, но другие поля могут совпадать.

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

(На данный момент нет кода - это больше запрос общей стратегии и подхода к кодированию.

Есть ликакие-нибудь пакеты, которые эффективно обрабатывают такие совпадения?)

1 Ответ

0 голосов
/ 21 июня 2019

Прежде чем приступить к поиску дубликатов, важно сначала получить / собрать хорошие данные.

Вы упомянули имя, фамилию, адрес электронной почты и номер телефона.Имена хороши, так как они обычно не меняются в отличие от адресов электронной почты и телефонных номеров.Фамилии могут меняться в результате брака / развода.Поэтому всегда полезно иметь другие переменные, не зависящие от времени, такие как «дата рождения» или «место рождения».

Даже при наличии хороших данных всегда будет проблема, соответствующая имени, фамилии идата рождения в большой базе данных клиентов.

Как вы указали в своих комментариях, матрица расстояний между строками 100 000 и более клиентов требует времени и вызывает проблемы с памятью.

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

Я скачал некоторые фальшивые данные из 1000 записей.К сожалению, он не содержит дубликатов, но для отображения основного рабочего процесса он не содержит реальных дубликатов.

Подход состоит из следующих шагов:

  1. Создание поля имени на основе последнегои имя.
  2. Расположите его в порядке возрастания (AZ).
  3. Разбейте его на группы по 50 клиентов (это для моего примера данных с 1000 строк, на самом деле работает группы из 500 следуетне будет проблем с точки зрения скорости и памяти).
  4. Создайте вложенный тиббл для работы с purrr::map.
  5. Примените настроенную функцию stringdistmatrix, которая работает в конвейере dplyrи дает вероятные совпадения имен клиентов в качестве выходных данных.
  6. Снимите единичные результаты, чтобы получить полный список возможных совпадений.

Идея разбивки данных заключается в том, что вы делаетене нужна матрица расстояний между 100 000 клиентов.Большинство имен настолько различны, что вам даже не нужно вычислять расстояние до строки.Сортировка имен и работа с небольшими подмножествами подобны сужению поиска.

Конечно, это всего лишь один из способов разбить данные.Он неполный, поскольку он пропускает, например, всех клиентов с опечаткой в ​​первой букве фамилии.Однако вы можете повторить этот подход для других переменных, таких как дата рождения, количество символов в имени и т. Д. В идеале вы делаете разные разбивки и собираете все вместе в конце.

Я скачал фиктивную дату через www.mockaroo.com.Я пытался поставить его здесь с помощью dput, но это было долго.Поэтому я просто показываю вам заголовок () моих данных, и вы можете создавать свои собственные поддельные данные или использовать реальные данные клиентов.

Одна заметка, касающаяся моей настроенной версии stringdistmatrix, которую я назвал str_dist_mtx.При работе с реальными данными вы должны корректировать размер группы (в примере она довольно мала, n = 50).И вы должны отрегулировать расстояние до строки string_dist, до которого вы хотите рассматривать два разных имени в качестве возможных совпадений.Я взял 6, чтобы хотя бы получить некоторые результаты, но я не работаю с данными, которые имеют реальные дубликаты.Поэтому в реальном приложении я бы выбрал 1 или 2, чтобы охватить самые основные опечатки.

# the head() of my data
test_data <- structure(list(first_name = c("Gabriel", "Roscoe", "Will", "Francyne", 
"Giorgi", "Dulcinea"), last_name = c("Jeandeau", "Chmiel", "Tuckwell", 
"Vaggers", "Fairnie", "Tommis"), date_of_birth = structure(c(9161, 
4150, 2557, 9437, -884, -4489), class = "Date")), row.names = c(NA, 
-6L), class = c("tbl_df", "tbl", "data.frame"))

Ниже приведен код, который я использовал.

library(dplyr)
library(tidyr)
library(ggplot2)
library(purrr)
library(stringdist)

# customized stringdistmatrix function
str_dist_mtx <- function(df, x, string_dist, n) {

  temp_mtx = stringdistmatrix(df[[x]],df[[x]])

  temp_tbl = tibble(name1 = rep(df[[x]], each = n),
                    name2 = rep(df[[x]], times = n),
                    str_dist = as.vector(temp_mtx)) %>% 
             filter(str_dist > 0 & str_dist < string_dist) 

  temp_tbl[!duplicated(data.frame(t(apply(temp_tbl,1,sort)))),]

}

# dplyr pipe doing the job
test_data2 <- test_data %>%
                mutate(name = paste0(last_name, first_name)) %>% 
                arrange(name) %>%
                mutate(slice_id = row_number(),
                      slice_id = cut_width(slice_id, 50, center = 25)) %>% 
                nest(-slice_id) %>% 
                mutate(str_mtx = map(data,
                                     ~ str_dist_mtx(., "name", string_dist = 6, n = 50))) %>% 
                select(str_mtx) %>% 
                unnest() 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...