我使用 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
我怎样才能在熊猫中做到这一点?
value_counts
可能是您正在寻找的答案:pandas.pydata.org/pandas-docs/stable/generated/…
我相信这就是你想要的:
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
这是另一种方法,它更简单。假设您的数据框名称为 daat
,列名称为 YEARMONTH
:
daat.YEARMONTH.value_counts()
DISTINCT
要求!此外,它不包括 NaN
的计数!
有趣的是,len(unique())
通常比 nunique()
快几倍 (3x-15x)。
.CLIENTCODE.apply(lambda x: len(x.unique()))
,来自 here
apply
调用中。例如,df.groupby('YEARMONTH')['CLIENTCODE'].apply(lambda x: x.unique().shape[0])
。
len(df['column'].unique())
不需要 lambda 函数
Chen's
评论中得到了 TypeError: object of type 'method' has no len()
,3novak's
为我工作。
我也在使用 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
列的不同以及其他列上的聚合
要获取任何列的不同数量的值(在您的情况下为 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)
grp_df = df.groupby('YEARMONTH').agg(CLIENTCODE_UNIQ_CNT = ('CLIENTCODE', 'nunique'), other_col_1_sum = ('other_col_1', 'sum'), other_col_1_cnt = ('other_col_1', 'count'))
使用 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
YEARMONTH
和 count
。我也可以按降序设置计数吗?
这是一种在多列上计数不同的方法。让我们有一些数据:
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
使用新的 Pandas 版本,很容易得到一个数据框:
unique_count = pd.groupby(['YEARMONTH'], as_index=False).agg(uniq_CLIENTCODE=('CLIENTCODE', pd.Series.count))
创建一个数据透视表并使用 nunique series 函数:
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
现在您还可以在 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