Объединить два csv-файла по столбцам с одинаковыми строками - PullRequest
0 голосов
/ 25 января 2020

Я начинаю использовать pandas, и я столкнулся с проблемой, которую не знаю, как решить.

У меня есть два кадра данных.

Первый содержит информацию об автомобиле в том числе модель автомобиля (столбец DESCR_MARCA_VEICULO)

df1
col1   col2   DESCR_MARCA_VEICULO
....   ....   'GM/CELTA 5 PORTAS SUPER'
....   ....   'VW/VOYAGE LS'
....   ....   'VW/GOL LS'
....   ....   'I/AUDI A4 2.0T FSI'
....   ....   'FIAT/UNO CS IE'

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

df2
ID     DESCR_MARCA_VEICULO
1      'GM - CELTA 5'
2      'VW - VOYAGE LS'
3      'VW - GOL LS'
4      'ACURA - INTEGRA GS 1.8'
5      'AUDI - 80 S2 AVANT'

И это не обязательно следует шаблону, как замена "/" на "-" или что-то в этом роде.

Однако у меня в DF1 более 5000 различных моделей автомобилей (что делает невозможным для меня поиск и мне нужно объединить DF1 и DF2, перенеся столбец ID в DF1 (это будет слияние). Однако, когда я объединяю dfs, нет совпадения из-за этих различий в строках.

Есть ли способ объединить эти dfs по сходству между строками в столбце DESCR_MARCA_VEICULO?

Спасибо:)

1 Ответ

0 голосов
/ 25 января 2020

Я рекомендую вам найти нечеткое соответствие с пакетом fuzzywuzzy

Один хак - удалить все символы из ваших строк, кроме букв и цифр

df1['var'] = df1['DESCR_MARCA_VEICULO'].str.replace('[^A-Za-z0-9]','')
df2['var'] = df2['DESCR_MARCA_VEICULO'].str.replace('[^A-Za-z0-9]','')

m = pd.merge(df1,df2,on='var').drop('var',axis=1)

print(m)

    col1     col2 DESCR_MARCA_VEICULO_x     matches  ID DESCR_MARCA_VEICULO_y
0  ....     ....           VW/VOYAGE LS  VWVOYAGELS   2        VW - VOYAGE LS
1  ....     ....              VW/GOL LS     VWGOLLS   3           VW - GOL LS

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

from fuzzywuzzy import fuzz
from fuzzywuzzy import process
def fuzzy_merge(df_1, df_2, key1, key2, threshold=90, limit=2):
    """
    df_1 is the left table to join
    df_2 is the right table to join
    key1 is the key column of the left table
    key2 is the key column of the right table
    threshold is how close the matches should be to return a match, based on Levenshtein distance
    limit is the amount of matches that will get returned, these are sorted high to low
    """
    s = df_2[key2].tolist()

    m = df_1[key1].apply(lambda x: process.extract(x, s, limit=limit))    
    df_1['matches'] = m

    m2 = df_1['matches'].apply(lambda x: ', '.join([i[0] for i in x if i[1] >= threshold]))
    df_1['matches'] = m2

    return df_1

print(fuzzy_merge(df1, df2, 'var', 'var', threshold=80))

    col1     col2      DESCR_MARCA_VEICULO                  var     matches
0  ....     ....   GM/CELTA 5 PORTAS SUPER  GMCELTA5PORTASSUPER    GMCELTA5
1  ....     ....              VW/VOYAGE LS           VWVOYAGELS  VWVOYAGELS
2  ....     ....                 VW/GOL LS              VWGOLLS     VWGOLLS
3  ....     ....        I/AUDI A4 2.0T FSI        IAUDIA420TFSI            
4  ....     ....            FIAT/UNO CS IE          FIATUNOCSIE   
...