single past multiple multiindex may lexsort index impact groupby from data python pandas indexing slice multi-index

python - past - pandas xs



Cómo consultar valores de columnas de índice MultiIndex en pandas (3)

Con un índice tipo "flotante", siempre desea utilizarlo como una columna en lugar de una acción de indexación directa. Todos estos funcionarán si los puntos finales existen o no.

In [11]: df Out[11]: C A B 1.1 111 81 222 45 3.3 222 98 333 13 5.5 333 89 6.6 777 98 In [12]: x = df.reset_index()

Q1

In [13]: x.loc[(x.A>=3.3)&(x.A<=6.6)] Out[13]: A B C 2 3.3 222 98 3 3.3 333 13 4 5.5 333 89 5 6.6 777 98

Q2

In [14]: x.loc[(x.A>=2.0)&(x.A<=4.0)] Out[14]: A B C 2 3.3 222 98 3 3.3 333 13

Q3

In [15]: x.loc[(x.B>=111.0)&(x.B<=500.0)] Out[15]: A B C 0 1.1 111 81 1 1.1 222 45 2 3.3 222 98 3 3.3 333 13 4 5.5 333 89

Si quiere que los índices vuelvan, simplemente configúrelos. Esta es una operación barata.

In [16]: x.loc[(x.B>=111.0)&(x.B<=500.0)].set_index([''A'',''B'']) Out[16]: C A B 1.1 111 81 222 45 3.3 222 98 333 13 5.5 333 89

Si REALMENTE desea los valores reales del índice

In [5]: x.loc[(x.B>=111.0)&(x.B<=500.0)].set_index([''A'',''B'']).index Out[5]: MultiIndex [(1.1, 111), (1.1, 222), (3.3, 222), (3.3, 333), (5.5, 333)]

Ejemplo de código:

In [171]: A = np.array([1.1, 1.1, 3.3, 3.3, 5.5, 6.6]) In [172]: B = np.array([111, 222, 222, 333, 333, 777]) In [173]: C = randint(10, 99, 6) In [174]: df = pd.DataFrame(zip(A, B, C), columns=[''A'', ''B'', ''C'']) In [175]: df.set_index([''A'', ''B''], inplace=True) In [176]: df Out[176]: C A B 1.1 111 20 222 31 3.3 222 24 333 65 5.5 333 22 6.6 777 74

Ahora, quiero recuperar valores A:
Q1 : dentro del rango [3.3, 6.6] - valor esperado de retorno: [3.3, 5.5, 6.6] o [3.3, 3.3, 5.5, 6.6] en caso de que el último inclusive, y [3.3, 5.5] o [3.3, 3.3, 5.5] si no.
Q2 : en el rango [2.0, 4.0] - valor esperado de retorno: [3.3] o [3.3, 3.3]

Lo mismo para cualquier otra dimensión MultiIndex , por ejemplo valores B:
Q3 : en el rango [111, 500] con repeticiones, como número de filas de datos en el rango - valor de retorno esperado: [111, 222, 222, 333, 333]

Más formal:

Supongamos que T es una tabla con las columnas A, B y C. La tabla incluye n filas. Las celdas de la tabla son números, por ejemplo números enteros A, B y C. Vamos a crear un DataFrame de la tabla T, vamos a llamarlo DF. Establezcamos los índices de las columnas A y B de DF (sin duplicación, es decir, no columnas separadas A y B como índices, y separados como datos), es decir, A y B, en este caso, MultiIndex .

Preguntas:

  1. ¿Cómo escribir una consulta en el índice, por ejemplo, para consultar el índice A (o B), por ejemplo, en el intervalo de etiquetas [120.0, 540.0]? Las etiquetas 120.0 y 540.0 existen. Debo aclarar que solo estoy interesado en la lista de índices como respuesta a la consulta.
  2. ¿Cómo lo mismo, pero en el caso de las etiquetas 120.0 y 540.0 no existen, pero hay etiquetas por valor inferior a 120, superior a 120 y inferior a 540, o superior a 540?
  3. En caso de que la respuesta para Q1 y Q2 fueran valores de índice únicos, ahora lo mismo, pero con repeticiones, como el número de filas de datos en el rango de índice.

Conozco las respuestas a las preguntas anteriores en el caso de las columnas que no son índices, pero en el caso de los índices, después de una larga investigación en la web y la experimentación con la funcionalidad de los pandas , no tuve éxito. El único método (sin programación adicional) que veo ahora es tener un duplicado de A y B como columnas de datos además del índice.


Para consultar el df por los valores de MultiIndex , por ejemplo, donde (A> 1.7) y (B <666) :

In [536]: result_df = df.loc[(df.index.get_level_values(''A'') > 1.7) & (df.index.get_level_values(''B'') < 666)] In [537]: result_df Out[537]: C A B 3.3 222 43 333 59 5.5 333 56

Por lo tanto, para obtener, por ejemplo, los valores del índice ''A'' , si todavía se requieren:

In [538]: result_df.index.get_level_values(''A'') Out[538]: Index([3.3, 3.3, 5.5], dtype=object)

El problema es que en grandes marcos de datos, el rendimiento de la selección del índice empeora en un 10% en comparación con la selección de filas regulares ordenadas. Y en el trabajo repetitivo, bucle, la demora acumulada. Ver ejemplo:

In [558]: df = store.select(STORE_EXTENT_BURSTS_DF_KEY) In [559]: len(df) Out[559]: 12857 In [560]: df.sort(inplace=True) In [561]: df_without_index = df.reset_index() In [562]: %timeit df.loc[(df.index.get_level_values(''END_TIME'') > 358200) & (df.index.get_level_values(''START_TIME'') < 361680)] 1000 loops, best of 3: 562 µs per loop In [563]: %timeit df_without_index[(df_without_index.END_TIME > 358200) & (df_without_index.START_TIME < 361680)] 1000 loops, best of 3: 507 µs per loop


Para una mejor legibilidad , simplemente podemos usar el método query() , para evitar el extenso df.index.get_level_values() y reset_index / set_index de un lado a otro.

Aquí está el DataFrame objetivo:

In [12]: df Out[12]: C A B 1.1 111 68 222 40 3.3 222 20 333 11 5.5 333 80 6.6 777 51

Respuesta para Q1 ( A en el rango [3.3, 6.6] ):

In [13]: df.query(''3.3 <= A <= 6.6'') # for closed interval Out[13]: C A B 3.3 222 20 333 11 5.5 333 80 6.6 777 51 In [14]: df.query(''3.3 < A < 6.6'') # for open interval Out[14]: C A B 5.5 333 80

y, por supuesto, uno puede jugar con <, <=, >, >= para cualquier tipo de inclusión.

Del mismo modo, responda para Q2 ( A en el rango [2.0, 4.0] ):

In [15]: df.query(''2.0 <= A <= 4.0'') Out[15]: C A B 3.3 222 20 333 11

Respuesta para Q3 ( B en el rango [111, 500] ):

In [16]: df.query(''111 <= B <= 500'') Out[16]: C A B 1.1 111 68 222 40 3.3 222 20 333 11 5.5 333 80

¡Y además, puedes COMBINAR la consulta para col A y B muy naturalmente!

In [17]: df.query(''0 < A < 4 and 150 < B < 400'') Out[17]: C A B 1.1 222 40 3.3 222 20 333 11