I panda contano (distinti) equivalenti


289

Sto usando i panda come sostituto del db poiché ho più database (oracle, mssql, ecc.) E non sono in grado di eseguire una sequenza di comandi con un equivalente SQL.

Ho una tabella caricata in un DataFrame con alcune colonne:

YEARMONTH, CLIENTCODE, SIZE, .... etc etc

In SQL, contare la quantità di client diversi all'anno sarebbe:

SELECT count(distinct CLIENTCODE) FROM table GROUP BY YEARMONTH;

E il risultato sarebbe

201301    5000
201302    13245

Come posso farlo nei panda?


Ho eseguito table.groupby (['YEARMONTH']) ['CLIENTCODE']. Unique () e sono arrivato con due serie indicizzate da YEARMONTH e con tutti i valori univoci. Come contare la quantità di valori su ciascuna serie?
Adriano Almeida,

Per alcuni, value_countspotrebbe essere la risposta che stai cercando: pandas.pydata.org/pandas-docs/stable/generated/…
sachinruk

Risposte:


434

Credo che questo sia quello che vuoi:

table.groupby('YEARMONTH').CLIENTCODE.nunique()

Esempio:

In [2]: table
Out[2]: 
   CLIENTCODE  YEARMONTH
0           1     201301
1           1     201301
2           2     201301
3           1     201302
4           2     201302
5           2     201302
6           3     201302

In [3]: table.groupby('YEARMONTH').CLIENTCODE.nunique()
Out[3]: 
YEARMONTH
201301       2
201302       3

2
Cosa succede se ho più colonne che voglio essere univoche insieme, come in .drop_duplicates (subset = ['col1', 'col2'])?
ErnestScribbler,

4
Come accedere a questo conteggio unico. Poiché non esiste un nome di colonna
Tarun Khaneja,

Grazie mille, ho usato questo stile sull'output di resample. df_watch_record.resample ('M'). user.nunique () conta il numero di utenti unici che hanno visto film al mese.
Mehdi Kazemi,

1
e ordinali con table.groupby ('YEARMONTH'). CLIENTCODE.nunique (). sort_values ​​(crescente = Falso)
wllbll,

È possibile recuperare l'identificatore di gruppo dopo nunique? Prova come potrei non riesco a trovare un modo, poiché il risultato di questa risposta è a Series, non a DataFrame.
Josh Hansen,

93

Ecco un altro metodo, molto semplice, diciamo che il tuo nome del frame di dati è daate il nome della colonna èYEARMONTH

daat.YEARMONTH.value_counts()

1
Mi piace questa risposta. Come posso usare questo metodo se il mio nome di colonna ha un '.' in esso (es. 'ck.Class')? Grazie

5
daat ['ck.Class']. value_counts ()
StatguyUser

28
Questo non affronta la domanda posta.
Aaron Schumacher,

6
questo conta il numero di osservazioni all'interno di ciascun gruppo, non il valore univoco di una determinata colonna di ciascun gruppo.
Jason Goal,

2
Questa è la risposta errata; non riflette il DISTINCTrequisito della domanda! Inoltre, non include i conteggi di NaN!
Corey Levinson,

47

È interessante notare che molto spesso len(unique())è più volte (3x-15x) più veloce di nunique().


11
Intendi questo? .CLIENTCODE.apply(lambda x: len(x.unique())), da qui
user4015990

6
@ user32185 dovresti lasciarlo cadere in una applychiamata con un lambda. Per esempio, df.groupby('YEARMONTH')['CLIENTCODE'].apply(lambda x: x.unique().shape[0]).
3novak,

3
La sintassi non è completamente chiara, non ho usato la len(df['column'].unique())funzione lambda
mlh351

Ho ricevuto TypeError: object of type 'method' has no len()da Chen'scommentare, 3novak'sha lavorato per me.
Jason Goal,

4

Utilizzando crosstab, questo restituirà più informazioni digroupby nunique

pd.crosstab(df.YEARMONTH,df.CLIENTCODE)
Out[196]: 
CLIENTCODE  1  2  3
YEARMONTH          
201301      2  1  0
201302      1  2  1

Dopo un po 'di modifica, ottieni il risultato

pd.crosstab(df.YEARMONTH,df.CLIENTCODE).ne(0).sum(1)
Out[197]: 
YEARMONTH
201301    2
201302    3
dtype: int64

Come posso esportare questo come due colonne YEARMONTHe count. Posso anche impostare il conteggio in ordine decrescente?
Murtaza Haji,

3

Sto anche usando, nuniquema sarà molto utile se devi usare una funzione aggregata come 'min', 'max', 'count' or 'mean'ecc.

df.groupby('YEARMONTH')['CLIENTCODE'].transform('nunique') #count(distinct)
df.groupby('YEARMONTH')['CLIENTCODE'].transform('min')     #min
df.groupby('YEARMONTH')['CLIENTCODE'].transform('max')     #max
df.groupby('YEARMONTH')['CLIENTCODE'].transform('mean')    #average
df.groupby('YEARMONTH')['CLIENTCODE'].transform('count')   #count

0

Con la nuova versione di Panda, è facile ottenere come frame di dati

unique_count = pd.groupby(['YEARMONTH'], as_index=False).agg(uniq_CLIENTCODE =('CLIENTCODE',pd.Series.count))

0

Ecco un approccio per avere un conteggio distinto su più colonne. Diamo alcuni dati:

data = {'CLIENT_CODE':[1,1,2,1,2,2,3],
        'YEAR_MONTH':[201301,201301,201301,201302,201302,201302,201302],
        'PRODUCT_CODE': [100,150,220,400,50,80,100]
       }
table = pd.DataFrame(data)
table

CLIENT_CODE YEAR_MONTH  PRODUCT_CODE
0   1       201301      100
1   1       201301      150
2   2       201301      220
3   1       201302      400
4   2       201302      50
5   2       201302      80
6   3       201302      100

Ora, elenca le colonne di interesse e usa groupby in una sintassi leggermente modificata:

columns = ['YEAR_MONTH', 'PRODUCT_CODE']
table[columns].groupby(table['CLIENT_CODE']).nunique()

Otteniamo:

YEAR_MONTH  PRODUCT_CODE CLIENT_CODE        
1           2            3
2           2            3
3           1            1

0

Distinto di colonna con aggregazioni su altre colonne

Per ottenere il numero distinto di valori per qualsiasi colonna ( CLIENTCODEnel tuo caso), possiamo usare nunique. Possiamo passare l'input come dizionario in aggfunzione, insieme alle aggregazioni su altre colonne:

grp_df = df.groupby('YEARMONTH').agg({'CLIENTCODE': ['nunique'],
                                      'other_col_1': ['sum', 'count']})

# to flatten the multi-level columns
grp_df.columns = ["_".join(col).strip() for col in grp_df.columns.values]

# if you wish to reset the index
grp_df.reset_index(inplace=True)
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.