熊猫“count(distinct)”等效
- 2025-01-17 09:23:00
- admin 原创
- 73
问题描述:
我使用 Pandas 作为数据库替代品,因为我有多个数据库(Oracle、SQL Server等),并且无法创建与 SQL 等效的命令序列。
我在 DataFrame 中加载了一张表,其中包含一些列:
YEARMONTH, CLIENTCODE, SIZE, etc., etc.
在 SQL 中,计算每年不同客户的数量如下:
SELECT count(distinct CLIENTCODE) FROM table GROUP BY YEARMONTH;
结果是
201301 5000
201302 13245
我怎样才能在 Pandas 中做到这一点?
解决方案 1:
我相信这就是你想要的:
table.groupby('YEARMONTH').CLIENTCODE.nunique()
例子:
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:
这是另一种方法,它更简单。假设您的数据框名称为daat
,列名称为YEARMONTH
:
daat.YEARMONTH.value_counts()
解决方案 3:
有趣的是,通常len(unique())
比快几倍(3 倍至 15 倍)nunique()
。
解决方案 4:
我也正在使用,但如果您必须使用诸如等nunique
聚合函数,它将非常有帮助。'min', 'max', 'count' or 'mean'
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
解决方案 5:
列的不同以及其他列上的聚合
为了获取任何列(在您的情况下)的不同数量的值CLIENTCODE
,我们可以使用nunique
。我们可以将输入作为agg
函数中的字典传递,以及其他列上的聚合:
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)
解决方案 6:
使用crosstab
,这将返回比 更多的信息groupby
nunique
:
pd.crosstab(df.YEARMONTH,df.CLIENTCODE)
Out[196]:
CLIENTCODE 1 2 3
YEARMONTH
201301 2 1 0
201302 1 2 1
经过一些修改后,得到以下结果:
pd.crosstab(df.YEARMONTH,df.CLIENTCODE).ne(0).sum(1)
Out[197]:
YEARMONTH
201301 2
201302 3
dtype: int64
解决方案 7:
以下是对多个列进行计数的方法。我们来看看一些数据:
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
现在,列出感兴趣的列并使用稍微修改过的语法进行 groupby:
columns = ['YEAR_MONTH', 'PRODUCT_CODE']
table[columns].groupby(table['CLIENT_CODE']).nunique()
我们得到:
YEAR_MONTH PRODUCT_CODE CLIENT_CODE
1 2 3
2 2 3
3 1 1
解决方案 8:
使用新版本的 Pandas,可以轻松获取数据框:
unique_count = pd.groupby(['YEARMONTH'], as_index=False).agg(uniq_CLIENTCODE=('CLIENTCODE', pd.Series.count))
解决方案 9:
创建数据透视表并使用nunique系列函数:
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)
输出:
id
domain
facebook.com 1
google.com 1
twitter.com 2
vk.com 3
解决方案 10:
现在您也可以使用Python 中的dplyr语法来执行此操作:
>>> 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
解决方案 11:
要获取每年不同客户的数量和规模(即多列的唯一值的数量),请使用以下列表:
df.groupby('YEARMONTH')[['CLIENTCODE', 'SIZE']].nunique()
df
实际上,可以使用SQL 语法pandasql
(基于 pandas 构建的模块,可让您使用 SQL 语法查询 pandas DataFrames)
获得上述代码的结果。
#! pip install pandasql
from pandasql import sqldf
sqldf("""
SELECT COUNT(DISTINCT CLIENTCODE),
COUNT(DISTINCT SIZE)
FROM df
GROUP BY YEARMONTH
""")
如果要将 YEARMONTH 保留为一列,即以下 SQL 查询的模拟
SELECT YEARMONTH,
COUNT(DISTINCT CLIENTCODE),
COUNT(DISTINCT SIZE)
FROM df
GROUP BY YEARMONTH
在 pandas 中如下(设置as_index
为False
):
df.groupby('YEARMONTH', as_index=False)[['CLIENTCODE', 'SIZE']].nunique()
如果需要给聚合列设置自定义名称,即模拟以下SQL查询:
SELECT YEARMONTH,
COUNT(DISTINCT CLIENTCODE) AS `No. clients`,
COUNT(DISTINCT SIZE) AS `No. size`
FROM df
GROUP BY YEARMONTH
在 Pandas 中使用命名聚合:
(
df.groupby('YEARMONTH', as_index=False)
.agg(**{'No. clients':('CLIENTCODE', 'nunique'),
'No. size':('SIZE', 'nunique')})
)
解决方案 12:
要计算多列的不同值,请len()
使用DataFrameGroupBy
。
例如,计算不同的值(a, b)
:
len(df.groupby(["a", "b"]))
等效 SQL:
SELECT count(distinct (a, b))
FROM df
这可以在组内通过使用groupby 方法完成.apply
。
例如,计算(a, b)
组内的不同值g
:
data.groupby("g").apply(lambda df: len(df.groupby(["a", "b"]))
等效 SQL:
SELECT count(distinct (a, b))
FROM df
GROUP BY g
.apply
是需要的,因为.agg
并且只允许您按列.transform
应用聚合或转换。