2013-01-03 10 views
12

Ich habe zwei Datenrahmen. df1 ist Multi-indiziert:Merge multi-indexed mit single-indexed Datenrahmen in Pandas

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

und DF2:

 value 
first 
a  10 
b  20 

Wie kann ich die beiden Datenrahmen mit nur einer des Multi-Indizes zusammenführen, in diesem Fall des 'erste' Index? Die gewünschte Ausgabe wäre:

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

Hinweis:

   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 

Antwort

9

Sie get_level_values verwenden könnten Sie sind fast (mit Ausnahme der df1 ist Multiindex) eine join hier tun ... so kann es sein, eine bessere Art, dies zu beschreiben ...

.

In einem Beispiel (ähnlich dem, was Sie haben):

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

Sie können * fast * wie folgt zusammen: 'df1.merge (DF2, left_on = df1.index.get_level_values ​​('first'), right_on = df2.index.get_level_values ​​('first'))' –

2

Da die .ix Syntax eine leistungsfähige Verknüpfung ist dies zu reindexing, aber in diesem Fall, dass Sie tatsächlich tun, keine kombinierten Zeilen/Spalten-Reindizierung, ein bisschen mehr elegant durchgeführt werden (für meine bescheidenen Gaumen) mit nur mit Reindizierung können:

Herstellung von 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']) 

Dann Dies sieht wie folgt 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 

Die mnemotechnic für welche Ebene Sie haben in der reindex Methode verwenden: Darin heißt es für die Ebene, die Sie bereits in dem größeren Index abgedeckt. Also, in diesem Fall hatte df2 bereits Level 0 des df1.index.

4

Gemäß the documentation, ab Pandas 0.14, können Sie einfach Single-Index- und Multiindex-Datenrahmen verbinden. Es wird auf den allgemeinen Indexnamen abgestimmt. Das how Argument funktioniert wie erwartet mit 'inner' und 'outer', obwohl es interessanterweise für 'left' und 'right' umgekehrt scheint (könnte das ein Fehler sein?).

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