Python Pandas: ¿Se conserva el orden al usar groupby() y agg()?

3 minutos de lectura

Avatar de usuario de BringMyCakeBack
TraeMiPastelDeVuelta

he frecuentado pandas usados’ agg() función para ejecutar estadísticas de resumen en cada columna de un data.frame. Por ejemplo, así es como produciría la media y la desviación estándar:

df = pd.DataFrame({'A': ['group1', 'group1', 'group2', 'group2', 'group3', 'group3'],
                   'B': [10, 12, 10, 25, 10, 12],
                   'C': [100, 102, 100, 250, 100, 102]})

>>> df
[output]
        A   B    C
0  group1  10  100
1  group1  12  102
2  group2  10  100
3  group2  25  250
4  group3  10  100
5  group3  12  102

En ambos casos, el orden en que las filas individuales se envían a la función agg no importa. Pero considere el siguiente ejemplo, que:

df.groupby('A').agg([np.mean, lambda x: x.iloc[1] ])

[output]

        mean  <lambda>  mean  <lambda>
A                                     
group1  11.0        12   101       102
group2  17.5        25   175       250
group3  11.0        12   101       102

En este caso, la lambda funciona según lo previsto, generando la segunda fila en cada grupo. Sin embargo, no he podido encontrar nada en la documentación de pandas que implique que esto esté garantizado en todos los casos. quiero usar agg() junto con una función de promedio ponderado, por lo que quiero estar seguro de que las filas que entran en la función estarán en el mismo orden en que aparecen en el marco de datos original.

¿Alguien sabe, idealmente a través de algún lugar del código fuente de docs o pandas, si se garantiza que este sea el caso?

  • Sí, no puedo ver ninguna garantía de que el orden se conserve en los documentos, por lo que parece un poco imprudente confiar en él. Si el pedido se refleja en su B columna, entonces podría ordenar cada grupo por B dentro de la lambda para asegurarse.

    – Mario

    19/10/2014 a las 23:38

  • Desafortunadamente, quiero mantener las filas ordenadas por una columna que no está incluida en la agregación. El marco de datos se ordena antes que el agg() llamada, por lo que solo es un problema si lo reordena como parte del groupby().

    – Trae mi pastel de vuelta

    20 de octubre de 2014 a las 0:02

Para mantener el orden, deberá pasar .groupby(..., sort=False). En su caso, la columna de agrupación ya está ordenada, por lo que no hace la diferencia, pero generalmente se debe usar el sort=False bandera:

 df.groupby('A', sort=False).agg([np.mean, lambda x: x.iloc[1] ])

  • Hay un indicador sort= para groupby, pero esto se relaciona con la clasificación de los grupos mismos y no con las observaciones dentro de un grupo.

    – El gato sin gracia

    14 de agosto de 2019 a las 8:03

  • deberían haber hecho de esto un parámetro predeterminado, considerando que esto se usa muy a menudo

    – NaN

    9 de septiembre de 2020 a las 12:58

  • Es irónico que la documentación también diga “Obtenga un mejor rendimiento desactivando esto”. Bueno, una razón más por la que debería haber sido una característica opcional, no predeterminada. Lo que es más importante, realiza cambios en los datos que la persona que llama podría no esperar.

    -Roland Pihlakas

    24 de diciembre de 2021 a las 12:57

  • a partir de pandas versión 1.5.3, sort tiene el valor predeterminado True. que era lo contrario de mis expectativas.

    – BenSeedGangMu

    15 de febrero a las 4:00


Ver esta mejora asunto

La respuesta corta es sí, groupby conservará los pedidos tal como se transmiten. Puede probar esto usando su ejemplo de esta manera:

In [20]: df.sort_index(ascending=False).groupby('A').agg([np.mean, lambda x: x.iloc[1] ])
Out[20]: 
           B             C         
        mean <lambda> mean <lambda>
A                                  
group1  11.0       10  101      100
group2  17.5       10  175      100
group3  11.0       10  101      100

Sin embargo, esto NO es cierto para el remuestreo, ya que requiere un índice monótono (funcionará con un índice no monótono, pero lo ordenará primero).

Su es un sort= flag a groupby, pero esto se relaciona con la clasificación de los grupos en sí y no con las observaciones dentro de un grupo.

