Как объединить рядом повторяющиеся строки в DataFrame

#python #pandas #dataframe #dictionary

#python #панды #фрейм данных #словарь

Вопрос:

Из исходных данных есть дублированные данные. Дубликаты с разными БД должны быть объединены с задней частью первого.Есть ли какой-либо способ объединить две таблицы в одну, как показано ниже, путем сравнения данных?

Из исходных данных, используя drop.duplicates и duplicated, я получаю две таблицы и хотел сравнить их с помощью словарей, но, создавая строки как словари в обеих таблицах, ключи одинаковы в каждом словаре, и я не могу объединить их вместе.

Это исходные данные

   DB TITLE  ISSN  IBSN
0  M     a     1   NaN
1  M     d     1   NaN
2  M     c     1   NaN
3  N     b     1   NaN
4  N     a     1   NaN
5  N     d     1   NaN
6  O     c     1   NaN
7  O     e     1   NaN
8  O     a     1   NaN
9  O     b     1   NaN
 

Используя drop_duplicates и дублированные:

   DB TITLE  ISSN  IBSN             DB TITLE  ISSN  IBSN        
0  M     a     1   NaN           0  N     a     1   NaN        
1  M     d     1   NaN           1  N     d     1   NaN         
2  M     c     1   NaN           2  O     c     1   NaN       
3  N     b     1   NaN           3  O     a     1   NaN
4  O     e     1   NaN           4  O     b     1   NaN
 

Это тот словарь, который я получаю из строк:

 {'DB': 'N', 'TITLE': 'a', 'ISSN': 1, 'IBSN': 'NaN'}
{'DB': 'M', 'TITLE': 'a', 'ISSN': 1, 'IBSN': 'NaN'}
 

Я ожидаю, что результат будет

     DB TITLE  ISSN  IBSN   DB TITLE  ISSN ISBN   DB TITLE  ISSN  IBSN
0    M     a   1.0   NaN    N     a   1.0  NaN    O     a   1.0   NaN
1    N     b   1.0   NaN    O     b   1.0  NaN  NaN   NaN   NaN   NaN
2    M     d   1.0   NaN    N     d   1.0  NaN  NaN   NaN   NaN   NaN
3    M     c   1.0   NaN    O     c   1.0  NaN  NaN   NaN   NaN   NaN
4    O     e   1.0   NaN  NaN   NaN   NaN  NaN  NaN   NaN   NaN   NaN
 

Порядок «ЗАГОЛОВКА» в столбце не важен, но база данных должна быть отсортирована в алфавитном порядке слева направо.

Ответ №1:

Я думаю, что самый простой способ сделать это — использовать cumcount для разделения подгрупп, а затем использовать concat с join='outer' :

 grps = [
    g.set_index('TITLE') for _, g in df.groupby(df.groupby('TITLE').cumcount())
]
pd.concat(grps, join='outer', axis=1, sort=True)

  DB  ISSN  IBSN   DB  ISSN  IBSN   DB  ISSN  IBSN
a  M     1   NaN    N   1.0   NaN    O   1.0   NaN
b  N     1   NaN    O   1.0   NaN  NaN   NaN   NaN
c  M     1   NaN    O   1.0   NaN  NaN   NaN   NaN
d  M     1   NaN    N   1.0   NaN  NaN   NaN   NaN
e  O     1   NaN  NaN   NaN   NaN  NaN   NaN   NaN
 

Если вам тоже нужен «ЗАГОЛОВОК», используйте set_index с drop=False :

 grps = [
    g.set_index('TITLE', drop=False) 
    for _, g in df.groupby(df.groupby('TITLE').cumcount())
]
pd.concat(grps, join='outer', axis=1, sort=True)

  DB TITLE  ISSN  IBSN   DB TITLE  ISSN  IBSN   DB TITLE  ISSN  IBSN
a  M     a     1   NaN    N     a   1.0   NaN    O     a   1.0   NaN
b  N     b     1   NaN    O     b   1.0   NaN  NaN   NaN   NaN   NaN
c  M     c     1   NaN    O     c   1.0   NaN  NaN   NaN   NaN   NaN
d  M     d     1   NaN    N     d   1.0   NaN  NaN   NaN   NaN   NaN
e  O     e     1   NaN  NaN   NaN   NaN   NaN  NaN   NaN   NaN   NaN
 

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

1. Привет! Здесь возникает еще один вопрос: что, если для совпадения требуется точное совпадение, отличное от DB, возможно ли по-прежнему использовать cumcount? Это означает, что ЗАГОЛОВОК ISSN IBSN должен совпадать, иначе он считается не дубликатом и должен переходить в другую строку.

2. @WeiLunss Измените df.groupby('TITLE') на df.groupby(['TITLE', 'ISSN', 'ISBN']) , и это должно сработать … если нет, я предлагаю открыть другой вопрос.