本文目录:

数据准备

MySQL 计算累计百分比

1.不分组情况

2.分组情况

Hive SQL计算累计百分比

1.不分组情况

2.分组情况

pandas计算累计百分比

1.不分组情况

cumsum函数

expanding函数

rolling函数

2.分组情况

cumsum函数

expanding函数

rolling函数

小结

本篇文章一起来探讨如何在SQL和pandas中计算累计百分比。仍然分别在MySQL,Hive SQL和pandas中用多种方案来实现。

◆ ◆ ◆  ◆ ◆

数据准备

我们仍然使用前一篇的orderamt数据,数据导入方式可以参考之前的内容。需要分别在MySQL,Hive,pandas中进行数据导入,在此不作赘述。公众号后台回复“对比五”,可以获取本文全部代码和数据。数据的样例为:

我们的目标是,计算累计到当天的销售额占总销售额的比例。在实现时,首先分别计算出累计到当天的销售金额和总计的金额,然后就可以很方便的求出比例了。

MySQL计算累计百分比

1.不分组情况

最直观的思路是,对每一行的金额,都累加从第一行到当前行的金额。在MySQL中,可以考虑自连接的方式,但需要使用不等值连接。代码和结果如下:

select a.id, a.dt, a.orderamt,
sum(b.orderamt) as cum--对b表的金额进行求和
from t_orderamt a
join t_orderamt b
on a.dt >= b.dt--使用不等值连接
group by a.id, a.dt, a.orderamt

图中的cum列即是我们想要求的累加值。而所有销售金额的总计值,我们可以直接使用sum求出。

select sum(orderamt) as total
from t_orderamt

结合上面的两段SQL,就可以求得累计的百分比,注意连接条件我们使用了1=1这种恒成立的方式。代码和结果如下:

select c.id, c.orderamt, c.cum,
concat(round((c.cum / d.total) * 100, 2), '%') as cum_pct
from
(
select a.id, a.dt, a.orderamt, sum(b.orderamt) as cum
from t_orderamt a
join t_orderamt b
on a.dt >= b.dt
group by a.id, a.dt, a.orderamt
) c
left join
(
select sum(orderamt) as total
from t_orderamt
) d on 1 = 1

2.分组情况

需要思考:我们的原始数据是两个月的数据,目前我们的算法是把两个月的销售额累计到一起算的。但在实际中可能更多会关心每天的累计销售额分别占当月的百分比。如何能按照月份分组求每组的累计百分比呢?

首先仍然是求累计金额,但要分月累计。在上面的基础上加上月份相等条件即可,从结果中可以看到,在11月和12月cum列是分别累计的。

select substr(a.dt, 1, 7) as mon, a.dt, a.orderamt, sum(b.orderamt) as cum
from t_orderamt a
join t_orderamt b
on a.dt >= b.dt and
substr(a.dt, 1, 7) = substr(b.dt, 1, 7)--增加了这个条件
group by substr(a.dt, 1, 7), a.dt, a.orderamt

求每月总计金额的代码比较简单:

select substr(a.dt, 1, 7) as mon, sum(orderamt) as total
from t_orderamt a
group by substr(a.dt, 1, 7)

同样的,我们把两段代码进行合并,就得到每月的累计百分比情况:

select c.mon, c.dt, c.orderamt, c.cum, d.total,
concat(round((c.cum / d.total) * 100, 2), '%') as cum_pct
from
(
select substr(a.dt, 1, 7) as mon, a.dt, a.orderamt, sum(b.orderamt) as cum
from t_orderamt a
join t_orderamt b
on a.dt >= b.dt and substr(a.dt, 1, 7) = substr(b.dt, 1, 7)
group by substr(a.dt, 1, 7), a.dt, a.orderamt
) c
left join
(
select substr(a.dt, 1, 7) as mon, sum(orderamt) as total
from t_orderamt a
group by substr(a.dt, 1, 7)
) d on c.mon = d.mon

Hive 计算累计百分比

1.不分组情况

