2013-10-01 13 views
30

Próbuję scalić między dwiema ramkami danych. Każda ramka danych ma dwa poziomy indeksu (data, cusip). W kolumnach niektóre kolumny odpowiadają między sobą (np. Walutą, datą przywiązania).Pandas Merge - jak uniknąć duplikowania kolumn

Jaki jest najlepszy sposób łączenia tych elementów według indeksu, ale nie należy pobierać dwóch kopii waluty i daty zawieszenia.

Każda ramka danych ma 90 kolumn, więc staram się nie pisać wszystkiego ręcznie.

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

Jeśli zrobić:

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

uzyskać

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 

Dziękujemy! ...

+0

Praktycznym rozwiązaniem może być usunięcie fałszywych kolumn. Chciałbym jednak zobaczyć lepszą odpowiedź. – Marcin

+0

Dlaczego nie wystarczy wybrać kolumny, które chcesz scalić w następujący sposób: 'dfNew = merge (df, df2 [['' data_col_2 ']], left_index = True, right_index = True, how =' outer ')' to unika duplikatu kolumny i konflikt – EdChum

+0

Zgadzam się na mniejsze ramki danych, ale każda ramka danych ma 90 kolumn i może być 10 nakładających się kolumn. – user1911092

Odpowiedz

49

Można pracować z kolumn, które są tylko w jednym dataframe i wykorzystują to, aby wybrać podzbiór kolumn w scaleniu

cols_to_use = df2.columns - df.columns 

następnie wykonać scalanie za pomocą tego (zauważ, że jest to celem indeksu, ale ma poręczny tolist() metody)

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

Pozwoli to uniknąć kolumny starcia w scaleniu

W wersji 0.15 i wyżej, nowa składnia jest preferowana:

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

dzięki @odedbd

+5

To jest świetne, chcę tylko zaktualizować to z 0.15 to da ostrzeżenie o przestarzałości, sugerując nową składnię cols_to_use = df2.columns.difference (df.columns) – odedbd

+0

@odedbd dzięki za komentarz, zaktualizowałem moją odpowiedź – EdChum

+0

Jeśli używasz left_on i right_on, to to rozwiązanie nie działa. – HVS

27

używam opcji suffixes w .merge():

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

Następnie można filtrować kolumny oparte na fladze "_y", czyli usuń je.

1

Jestem świeżo nowy w Pandach, ale chciałem osiągnąć to samo, automatycznie unikając nazw kolumn za pomocą _x lub _y i usuwając zduplikowane dane. I wreszcie zrobił to za pomocą tego answer i ten one z Stackoverflow

sales.csv

 
    city;state;units 
    Mendocino;CA;1 
    Denver;CO;4 
    Austin;TX;2 

revenue.csv

 
    branch_id;city;revenue;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;I 

merge.py import pandy

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

Podczas wykonywania polecenia scalania wymienić _x przyrostek z pustym ciągiem znaków i można je usunąć kolumny kończąc _y

wyjściu.csv

 
    id;city;state;units;branch_id;revenue;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 
Powiązane problemy