2015-06-05 5 views
1

Вот мой предыдущий вопрос, повторно обработанный форматом R.R - Объединение двух файлов данных на основе частичного совпадения несогласованных форматов полного имени

Я ищу способ объединить два файла данных на основе частичного совпадения полных имен участников, которые иногда вводятся в разных форматах и ​​иногда с ошибками. Я знаю, что есть несколько вариантов функций для частичных совпадений (например, agrep и pmatch) и для слияния файлов данных, но мне нужна помощь в: a) объединении двух; б) выполнение частичного соответствия, которое может игнорировать средние имена; c) в объединенном хранилище данных хранятся как оригинальные форматы имен, так и d) сохраняются уникальные значения, даже если они не совпадают.

К примеру, у меня есть следующие два файла данных:

Имя файла: Employee Data (df1 в R) Название

 Full.Name Date.Started Orders 
1 ANGELA MUIR  6/15/14 25  44 
2 EILEEN COWIE  6/15/14  40 
3 LAURA CUMMING  10/6/14  43 
4 ELENA POPA  1/21/15  37 
5 KAREN MACEWAN  3/15/99  39 

Файл: Данные оценки (df2 в R)

  Candidate Leading.Factor SI.D SI.I 
1   Angie muir    I -3 12 
2  Caroline Burn    S -5 -3 
3 Eileen Mary Cowie    S -5 5 
4   Elena Pope    C -4 7 
5  Henry LeFeuvre    C -5 -1 
6  Jennifer Ford    S -3 -2 
7  Karen McEwan    I -4 10 
8  Laura Cumming    S 0 6 
9  Mandip Johal    C -2 2 
10 Mubarak Hussain    D 6 -1 

Я хочу объединить их по именам (Полное имя в df1 и Кандидат в df2), игнорируя второе имя (например, Eilen Cowie = Eileen Mary Cowie), дополнительные пробелы (Laura Cumming = Laura Cumming); misspells (например, Елена Попа = Елена Pope) и т.д.

Идеальный выход будет выглядеть следующим образом:

   Name  Full.Name   Candidate Date.Started Orders Leading.Factor SI.D SI.I 
1 ANGELA MUIR ANGELA MUIR   Angie muir 6/15/14 25  44    I -3 12 
2 EILEEN COWIE EILEEN COWIE Eileen Mary Cowie  6/15/14  40    S -5 5 
3 LAURA CUMMING LAURA CUMMING  Laura Cumming  10/6/14  43    S 0 6 
4  ELENA POPA  ELENA POPA   Elena Pope  1/21/15  37    C -4 7 
5 KAREN MACEWAN KAREN MACEWAN  Karen McEwan  3/15/99  39    I -4 10 
6 Caroline Burn   N/A  Caroline Burn   N/A N/A    S -5 -3 
7 Henry LeFeuvre   N/A Henry LeFeuvre   N/A N/A    C -5 -1 
8 Jennifer Ford   N/A  Jennifer Ford   N/A N/A    S -3 -2 
9  Mandip Johal   N/A  Mandip Johal   N/A N/A    C -2 2 
10 Mubarak Hussain   N/A Mubarak Hussain   N/A N/A    D 6 -1 

Любые предложения будут высоко оценены!

+0

Единственная функция слияния, с которой я сталкиваюсь, - это слияние, но я не уверен, как использовать это с кодом, соответствующим совпадающим строкам. –

ответ

2

Для первого прохода я бы предложил двухэтапный процесс.

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

stringCleaning <- function(x) { 
# x <- stringr::str_trim(x) 
# x <- tolower(x) 
# x <- gsub("\\s+", " ", x) 
# x <- gsub("[^[:space:]A-z0-9]", "", x) 
    stringr::str_trim(tolower(gsub("\\s+", " ", gsub("[^[:space:]A-z0-9]", "", x)))) 
} 

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

Два, используйте расстояния Levenshtein (или отредактируйте), чтобы найти ваши ближайшие совпадения. Пакет stringdist включает простой калькулятор расстояния, который поможет вам.

stringdist::stringdist('your mother', c("bellow", "your mom", 'yourmother')) 
min(stringdist::stringdist('your mother', c("bellow", "your mom", 'yourmother'))) 
which.min(stringdist::stringdist('your mother', c("bellow", "your mom", 'yourmother'))) 

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

df1 <- data.frame(name = c("Jena Stars", "Gina Starz")) 
df2 <- data.frame(name = c("gina starz", "Jena starz ")) 

df1$clean <- stringCleaning(df1$name) 
df2$clean <- stringCleaning(df2$name) 

df1$check <- df2$name[sapply(df1$clean, function(x) { 
    which.min(stringdist::stringdist(x, df2$clean)) 
    })] 
df1 

Небольшой пример, но я надеюсь, что это будет полезно.

+0

Спасибо, да это невероятно полезно! Теперь мне просто нужно объединить два файла вместе на основе созданной вами функции соответствия. однако мне нужно будет объединить их, сохранив уникальные строки, которые не совпадают в другой части данных. Я знаю, что могу использовать аргумент all.x в слиянии, но я не уверен, как интегрировать функцию слияния с этим кодом соответствия строк. –

+1

Я думаю, что эта функция должна это сделать: merge (df1, df2, by.x = "check", by.y = "name", all.x = TRUE, all.y = TRUE, sort = TRUE) –

+0

У меня есть вопрос о коде stringdist выше (или вообще функция).Используя текущий код в ответе, если бы я попытался сопоставить имя Уэйн Синклер с Дэном Инчем или Уэйн Дэниелсон Синклер, он вернул бы матч Дэн Инч: min (stringdist :: stringdist ('Wayne Sinclair', c (" Wayne Danielson Sincalir "))) = 11 while min (stringdist :: stringdist ('Wayne Sinclair', c (" Dan Inch "))) = 9. Есть ли что-то, что я могу сделать (возможно, используя функцию amatch и параметр веса) исправить это и установить правило, которое говорит, возвращать N/A в соответствие, если оно требует слишком большого редактирования строк? –