Как объединить два фрейма данных с неидентичными столбцами таким образом? Python

#python #python-3.x #pandas #dataframe #merge

Вопрос:

У меня есть два фрейма данных, которые выглядят так (реальные больше):

DF1:

Alliances_names Значение 1
cgc inc / nshow ltd / noracle inc 500
steam / nsoap jv NaN
saints bd 8
watrloo jv / ncgc inc / nflow inc 19

DF2:

Компания Number1 Number2
Steam 15 y
soap jv 2000 n
cgc inc 4565 n
показать ооо 1 n
flow inc 1111 y
watrloo jv 6756 n

Я должен объединить эти два фрейма данных со столбцами альянсов и компаний. Если это компания в альянсе, я должен добавить эту информацию в строку. (В DF1 есть разделитель / n между компаниями)
Результат должен быть таким:

Alliances_names Значение 1 Компания Number1 Number2
cgc inc / nshowltd /noracle inc 500 cgc inc 4565 n
cgc inc / nshowltd /noracle inc 500 показать ооо 1 n
steam / nsoap jv NaN Steam 15 y
steam / nsoap jv NaN soap jv 2000 n
saints bd 8 NaN NaN NaN
watrloo jv / ncgc inc / nflow inc 19 watrloo jv 6756 n
watrloo jv / ncgc inc / nflow inc 19 cgc inc 4565 n
watrloo jv / ncgc inc / nflow inc 19 flow inc 1111 y

Мне нужно дублировать название альянсов для каждой компании в этом. Я попытался разделить компании в «название альянса» и создать еще один столбец со списками компаний в каждой ячейке, но «isin» не очень хорошо с этим справился, и я не смог создать фреймы данных с дубликатами.

Ответ №1:

  1. Создайте отдельный столбец (называемый «Company») с отдельными названиями компаний, используя split и explode .
  2. merge два фрейма данных в столбце «Компания».
 df1["Company"] = df1["Alliances_names"].str.split("/n")
df1 = df1.explode("Company")
output = df1.merge(df2, on="Company", how="left")

>>> output
                 Alliances_names  Value1     Company  Number1 Number2
0  cgc inc/nshow ltd/noracle inc   500.0     cgc inc   4565.0       n
1  cgc inc/nshow ltd/noracle inc   500.0    show ltd      1.0       n
2  cgc inc/nshow ltd/noracle inc   500.0  oracle inc      NaN     NaN
3                 steam/nsoap jv     NaN       steam     15.0       y
4                 steam/nsoap jv     NaN     soap jv   2000.0       n
5                      saints bd     8.0   saints bd      NaN     NaN
6  watrloo jv/ncgc inc/nflow inc    19.0  watrloo jv   6756.0       n
7  watrloo jv/ncgc inc/nflow inc    19.0     cgc inc   4565.0       n
8  watrloo jv/ncgc inc/nflow inc    19.0    flow inc   1111.0       y
 
Редактировать:

Чтобы сохранить только строки, в которых находятся все Alliances_names df2 , вы можете сделать:

 output = output[output["Alliances_names"].str.split("/n").map(set(df2["Company"]).issuperset)]

>>> output
                 Alliances_names  Value1     Company  Number1 Number2
3                 steam/nsoap jv     NaN       steam     15.0       y
4                 steam/nsoap jv     NaN     soap jv   2000.0       n
6  watrloo jv/ncgc inc/nflow inc    19.0  watrloo jv   6756.0       n
7  watrloo jv/ncgc inc/nflow inc    19.0     cgc inc   4565.0       n
8  watrloo jv/ncgc inc/nflow inc    19.0    flow inc   1111.0       y
 

Комментарии:

1. Еще один вопрос. Есть ли способ удалить альянсы из «alliances_names», если в df2 есть не все альянсы? В результате останется только совместное предприятие steam / nsoap с дубликатами и совместное предприятие watrloo / ncgc inc / nflow inc с дубликатами.

2. Спасибо! но это странно работает в наборе данных с 164000 строками. Он удаляет некоторые строки с альянсами, в которых все компании указаны в «company», я не знаю почему: ( Я заметил это, когда проверял некоторые данные вручную.

3. Не следует — логика не зависит от размера вашего фрейма данных. Могут быть ваши фактические данные (различия в написании или начальные / конечные пробелы и т. Д.).