Pandalar Birleştirme - Sütunları çoğaltmaktan nasıl kaçınılır


93

İki veri çerçevesi arasında birleştirme yapmaya çalışıyorum. Her veri çerçevesinin iki dizin seviyesi vardır (tarih, cusip). Sütunlarda, örneğin bazı sütunlar ikisi (para birimi, ek tarihi) arasında eşleşir.

Bunları endekse göre birleştirmenin en iyi yolu nedir, ancak iki kopya para birimi ve ek tarih almamaktır.

Her veri çerçevesi 90 sütundur, bu yüzden her şeyi elle yazmaktan kaçınmaya çalışıyorum.

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

Eğer yaparsam:

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

alırım

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

Teşekkür ederim! ...

Yanıtlar:


143

Yalnızca bir DataFrame'deki sütunları hesaplayabilir ve bunu birleştirmede bir sütun alt kümesi seçmek için kullanabilirsiniz.

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

Ardından birleştirmeyi gerçekleştirin (bunun bir dizin nesnesi olduğunu ancak kullanışlı bir tolist()yöntemi olduğunu unutmayın).

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

Bu, birleştirmede herhangi bir sütun çakışmasını önleyecektir.


Ya anahtar bir sütun ise ve ona aynıysa? İlk adımda düşülürdü.
Guerra

çok teşekkür ederim!!!
Cloudy_Green

88

suffixesSeçeneği şurada kullanıyorum .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)

Teşekkürler @ijoseph


15
İnglem için kod içeriyorsa daha yararlı bir cevap olabilirdi filter(bu oldukça basittir, ancak yine de aranması zaman alıcıdır / hatırlanması hataya açıktır). yani dfNew.drop(list(dfNew.filter(regex='_y$')), axis=1, inplace=True)
ijoseph

5

Pandalar konusunda yeniyim ama aynı şeyi, _x veya _y ile sütun adlarından otomatik olarak kaçınarak ve yinelenen verileri kaldırarak aynı şeyi elde etmek istedim. Sonunda bu kullanarak yaptım cevabı ve bu bir Stackoverflow dan

sales.csv

    şehir; eyalet; birimler
    Mendocino; CA; 1
    Denver; CO; 4
    Austin; TX; 2

gelir.csv

    branch_id; şehir; gelir; durum_kimliği
    10; Austin; 100; TX
    20; Austin; 83; TX
    30; Austin; 4; TX
    47; Austin; 200; TX
    20; Denver; 83; CO
    30; Springfield; 4; ben

merge.py pandaları içe aktar

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

Birleştirme komutunu çalıştırırken, _xsoneki boş bir dizeyle değiştiriyorum ve bunları ile biten sütunları kaldırabiliyorum._y

output.csv

    id; şehir; eyalet; birimler; şube_kimliği; gelir; durum_kimliği
    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

3

@ Rprog'un cevabına dayanarak, son ekin çeşitli parçalarını birleştirebilir ve negatif bir normal ifade kullanarak tek bir satıra filtre uygulayabilirsiniz:

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

Veya kullanarak df.join:

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

Buradaki normal ifade , "DROP" kelimesiyle bitmeyen herhangi bir şeyi saklıyor , bu nedenle sütunlar arasında zaten görünmeyen bir sonek kullandığınızdan emin olun.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.