Pandas Merge - Bagaimana menghindari duplikasi kolom

93

Saya mencoba menggabungkan antara dua bingkai data. Setiap frame data memiliki dua level indeks (tanggal, cusip). Di kolom, beberapa kolom cocok antara keduanya (mata uang, tanggal penyerahan) misalnya.

Apa cara terbaik untuk menggabungkan ini dengan indeks, tetapi tidak mengambil dua salinan mata uang dan tanggal adj.

Setiap bingkai data terdiri dari 90 kolom, jadi saya mencoba untuk tidak menulis semuanya dengan tangan.

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
...

Bila saya lakukan:

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

saya mendapat

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

Terima kasih! ...

pengguna1911092
sumber

Jawaban:

143

Anda dapat mengerjakan kolom yang hanya ada di satu DataFrame dan menggunakan ini untuk memilih subset kolom dalam gabungan.

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

Kemudian lakukan penggabungan (perhatikan bahwa ini adalah objek indeks tetapi memiliki tolist()metode praktis ).

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

Ini akan menghindari setiap kolom bentrok dalam penggabungan.

EdChum
sumber
Bagaimana jika kuncinya adalah kolom dan disebut sama? Itu akan dijatuhkan dengan langkah pertama.
Guerra
Terima kasih banyak!!!
Cloudy_Green
88

Saya menggunakan suffixesopsi dalam .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)

Terima kasih @ijoseph

rprog
sumber
15
Akan menjadi jawaban yang lebih membantu jika menyertakan kode untuk filtering (yang cukup mudah, namun masih memakan waktu untuk mencari / rawan kesalahan untuk mengingat). yaitu dfNew.drop(list(dfNew.filter(regex='_y$')), axis=1, inplace=True)
ijoseph
5

Saya baru mengenal Pandas tetapi saya ingin mencapai hal yang sama, secara otomatis menghindari nama kolom dengan _x atau _y dan menghapus data duplikat. Aku akhirnya melakukannya dengan menggunakan ini jawaban dan ini salah satu dari Stackoverflow

sales.csv

    kota; negara bagian; unit
    Mendocino; CA; 1
    Denver; CO; 4
    Austin; TX; 2

revenue.csv

    branch_id; city; pendapatan; state_id
    10; Austin; 100; TX
    20; Austin; 83; TX
    30; Austin; 4; TX
    47; Austin; 200; TX
    20; Denver; 83; CO
    30; Springfield; 4; Saya

merge.py import pandas

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=';')

Saat menjalankan perintah merge, saya mengganti _xsufiks dengan string kosong dan saya dapat menghapus kolom yang diakhiri dengan_y

output.csv

    id; kota; negara bagian; unit; branch_id; pendapatan; state_id
    0; Denver; CO; 4; 20; 83; CO
    1; Austin; TX; 2; 10; 100; TX
    2; Austin; TX; 2; 20; 83; TX
    3; Austin; TX; 2; 30; 4; TX
    4; Austin; TX; 2; 47; 200; TX
JulienD
sumber
4

Berdasarkan jawaban @ rprog, Anda dapat menggabungkan berbagai langkah sufiks & filter ke dalam satu baris menggunakan regex negatif:

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

Atau menggunakan df.join:

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

Regex di sini menyimpan apa pun yang tidak diakhiri dengan kata "DROP", jadi pastikan untuk menggunakan sufiks yang belum muncul di antara kolom.

Elliott Collins
sumber