Как слить на примерные строки?

Я хотел бы объединить 2 фрейма данных по приблизительному названию страны с помощью слияния по состоянию на но я получаю следующую ошибку:

TypeError: объект «NoneType» не может быть вызван

См. иллюстративный код ниже:

cl =  {'Country' : ["Brazil", "US", "Russia"], 'BL?':['No', 'No','Yes']}
clist = pd.DataFrame.from_dict(cl)

cd = {'Country' : ["Braizl", "us", "Rusia"]}
cdata  = pd.DataFrame.from_dict(cd)

clist = clist.sort_values('Country')
cdata = cdata.sort_values('Country')


cdata = pd.merge_asof(cdata,clist,on='Country')  

Ожидаемый результат объединит две df, а cdata df будет иметь 'BL?' столбец со значениями ДА/НЕТ.

Заранее спасибо!

inplace=True заставляет sort_values ​​возвращать None, потому что вы указываете метод, чтобы сделать это на месте
Dani Mesejo 02.02.2019 16:01

Правда, я получаю, что объект nonetype теперь не вызывается после удаления на месте

TPguru 02.02.2019 16:03

я отредактировал код

TPguru 02.02.2019 16:04

Я думаю, что merge_asof работает только с целыми числами. Если вы не хотите найти ближайшую строку к другой, вы можете использовать расстояние Левенштейна, но я не знаю о какой-либо его реализации в библиотеке Pandas.

ldoe 02.02.2019 16:10

Как бы я применил это к 2 диктовкам?

TPguru 02.02.2019 16:11

см. это: stackoverflow.com/questions/13636848/…

Dani Mesejo 02.02.2019 16:22

Это не работает для этого, я уже видел это

TPguru 02.02.2019 16:31
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
7
963
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Учитывая ваш пример, я пришел к решению. Это не очень pythonic, но это работает! (при условии, что у вас есть совпадающее название страны в clist для каждой страны с ошибкой cdata)

def get_closest(x, column):
    tmp = 1000
    for i2, r2 in clist.iterrows():
        levenshtein = editdistance.eval(x,r2['Country'])
        if levenshtein <= tmp:
            tmp = levenshtein
            res = r2

    return res['BL?']

cdata['BL'] = cdata['Country'].apply(lambda x: get_closest(x, clist))

Вывод :

   Country   BL
0  Braizl   No
1      us   No
2   Rusia  Yes

Я использую библиотеку изменить расстояние для вычисления расстояния Левенштейна. Вы можете установить его с помощью pip :

pip install editdistance

Ну должно быть два. Можете ли вы опубликовать, как выглядит ваш код?

ldoe 02.02.2019 17:01
Ответ принят как подходящий

Это должно приблизить вас, но это не будет на 100% точным. Вы можете использовать пушистый. fuzzywuzzy использует расстояние Левенштейна для вычисления разницы между двумя строками:

from fuzzywuzzy import process

# create a choice list
choices = clist['Country'].values.tolist()

# apply fuzzywuzzy to each row using lambda expression
cdata['Close Country'] = cdata['Country'].apply(lambda x: process.extractOne(x, choices)[0])

# merge
cdata.merge(clist, left_on='Close Country', right_on='Country')


  Country_x Close Country Country_y  BL?
0    Braizl        Brazil    Brazil   No
1     Rusia        Russia    Russia  Yes
2        us            US        US   No

Вы даже можете вернуть процентное совпадение и сохранить только значения > n, если вы хотите сохранить только совпадения, скажем, больше 85%

добавить процентное соответствие

from fuzzywuzzy import process

# create a choice list
choices = clist['Country'].values.tolist()

# apply fuzzywuzzy to each row using lambda expression
cdata['Close Country'] = cdata['Country'].apply(lambda x: process.extractOne(x, choices))

# add percent match wiht apply
cdata[['Close Country', 'Percent Match']] = cdata['Close Country'].apply(pd.Series)

# merge
cdata.merge(clist, left_on='Close Country', right_on='Country')

  Country_x Close Country  Percent Match Country_y  BL?
0    Braizl        Brazil             83    Brazil   No
1     Rusia        Russia             91    Russia  Yes
2        us            US            100        US   No

вы можете выполнить логическое индексирование либо перед слиянием, чтобы удалить плохое совпадение, либо слить:

cdata[['Close Country', 'Percent Match']] = cdata['Close Country'].apply(pd.Series)
cdata = cdata[cdata['Percent Match']>85]

или вы можете сделать это после слияния:

merge = cdata.merge(clist, left_on='Close Country', right_on='Country')
merge[merge['Percent Match'] > 85]

fuzzywuzzy возвращает процент совпадения как часть функции process. В первом примере я удалил его, вызвав первый элемент кортежа: process.extractOne(x, choices)[0]

Браво! Большое тебе спасибо!

TPguru 02.02.2019 17:14

Как я могу вернуть совпадение%?

TPguru 02.02.2019 17:19

@TPguru Вы хотите, чтобы это была новая колонка?

It_is_Chris 02.02.2019 17:30

Да, это было бы отлично

TPguru 02.02.2019 17:31

Попробуйте заменить from fuzzywuzzy import process на from rapidfuzz import process. Вы увидите резкое улучшение времени выполнения с теми же результатами.

Shreyesh Desai 13.04.2021 17:52

Другие вопросы по теме