2017-08-22 3 views
0

Ich möchte einen Multiindex-Dataframe in Scheiben schneiden. Lets nehmen diese df als Beispiel:Schnitt auf Pandas Multiindex

import pandas as pd 

arrays = [['bar', 'bar', 'bar','bar', 'foo','foo', 'qux', 'qux', 
'qux','qux', 'qux'], 
     ['2', '3', '4','10', '3','10','2','3','6','10','11']] 
df = pd.DataFrame(np.random.randn(11, 4), index=arrays).sort_index() 

->

   0   1   2   3 
bar 10 1.411962 -0.742729 0.950159 1.074269 
    2 1.214804 -0.654806 -1.138855 0.609101 
    3 0.135363 1.226927 -0.501535 -0.791849 
    4 1.118516 -1.340844 -1.365790 -0.099575 
foo 10 -0.004108 -0.067574 -0.139101 -0.358282 
    3 0.612849 -0.598579 0.923299 -0.218198 
qux 10 0.112769 -1.330163 2.195480 -0.347462 
    11 0.057467 -0.204044 0.020474 -1.198299 
    2 1.011604 -0.411514 0.941112 -0.509703 
    3 0.524958 -0.855275 0.257481 0.630311 
    6 1.989778 -0.099014 0.302340 -0.067559 

Und jetzt will ich nur die Zeilen bekommen, wo der zweite Index einige Werte hat. So können sagen, ich will nur Zeilen, in denen der zweite Index enthält '2' und '3' und '10', so konnte ich tun:

sliced = df.loc[(slice(None), ['2','3','10']), :] 

, die ergibt:

   0   1   2   3 
bar 10 1.411962 -0.742729 0.950159 1.074269 
    2 1.214804 -0.654806 -1.138855 0.609101 
    3 0.135363 1.226927 -0.501535 -0.791849 
foo 10 -0.004108 -0.067574 -0.139101 -0.358282 
    3 0.612849 -0.598579 0.923299 -0.218198 
qux 10 0.112769 -1.330163 2.195480 -0.347462 
    2 1.011604 -0.411514 0.941112 -0.509703 
    3 0.524958 -0.855275 0.257481 0.630311 

aber ich möchte nicht, die Reihe mit ['10', '3']. So würde das gewünschte Ergebnis sein:

   0   1   2   3 
bar 10 1.411962 -0.742729 0.950159 1.074269 
    2 1.214804 -0.654806 -1.138855 0.609101 
    3 0.135363 1.226927 -0.501535 -0.791849 
qux 10 0.112769 -1.330163 2.195480 -0.347462 
    2 1.011604 -0.411514 0.941112 -0.509703 
    3 0.524958 -0.855275 0.257481 0.630311 

Ich versuchte, aber ich konnte nicht meinen Kopf bekommen, wie man das richtig löst. Jede Hilfe wird sehr geschätzt.

+0

Nein ... glaube nicht, dass dies durch Schneiden möglich ist. –

Antwort

0

Wie COLDSPEED sagte, es scheint nicht möglich, reine Indexierung warf. Allerdings können Sie es in ein paar Schritten durch eine groupby-Anweisung tun. Wenn wir den Code nehmen wieder

import pandas as pd 
import numpy as np 
arrays = [['bar', 'bar', 'bar','bar', 'foo','foo', 'qux', 'qux', 
'qux','qux', 'qux'], 
     ['2', '3', '4','10', '3','10','2','3','6','10','11']] 
df = pd.DataFrame(np.random.randn(11, 4), index=arrays).sort_index() 
# your slice 
col_list = ['2','3','10'] 
sliced = df.loc[(slice(None), col_list), :] 

Dann können wir eine groupby gelten die Anzahl der Elemente pro ersten Ebene Index zu finden. Dann vergleichen wir es mit der Anzahl der Dinge, die Sie erwarten. Schließlich verwenden wir die erstellte boolesche Maske, um unseren Datenrahmen zu filtern (mehr Details dazu here).

>>> mask = sliced.groupby(level=0)[0].count() == len(col_list) 
>>> sliced[mask[sliced.index.get_level_values(0)].values] 

       0   1   2   3 
bar 10 0.026192 -1.367292 -1.732297 -0.174405 
    2 -0.351960 0.563901 0.634585 -0.540770 
    3 0.489480 0.265043 0.989557 0.783377 
qux 10 0.544202 -0.061462 1.020261 -2.170451 
    2 -0.506330 0.335722 -0.303334 -0.916619 
    3 0.877082 0.235224 0.868546 2.197707