past multiindex may lexsort impact python pandas dataframe multi-index

python - multiindex - pandas pivot



Cómo dividir un DataFrame de MultiIndex con el MultiIndex de otro (3)

Aquí hay una manera de obtener esta porción:

df.sort_index(inplace=True) idx = pd.IndexSlice df.loc[idx[:, (''foo'',''bar''), ''can''], :]

flexible

hi a b c 1 bar can 3 foo can 1 2 bar can 7 foo can 5 3 bar can 11 foo can 9

Tenga en cuenta que es posible que necesite ordenar MultiIndex antes de poder cortarlo. Los pandas bien tienen la amabilidad de advertirte si necesitas hacerlo:

KeyError: ''MultiIndex Slicing requires the index to be fully lexsorted tuple len (3), lexsort depth (1)''

Puede leer más sobre cómo usar slicers en los documentos

Si por alguna razón, usar slicers no es una opción, aquí hay una manera de obtener el mismo sector utilizando el método .isin() :

df[df.index.get_level_values(''b'').isin(ix_use.get_level_values(0)) & df.index.get_level_values(''c'').isin(ix_use.get_level_values(1))]

Lo cual claramente no es tan conciso.

ACTUALIZAR:

Para las condiciones que ha actualizado aquí hay una forma de hacerlo:

cond1 = (df.index.get_level_values(''b'').isin([''foo''])) & (df.index.get_level_values(''c'').isin([''can''])) cond2 = (df.index.get_level_values(''b'').isin([''bar''])) & (df.index.get_level_values(''c'').isin([''baz''])) df[cond1 | cond2]

productor:

hi a b c 1 foo can 1 bar baz 2 2 foo can 5 bar baz 6 3 foo can 9 bar baz 10

Tengo un marco de datos de pandas con 3 niveles de un MultiIndex. Estoy tratando de extraer filas de este marco de datos de acuerdo con una lista de valores que corresponden a dos de los niveles.

Tengo algo como esto:

ix = pd.MultiIndex.from_product([[1, 2, 3], [''foo'', ''bar''], [''baz'', ''can'']], names=[''a'', ''b'', ''c'']) data = np.arange(len(ix)) df = pd.DataFrame(data, index=ix, columns=[''hi'']) print(df) hi a b c 1 foo baz 0 can 1 bar baz 2 can 3 2 foo baz 4 can 5 bar baz 6 can 7 3 foo baz 8 can 9 bar baz 10 can 11

Ahora quiero tomar todas las filas donde los niveles de índice ''b'' y ''c'' están en este índice:

ix_use = pd.MultiIndex.from_tuples([(''foo'', ''can''), (''bar'', ''baz'')], names=[''b'', ''c''])

es decir, los valores de hi having (''foo'', ''can'') o (''bar'', ''baz'') en los niveles b : (1, 2, 5, 6, 9, 10) .

Así que me gustaría tomar una slice(None) en el primer nivel, y sacar tuplas específicas en el segundo y tercer niveles.

Inicialmente pensé que pasar un objeto de varios índices a .loc eliminaría los valores / niveles que quería, pero esto no está funcionando. ¿Cuál es la mejor manera de hacer algo como esto?


Me parece interesante que esto no funcione:

In [45]: df.loc[(idx[:, ''foo'', ''can''], idx[:, ''bar'', ''baz'']), ] Out[45]: hi a b c 1 bar baz 2 can 3 foo baz 0 can 1 2 bar baz 6 can 7 foo baz 4 can 5 3 bar baz 10 can 11 foo baz 8 can 9

De alguna manera, parece que "debería". En cualquier caso, aquí hay una solución razonable:

Supongamos que las tuplas que desea DataFrame están en el índice de otro DataFrame (¡ya que parece que probablemente estén en su caso!).

In [53]: ix_use = pd.MultiIndex.from_tuples([(''foo'', ''can''), (''bar'', ''baz'')], names=[''b'', ''c'']) In [55]: other = pd.DataFrame(dict(a=1), index=ix_use) In [56]: other Out[56]: a b c foo can 1 bar baz 1

Ahora, para cortar df por el índice de other , podemos usar el hecho de que .loc / .ix permite dar una lista de tuplas (vea el último ejemplo aquí ).

Primero construyamos la lista de tuplas que queremos:

In [13]: idx = [(x, ) + y for x in df.index.levels[0] for y in other.index.values] In [14]: idx Out[14]: [(1, ''foo'', ''can''), (1, ''bar'', ''baz''), (2, ''foo'', ''can''), (2, ''bar'', ''baz''), (3, ''foo'', ''can''), (3, ''bar'', ''baz'')]

Ahora podemos pasar esta lista a .ix o .loc :

In [17]: df.ix[idx] Out[17]: hi a b c 1 foo can 1 bar baz 2 2 foo can 5 bar baz 6 3 foo can 9 bar baz 10


Recomendaría el método query() al igual que en este Q & A.

Simplemente usando esto, que creo que es una forma más natural de expresar:

In [27]: df.query("(b == ''foo'' and c == ''can'') or (b == ''bar'' and c == ''baz'')") Out[27]: hi a b c 1 foo can 1 bar baz 2 2 foo can 5 bar baz 6 3 foo can 9 bar baz 10