计算各类别产品销售额的三种占比

CDA老师1

Python
# 计算各类别产品销售额的三种占比 ```                                                 ----------- 每篇一个pandas小技巧之三,分组数据计算各种占比 ``` ## 需求背景 **公司销售多种品牌的多种产品,现需要计算每个品牌下每种产品销售额的组内占比,组内累计占比和每组销售额占总销售的比例。以下列数据为例,简单解释这三种需求** ``` df ``` ``` .dataframe tbody tr th {   vertical-align: top; } .dataframe thead th {   text-align: right; } ``` **** | | 销售日期 | 品牌 | 类别 | 款号 | 销量 | | ---- | ------------ | ------ | -------- | ------ | ------ | | 0 | 2021-01-01 | A | T恤 | 1001 | 63 | | 1 | 2021-01-02 | A | T恤 | 1002 | 21 | | 2 | 2021-01-03 | A | T恤 | 1003 | 88 | | 3 | 2021-01-04 | B | T恤 | 1004 | 88 | | 4 | 2021-01-05 | B | T恤 | 1005 | 17 | | 5 | 2021-01-06 | B | T恤 | 1006 | 98 | | 6 | 2021-01-07 | A | T恤 | 1007 | 100 | | 7 | 2021-01-08 | A | T恤 | 1008 | 95 | | 8 | 2021-01-09 | B | T恤 | 1009 | 63 | | 9 | 2021-01-10 | B | T恤 | 1010 | 86 | | 10 | 2021-01-11 | A | 裤子 | 1011 | 77 | | 11 | 2021-01-12 | A | 裤子 | 1012 | 81 | | 12 | 2021-01-13 | A | 连衣裙 | 1013 | 51 | | 13 | 2021-01-14 | A | 连衣裙 | 1014 | 93 | | 14 | 2021-01-15 | A | 裤子 | 1015 | 96 | | 15 | 2021-01-16 | A | 裤子 | 1016 | 39 | | 16 | 2021-01-17 | A | 连衣裙 | 1017 | 48 | | 17 | 2021-01-18 | A | 连衣裙 | 1018 | 98 | | 18 | 2021-01-19 | A | 连衣裙 | 1019 | 57 | | 19 | 2021-01-20 | B | 连衣裙 | 1020 | 12 | | 20 | 2021-01-21 | B | 连衣裙 | 1021 | 82 | | 21 | 2021-01-22 | B | 毛衣 | 1022 | 36 | | 22 | 2021-01-23 | B | 毛衣 | 1023 | 66 | | 23 | 2021-01-24 | B | 毛衣 | 1024 | 97 | | 24 | 2021-01-25 | B | 连衣裙 | 1025 | 72 | | 25 | 2021-01-26 | B | 连衣裙 | 1026 | 53 | | 26 | 2021-01-27 | B | 毛衣 | 1027 | 100 | | 27 | 2021-01-28 | B | 毛衣 | 1028 | 10 | **
** **从上述数据可以看出,该表记录的是每个品牌下每种产品在某日期的销售情况,以品牌A中的连衣裙为例:** 1. **计算每一天连衣裙的销售额占连衣裙总销售额的占比** 2. **计算每一天连衣裙的销售额占连衣裙总销售额的累计占比** 3. **计算品牌A连衣裙的总销售额在所有产品总销售额中的占比** **最终的表中,数据行数不变,每一条销售记录后边都添加上该条记录销售额的组内占比、组内累计占比和该品类销售额占所有产品销售额的比例。** **首先,把原表中的数据按照品牌、类别和销量进行排序,其中品牌和类别是升序排序,销量降序排序。** **不对销量排序也可以,这里为了效果明显,销量也进行了排序。** ``` df1 = df.sort_values(["品牌","类别","销量"],ascending=[True,True,False]) #对原表按照品牌、类别、销量进行排序,其中品牌和类别升序排序,销量降序排序 ``` ## 组内累计占比 **计算组内累计占比,首先按照品牌和类别进行分组,然后计算销量的累计和,用累计和除以分组后销量的总和即可。** **计算过程中用到transform,前一篇文章里有介绍过transform的用法,这里不再赘述。** ``` ss = df1.groupby(["品牌","类别"])["销量"].transform("cumsum")/df1.groupby(["品牌","类别"])["销量"].transform("sum") # 按照品牌和类别分组,对分组后的数据按照分组求累计和,再对分组后的数据按照分组求和,两者相除得到组内累计占比,生成一个series ``` ``` ss ``` ``` 6     0.272480 7     0.531335 2     0.771117 0     0.942779 1     1.000000 14   0.327645 11   0.604096 10   0.866894 15   1.000000 17   0.282421 13   0.550432 18   0.714697 12   0.861671 16   1.000000 5     0.278409 3     0.528409 9     0.772727 8     0.951705 4     1.000000 26   0.323625 23   0.637540 22   0.851133 21   0.967638 27   1.000000 20   0.374429 24   0.703196 25   0.945205 19   1.000000 Name: 销量, dtype: float64 ``` **计算的累计占比是series数据结构,其中的元素值都是浮点数,可以把浮点数转化成百分数。** **注意在python中,数值型的数据中没有百分数这种数据类型,所以想要以百分数的形式展现,只能把浮点数转化成字符串,运用字符串的格式化方法。** **具体代码和代码效果如下:** ``` df1['类别累计占比'] = ss.apply(lambda x : format(x,'.2%')) # 得到的累计占比是浮点数形式,修改成百分比形式 ``` ``` df1 ``` ``` .dataframe tbody tr th {   vertical-align: top; } .dataframe thead th {   text-align: right; } ``` **** | | 销售日期 | 品牌 | 类别 | 款号 | 销量 | 类别累计占比 | | ---- | ------------ | ------ | -------- | ------ | ------ | -------------- | | 6 | 2021-01-07 | A | T恤 | 1007 | 100 | 27.25% | | 7 | 2021-01-08 | A | T恤 | 1008 | 95 | 53.13% | | 2 | 2021-01-03 | A | T恤 | 1003 | 88 | 77.11% | | 0 | 2021-01-01 | A | T恤 | 1001 | 63 | 94.28% | | 1 | 2021-01-02 | A | T恤 | 1002 | 21 | 100.00% | | 14 | 2021-01-15 | A | 裤子 | 1015 | 96 | 32.76% | | 11 | 2021-01-12 | A | 裤子 | 1012 | 81 | 60.41% | | 10 | 2021-01-11 | A | 裤子 | 1011 | 77 | 86.69% | | 15 | 2021-01-16 | A | 裤子 | 1016 | 39 | 100.00% | | 17 | 2021-01-18 | A | 连衣裙 | 1018 | 98 | 28.24% | | 13 | 2021-01-14 | A | 连衣裙 | 1014 | 93 | 55.04% | | 18 | 2021-01-19 | A | 连衣裙 | 1019 | 57 | 71.47% | | 12 | 2021-01-13 | A | 连衣裙 | 1013 | 51 | 86.17% | | 16 | 2021-01-17 | A | 连衣裙 | 1017 | 48 | 100.00% | | 5 | 2021-01-06 | B | T恤 | 1006 | 98 | 27.84% | | 3 | 2021-01-04 | B | T恤 | 1004 | 88 | 52.84% | | 9 | 2021-01-10 | B | T恤 | 1010 | 86 | 77.27% | | 8 | 2021-01-09 | B | T恤 | 1009 | 63 | 95.17% | | 4 | 2021-01-05 | B | T恤 | 1005 | 17 | 100.00% | | 26 | 2021-01-27 | B | 毛衣 | 1027 | 100 | 32.36% | | 23 | 2021-01-24 | B | 毛衣 | 1024 | 97 | 63.75% | | 22 | 2021-01-23 | B | 毛衣 | 1023 | 66 | 85.11% | | 21 | 2021-01-22 | B | 毛衣 | 1022 | 36 | 96.76% | | 27 | 2021-01-28 | B | 毛衣 | 1028 | 10 | 100.00% | | 20 | 2021-01-21 | B | 连衣裙 | 1021 | 82 | 37.44% | | 24 | 2021-01-25 | B | 连衣裙 | 1025 | 72 | 70.32% | | 25 | 2021-01-26 | B | 连衣裙 | 1026 | 53 | 94.52% | | 19 | 2021-01-20 | B | 连衣裙 | 1020 | 12 | 100.00% | **
** **能看到,在dataframe的最后多了一类累计占比。** **前一篇的文章中我们已经讨论过组内占比的计算方法,这里我们可以再计算一遍,用来验证累计占比的结果是否正确** ## 组内占比 **组内占比计算方法前一篇文章已经讨论过,这里不再赘述,具体代码如下:** ``` df1["类别组内占比"] = (df1["销量"]/df1.groupby(["品牌","类别"])["销量"].transform("sum")).apply(lambda x : format(x,'.2%')) ``` ``` df1 ``` ``` .dataframe tbody tr th {   vertical-align: top; } .dataframe thead th {   text-align: right; } ``` **** | | 销售日期 | 品牌 | 类别 | 款号 | 销量 | 类别累计占比 | 类别组内占比 | | ---- | ------------ | ------ | -------- | ------ | ------ | -------------- | -------------- | | 6 | 2021-01-07 | A | T恤 | 1007 | 100 | 27.25% | 27.25% | | 7 | 2021-01-08 | A | T恤 | 1008 | 95 | 53.13% | 25.89% | | 2 | 2021-01-03 | A | T恤 | 1003 | 88 | 77.11% | 23.98% | | 0 | 2021-01-01 | A | T恤 | 1001 | 63 | 94.28% | 17.17% | | 1 | 2021-01-02 | A | T恤 | 1002 | 21 | 100.00% | 5.72% | | 14 | 2021-01-15 | A | 裤子 | 1015 | 96 | 32.76% | 32.76% | | 11 | 2021-01-12 | A | 裤子 | 1012 | 81 | 60.41% | 27.65% | | 10 | 2021-01-11 | A | 裤子 | 1011 | 77 | 86.69% | 26.28% | | 15 | 2021-01-16 | A | 裤子 | 1016 | 39 | 100.00% | 13.31% | | 17 | 2021-01-18 | A | 连衣裙 | 1018 | 98 | 28.24% | 28.24% | | 13 | 2021-01-14 | A | 连衣裙 | 1014 | 93 | 55.04% | 26.80% | | 18 | 2021-01-19 | A | 连衣裙 | 1019 | 57 | 71.47% | 16.43% | | 12 | 2021-01-13 | A | 连衣裙 | 1013 | 51 | 86.17% | 14.70% | | 16 | 2021-01-17 | A | 连衣裙 | 1017 | 48 | 100.00% | 13.83% | | 5 | 2021-01-06 | B | T恤 | 1006 | 98 | 27.84% | 27.84% | | 3 | 2021-01-04 | B | T恤 | 1004 | 88 | 52.84% | 25.00% | | 9 | 2021-01-10 | B | T恤 | 1010 | 86 | 77.27% | 24.43% | | 8 | 2021-01-09 | B | T恤 | 1009 | 63 | 95.17% | 17.90% | | 4 | 2021-01-05 | B | T恤 | 1005 | 17 | 100.00% | 4.83% | | 26 | 2021-01-27 | B | 毛衣 | 1027 | 100 | 32.36% | 32.36% | | 23 | 2021-01-24 | B | 毛衣 | 1024 | 97 | 63.75% | 31.39% | | 22 | 2021-01-23 | B | 毛衣 | 1023 | 66 | 85.11% | 21.36% | | 21 | 2021-01-22 | B | 毛衣 | 1022 | 36 | 96.76% | 11.65% | | 27 | 2021-01-28 | B | 毛衣 | 1028 | 10 | 100.00% | 3.24% | | 20 | 2021-01-21 | B | 连衣裙 | 1021 | 82 | 37.44% | 37.44% | | 24 | 2021-01-25 | B | 连衣裙 | 1025 | 72 | 70.32% | 32.88% | | 25 | 2021-01-26 | B | 连衣裙 | 1026 | 53 | 94.52% | 24.20% | | 19 | 2021-01-20 | B | 连衣裙 | 1020 | 12 | 100.00% | 5.48% | **
** **把组内占比的数据添加到累计占比后,很明显能够看出,我们累计占比的计算结果是正确的。** ## 计算每个分组的销量占总销量的比例 **计算每个分组的销售额占所有产品销售额的方法并不难,数据分组后求和,然后和所有产品销售额相除即可。** **但是在当前问题中,我们希望让每一条销售记录后边都添加上该类产品销售额在总销售额中的占比,这里用到的也是transform。** **这也是transform和apply两个方法之间的一个区别,要实现上述效果,apply做不到,因为apply输出汇总后的数据,两者的具体区别见如下代码:** ``` df1.groupby(["品牌","类别"])["销量"].transform("sum")/df1["销量"].sum() ``` ``` 6     0.194489 7     0.194489 2     0.194489 0     0.194489 1     0.194489 14   0.155273 11   0.155273 10   0.155273 15   0.155273 17   0.183890 13   0.183890 18   0.183890 12   0.183890 16   0.183890 5     0.186539 3     0.186539 9     0.186539 8     0.186539 4     0.186539 26   0.163752 23   0.163752 22   0.163752 21   0.163752 27   0.163752 20   0.116057 24   0.116057 25   0.116057 19   0.116057 Name: 销量, dtype: float64 ``` ``` df1.groupby(["品牌","类别"])["销量"].apply(sum)/df1["销量"].sum() ``` ``` 品牌 类别 A   T恤     0.194489   裤子     0.155273   连衣裙   0.183890 B   T恤     0.186539   毛衣     0.163752   连衣裙   0.116057 Name: 销量, dtype: float64 ``` **apply也可以计算每个分组的销售额占总销售的比值,但是最终得到得的结果和原表中的数据量不匹配,无法添加到原表中,所以这里需要用transform方法,具体的代码如下:** ``` (df1.groupby(["品牌","类别"])["销量"].transform("sum")/df1["销量"].sum()).apply(lambda x : format(x,'.2%')) ``` ``` 6     19.45% 7     19.45% 2     19.45% 0     19.45% 1     19.45% 14   15.53% 11   15.53% 10   15.53% 15   15.53% 17   18.39% 13   18.39% 18   18.39% 12   18.39% 16   18.39% 5     18.65% 3     18.65% 9     18.65% 8     18.65% 4     18.65% 26   16.38% 23   16.38% 22   16.38% 21   16.38% 27   16.38% 20   11.61% 24   11.61% 25   11.61% 19   11.61% Name: 销量, dtype: object ``` ``` df1["本组销量占比"] = (df1.groupby(["品牌","类别"])["销量"].transform("sum")/df1["销量"].sum()).apply(lambda x : format(x,'.2%')) ``` ``` df1 ``` ``` .dataframe tbody tr th {   vertical-align: top; } .dataframe thead th {   text-align: right; } ``` **** | | 销售日期 | 品牌 | 类别 | 款号 | 销量 | 类别累计占比 | 类别组内占比 | 本组销量占比 | | ---- | ------------ | ------ | -------- | ------ | ------ | -------------- | -------------- | -------------- | | 6 | 2021-01-07 | A | T恤 | 1007 | 100 | 27.25% | 27.25% | 19.45% | | 7 | 2021-01-08 | A | T恤 | 1008 | 95 | 53.13% | 25.89% | 19.45% | | 2 | 2021-01-03 | A | T恤 | 1003 | 88 | 77.11% | 23.98% | 19.45% | | 0 | 2021-01-01 | A | T恤 | 1001 | 63 | 94.28% | 17.17% | 19.45% | | 1 | 2021-01-02 | A | T恤 | 1002 | 21 | 100.00% | 5.72% | 19.45% | | 14 | 2021-01-15 | A | 裤子 | 1015 | 96 | 32.76% | 32.76% | 15.53% | | 11 | 2021-01-12 | A | 裤子 | 1012 | 81 | 60.41% | 27.65% | 15.53% | | 10 | 2021-01-11 | A | 裤子 | 1011 | 77 | 86.69% | 26.28% | 15.53% | | 15 | 2021-01-16 | A | 裤子 | 1016 | 39 | 100.00% | 13.31% | 15.53% | | 17 | 2021-01-18 | A | 连衣裙 | 1018 | 98 | 28.24% | 28.24% | 18.39% | | 13 | 2021-01-14 | A | 连衣裙 | 1014 | 93 | 55.04% | 26.80% | 18.39% | | 18 | 2021-01-19 | A | 连衣裙 | 1019 | 57 | 71.47% | 16.43% | 18.39% | | 12 | 2021-01-13 | A | 连衣裙 | 1013 | 51 | 86.17% | 14.70% | 18.39% | | 16 | 2021-01-17 | A | 连衣裙 | 1017 | 48 | 100.00% | 13.83% | 18.39% | | 5 | 2021-01-06 | B | T恤 | 1006 | 98 | 27.84% | 27.84% | 18.65% | | 3 | 2021-01-04 | B | T恤 | 1004 | 88 | 52.84% | 25.00% | 18.65% | | 9 | 2021-01-10 | B | T恤 | 1010 | 86 | 77.27% | 24.43% | 18.65% | | 8 | 2021-01-09 | B | T恤 | 1009 | 63 | 95.17% | 17.90% | 18.65% | | 4 | 2021-01-05 | B | T恤 | 1005 | 17 | 100.00% | 4.83% | 18.65% | | 26 | 2021-01-27 | B | 毛衣 | 1027 | 100 | 32.36% | 32.36% | 16.38% | | 23 | 2021-01-24 | B | 毛衣 | 1024 | 97 | 63.75% | 31.39% | 16.38% | | 22 | 2021-01-23 | B | 毛衣 | 1023 | 66 | 85.11% | 21.36% | 16.38% | | 21 | 2021-01-22 | B | 毛衣 | 1022 | 36 | 96.76% | 11.65% | 16.38% | | 27 | 2021-01-28 | B | 毛衣 | 1028 | 10 | 100.00% | 3.24% | 16.38% | | 20 | 2021-01-21 | B | 连衣裙 | 1021 | 82 | 37.44% | 37.44% | 11.61% | | 24 | 2021-01-25 | B | 连衣裙 | 1025 | 72 | 70.32% | 32.88% | 11.61% | | 25 | 2021-01-26 | B | 连衣裙 | 1026 | 53 | 94.52% | 24.20% | 11.61% | | 19 | 2021-01-20 | B | 连衣裙 | 1020 | 12 | 100.00% | 5.48% | 11.61% | **** **从最终的结果表中,能够清楚的展现出每一笔销售额在组内的占比、累计占比以及本组销售额占总销售额的比例。** **以上代码都不复杂,有不理解的地方或者不同意见欢迎留言讨论哦,**
0.0320 6 0 关注作者 收藏 2022-12-20   阅读量: 417

评论(0)


暂无数据

热门用户

博客推荐