Слияние Pandas DataFrames с ключами в разных столбцах - PullRequest
2 голосов
/ 26 февраля 2020

Я пытаюсь объединить два Pandas кадра данных, которые выглядят следующим образом:

import pandas as pd

df1 = pd.DataFrame({'PAIR': ['140-120', '200-280', '350-310', '410-480', '500-570'],
                    'SCORE': [99, 70, 14, 84, 50]})
print(df1)

      PAIR  SCORE
0  140-120     99
1  200-280     70
2  350-310     14
3  410-480     84
4  500-570     50

df2 = pd.DataFrame({'PAIR1': ['140-120', '280-200', '350-310', '480-410', '500-570'],
                    'PAIR2': ['120-140', '200-280', '310-350', '410-480', '570-500'],
                    'BRAND' : ['A', 'V', 'P', 'V', 'P']})
print(df2)

     PAIR1    PAIR2 BRAND
0  140-120  120-140     A
1  280-200  200-280     V
2  350-310  310-350     P
3  480-410  410-480     V
4  500-570  570-500     P

Если вы посмотрите поближе, вы заметите, что каждое значение в столбце PAIR df1 соответствует либо значение в PAIR1 или PAIR2 из df2. В df2 ключи присутствуют обоими способами (например, 140-120 и 120-140) .

Моя цель - объединить два кадра данных в получить следующий результат:

      PAIR  SCORE BRAND
0  140-120     99     A
1  200-280     70     V
2  350-310     14     P
3  410-480     84     V
4  500-570     50     P

Я попытался сначала объединить df1 с df2 следующим образом:

df3 = pd.merge(left = df1, right = df2, how = 'left', left_on = 'PAIR', right_on = 'PAIR1')

Затем, получив получившийся DataFrame df3 и объединить обратно с df2:

df4 = pd.merge(left = df3, right = df2, how = 'left', left_on = 'PAIR', right_on = 'PAIR2')

print(df4)

      PAIR  SCORE  PAIR1_x  PAIR2_x BRAND_x  PAIR1_y  PAIR2_y BRAND_y
0  140-120     99  140-120  120-140       A      NaN      NaN     NaN
1  200-280     70      NaN      NaN     NaN  280-200  200-280       V
2  350-310     14  350-310  310-350       P      NaN      NaN     NaN
3  410-480     84      NaN      NaN     NaN  480-410  410-480       V
4  500-570     50  500-570  570-500       P      NaN      NaN     NaN

Это не мой желаемый результат. Я не знаю, как еще я могу объяснить тот факт, что правильный ключ может быть либо в PAIR1, либо PAIR2. Любая помощь будет оценена.

Ответы [ 3 ]

3 голосов
/ 26 февраля 2020

Несколько неуклюжее решение: создайте серию, в которой каждая пара в df2 сопоставляется с соответствующим брендом, а затем передайте это сопоставление df1['PAIR'].map().

# Build a series whose index maps pairs to values
mapper = df2.melt(id_vars='BRAND').set_index('value')['BRAND']
mapper
value
140-120    A
280-200    V
350-310    P
480-410    V
500-570    P
120-140    A
200-280    V
310-350    P
410-480    V
570-500    P
Name: BRAND, dtype: object

# Use the mapper on df1['PAIR']
df1['BRAND'] = df1['PAIR'].map(mapper)
df1
      PAIR  SCORE BRAND
0  140-120     99     A
1  200-280     70     V
2  350-310     14     P
3  410-480     84     V
4  500-570     50     P
1 голос
/ 26 февраля 2020
temp_df1 = df2[['PAIR1', 'BRAND']]

temp_df2 = df2[['PAIR2', 'BRAND']]

temp_df2.rename(columns= {'PAIR2' : 'PAIR1'}, inplace= True)

big_df = pd.concat([temp_df1, temp_df2])

pd.merge(df1, big_df, how = 'left',  left_on = 'PAIR', right_on = 'PAIR1')
0 голосов
/ 26 февраля 2020

Вы пытаетесь последовательно объединить пары столбцов PAIR и PAIR1 & PAIR и PAIR2 оба раза, поддерживая аргумент how='left', который создает все значения NaN.

Взгляните на Pandas Объединение 101 .

Для вашей текущей реализации вам нужно взять подмножество текущего результата и удалить NaN.

Гораздо более простым решением было бы манипулировать PAIR в df1, чтобы он соответствовал шаблону (большой-маленький) или (маленький-большой) в PAIR1 или PAIR2

# for working with PAIR2
df1['FOR_MERGE'] = df1['PAIR'].map(lambda x: '-'.join([str(_) for _ in sorted(x.split('-'))])).values

df2['FOR_MERGE'] = df2['PAIR1'].map(lambda x: '-'.join([str(_) for _ in sorted(x.split('-'))])).values


pd.merge(df1[['FOR_MERGE', 'SCORE']], df2[['FOR_MERGE', 'BRAND']], how='left')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...