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 daat
is 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 groupby
nunique
:
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 (CLIENTCODE
in uw geval) te krijgen, kunnen we nunique
gebruiken. 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