name index iloc columns column pandas

pandas - index - Seleccione una sección transversal de varias claves de un DataFrame



pandas select columns (4)

Convertir a un panel, entonces la indexación es directa

In [20]: df = pd.DataFrame(dict(time = pd.Timestamp(''20130102''), A = np.random.rand(3), ticker=[''SPY'',''SLV'',''GLD''])).set_index([''time'',''ticker'']) In [21]: df Out[21]: A time ticker 2013-01-02 SPY 0.347209 SLV 0.034832 GLD 0.280951 In [22]: p = df.to_panel() In [23]: p Out[23]: <class ''pandas.core.panel.Panel''> Dimensions: 1 (items) x 1 (major_axis) x 3 (minor_axis) Items axis: A to A Major_axis axis: 2013-01-02 00:00:00 to 2013-01-02 00:00:00 Minor_axis axis: GLD to SPY In [24]: p.ix[:,:,[''SPY'',''GLD'']] Out[24]: <class ''pandas.core.panel.Panel''> Dimensions: 1 (items) x 1 (major_axis) x 2 (minor_axis) Items axis: A to A Major_axis axis: 2013-01-02 00:00:00 to 2013-01-02 00:00:00 Minor_axis axis: SPY to GLD

Tengo un DataFrame "df" con (time, ticker) Multiindex y columnas de datos bid / ask / etc:

tod last bid ask volume time ticker 2013-02-01 SPY 1600 149.70 150.14 150.17 1300 SLV 1600 30.44 30.38 30.43 3892 GLD 1600 161.20 161.19 161.21 3860

Me gustaría seleccionar una sección transversal de segundo nivel (nivel = 1) con varias teclas. En este momento, puedo hacerlo usando una tecla, es decir

df.xs(''SPY'', level=1)

Lo que me da una serie temporal de SPY. ¿Cuál es la mejor manera de seleccionar una sección transversal de varias teclas, es decir, una sección transversal combinada de SPY y GLD, algo así como:

df.xs([''SPY'', ''GLD''], level=1)

?


Hay mejores formas de hacerlo con las versiones más recientes de Pandas:

regression_df.loc[(slice(None), [''SPY'', ''GLD'']), :]

Este enfoque requiere que el índice se df.sort_index() lexicográficamente (use df.sort_index() ).


No pude encontrar una forma más directa que no sea usar select :

>>> df last tod A SPY 1 1600 SLV 2 1600 GLD 3 1600 >>> df.select(lambda x: x[1] in [''SPY'',''GLD'']) last tod A SPY 1 1600 GLD 3 1600


Por lo que vale, hice lo siguiente:

foo = pd.DataFrame(np.random.rand(12,3), index=pd.MultiIndex.from_product([[''A'',''B'',''C'',''D''],[''Green'',''Red'',''Blue'']], names=[''Letter'',''Color'']), columns=[''X'',''Y'',''Z'']).sort_index() foo.reset_index()/ .loc[foo.reset_index().Color.isin({''Green'',''Red''})]/ .set_index(foo.index.names)

Este enfoque es similar a seleccionar, pero evita la iteración sobre todas las filas con un lambda.

Sin embargo, comparé esto con el enfoque del Panel, y parece que la solución del Panel es más rápida (2.91 ms para index / loc vs 1.48 ms para to_panel / to_frame:

foo.to_panel()[:,:,[''Green'',''Red'']].to_frame()

Veces:

In [56]: %%timeit foo.reset_index().loc[foo.reset_index().Color.isin({''Green'',''Red''})].set_index(foo.index.names) 100 loops, best of 3: 2.91 ms per loop In [57]: %%timeit foo2 = foo.reset_index() foo2.loc[foo2.Color.eq(''Green'') | foo2.Color.eq(''Red'')].set_index(foo.index.names) 100 loops, best of 3: 2.85 ms per loop In [58]: %%timeit foo2 = foo.reset_index() foo2.loc[foo2.Color.ne(''Blue'')].set_index(foo.index.names) 100 loops, best of 3: 2.37 ms per loop In [54]: %%timeit foo.to_panel()[:,:,[''Green'',''Red'']].to_frame() 1000 loops, best of 3: 1.18 ms per loop

ACTUALIZAR

Después de revisar este tema (nuevamente), observé lo siguiente:

In [100]: %%timeit foo2 = pd.DataFrame({k: foo.loc[k] for k in foo.index if k[1] in [''Green'',''Red'']}).transpose() foo2.index.names = foo.index.names foo2.columns.names = foo2.columns.names 100 loops, best of 3: 1.97 ms per loop In [101]: %%timeit foo2 = pd.DataFrame.from_dict({k: foo.loc[k] for k in foo.index if k[1] in [''Green'',''Red'']}, orient=''index'') foo2.index.names = foo.index.names foo2.columns.names = foo2.columns.names 100 loops, best of 3: 1.82 ms per loop

Si no le importa conservar el orden original y la denominación de los niveles, puede utilizar:

%%timeit pd.concat({key: foo.xs(key, axis=0, level=1) for key in [''Green'',''Red'']}, axis=0) 1000 loops, best of 3: 1.31 ms per loop

Y si solo estás seleccionando en el primer nivel:

%%timeit pd.concat({key: foo.loc[key] for key in [''A'',''B'']}, axis=0, names=foo.index.names) 1000 loops, best of 3: 1.12 ms per loop

versus:

%%timeit foo.to_panel()[:,[''A'',''B''],:].to_frame() 1000 loops, best of 3: 1.16 ms per loop

Otra actualización

Si ordena el índice del ejemplo foo , muchas de las veces anteriores mejoran (los tiempos se han actualizado para reflejar un índice pre-ordenado). Sin embargo, cuando el índice está ordenado, puede usar la solución descrita por user674155:

%%timeit foo.loc[(slice(None), [''Blue'',''Red'']),:] 1000 loops, best of 3: 582 µs per loop

Este es el más eficiente e intuitivo en mi opinión (el usuario no necesita entender los paneles y cómo se crean a partir de marcos).

Nota: incluso si el índice aún no se ha ordenado, la clasificación del índice de foo sobre la marcha es comparable en rendimiento a la opción to_panel .