Pandas Merge - Як уникнути дублювання стовпців


93

Я намагаюся об'єднати два кадри даних. Кожен фрейм даних має два рівні індексу (дата, cusip). Наприклад, у стовпцях деякі стовпці збігаються між собою (валюта, дата коригування).

Який найкращий спосіб об’єднати їх за індексом, але не брати дві копії валюти та дати коригування.

Кожен фрейм даних - 90 стовпців, тому я намагаюся уникати виписування всього вручну.

df:                 currency  adj_date   data_col1 ...
date        cusip
2012-01-01  XSDP      USD      2012-01-03   0.45
...

df2:                currency  adj_date   data_col2 ...
date        cusip
2012-01-01  XSDP      USD      2012-01-03   0.45
...

Якщо я:

dfNew = merge(df, df2, left_index=True, right_index=True, how='outer')

я отримав

dfNew:              currency_x  adj_date_x   data_col2 ... currency_y adj_date_y
date        cusip
2012-01-01  XSDP      USD      2012-01-03   0.45             USD         2012-01-03

Дякую! ...

Відповіді:


143

Ви можете опрацювати стовпці, які містяться лише в одному DataFrame, і використовувати це для вибору підмножини стовпців у злитті.

cols_to_use = df2.columns.difference(df.columns)

Потім виконайте злиття (зверніть увагу, це об’єкт індексу, але він має зручний tolist()метод).

dfNew = merge(df, df2[cols_to_use], left_index=True, right_index=True, how='outer')

Це дозволить уникнути зіткнення стовпців під час злиття.


Що робити, якщо ключем є стовпець і він називається однаково? Це було б відкинуто з першого кроку.
Герра,

Дуже дякую!!!
Cloudy_Green

88

Я використовую suffixesопцію в .merge():

dfNew = df.merge(df2, left_index=True, right_index=True,
                 how='outer', suffixes=('', '_y'))
dfNew.drop(dfNew.filter(regex='_y$').columns.tolist(),axis=1, inplace=True)

Дякую @ijoseph


15
Було б більш корисною відповіддю, якщо б він містив код для введення filter(що досить просто, але все одно вимагає багато часу для пошуку / схильності до помилок). тобто dfNew.drop(list(dfNew.filter(regex='_y$')), axis=1, inplace=True)
ijoseph

5

Я нещодавно новачок у Pandas, але я хотів досягти того самого, автоматично уникаючи імен стовпців із _x або _y та видаляючи повторювані дані. Я , нарешті , зробив це, використовуючи цей відповідь , і цей один з Stackoverflow

продажі.csv

    місто; держава; одиниці
    Мендоцино; Каліфорнія; 1
    Денвер; CO; 4
    Остін; Техас; 2

дохід.csv

    branch_id; city; доход; state_id
    10; Остін; 100; Техас
    20; Остін; 83; Техас
    30; Остін; 4; Техас
    47; Остін; 200; Техас
    20; Денвер; 83; CO
    30; Спрінгфілд; 4; I

merge.py імпорт панд

def drop_y(df):
    # list comprehension of the cols that end with '_y'
    to_drop = [x for x in df if x.endswith('_y')]
    df.drop(to_drop, axis=1, inplace=True)


sales = pandas.read_csv('data/sales.csv', delimiter=';')
revenue = pandas.read_csv('data/revenue.csv', delimiter=';')

result = pandas.merge(sales, revenue,  how='inner', left_on=['state'], right_on=['state_id'], suffixes=('', '_y'))
drop_y(result)
result.to_csv('results/output.csv', index=True, index_label='id', sep=';')

При виконанні команди злиття я замінюю _xсуфікс порожнім рядком, і я можу видалити стовпці, що закінчуються на_y

вихід.csv

    ідентифікатор; місто; держава; одиниці; ідентифікатор філії; дохід; ідентифікатор держави
    0; Денвер; CO; 4; 20; 83; CO
    1; Остін; Техас; 2; 10; 100; Техас
    2; Остін; Техас; 2; 20; 83; Техас
    3; Остін; Техас; 2; 30; 4; Техас
    4; Остін; Техас; 2; 47; 200; Техас

4

Спираючись на відповідь @ rprog, ви можете об’єднати різні частини кроку суфікса та фільтра в один рядок, використовуючи негативний регулярний вираз:

dfNew = df.merge(df2, left_index=True, right_index=True,
             how='outer', suffixes=('', '_DROP')).filter(regex='^(?!.*_DROP)')

Або використовуючи df.join:

dfNew = df.join(df2),lsuffix="DROP").filter(regex="^(?!.*DROP)")

Тут регулярний вираз зберігає все, що не закінчується словом "DROP", тому просто переконайтеся, що використовуєте суфікс, який ще не відображається серед стовпців.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.