Para tu información: df.groupby('A').nth(1) es una forma segura de obtener el segundo valor de un grupo (ya que su método anterior fallará si un grupo tiene

  • ¡Gracias por la aclaración y el enlace del problema! originalmente usé iloc como ejemplo porque no pude averiguar cómo pasar nth() hacia agg() llamar (porque en ese momento x es una serie). hay alguna forma de llamar nth() que no sea como una función miembro de DataFrame?

    – Trae mi pastel de vuelta

    20/10/2014 a las 22:09

  • nth solo se define en un groupby. ¿Qué quiere decir ‘que no sea una función miembro de DataFrame’?

    – Jeff

    20/10/2014 a las 22:13

  • Quise decir que no podía averiguar cómo pasar nth() como una de las funciones enviadas en la lista a agg(). no puedes hacer .agg([np.mean, nth])o DataFrame.nth() o lambda x: x.nth(2). Eso es lo que me llevó a iloc, aunque generará errores de índice. La mejor manera es probablemente no tratar de hacerlo todo en un solo paso; primer uso nth() entonces usa agg()luego fusionarlos.

    – Trae mi pastel de vuelta

    21 de octubre de 2014 a las 3:21

Avatar de usuario de Uwe Mayer
uwe mayer

El documento 0.19.1 de Panda dice “groupby conserva el orden de las filas dentro de cada grupo”, por lo que este es un comportamiento garantizado.

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.groupby.html

Avatar de usuario de Jigidi Sarnath
Jigidi Sarnath

Referencia:
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.groupby.html

La API acepta “SORT” como argumento.

La descripción del argumento SORT es así:

sort : bool, claves de grupo True Sort predeterminadas. Obtenga un mejor rendimiento desactivando esto. Tenga en cuenta que esto no influye en el orden de las observaciones dentro de cada grupo. Groupby conserva el orden de las filas dentro de cada grupo.

Por lo tanto, está claro que “Groupby” conserva el orden de las filas dentro de cada grupo.

Desafortunadamente, la respuesta a esta pregunta es no. En los últimos días, creé un algoritmo para la fragmentación no uniforme y descubrí que no es posible mantener el orden porque un groupby introduce subtramas donde la clave de cada trama es la entrada de groupby. Entonces terminas con:

allSubFrames = df.groupby("myColumnToOrderBy")
for orderKey, individualSubFrame in allSubFrames:
     do something...

Debido a que usa diccionarios, pierde el orden.

Si realiza una clasificación después, como se mencionó anteriormente, que acabo de probar para un conjunto de datos masivo, termina con un cálculo O (n log n).

Sin embargo, descubrí que si, por ejemplo, ordenó datos de series temporales en orden, donde desea conservar el orden, es mejor cambiar la columna de ordenación en una lista y luego crear un contador que registre el primer elemento en cada serie temporal. . Esto da como resultado un cálculo de O(n).

Entonces, esencialmente, si está utilizando un conjunto de datos relativamente pequeño, las respuestas propuestas anteriormente son razonables, pero si usa un conjunto de datos grande, debe considerar evitar agrupar y ordenar. En su lugar, use: list(df['myColumnToOrderBy']) e iterador sobre él.

  • ¿Puede, por favor, agregar un ejemplo de código de trabajo simple a su respuesta?

    – Nimpo

    7 febrero 2022 a las 17:54

  • No, no puedo porque necesita un conjunto de datos masivo, y me tomó mucho tiempo resolver este problema y ya no estoy trabajando en ese proyecto.

    – Eamon Kenny

    7 de marzo de 2022 a las 13:59

Avatar de usuario de TinaW
tinaw

Aún más fácil:

  import pandas as pd
  pd.pivot_table(df,index='A',aggfunc=(np.mean))

producción:

            B    C
     A                
   group1  11.0  101
   group2  17.5  175
   group3  11.0  101

  • ¿Puede, por favor, agregar un ejemplo de código de trabajo simple a su respuesta?

    – Nimpo

    7 febrero 2022 a las 17:54

  • No, no puedo porque necesita un conjunto de datos masivo, y me tomó mucho tiempo resolver este problema y ya no estoy trabajando en ese proyecto.

    – Eamon Kenny

    7 de marzo de 2022 a las 13:59

¿Ha sido útil esta solución?