Соответствующие столбцы со строковыми значениями, которые не на 100% идентичны для объединения данных - PullRequest
0 голосов
/ 26 апреля 2020

Я пытаюсь объединить два фрейма данных, и, к сожалению, единственными общими столбцами являются столбцы имени, и они не имеют 100% идентичных значений. Есть ли способ, которым я могу сопоставить имена, основанные на вероятности, скажем, если есть 80% или более совпадающих строк между двумя значениями, они будут сопоставлять их вместе. ниже приведен пример того, с чем я сталкиваюсь:

df1= pd.DataFrame({"Name":["John", "Mary", "Sarah", "Jack"], "B":[1,2,3,4]})
df2= pd.DataFrame({"Name":["Jon", 'Mary", "Sara", "Jak", "lilly"], "C":["foo", "bar", "bar", "foo", "bar"]})

Я довольно новичок в кодировании и буду признателен за ваш совет:)

Ответы [ 3 ]

0 голосов
/ 26 апреля 2020

Если вам не нужно что-то слишком причудливое, может хватить встроенного difflib.get_close_matches:

from difflib import get_close_matches

def get_closest_match(name):
    matches = get_close_matches(name, df1['Name']
    if len(matches) > 0:
        return matches[0]
    else:
        return None

df2['ClosestName'] = df2['Name'].apply(get_closest_match)
df1.merge(df2, left_on='Name', right_on='ClosestName')

Результат:

Name_x  B Name_y    C ClosestName
  John  1    Jon  foo        John
  Mary  2   Mary  bar        Mary
 Sarah  3   Sara  bar       Sarah
  Jack  4    Jak  foo        Jack
0 голосов
/ 26 апреля 2020

Может быть два решения.

Первое решение работает, если у вас есть все действительные имена (пространство имен) для столбца «Имя». Затем вы можете перебрать значения в столбце «Имя» и:

  1. Рассчитать его расстояние со всеми возможными значениями в пространстве имен (расстояние Левенштейна должно работать)
  2. Выберите одно с минимальное расстояние (наибольшее сходство) и замените его 2.5 Чтобы избежать подверженной ошибкам замены, вы можете установить отсечение для расстояния
  3. Просто слияние (внешнее соединение)

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

0 голосов
/ 26 апреля 2020

Как предлагает @Scott Boston, вы можете сделать это с помощью пакета fuzzywuzzy. Вам нужно создать новый столбец, который будет содержать самое похожее слово из df1, а затем вы сможете присоединиться к этому столбцу.

In [88]: df2['key'] = df2['Name'].apply(lambda x : [process.extract(x, df1['Name'], limit=1)][0][0][0])

In [89]: df2
Out[89]:
    Name    C    key
0    Jon  foo   John
1   Mary  bar   Mary
2   Sara  bar  Sarah
3    Jak  foo   Jack
4  lilly  bar   Mary

In [90]: df2.merge(df1, left_on='key',right_on='Name')
Out[90]:
  Name_x    C    key Name_y  B
0    Jon  foo   John   John  1
1   Mary  bar   Mary   Mary  2
2  lilly  bar   Mary   Mary  2
3   Sara  bar  Sarah  Sarah  3
4    Jak  foo   Jack   Jack  4
...