2016-03-21 2 views
1

sagen, dass ich einen Datenrahmen mit Pandas konstruieren, multi-indizierte Spalten:Wie wird der Lexsort-Status beim Hinzufügen zu einem multi-indexierten DataFrame beibehalten?

mi  = pd.MultiIndex.from_product([['trial_1', 'trial_2', 'trial_3'], ['motor_neuron','afferent_neuron','interneuron'], ['time','voltage','calcium']]) 
ind  = np.arange(1,11) 
df  = pd.DataFrame(np.random.randn(10,27),index=ind, columns=mi) 

Link to image of output dataframe

sagen, dass ich von der Testversion 1. Ich kenne nur die Spannungsdaten möchten, dass der folgende Code fehlschlägt, weil die Indizes sind lexikalisch nicht sortiert:

idx = pd.IndexSlice 
df.loc[:,idx['trial_1',:,'voltage']] 

wie in another post erläutert, ist die Lösung der Datenrahmen der Indizes zu sortieren, die wie erwartet funktioniert:

dfSorted = df.sortlevel(axis=1) 
dfSorted.loc[:,idx['trial_1',:,'voltage']] 

Ich verstehe, warum dies notwendig ist. Allerdings sage ich eine neue Spalte hinzufügen möchten:

dfSorted.loc[:,('trial_1','interneuron','scaledTime')] = 100 * dfSorted.loc[:,('trial_1','interneuron','time')] 

Jetzt dfSorted nicht mehr sortiert, da die neue Spalte auf das Ende geheftet wurde, anstatt in Ordnung kuschelte. Wieder muss ich sortlevel anrufen, bevor ich mehrere Spalten auswähle.

Ich denke, dass dies für sich wiederholenden, fehleranfälligen Code sorgt, besonders wenn ich dem viel größeren Datenrahmen in meinem eigenen Projekt viele Spalten hinzufüge. Gibt es eine (möglichst saubere) Art, neue Spalten in lexikalischer Reihenfolge einzufügen, ohne Sortlevel immer wieder aufrufen zu müssen?

+1

Es ist eine gute Frage und ich habe keine Antwort, aber vielleicht Panel (http: // Pandas. pydata.org/pandas-docs/stable/dsintro.html#panel) oder xarray (http://xarray.pydata.org/en/stable/) wäre eine Option anstelle von Multiindex? – JohnE

+0

In dem Beispiel, das ich hier eingefügt habe, würde ein Panel oder ein Xarray funktionieren, weil die Multi-Index-Struktur für alle Indizes gleich ist. Aber in meinem aktuellen Projekt haben einige Indizes völlig unterschiedliche Subindex-Gruppen, daher kann ich Panel oder Xarray nicht verwenden. – akrodha

Antwort

1

Ein Ansatz wäre filter zu verwenden, die auf den Spaltennamen einen Textfilter tut:

In [117]: df['trial_1'].filter(like='voltage') 
Out[117]: 
    motor_neuron afferent_neuron interneuron 
     voltage   voltage  voltage 
1  -0.548699  0.986121 -1.339783 
2  -1.320589  -0.509410 -0.529686 
+0

Ich sehe, wie Ihr Code einen Teil einer multi-indizierten Tabelle zurückgibt. Aber ich sehe nicht, wie es verwendet werden kann, um eine neue Spalte einzufügen und den Lexsort-Status beizubehalten. – akrodha

+0

Ich glaube nicht, dass Sie sich um Lexsort kümmern müssen, wenn Sie nicht 'loc' zum Indexieren verwenden. Fügen Sie einfach Ihre zusätzlichen Spalten hinzu wie 'df [('trial_1', 'internneuron', 'scaledtime')] = 100 * df [('trial_1', 'internneuron', 'time')]' und der Filter sollte trotzdem funktionieren – maxymoo

+0

Lassen Sie mich sicherstellen, dass ich das richtig verstanden habe: filter ist eine Problemumgehung, die es nicht interessiert, ob der Datenframe sortiert ist. Indizierung erfordert indessen einen sortierten Datenrahmen. Wenn dies der Fall ist, dauert die Berechnung des Filters möglicherweise länger, da er jedes Mal die Indexhierarchie durchlaufen muss. Indizierung ist im Allgemeinen schneller, aber es kommt mit der Anforderung, dass Sie Ihre Tabelle nach jeder Änderung sortieren. – akrodha

Verwandte Themen