問題描述:我需要在每個有數據的domain
中計算唯一的ID
值
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'
我嘗試過df.groupby(['domain', 'ID']).count()
,但輸出不符合預期。我真正想獲得的是:
domain, count
vk.com 3
twitter.com 2
facebook.com 1
google.com 1
即每個domain分組中不同的“ID”數量。
方法一:
您需要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
如果需要strip
'
字符:
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
或者:
df.groupby(df.domain.str.strip("'"))['ID'].nunique()
您還可以像這樣保留列名:
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
區別在於nunique()
返回一個Series,agg()
返回一個DataFrame。
方法二
通常,要在單列中計算不同的值,可以使用Series.value_counts
:
df.domain.value_counts()
#'vk.com' 5
#'twitter.com' 2
#'facebook.com' 1
#'google.com' 1
#Name: domain, dtype: int64
要查看一列中有多少個唯一值,請使用Series.nunique
:
df.domain.nunique()
# 4
要獲取所有這些不同的值,可以使用unique
或drop_duplicates
,這兩個函數之間的細微差別是unique
返回numpy.array
,而drop_duplicates
返回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
對於本文最前麵提到的這個特定的問題,由於您想針對另一個變量計算不同的值,除了這裏其他答案提供的groupby
方法之外,您還可以先簡單地刪除重複項,然後再執行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
不同方法的性能對比
對於第二種方法,也可以嘗試以下操作:
output = df.drop_duplicates()
output.groupby('domain').size()
輸出:
domain
facebook.com 1
google.com 1
twitter.com 2
vk.com 3
dtype: int64
從性能來看,也可以使用效率稍低的value_counts
,但是最好的方法是使用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
參考資料