我有一个超大的客户数据框,项目类别和价格。我想做一些初步调查:
这需要转动和排序。这是一个样本数据生成器,感谢here。
import numpy as np
import pandas as pd
from numpy.core.defchararray import add
np.random.seed(42)
n = 20
cols = np.array(['cust', 'cat'])
arr1 = (np.random.randint(5, size=(n, 2)) // [2, 1]).astype(str)
df = pd.DataFrame(
add(cols, arr1), columns=cols
).join(
pd.DataFrame(np.random.rand(n, 1).round(2)).add_prefix('val')
)
print(df)
df.pivot_table(index=['cust'],values=['val0'],aggfunc=[np.sum])
df.pivot_table(index=['cust','cat'],values=['val0'],aggfunc=[np.size,np.sum])
# the order according the previous line should be cust1,cust0,cust2. How to do? The following is the desired output in this case.
size sum
val0 val0
cust cat
cust1 cat4 6.0 4.27
cat3 2.0 1.07
cat2 2.0 0.98
cat0 2.0 0.44
cat1 2.0 0.43
cust0 cat1 1.0 0.94
cat4 1.0 0.91
cat2 1.0 0.66
cat3 1.0 0.03
cust2 cat1 2.0 1.25
非常感谢你!
这里有更好的聚合sum
,以避免列中的MultiIndex
。
第一次聚合sum
:
s = df.groupby('cust')['val0'].sum()
print (s)
cust
cust0 2.54
cust1 7.19
cust2 1.25
Name: val0, dtype: float64
然后通过Series.nlargest
得到最高值:
top5 = s.nlargest(5)
print (top5)
cust
cust1 7.19
cust0 2.54
cust2 1.25
Name: val0, dtype: float64
如有必要,可以通过boolean indexing
和isin
过滤top5值:
df1 = df[df['cust'].isin(top5.index)].copy()
#print(df1)
为了正确排序cust
创建有序分类并通过两个过滤列聚合,最后排序第一级cust
和列size
:
df1['cust'] = pd.Categorical(df1['cust'], ordered=True, categories=top5.index)
df2 = (df1.groupby(['cust','cat'])['val0'].agg([np.size,np.sum])
.sort_values(['cust','size'], ascending=[True, False])
.reset_index())
print (df2)
cust cat size sum
0 cust1 cat4 6.0 4.27
1 cust1 cat0 2.0 0.44
2 cust1 cat1 2.0 0.43
3 cust1 cat2 2.0 0.98
4 cust1 cat3 2.0 1.07
5 cust0 cat1 1.0 0.94
6 cust0 cat2 1.0 0.66
7 cust0 cat3 1.0 0.03
8 cust0 cat4 1.0 0.91
9 cust2 cat1 2.0 1.25
DataFrame.plot.bar
的最后一个支点和情节:
df2.pivot('cust','cat','size').plot.bar()
不确定我是否理解您想要的确切概述,但这也可以通过使用groupby
然后使用agg
方法,如下所示:
overview = df.groupby('cust').agg({'val0':'sum',
'cat':'max'}).reset_index().sort_values('val0', ascending=False)
cust val0 cat
1 cust1 7.19 cat4
0 cust0 2.54 cat4
2 cust2 1.25 cat1
因此,这会聚合在客户层面并汇总其总支出,并显示他们花费最多的类别。
您不必使用reset_index()
函数,在这种情况下,它会产生以下结果:
overview = df.groupby('cust').agg({'val0':'sum',
'cat':'max'}).sort_values('val0', ascending=False)
val0 cat
cust
cust1 7.19 cat4
cust0 2.54 cat4
cust2 1.25 cat1
最后,如果您想要前5位客户,您可以简单地使用.head(5)
,因为值已经按降序排序:
overview = df.groupby('cust').agg({'val0':'sum',
'cat':'max'}).sort_values('val0', ascending=False).head(5)