Pandas zählen (verschiedene) Äquivalente


288

Ich verwende Pandas als Datenbankersatz, da ich mehrere Datenbanken (Oracle, MSSQL usw.) habe und keine Befehlsfolge zu einem SQL-Äquivalent erstellen kann.

Ich habe eine Tabelle in einen DataFrame mit einigen Spalten geladen:

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

In SQL würde die Anzahl der verschiedenen Clients pro Jahr gezählt:

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

Und das Ergebnis wäre

201301    5000
201302    13245

Wie kann ich das bei Pandas machen?


Ich habe table.groupby (['YEARMONTH']) ['CLIENTCODE']. Unique () erstellt und kam mit zwei von YEARMONTH indizierten Serien und mit allen eindeutigen Werten. Wie zähle ich die Anzahl der Werte für jede Serie?
Adriano Almeida

Für einige value_countskönnte die Antwort sein, die Sie suchen: pandas.pydata.org/pandas-docs/stable/generated/…
sachinruk

Antworten:


434

Ich glaube, das ist was du willst:

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

Beispiel:

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
Was ist, wenn ich mehrere Spalten habe, die zusammen eindeutig sein sollen, wie in .drop_duplicates (subset = ['col1', 'col2'])?
ErnestScribbler

4
So greifen Sie auf diese eindeutige Anzahl zu. Da es keinen Spaltennamen gibt
Tarun Khaneja

Vielen Dank, ich habe diesen Stil bei der Ausgabe von Resample verwendet. df_watch_record.resample ('M'). user.nunique () zählt die Anzahl der eindeutigen Benutzer, die sich pro Monat einen Film angesehen haben.
Mehdi Kazemi

1
und sortiere sie mit table.groupby ('YEARMONTH'). CLIENTCODE.nunique (). sort_values ​​(aufsteigend = False)
wllbll

Ist es möglich, die Gruppen-ID danach abzurufen nunique? Versuchen Sie, wie ich könnte, ich kann keinen Weg finden, da das Ergebnis dieser Antwort a ist Series, nicht a DataFrame.
Josh Hansen

92

Hier ist eine andere Methode, die sehr einfach ist. Nehmen wir an, Ihr Datenrahmenname ist daatund der Spaltenname istYEARMONTH

daat.YEARMONTH.value_counts()

1
Ich mag diese Antwort. Wie kann ich diese Methode verwenden, wenn mein Spaltenname ein '.' drin (zB 'ck.Class')? Danke

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

28
Dies geht nicht auf die gestellte Frage ein.
Aaron Schumacher

6
Dabei wird die Anzahl der Beobachtungen innerhalb jeder Gruppe gezählt, nicht der eindeutige Wert einer bestimmten Spalte, die jede Gruppe hat.
Jason Goal

2
Dies ist die falsche Antwort. es spiegelt nicht die DISTINCTAnforderung aus der Frage wider ! Darüber hinaus enthält es keine Zählungen von NaN!
Corey Levinson

47

Interessanterweise ist sehr oft len(unique())ein paar Mal (3x-15x) schneller als nunique().


11
Du meinst das? .CLIENTCODE.apply(lambda x: len(x.unique())), von hier
user4015990

6
@ user32185 Sie müssten es in einen applyAnruf mit einem Lambda fallen lassen. Zum Beispiel df.groupby('YEARMONTH')['CLIENTCODE'].apply(lambda x: x.unique().shape[0]).
3novak

3
Die Syntax ist nicht ganz klar, ich habe len(df['column'].unique())keine Lambda-Funktion benötigt
mlh351

Ich habe TypeError: object of type 'method' has no len()von Chen'sKommentar bekommen, 3novak'sfür mich gearbeitet.
Jason Goal

4

Bei Verwendung von crosstabwird mehr Informationen zurückgegeben alsgroupby nunique

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

Nach ein wenig Änderung erhalten Sie das Ergebnis

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

Wie kann ich dies als zweispaltig exportieren YEARMONTHund count. Kann ich die Anzahl auch in absteigender Reihenfolge einstellen?
Murtaza Haji

3

Ich benutze auch, nuniqueaber es wird sehr hilfreich sein, wenn Sie eine Aggregatfunktion wie 'min', 'max', 'count' or 'mean'etc. verwenden müssen.

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

Mit der neuen Pandas-Version ist es einfach, als Datenrahmen zu erhalten

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

0

Hier ein Ansatz, um die Anzahl über mehrere Spalten zu unterscheiden. Lassen Sie uns einige Daten haben:

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

Listen Sie nun die interessierenden Spalten auf und verwenden Sie groupby in einer leicht geänderten Syntax:

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

Wir erhalten:

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

0

Unterscheidung der Spalte zusammen mit Aggregationen auf anderen Spalten

Um die eindeutige Anzahl von Werten für eine Spalte ( CLIENTCODEin Ihrem Fall) zu erhalten, können wir verwenden nunique. Wir können die Eingabe als Wörterbuch in aggFunktion übergeben, zusammen mit Aggregationen in anderen Spalten:

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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.