2017-08-24 4 views
2

Ich versuche, eine Reihe in eine andere zu setzen, bei einem Multi-Index-Wert. Ich kann keinen Weg finden, dies in Pandas ohne komplexe Hacks zu tun.Werte in einer Pandas MultiIndex-Reihe einstellen

Meine Original-Serie:

one 1 0.522764 
    3 0.362663 
    7 0.963108 
two 2 0.717855 
    4 0.004645 
    5 0.077471 

Die Daten, die ich auf der Ebene verketten möchten three:

2 0.8 
7 0.9 
8 0.7 

Die gewünschte Ausgabe:

one 1 0.522764 
     3 0.362663 
     7 0.963108 
two 2 0.717855 
     4 0.004645 
     5 0.077471 
three 2 0.800000 
     7 0.900000 
     8 0.700000 

Ich kann nicht eine elegante heraus Weg, dies in Pandas zu tun. Alles, was ich tun konnte bereits in dem folgenden Hack:

# imports 
import numpy as np 
import pandas as pd 

# to replicate the Series: 
np.arrays = [['one','one','one','two','two','two'],[1,3,7,2,4,5]] 
my_series = pd.Series([np.random.random() for i in range(6)], 
       index=pd.MultiIndex.from_tuples(list(zip(*np.arrays)))) 

# the new data I need to add: 
new_data = pd.Series({1: .9, 2: .7, 3: .8}) 

Hier ist, wie ich es bin derzeit zu lösen:

# rename the index so that I can call it later 
new_data.index.name = 'level_1' 

# turn it into temporary a dataframe so that I can add a new column 
temp = pd.DataFrame(new_data) 

# create a new column with the desired name for first index level 
temp['level_0'] = 'three' 

# reset index, set the new index, turn into Series again 
temp = temp.reset_index().set_index(['level_0', 'level_1'])[0]        

# append it to the larger dataframe 
my_series = my_series.append(temp)     

Dies ergibt die gewünschte Ausgabe.

Frage: Gibt es eine einfache, elegante Möglichkeit, dies in Pandas zu tun?

+0

Ihre Notation ist ein wenig verwirrend, weil 'df' kein Datenrahmen ist ... – C8H10N4O2

+0

bezogen werden: https://stackoverflow.com/questions/18062135/combining-two-series-into-a-dataframe- In-Pandas? – C8H10N4O2

+0

@ C8H10N4O2 gut gefangen, behoben –

Antwort

3

Option 1

pd.concat ist eine praktische Möglichkeit, eine Index- oder Spaltenebene mithilfe des Arguments keys voranzustellen. Kombiniert dies mit einem zweiten pd.concat, um die Arbeit zu erledigen.

pd.concat([my_series, pd.concat([new_data], keys=['Three'])]) 

one 1 0.943246 
     3 0.412200 
     7 0.379641 
two 2 0.883960 
     4 0.182983 
     5 0.773227 
Three 1 0.900000 
     2 0.700000 
     3 0.800000 
dtype: float64 

Option 2
Oder wir eine neue Serie konstruieren, während ein zusätzliches Array in das Argument index eingefügt wird. Mit pd.concat wieder zu kombinieren. Hinweis Ich hätte pd.MultiIndex.from_arrays verwenden können, aber die Syntax wird vereinfacht, indem die Arrays direkt an das index Argument übergeben werden.

pd.concat([ 
    my_series, 
    pd.Series(new_data.values, [['Three'] * new_data.size, new_data.index]) 
]) 

one 1 0.943246 
     3 0.412200 
     7 0.379641 
two 2 0.883960 
     4 0.182983 
     5 0.773227 
Three 1 0.900000 
     2 0.700000 
     3 0.800000 
dtype: float64 

Option 3
Noch ein weiterer Weg, um eine Serie mit einem Multiindex zu rekonstruieren. Dieser verwendet pd.MultiIndex.from_product.

pd.concat([ 
    my_series, 
    pd.Series(new_data.values, pd.MultiIndex.from_product([['Three'], new_data.index])) 
]) 

one 1 0.943246 
     3 0.412200 
     7 0.379641 
two 2 0.883960 
     4 0.182983 
     5 0.773227 
Three 1 0.900000 
     2 0.700000 
     3 0.800000 
dtype: float64 
+0

Oh! Ich wusste, dass das 'Schlüssel'-Argument nützlich war. Das ist schlau. –

+0

Danke sir sir (-: – piRSquared

+0

Ich glaube, ich sollte innerhalb der nächsten 24 Stunden mein silbernes Pandabad bekommen. Danke für all die Unterstützung und dieses aufmunternde Gespräch von langer Zeit. Kann es nicht vergessen. –

4

Sie könnten versuchen, pd.concat mit:

In [370]: pd.concat([df, new_data.to_frame().assign(_='three').set_index(['_', new_data.index]).iloc[:, 0]]) 
Out[370]: 
one 1 0.618472 
     3 0.026207 
     7 0.766849 
two 2 0.651633 
     4 0.282038 
     5 0.160714 
three 1 0.900000 
     2 0.700000 
     3 0.800000 
dtype: float64 
+0

@ C8H10N4O2 Das 'df' war irreführend. –

+0

@ C8H10N4O2 Viel Glück, ich suche nach einer besseren Lösung als diese selbst, aber ich kann es nicht finden. –

2

Wenn Sie new_data mit einem äquivalenten Mehr Index beginnen, können Sie das Series es direkt mit pd.concat ohne Nötigung zu DataFrame und zurück, wie in verketten:

new_series = pd.Series([0.8,0.9,0.7], 
       index=pd.MultiIndex.from_tuples([('three',x) for x in range(1,4)]) 
      ) 
pd.concat([my_series,new_series]) #note OP changed name of orig series from df to my_series 
#============================================================================== 
# one 1 0.236158 
#  3 0.699102 
#  7 0.421937 
# two 2 0.887081 
#  4 0.520304 
#  5 0.211461 
# three 1 0.800000 
#  2 0.900000 
#  3 0.700000 
# dtype: float64 
#============================================================================== 

type(pd.concat([my_series,new_series])) # pandas.core.series.Series 
+0

Sieht gut aus, obwohl OP vielleicht etwas gewollt hat, was nicht beinhaltet, den Multi-Index zu deklarieren, obwohl ich mir nicht sicher bin, ob das möglich ist. –

Verwandte Themen