Il frame di dati di Panda ottiene la prima riga di ciascun gruppo


137

Ho un panda DataFramecome il seguente.

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"]})

Voglio raggruppare questo per ["id", "value"] e ottenere la prima riga di ciascun gruppo.

        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

Risultato previsto

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

Ho provato a seguire che dà solo la prima riga del file DataFrame. Qualsiasi aiuto in merito è apprezzato.

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

2
Mi rendo conto che questa domanda è piuttosto vecchia, ma suggerirei di accettare la risposta di @vital_dml perché il comportamento first()rispetto a Nans è molto sorprendente e qualcosa che penso che la maggior parte delle persone non si aspetterà.
user545424

Risposte:


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

Se è necessario idcome colonna:

>>> 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

Per ottenere n primi record, puoi usare 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
Molte grazie! Ha funzionato bene :) Non è possibile ottenere la seconda fila allo stesso modo, giusto? Puoi spiegarlo anche tu?
Nilani Algiriyage,

g = df.groupby (['session']) g.agg (lambda x: x.iloc [0]) funziona anche questo, non hai idea di ottenere il secondo valore? :(
Nilani Algiriyage,

supponiamo che il conteggio dall'alto desideri ottenere il numero di riga top_n, quindi dx = df.groupby ('id'). head (top_n) .reset_index (drop = True) e supponiamo che il conteggio dal basso desideri ottenere il numero di riga bottom_n, quindi dx = df.groupby ('id'). tail (bottom_n) .reset_index (drop = True)
Quetzalcoatl

3
Nel caso in cui si desideri le ultime n righe, utilizzare tail(n)(il valore predefinito è n = 5) ( rif. ). Da non confondere last(), ho fatto quell'errore.
rocarvaj,

groupby('id',as_index=False)mantiene anche idcome una colonna
Richard DiSalvo il

50

Questo ti darà la seconda riga di ciascun gruppo (zero indicizzato, nth (0) è uguale a first ()):

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

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


8
Se vuoi multipli, come i primi tre, ad esempio, usa una sequenza come nth((0,1,2))o nth(range(3)).
Ronan Paixão,

@ RonanPaixão: in qualche modo quando do raggio, genera un errore:TypeError: n needs to be an int or a list/set/tuple of ints
Tranquillo

@Peaceful: stai usando Python 3? In tal caso, range(3)non restituisce un elenco a meno che non si digiti list(range(3)).
Ben

41

Suggerirei di utilizzare .nth(0)piuttosto che .first()se hai bisogno di ottenere la prima riga.

La differenza tra loro è il modo in cui gestiscono i NaN, quindi .nth(0)restituirà la prima riga del gruppo indipendentemente dai valori in questa riga, mentre .first()alla fine restituirà il primo no NaN valore in ogni colonna.

Ad esempio se il set di dati è:

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

E

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

1
buon punto. .head(1)sembra anche comportarsi come .nth(0), ad eccezione dell'indice
Richard DiSalvo,

1
Un'altra differenza è che nth (0) conserverà l'indice originale (se as_index = False), mentre first () no. Una volta per me questa è stata una differenza sostanziale, poiché avevo bisogno dell'indice stesso.
Oleg O

7

forse questo è quello che vuoi

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

Se hai bisogno solo della prima riga di ogni gruppo con cui possiamo fare drop_duplicates, nota il metodo predefinito della funzione 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.