Panda’s ‘count(distinct)’ equivalent

Ik gebruik Panda’s als vervanging voor databases omdat ik meerdere databases heb (Oracle, SQL Server, enz.), en ik kan geen reeks opdrachten naar een SQL maken gelijkwaardig.

Ik heb een tabel geladen in een DataFrame met enkele kolommen:

YEARMONTH, CLIENTCODE, SIZE, etc., etc.

In SQL zou het tellen van het aantal verschillende clients per jaar zijn:

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

En het resultaat zou zijn

201301    5000
201302    13245

Hoe kan ik dat doen in Panda’s?


Antwoord 1, autoriteit 100%

Ik geloof dat dit is wat je wilt:

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

Voorbeeld:

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

Antwoord 2, autoriteit 23%

Hier is een andere methode en deze is veel eenvoudiger. Stel dat uw dataframenaam daatis en de kolomnaam YEARMONTH:

daat.YEARMONTH.value_counts()

Antwoord 3, Autoriteit 10%

Interessant genoeg, heel vaak len(unique())is een paar keer (3x-15x) sneller dan nunique().


Antwoord 4, Autoriteit 2%

Ik gebruik ook nunique, maar het zal zeer nuttig zijn als u een geaggregeerde functie wilt gebruiken zoals 'min', 'max', 'count' or 'mean'enz.

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

Antwoord 5

Gebruik crosstab, dit retourneert meer informatie dan groupbynunique:

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

Na een klein beetje wijziging levert het het resultaat op:

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

Antwoord 6

Deselecteerd van kolom samen met aggregaties op andere kolommen

Om het verschillende aantal waarden voor elke kolom (CLIENTCODEin uw geval) te krijgen, kunnen we nuniquegebruiken. We kunnen de invoer doorgeven als woordenboek in agg-functie, samen met aggregaties op andere kolommen:

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)

Antwoord 7

Met de nieuwe Pandas-versie is het gemakkelijk om een dataframe te krijgen:

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

Antwoord 8

Hier is een benadering om het aantal verschillende kolommen te onderscheiden. Laten we wat gegevens hebben:

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

Maak nu een lijst van de kolommen van interesse en gebruik groupby in een licht gewijzigde syntaxis:

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

We verkrijgen:

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

Antwoord 9

Je kunt nu ook de dplyr-syntaxis in Python gebruiken om dit te doen:

>>> from datar.all import f, tibble, group_by, summarise, n_distinct
>>>
>>> data = tibble(
...     CLIENT_CODE=[1,1,2,1,2,2,3],
...     YEAR_MONTH=[201301,201301,201301,201302,201302,201302,201302]
... )
>>>
>>> data >> group_by(f.YEAR_MONTH) >> summarise(n=n_distinct(f.CLIENT_CODE))
   YEAR_MONTH       n
      <int64> <int64>
0      201301       2
1      201302       3

Antwoord 10

Maak een draaitabel en gebruik de functie nuniqueseries:

ID = [ 123, 123, 123, 456, 456, 456, 456, 789, 789]
domain = ['vk.com', 'vk.com', 'twitter.com', 'vk.com', 'facebook.com',
          'vk.com', 'google.com', 'twitter.com', 'vk.com']
df = pd.DataFrame({'id':ID, 'domain':domain})
fp = pd.pivot_table(data=df, index='domain', aggfunc=pd.Series.nunique)
print(fp)

Uitvoer:

              id
domain
facebook.com   1
google.com     1
twitter.com    2
vk.com         3

Other episodes