Tel unieke waarden per groep met Panda’s

Ik moet unieke ID-waarden tellen in elk domain.

Ik heb gegevens:

ID, domain
123, 'vk.com'
123, 'vk.com'
123, 'twitter.com'
456, 'vk.com'
456, 'facebook.com'
456, 'vk.com'
456, 'google.com'
789, 'twitter.com'
789, 'vk.com'

Ik probeer df.groupby(['domain', 'ID']).count()

Maar ik wil

domain, count
vk.com   3
twitter.com   2
facebook.com   1
google.com   1

Antwoord 1, autoriteit 100%

Je hebt nunique:

df = df.groupby('domain')['ID'].nunique()
print (df)
domain
'facebook.com'    1
'google.com'      1
'twitter.com'     2
'vk.com'          3
Name: ID, dtype: int64

Als je moet strip'tekens:

df = df.ID.groupby([df.domain.str.strip("'")]).nunique()
print (df)
domain
facebook.com    1
google.com      1
twitter.com     2
vk.com          3
Name: ID, dtype: int64

Of zoals Jon Clementsopmerkte:

df.groupby(df.domain.str.strip("'"))['ID'].nunique()

U kunt de kolomnaam als volgt behouden:

df = df.groupby(by='domain', as_index=False).agg({'ID': pd.Series.nunique})
print(df)
    domain  ID
0       fb   1
1      ggl   1
2  twitter   2
3       vk   3

Het verschil is dat nunique()retourneert een reeks en agg()retourneert een dataframe.


Antwoord 2, Autoriteit 83%

Over het algemeen om verschillende waarden in een enkele kolom te tellen, kunt u Series.value_counts:

df.domain.value_counts()
#'vk.com'          5
#'twitter.com'     2
#'facebook.com'    1
#'google.com'      1
#Name: domain, dtype: int64

Om te zien hoeveel unieke waarden in een kolom, gebruikt u Series.nunique:

df.domain.nunique()
# 4

Om al deze verschillende waarden te krijgen, kunt u gebruiken uniqueof drop_duplicates, het kleine verschil tussen de twee functies is dat uniqueretourneer een numpy.arrayterwijl drop_duplicatesretourneert een pandas.Series:

df.domain.unique()
# array(["'vk.com'", "'twitter.com'", "'facebook.com'", "'google.com'"], dtype=object)
df.domain.drop_duplicates()
#0          'vk.com'
#2     'twitter.com'
#4    'facebook.com'
#6      'google.com'
#Name: domain, dtype: object

Wat dit specifieke probleem betreft, aangezien u de onderscheidende waarde wilt tellen met betrekking tot een andere variabele, kunt u naast de groupby-methode die door andere antwoorden hier wordt geboden, ook eerst duplicaten laten vallen en vervolgens doen value_counts():

import pandas as pd
df.drop_duplicates().domain.value_counts()
# 'vk.com'          3
# 'twitter.com'     2
# 'facebook.com'    1
# 'google.com'      1
# Name: domain, dtype: int64

Antwoord 3, autoriteit 17%

df.domain.value_counts()

>>> df.domain.value_counts()
vk.com          5
twitter.com     2
google.com      1
facebook.com    1
Name: domain, dtype: int64

Antwoord 4, autoriteit 4%

Als ik het goed begrijp, wil je het aantal verschillende ID‘s voor elk domain. Dan kun je dit proberen:

output = df.drop_duplicates()
output.groupby('domain').size()

Uitvoer:

   domain
facebook.com    1
google.com      1
twitter.com     2
vk.com          3
dtype: int64

U kunt ook value_countsgebruiken, wat iets minder efficiënt is. Maar het beste is Jezraëls antwoordmet behulp van nunique:

%timeit df.drop_duplicates().groupby('domain').size()
1000 loops, best of 3: 939 µs per loop
%timeit df.drop_duplicates().domain.value_counts()
1000 loops, best of 3: 1.1 ms per loop
%timeit df.groupby('domain')['ID'].nunique()
1000 loops, best of 3: 440 µs per loop

Other episodes