#python #pandas #dataframe #join #merge
#python #pandas #dataframe #Присоединиться #слияние
Вопрос:
Я пытаюсь объединить 2 фрейма данных в нескольких столбцах: ['Unit','Geo','Region']
. И условие таково: когда значение из right_df
встречает «пустую строку» в left_df
, оно должно рассматриваться как совпадение.
например., когда первая строка right_df
соединяется с первой строкой left_df
, мы получаем пустую строку для столбца: 'Region'
. Итак, нужно рассматривать пустую строку как совпадение с ‘AU’ и получить конечный результат ‘DE».
left_df = pd.DataFrame({'Unit':['DEV','DEV','DEV','DEV','DEV','TEST1','TEST2','ACCTEST1','ACCTEST1','ACCTEST1'],
'Geo':['AP','JAPAN','NA','Europe','Europe','','','AP','Europe','NA'],
'Region':['','','','France','BENELUX','','','','',''],
'Resp':['DE','FG','BO','MD','KR','PM','NJ','JI','HN','FG']})
right_df = pd.DataFrame({'Unit':['DEV','DEV','DEV','DEV','TEST1','TEST2','ACCTEST1','DEV','ACCTEST1','TEST1','TEST2','DEV','TEST1','TEST2'],
'Geo':['AP','JAPAN','AP','NA','AP','Europe','Europe','Europe','AP','JAPAN','AP','Europe','Europe','Europe'],
'Region':['AU','JAPAN','ISA','USA','AU/NZ','France','CEE','France','ISA','JAPAN','ISA','BENELUX','CEE','CEE']})
Я пробовал использовать приведенный ниже код, но это работает, только если «пустые строки» имеют значения. Я изо всех сил пытаюсь добавить условие, гласящее «рассматривать пустую строку как совпадение» или «игнорировать, если right_df
встречается пустая строка, и продолжить с доступным совпадением». Был бы признателен за любую помощь. Спасибо!!
result_df = pd.merge(left_df, right_df, how='inner', on=['Unit','Geo','Region'])
Комментарии:
1. попробуйте
left_df.replace('', np.NaN).combine_first(right_df.replace('', np.NaN))
,DataFrame.combine_first
но все равно вы можете найти некоторые пропущенные значения из-за несоответствия в данных.
Ответ №1:
Используйте понимание DataFrame.merge
внутри списка и выполняйте left
операции слияния в следующем порядке:
-
Объедините
right_df
сleft_df
в столбцахUnit
,Geo
иRegion
и выберите столбецResp
. -
Объедините
right_df
сleft_df
(удалите повторяющиеся значения в единицах измерения и гео) в столбцахUnit
,Geo
и выберите столбецResp
. -
Объедините
right_df
сleft_df
(удалите повторяющиеся значения в единицах измерения) в столбцеUnit
и выберите столбецResp
.
Затем используйте functools.reduce
с функцией уменьшения Series.combine_first
, чтобы объединить все ряды в списке s
и присвоить этот результат Resp
столбцу в right_df
.
from functools import reduce
c = ['Unit', 'Geo', 'Region']
s = [right_df.merge(left_df.drop_duplicates(c[:len(c) - i]),
on=c[:len(c) - i], how='left')['Resp'] for i in range(len(c))]
right_df['Resp'] = reduce(pd.Series.combine_first, s)
Результат:
print(right_df)
Unit Geo Region Resp
0 DEV AP AU DE
1 DEV JAPAN JAPAN FG
2 DEV AP ISA DE
3 DEV NA USA BO
4 TEST1 AP AU/NZ PM
5 TEST2 Europe France NJ
6 ACCTEST1 Europe CEE HN
7 DEV Europe France MD
8 ACCTEST1 AP ISA JI
9 TEST1 JAPAN JAPAN PM
10 TEST2 AP ISA NJ
11 DEV Europe BENELUX KR
12 TEST1 Europe CEE PM
13 TEST2 Europe CEE NJ
Ответ №2:
Похоже, что в вашем сопоставлении есть некоторое несоответствие, однако вы можете использовать update
метод для обработки пустых строк:
# replace empty strings with nan
left_df = left_df.replace('', np.nan)
# replace np.nan with values from other dataframe
left_df.update(right_df, overwrite=False)
# merge
df = pd.merge(left_df, right_df, how='right', on=['Unit','Geo','Region'])
Надеюсь, это даст вам некоторое представление.
Комментарии:
1.
update
будет работать, только если соответствующиеindices
иcolumns
в обоих фреймах данных совпадают :).