Python / Pandas — Учитывайте «пустую строку» как совпадение при слиянии с использованием нескольких столбцов

#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 операции слияния в следующем порядке:

  1. Объедините right_df с left_df в столбцах Unit , Geo и Region и выберите столбец Resp .

  2. Объедините right_df с left_df (удалите повторяющиеся значения в единицах измерения и гео) в столбцах Unit , Geo и выберите столбец Resp .

  3. Объедините 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 в обоих фреймах данных совпадают :).