2013-02-21 8 views
23

Ho un frame di dati e vorrei raggrupparlo per una colonna particolare (o, in altre parole, per i valori di una particolare colonna). Posso farlo nel modo seguente: grouped = df.groupby(['ColumnName']).Come applicare le funzioni "primo" e "ultimo" alle colonne mentre si utilizza il raggruppamento per in panda?

Immagino il risultato di questa operazione come una tabella in cui alcune celle possono contenere set di valori anziché singoli valori. Per ottenere una tabella usuale (ad esempio una tabella in cui ogni cella contiene solo un singolo valore), è necessario indicare quale funzione si desidera utilizzare per trasformare gli insiemi di valori nelle celle in valori singoli.

Ad esempio, è possibile sostituire insiemi di valori in base alla loro somma o al loro valore minimo o massimo. Posso farlo nel modo seguente: grouped.sum() o grouped.min() e così via.

Ora voglio utilizzare diverse funzioni per colonne diverse. Ho capito che posso farlo nel modo seguente: grouped.agg({'ColumnName1':sum, 'ColumnName2':min}).

Tuttavia, a causa di alcuni motivi, non è possibile utilizzare first. In ulteriori dettagli, grouped.first() funziona, ma grouped.agg({'ColumnName1':first, 'ColumnName2':first}) non funziona. Di conseguenza ottengo un NameError: NameError: name 'first' is not defined. Quindi, la mia domanda è: perché succede e come risolvere questo problema.

AGGIUNTO

Here ho trovato il seguente esempio:

grouped['D'].agg({'result1' : np.sum, 'result2' : np.mean}) 

Può essere Ho anche bisogno di usare np? Ma nel mio caso python non riconosce "np". Dovrei importarlo?

+0

Non è necessario 'np', funzionerà con semplice' somma' (solo in modo meno efficiente). numpy viene importato con i panda (se si importa 'panda come pd' è 'pd.np') ma la maggior parte delle persone lo importerà anche separatamente per comodità. –

risposta

23

Penso che il problema sia che esistono due diversi metodi first che condividono un nome ma che agiscono in modo diverso, uno è per groupby objects e another for a Series/DataFrame (da utilizzare con gli orari).

per replicare il comportamento del metodo groupby first su uno dataframe utilizzando agg è possibile utilizzare iloc[0] (che ottiene la prima riga di ciascun gruppo (dataframe/Series) per indice):

grouped.agg(lambda x: x.iloc[0]) 

Ad esempio:

In [1]: df = pd.DataFrame([[1, 2], [3, 4]]) 

In [2]: g = df.groupby(0) 

In [3]: g.first() 
Out[3]: 
    1 
0 
1 2 
3 4 

In [4]: g.agg(lambda x: x.iloc[0]) 
Out[4]: 
    1 
0 
1 2 
3 4 

Analogamente è possibile replicare last usando iloc[-1].

Nota: Questa volontà funziona colonna-saggio, et al:

g.agg({1: lambda x: x.iloc[0]}) 

Nella versione precedente di panda si potrebbe dovrebbe utilizzare il metodo IRow (ad esempio x.irow(0), vedere le modifiche precedenti


.

Un paio di note aggiornate:

Questo è fatto meglio utilizzando il nth metodo GroupBy, che è molto più veloce> = 0,13:

g.nth(0) # first 
g.nth(-1) # last 

Si deve prendere cura un po ', come il comportamento predefinito per first e last ignora le righe NaN ... e IIRC per dataframe groupbys era rotto pre-0.13 ... c'è l'opzione dropna per nth.

È possibile utilizzare le stringhe piuttosto che built-in (anche se macchie panda IIRC è il sum incorporato e applica np.sum):

grouped['D'].agg({'result1' : "sum", 'result2' : "mean"}) 
+0

Nel caso sia utile a chiunque, secondo [i documenti] (http://pandas.pydata.org/pandas-docs/dev/indexing.html), 'irow' ora è deprecato (' x.iloc [0] 'fa invece il trucco) – cd98

+0

@ cd98 Grazie per averlo indicato, ho aggiornato questo con la sintassi più recente :) –

+0

Sono confuso con [il Documenti] (http://pandas.pydata.org/pandas-docs/stable/groupby.html#aggregation); afferma: 'Le funzioni di aggregazione sono quelle che riducono la dimensione degli oggetti restituiti, ad esempio: media, somma, dimensione, conteggio, std, var, sem, descrivi, prima, ultima, ennesima, massima, massima. stanno parlando? – Tjorriemorrie

0

non sono sicuro se questo è davvero il problema, ma sum e min sono Python built-in che prendono alcuni iterables come input, mentre first è un metodo di oggetto panda Series, quindi forse non è nello spazio dei nomi. Inoltre ci vuole qualcos'altro come input (il documento dice qualche valore di offset).

immagino un modo per aggirare l'ostacolo è quello di creare la propria funzione first, e definirlo tale che ci vuole un oggetto della serie come input, ad esempio:

def first(Series, offset): 
    return Series.first(offset) 

o qualcosa del genere ..

+0

È un peccato che 'pd.Series.first' non funzioni – Tjorriemorrie

6

Invece di usare first o last, utilizzare le loro rappresentazioni di stringa nel agg metodo. Per esempio nel caso dell'OP:

grouped = df.groupby(['ColumnName']) 
grouped['D'].agg({'result1' : np.sum, 'result2' : np.mean}) 

#you can do the string representation for first and last 
grouped['D'].agg({'result1' : 'first', 'result2' : 'last'}) 
Problemi correlati