Hive SQL中我们可以沿用MySQL中的思路,但需要注意,Hive 不支持在on中写不等号的连接条件,虽然可以采用where的方式改造一下,代码如下所示。但这并不是最优的方案。我们可以使用Hive中的窗口函数,很方便的计算累计值。

--where方法
select a.id, a.dt, a.orderamt,
sum(b.orderamt) as cum--对b表的金额进行求和
from t_orderamt a
join t_orderamt b
on 1=1
where a.dt >= b.dt--使用不等值连接
group by a.id, a.dt, a.orderamt--窗口函数
select *, sum(orderamt) over(order by dt) as cum from t_orderamt;

两段代码的执行结果都如下图所示:

接下来我们重点看窗口函数的方式。在计算总计值的时候和前面MySQL的方式类似,累计百分比的计算也是需要把两部分代码结合在一起。

select c.id, c.dt, c.orderamt, c.cum,
concat(round((c.cum / d.total) * 100, 2), '%') as cum_pct
from
(
select *, sum(orderamt) over(order by dt) as cum
from t_orderamt
) c
left join
(
select sum(orderamt) as total
from t_orderamt
) d
on 1 = 1--在Hive中这个条件可以不写

2.分组情况

分组的情况,在窗口函数里是可以用partition by直接指定分组的,见如下代码

select id, substr(dt, 1, 7) as mon,
dt, orderamt,
sum(orderamt) over(partition by substr(dt, 1, 7) order by dt) as cum
from t_orderamt;

可以看到,同前面的分组情况一样,在11月和12月cum列是分别累计的。

接下来也很容易就写出分组计算累计百分比的代码,结果和上面也是一致的。

select c.mon, c.dt, c.orderamt, c.cum, d.total,
concat(round((c.cum / d.total) * 100, 2), '%') as cum_pct
from
(
select id, substr(dt, 1, 7) as mon, dt, orderamt, sum(orderamt) over(partition by substr(dt, 1, 7) order by dt) as cum
from t_orderamt
) c
left join
(
select substr(dt, 1, 7) as mon, sum(orderamt) as total
from t_orderamt
group by substr(dt, 1, 7)
) d on c.mon = d.mon

pandas计算累计百分比

在pandas中,提供了专门的函数来计算累计值,分别是cumsum函数,expanding函数,rolling函数。我们一起来看一下使用三种函数计算分组和不分组累计百分比的方法。

1.不分组情况

cumsum函数

cumsum是pandas中专门用于计算累计和的函数。类似的函数还有cumprod计算累计积,cummax计算前n个值的最大值,cummin计算前n个值的最小值。

import pandas as pd
orderamt = pd.read_excel('orderamt.xlsx')
orderamt['cum_amt'] = orderamt['amt'].cumsum()
orderamt.head(15)

直接对amt列使用cumsum函数即可计算累计值,结果和用SQL计算得到的一致。

计算累计的百分比也很容易。

orderamt['cum_amt_pct'] = orderamt['cum_amt'] / orderamt['amt'].sum()
orderamt.head(15)

关于结果如何显示成百分比的形式,可以参考上一篇文章,此处略 。

expanding函数

pandas中的expanding函数是窗口函数的一种,它不固定窗口的大小,而是进行累计的计算。类似于cumsum(),但更强大。

orderamt = pd.read_excel('orderamt.xlsx')
orderamt['mon'] = orderamt['dt'].dt.strftime('%Y-%m')#得到字符串形式的月份
orderamt['cum_expand'] = orderamt.expanding(min_periods=1)['amt'].sum()
orderamt.head(15)

参数min_periods表示最小的观测窗口,默认为1,可以设置为其他值,但如果窗口内记录数不足该值,则会显示NA。

有了累计值,计算累计的百分比,可以按照cumsum中的方法进行,此处省略。

rolling函数

rolling函数与expanding相比,主要是固定了窗口大小。当窗口超过dataframe的长度时,可以实现与expanding同样的效果。上面的代码使用rolling函数的方式可以改写如下,注意指定了window参数为len(orderamt):

