2015-05-19 9 views
5

Ho 2 dataframes. desidero trasmettere un'operazione di divisioneDividi un panda Dataframe per un altro - Ignora indice ma rispetta le colonne

df1= pd.DataFrame([[1.,2.,3.,4.], [5.,6.,7.,8.], [9.,10.,11.,12.]], 
        columns=['A','B','C','D'], index=['x','y','z']) 

df2= pd.DataFrame([[0.,1.,2.,3.]], columns=['A','B','D','C'], index=['q']) 

noti che le colonne sono allineate in modo leggermente diverso DF2.

Vorrei dividere df1 da df2 in cui viene trasmessa la riga ma le etichette di colonna sono rispettate.

A B C D 
x 1 2 3 4 
y 5 6 7 8 
z 9 10 11 12 


    A B D C 
q 0 1 2 3 

Questo sarebbe sbagliato.

df1.values/df2.values 

[[   inf 2.   1.5   1.33333333] 
[   inf 6.   3.5   2.66666667] 
[   inf 10.   5.5   4.  ]] 

risposta che desidero è:

A B C  D 
x inf 2 1  2 
y inf 6 2.33 4 
z inf 10 3.66 6 

risposta

2

Se si divide da una serie (selezionando quella riga della seconda dataframe), pandas allineerà questa serie sulle colonne della prima dataframe, dà il risultato desiderato:

In [75]: df1/df2.loc['q'] 
Out[75]: 
    A B   C D 
x inf 2 1.000000 2 
y inf 6 2.333333 4 
z inf 10 3.666667 6 

Se non si conosce/si desidera utilizzare il nome di quella riga, è possibile utilizzare squeeze per convertire il dataframe a una colonna in una serie: df1/df2.squeeze() (vedere la risposta di @EdChum).

+0

molto bello e conciso +1 – EdChum

1

può essere, si poteva ordinare i tuoi df2 colonne stesse di df1 e poi dividere sui valori

In [53]: df1.values/df2[df1.columns].values 
Out[53]: 
array([[   inf, 2.  , 1.  , 2.  ], 
     [   inf, 6.  , 2.33333333, 4.  ], 
     [   inf, 10.  , 3.66666667, 6.  ]]) 
1

È possibile riordinare la colonna e poi chiama squeeze per appiattire l'array e quindi chiama div:

In [114]: 

df1= pd.DataFrame([[1.,2.,3.,4.],[5.,6.,7.,8.],[9.,10.,11.,12.]] ,columns = ['A','B','C','D'], index = ['x','y','z']) 
df2= pd.DataFrame([[0.,1.,2.,3.]] ,columns = ['A','B','D','C'], index = ['q']) ​ 
df1.div(df2.ix[:,df1.columns].squeeze()) 

Out[114]: 
    A B   C D 
x inf 2 1.000000 2 
y inf 6 2.333333 4 
z inf 10 3.666667 6 

df1/df2.ix[:,df1.columns].squeeze() funziona anche, ma @ risposta di Joris è molto più bello

EDIT

Come sottolineato dal @joris il riordino della colonna non è necessaria come panda naturalmente allineare contro le colonne in ogni caso così:

df1.div(df2squeeze()) 

o

df1./df2squeeze() 

funzionerebbe

+0

grazie per avermi insegnato .squeeze() – Dickster

+1

@EdChum non hai bisogno della parte '.ix [:, df1.columns]' quando usi 'div', poiché allinea gli indici automaticamente: solo' df1.div (df2.squeeze()) 'funziona pure (che è anche una bella soluzione!) – joris

+1

@joris yeah stava pensando troppo, mi piace un po 'troppo l'indicizzazione, aggiornerò, grazie – EdChum