El marco de datos de pandas obtiene la primera fila de cada grupo


137

Tengo unos pandas DataFramecomo los siguientes.

df = pd.DataFrame({'id' : [1,1,1,2,2,3,3,3,3,4,4,5,6,6,6,7,7],
                'value'  : ["first","second","second","first",
                            "second","first","third","fourth",
                            "fifth","second","fifth","first",
                            "first","second","third","fourth","fifth"]})

Quiero agrupar esto por ["id", "valor"] y obtener la primera fila de cada grupo.

        id   value
0        1   first
1        1  second
2        1  second
3        2   first
4        2  second
5        3   first
6        3   third
7        3  fourth
8        3   fifth
9        4  second
10       4   fifth
11       5   first
12       6   first
13       6  second
14       6   third
15       7  fourth
16       7   fifth

Gastos esperados

    id   value
     1   first
     2   first
     3   first
     4  second
     5  first
     6  first
     7  fourth

Intenté seguir lo que solo da la primera fila de DataFrame. Cualquier ayuda con respecto a esto es apreciada.

In [25]: for index, row in df.iterrows():
   ....:     df2 = pd.DataFrame(df.groupby(['id','value']).reset_index().ix[0])

2
Me doy cuenta de que esta pregunta es bastante antigua, pero sugeriría aceptar la respuesta de @vital_dml porque el comportamiento first()con respecto a nans es muy sorprendente y es algo que creo que la mayoría de la gente no esperará.
user545424

Respuestas:


238
>>> df.groupby('id').first()
     value
id        
1    first
2    first
3    first
4   second
5    first
6    first
7   fourth

Si necesitas idcomo columna:

>>> df.groupby('id').first().reset_index()
   id   value
0   1   first
1   2   first
2   3   first
3   4  second
4   5   first
5   6   first
6   7  fourth

Para obtener n primeros registros, puede usar head ():

>>> df.groupby('id').head(2).reset_index(drop=True)
    id   value
0    1   first
1    1  second
2    2   first
3    2  second
4    3   first
5    3   third
6    4  second
7    4   fifth
8    5   first
9    6   first
10   6  second
11   7  fourth
12   7   fifth

1
¡Muchas gracias! Funcionó bien :) No es posible obtener la segunda fila de la misma manera, ¿verdad? ¿Puedes explicarlo también?
Nilani Algiriyage

g = df.groupby (['session']) g.agg (lambda x: x.iloc [0]) esto también está funcionando, ¿no tienes idea de obtener el segundo valor? :(
Nilani Algiriyage

supongamos que contando desde arriba desea obtener el número de fila top_n, luego dx = df.groupby ('id'). head (top_n) .reset_index (drop = True) y suponga que contando desde abajo desea obtener el número de fila bottom_n, luego dx = df.groupby ('id'). tail (bottom_n) .reset_index (drop = True)
Quetzalcoatl

3
En caso de que desee las últimas n filas, use tail(n)(el valor predeterminado es n = 5) ( ref. ). No debe confundirse con last(), cometí ese error.
rocarvaj

groupby('id',as_index=False)también se mantiene idcomo una columna
Richard DiSalvo

50

Esto le dará la segunda fila de cada grupo (cero indexado, nth (0) es lo mismo que first ()):

df.groupby('id').nth(1) 

Documentación: http://pandas.pydata.org/pandas-docs/stable/groupby.html#taking-the-nth-row-of-each-group


8
Si desea múltiplos, como los tres primeros, por ejemplo, use una secuencia como nth((0,1,2))o nth(range(3)).
Ronan Paixão

@ RonanPaixão: De alguna manera, cuando doy alcance, arroja un error:TypeError: n needs to be an int or a list/set/tuple of ints
Pacífica

@Peaceful: ¿estás usando Python 3? Si es así, range(3)no devuelve una lista a menos que escriba list(range(3)).
Ben

41

Sugeriría usar en .nth(0)lugar de .first()si necesita obtener la primera fila.

La diferencia entre ellos es cómo manejan los NaN, por .nth(0)lo que devolverá la primera fila del grupo sin importar cuáles sean los valores en esta fila, mientras .first()que eventualmente devolverá el primer valor no NaN en cada columna.

Por ejemplo, si su conjunto de datos es:

df = pd.DataFrame({'id' : [1,1,1,2,2,3,3,3,3,4,4],
            'value'  : ["first","second","third", np.NaN,
                        "second","first","second","third",
                        "fourth","first","second"]})

>>> df.groupby('id').nth(0)
    value
id        
1    first
2    NaN
3    first
4    first

Y

>>> df.groupby('id').first()
    value
id        
1    first
2    second
3    first
4    first

1
buen punto. .head(1)también parece comportarse como .nth(0), excepto por el índice
Richard DiSalvo

1
Otra diferencia es que nth (0) preservará el índice original (si as_index = False), mientras que first () no lo hará. Una vez para mí, esta fue una diferencia sustancial, ya que necesitaba el índice en sí.
Oleg O

7

tal vez esto es lo que quieres

import pandas as pd
idx = pd.MultiIndex.from_product([['state1','state2'],   ['county1','county2','county3','county4']])
df = pd.DataFrame({'pop': [12,15,65,42,78,67,55,31]}, index=idx)
                pop
state1 county1   12
       county2   15
       county3   65
       county4   42
state2 county1   78
       county2   67
       county3   55
       county4   31
df.groupby(level=0, group_keys=False).apply(lambda x: x.sort_values('pop', ascending=False)).groupby(level=0).head(3)

> Out[29]: 
                pop
state1 county3   65
       county4   42
       county2   15
state2 county1   78
       county2   67
       county3   55

7

Si solo necesita la primera fila de cada grupo con el que podemos hacerlo drop_duplicates, observe el método predeterminado de la función keep='first'.

df.drop_duplicates('id')
Out[1027]: 
    id   value
0    1   first
3    2   first
5    3   first
9    4  second
11   5   first
12   6   first
15   7  fourth
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.