orderamt = pd.read_excel('orderamt.xlsx')
orderamt['mon'] = orderamt['dt'].dt.strftime('%Y-%m')#得到字符串形式的月份
orderamt['cum_roll'] = orderamt.rolling(window=len(orderamt), min_periods=1)['amt'].sum()
orderamt.head(15)

此处同样省略计算累计百分比的代码。

2.分组情况

cumsum函数

#添加pandas显示设置,显示所有行
pd.set_option('display.max_rows', None)orderamt = pd.read_excel('orderamt.xlsx')
orderamt['mon'] = orderamt['dt'].dt.strftime('%Y-%m')#分组后对amt求累计和
orderamt['cum_mon'] = orderamt.groupby('mon')['amt'].cumsum()
orderamt

接下来计算分组的总计值,这里用到了pandas中的transform函数,可以把分组后计算的总计值写入原dataframe。如果你不是很理解,可以参考下面这篇文章,讲的很清楚。

https://www.jianshu.com/p/509d7b97088c

orderamt['mon_total'] = orderamt.groupby('mon')["amt"].transform('sum')
orderamt['grp_cum_pct'] = orderamt['cum_mon'] / orderamt['mon_total']
orderamt

结果和前面SQL计算的是一致的。此处同样省略了转换百分比格式的代码,可参考前一篇文章。

expanding函数

分组情况下使用expanding函数需要和groupby结合,注意得到的结果是多重索引,需要取values才能赋值给原dataframe。

orderamt = pd.read_excel('orderamt.xlsx')
orderamt['mon'] = orderamt['dt'].dt.strftime('%Y-%m')
orderamt_mon_group = orderamt.groupby('mon').expanding(min_periods=1)['amt'].sum()
#这里的orderamt_mon_group索引会有两重,我们直接取values的值就可以和原dataframe拼接在一起
orderamt['orderamt_mon_group'] = orderamt_mon_group.values
orderamt

接下来就可以用前面同样的方法,计算分组的总计值,然后求得分组累计百分比了。

rolling函数

通过上文我们知道,rolling函数与expanding函数的代码几乎一样,需要加上window参数。如下所示:

orderamt = pd.read_excel('orderamt.xlsx')
orderamt['mon'] = orderamt['dt'].dt.strftime('%Y-%m')
orderamt_mon_group_roll = orderamt.groupby('mon').rolling(len(orderamt),min_periods=1)['amt'].sum()
#这里的orderamt_mon_group_roll索引会有两重,我们直接取values的值就可以和原dataframe拼接在一起
orderamt['orderamt_mon_group_roll'] = orderamt_mon_group_roll.values
orderamt

结果和上面的是一致的。

至此,我们用多种方法实现了对于累计百分比的计算。

小结

本篇我们计算了分组和不分组情况的累计百分比。在MySQL中用了不等值连接的方法,在Hive SQL中使用了sum窗口函数。在pandas中学习了cumsum,expanding,rolling函数,最终都需要将累加值除以总计值得出累计百分比 。

