2013-10-01 20 views
30

Sto tentando un'unione tra due frame di dati. Ogni frame di dati ha due livelli di indice (data, cusip). Nelle colonne, alcune colonne corrispondono tra le due (valuta, data di aggiustamento) per esempio.Panda unione - Come evitare la duplicazione delle colonne

Qual è il modo migliore per unire questi per indice, ma per non prendere due copie di valuta e data di registrazione.

Ogni frame di dati è 90 colonne, quindi sto cercando di evitare di scrivere tutto a mano.

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

Se lo faccio:

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

ottengo

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 

Grazie! ...

+0

Una soluzione pratica potrebbe essere quella di eliminare le colonne spurie. Mi piacerebbe vedere una risposta migliore, però. – Marcin

+0

Perché non selezionare semplicemente le colonne su cui vuoi unire in questo modo: 'dfNew = unisci (df, df2 [['data_col_2']], left_index = True, right_index = True, how = 'outer')' questo evita il duplicato colonne e scontro – EdChum

+0

Sono d'accordo per i dataframmi più piccoli, ma ogni dataframe è di 90 colonne e possono esserci 10 colonne sovrapposte. – user1911092

risposta

49

È possibile lavorare le colonne che sono solo in una dataframe e utilizzano questo per selezionare un sottoinsieme di colonne nell'unione

cols_to_use = df2.columns - df.columns 

poi eseguire la stampa utilizzando questo (notare che questo è un indice oggetto ma comprende una tolist() metodo pratico)

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

Ciò eviterà eventuali colonne scontrarsi nell'unione

Per la versione 0.15 e superiori, la nuova sintassi preferito è:

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

grazie @odedbd

+5

Questo è grandioso, voglio solo aggiornare che con 0.15 questo darà un avviso di deprecazione, suggerendo la nuova sintassi cols_to_use = df2.columns.difference (df.columns) – odedbd

+0

@odedbd grazie per il commento, ho aggiornato la mia risposta – EdChum

+0

Se usi left_on e right_on, allora questa soluzione non funziona. – HVS

27

si utilizza l'opzione suffixes in .merge():

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

È quindi possibile filtrare le colonne in base sulla bandiera "_y", cioè cancellali.

1

Sono appena uscito da Pandas ma volevo ottenere lo stesso risultato, evitando automaticamente i nomi delle colonne con _x o _y e rimuovendo i dati duplicati. Alla fine ho fatto utilizzando questo answer e questo one da 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 panda importazione

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

Quando si esegue il comando di unione che sostituire il suffisso _x con una stringa vuota e li posso rimuovere colonne terminanti con _y

uscita.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 
Problemi correlati