2013-01-03 8 views
12

Ho due frame di dati. df1 è multi-indicizzato:Unisci multiindicizzato con frame di dati a indice singolo nei panda

   value 
first second  
a  x   0.471780 
     y   0.774908 
     z   0.563634 
b  x   -0.353756 
     y   0.368062 
     z   -1.721840 

e DF2:

 value 
first 
a  10 
b  20 

Come posso unire i due frame di dati con una sola delle multi-indici, in questo caso il 'prima' index? L'output desiderato sarebbe:

   value1  value2 
first second  
a  x   0.471780 10 
     y   0.774908 10 
     z   0.563634 10 
b  x   -0.353756 20 
     y   0.368062 20 
     z   -1.721840 20 

risposta

9

si potrebbe usare get_level_values:

firsts = df1.index.get_level_values('first') 
df1['value2'] = df2.ix[firsts].values 

Nota: sei quasi facendo un join qui (ad eccezione del df1 è MultiIndex) ... quindi non ci può essere un modo più ordinato per descrivere questo ...

.

In un esempio (simile a quello che hai):

df1 = pd.DataFrame([['a', 'x', 0.123], ['a','x', 0.234], 
        ['a', 'y', 0.451], ['b', 'x', 0.453]], 
        columns=['first', 'second', 'value1'] 
        ).set_index(['first', 'second']) 
df2 = pd.DataFrame([['a', 10],['b', 20]], 
        columns=['first', 'value']).set_index(['first']) 

firsts = df1.index.get_level_values('first') 
df1['value2'] = df2.ix[firsts].values 

In [5]: df1 
Out[5]: 
       value1 value2 
first second     
a  x  0.123  10 
     x  0.234  10 
     y  0.451  10 
b  x  0.453  20 
+0

è possibile * quasi * unire in questo modo: 'df1.merge (DF2, left_on = df1.index.get_level_values ​​('prima'), right_on = df2.index.get_level_values ​​('prima'))' –

2

Come la sintassi .ix è un potente scorciatoia per reindicizzazione, ma in questo caso si sta in realtà non sta facendo alcun reindicizzazione file combinati/colonna, questo si può fare un po 'più elegante (per le mie papille gustative umili) con solo utilizzando reindicizzazione:

Preparazione da Hayden:

df1 = pd.DataFrame([['a', 'x', 0.123], ['a','x', 0.234], 
        ['a', 'y', 0.451], ['b', 'x', 0.453]], 
        columns=['first', 'second', 'value1'] 
        ).set_index(['first', 'second']) 
df2 = pd.DataFrame([['a', 10],['b', 20]], 
        columns=['first', 'value']).set_index(['first']) 

Poi questo sembra come questo in ipython:

In [4]: df1 
Out[4]: 
       value1 
first second   
a  x  0.123 
     x  0.234 
     y  0.451 
b  x  0.453 

In [5]: df2 
Out[5]: 
     value 
first  
a   10 
b   20 

In [7]: df2.reindex(df1.index, level=0) 
Out[7]: 
       value 
first second  
a  x   10 
     x   10 
     y   10 
b  x   20 

In [8]: df1['value2'] = df2.reindex(df1.index, level=0) 

In [9]: df1 
Out[9]: 
       value1 value2 
first second     
a  x  0.123  10 
     x  0.234  10 
     y  0.451  10 
b  x  0.453  20 

Il mnemotechnic per quale livello si deve utilizzare nel metodo reindex: Essa afferma per il livello che già coperto nell'indice più grande. Quindi, in questo caso df2 aveva già coperto il livello 0 di df1.index.

4

Secondo the documentation, a partire da panda 0.14, è possibile unire semplicemente i dataset di indice singolo e multiindice. Corrisponde al nome dell'indice comune. L'argomento how funziona come previsto con 'inner' e 'outer', anche se sembra interessante essere invertito per 'left' e 'right' (potrebbe essere un errore?).

df1 = pd.DataFrame([['a', 'x', 0.471780], ['a','y', 0.774908], ['a', 'z', 0.563634], 
        ['b', 'x', -0.353756], ['b', 'y', 0.368062], ['b', 'z', -1.721840], 
        ['c', 'x', 1], ['c', 'y', 2], ['c', 'z', 3], 
        ], 
        columns=['first', 'second', 'value1'] 
        ).set_index(['first', 'second']) 
df2 = pd.DataFrame([['a', 10], ['b', 20]], 
        columns=['first', 'value2']).set_index(['first']) 

print(df1.join(df2, how='inner')) 
       value1 value2 
first second     
a  x  0.471780  10 
     y  0.774908  10 
     z  0.563634  10 
b  x  -0.353756  20 
     y  0.368062  20 
     z  -1.721840  20 
Problemi correlati