使用SQL和Pandas计算累计百分比相关推荐

  1. pandas 计算累计和及累计占比

    累计和:cumsum() 总量累计:sum() 累计占比:selectgroup['CellMRCount'].cumsum()/selectgroup['CellMRCount'].sum()

  2. oracle统计比例,oracle实现累加,累计百分比计算

    这几天一直在搞报表,发现Oracle真的很强大,需要用到累加功能,发现强大的oracle还真有,用over(order by field)解决的 例子: 数据表中最后一列就是累加的效果 累加sql: ...

  3. oracle中怎么用累计,oracle实现累加,累计百分比计算

    最近做数据分析,需要用到累加功能,发现强大的oracle还真有,用over(order by field) 例子: 数据表中最后一列就是累加的效果 累加sql: select t.acc_pedal_ ...

  4. oracle实现累加,累计百分比计算

    最近做数据分析,需要用到累加功能,发现强大的oracle还真有,用over(order by field) 例子: 数据表中最后一列就是累加的效果 累加sql: select t.acc_pedal_ ...

  5. SQL如何进行帕累托分析?(窗口函数、累计百分比分类)

    帕累托分析法是指定决策的统计方法,包含按降序排序的列和表示累积总百分比的线条 [面试题]有一张"学生成绩表",包含3个字段:学号.课程.成绩. 问题:找出每门课程A类和B类的学生, ...

  6. 【SQL】窗口函数:求数据的整体百分比、整体累计值,组内累计值和组内累计百分比...

    〇.概述 1.所需资料 窗口函数实现组内百分比.累计值.累计百分比:https://blog.csdn.net/weixin_39751959/article/details/88828922 2.背 ...

  7. SQL语句中计算百分比

    SQL语句中计算百分比  A.TOTAL_COUNT TOTALCOUNT,    A..QUES_COUNT  QUESCOUNT,    CASE WHEN TOTAL_COUNT = QUES_ ...

  8. Tableau 快速表计算 显示百分比 / 累计走势

    文章目录 快速表计算 累计加和 ```汇总``` 显示百分比 ```合计百分比``` 快速表计算 (2019.4.8) 累计加和 汇总 快速表计算 >> 合计百分比 实际计算函数:RUNN ...

  9. 窗口函数:实现组内百分比、累计值、累计百分比

    0 前言 最近做数据分析,需要求每一组内的元素的百分比以及累计百分比,实在想不出怎么使用sql实现,就先将数据导出,然后使用excel计算.趁着夜深人静的时候,思维敏捷,尝试一下使用窗口函数实现一下, ...

最新文章

  1. Apache JMeter2.13 实战
  2. 赠书 | 在Python领域,你与专家之间的距离只差这两本书
  3. poi设置单元格格式为文本_身份证号乱码?日期显示不对?都是单元格格式的锅...
  4. python中的函数参数主要有四种_python3中函数参数的四种简单用法
  5. MATLAB中常用的产生随机数的几种函数
  6. 2009.09.01 博客近期改进公告!
  7. jsp mysql 分页插件_知识分享:Mybatis框架如何使用分页插件呢?
  8. ORACLE SQL调优之执行计划与隐藏参数_complex_view_merging
  9. php防止订单重复计算,php防止用户重复提交表单
  10. 面试不谈钱,难道要我跟你谈恋爱?真会扯
  11. Hashtable和HashMap类的区别
  12. matlab如何实现隔直滤波器,matlab的滤波器仿真——低通滤波器与插值滤波器
  13. MySQL 有这一篇就够(呕心狂敲37k字,只为博君一点赞!!!)
  14. ## 2019-8-30 光滑粒子流体力学开源软件(Dual)sphysics使用中遇到的一些问题1
  15. Autovue 21.0.2.3 新功能介绍
  16. 数据库课程设计------书店管理系统
  17. MySql 笔记(五)InnoDB引擎页分裂与页合并的原理
  18. Python u,b,r前缀的作用及应用
  19. 【高通SDM660平台 Android 10.0】(21) --- 高通Camera persist使用手册
  20. BMW Standard Tools 宝马FSC工具套装下载

热门文章

  1. 我也写了部lt;西游记gt;
  2. 惠普136w耗材贵吗_性价比利器 惠普MFP 136w轻体验
  3. DirectX11进阶5_硬件实例化与视锥体裁剪及鼠标拾取交互
  4. PS字体加粗的小方法、、
  5. 成功解决Windows和VM下的Ubuntu虚拟系统之间相互复制粘贴的问题
  6. DS SIMULIA Antenna Magus Professional 2021.5
  7. 微信公众号开发整理(五)--自定义菜单
  8. 集合竞价如何买入_股票买入技巧:如何进行集合竞价?
  9. 行业说 | 建筑业面临失宠,越来越留不住年轻人?原因在这
  10. 爱签:行业利好不断 电子签章、电子合同将扩大应用