前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一场pandas与SQL的巅峰大战(四)

一场pandas与SQL的巅峰大战(四)

作者头像
超哥的杂货铺
发布2020-02-20 17:07:22
1.8K0
发布2020-02-20 17:07:22
举报
文章被收录于专栏:超哥的杂货铺超哥的杂货铺

数据准备 SQL计算周同比和日环比 pandas计算周同比和日环比

在之前的三篇系列文章中,我们对比了pandas和SQL在数据方面的多项操作。

具体来讲,第一篇文章一场pandas与SQL的巅峰大战涉及到数据查看去重计数条件选择合并连接分组排序等操作。

第二篇文章一场pandas与SQL的巅峰大战(二)涉及字符串处理窗口函数行列转换类型转换等操作。

第三篇文章一场pandas与SQL的巅峰大战(三)围绕日期操作展开,主要讨论了日期获取日期转换日期计算等内容。

本篇文章一起来学习常见的应用实例:如何在SQL和pandas中计算同环比。将分别在MySQL,Hive SQL和pandas中用多种方案来实现样例数据日环比,周同比计算。

◆ ◆ ◆ ◆ ◆

数据准备

同比和环比本身都是相对的概念。同比是指和上个周期内同期数据的对比,可以是年同比,月同比,周同比等。环比是指连续两个统计周期内数据的对比,可以是日环比,周环比,月环比等。工作中常见的是周同比和日环比。周同比即当天和上周同一天数据的变化百分比,日环比即当天和昨天数据的变化百分比。本文也主要计算周同比和日环比。数据概况如下,是随机生成的两个月的销售额数据。

数据样例如下所示,从左到右依次表示,id,日期,当日销售额,数据周期从2019-11-01到2019-12-31。公众号后台回复“对比四”,即可获取本文全部代码和数据。

pandas加载数据

代码语言:javascript
复制
import pandas as pd
import datetime

orderamt = pd.read_excel('orderamt.xlsx')
orderamt.head()

MySQL加载数据

和前面的文章类似,使用navicate把我准备的orderamt.sql导入数据库中即可。

Hive加载数据

代码语言:javascript
复制
CREATE TABLE `t_orderamt`(
  `id` int, 
  `dt` string, 
  `orderamt` float)
row format delimited fields terminated by ','
stored as textfile;
SQL
load data local inpath 'orderamt.txt' overwrite into table t_orderamt;
select * from t_orderamt limit 20;

按照上面的代码建表,然后把orderamt.txt的内容加载到表中即可,最终数据如上图所示。

SQL计算周同比和日环比

我们关注的是周同比和日环比,其实就是关注当天,昨天,7天前的数据,然后相应的算一下变化的百分比即可。思路一:自关联,关联条件是日期差分别是1和7,分别求出当天,昨天,7天前的数据,用三列形式展示,之后就可以进行作差和相除求得百分比。思路二:不进行关联,直接查询当前日期前一天和前七天的数据,同样以3列的形式展示。

来看一下SQL代码:

上面代码中我们关联了两次,条件分别是日期相差1天和日期相差7天。关联不上的则留空。

再来看另一种写法:

这种写法巧妙地使用表的别名查询出了前1天和前7天的金额,效果和第一种写法一样,不过这种写法可能小众一点。

回到上面的思路2,我们在前面的学习中知道,Hive中有窗口函数支持查询当前行前n行的数据,可以实现同样的效果。代码如下:

代码语言:javascript
复制
select *, 
lag(orderamt, 1) over(order by dt) ld_amt, 
lag(orderamt, 7) over(order by dt) lw_amt
from t_orderamt;

以上面的代码为基础,稍加修改,增加计算百分比的代码,就可以分别得到周同比和日环比。

代码语言:javascript
复制
--第一段修改
select a.*, concat(round(((a.orderamt - b.orderamt) / b.orderamt) * 100,2), '%') as ld_pct,
concat(round(((a.orderamt - c.orderamt) / c.orderamt) * 100,2), '%') as lw_pct
from t_orderamt a
left join t_orderamt b
on DATEDIFF(a.dt, b.dt) = 1
left join t_orderamt c
on DATEDIFF(a.dt, c.dt) = 7
order by dt
;

--第二段修改
select 
b.id, b.dt, b.orderamt,
concat(round(((b.orderamt - ld_amt) / ld_amt) * 100,2), '%') as ld_pct,
concat(round(((b.orderamt - lw_amt) / lw_amt) * 100,2), '%') as lw_pct
from
(
select *, 
(select orderamt from t_orderamt where dt = date_add(a.dt, interval -1 day)) ld_amt,
(select orderamt from t_orderamt where dt = date_add(a.dt, interval -7 day)) lw_amt
from t_orderamt a
) b
;

--第三段修改
select 
b.id, b.dt, b.orderamt,
concat(round(((b.orderamt - ld_amt) / ld_amt) * 100,2), '%') as ld_pct,
concat(round(((b.orderamt - lw_amt) / lw_amt) * 100,2), '%') as lw_pct
from
(
select *, lag(orderamt, 1) over(order by dt) ld_amt, 
lag(orderamt, 7) over(order by dt) lw_amt
from t_orderamt
) b 

pandas计算周同比和日环比

在pandas中,我们同样首先按照上面的两种思路进行计算。

方法一:日期关联的方法

代码语言:javascript
复制
import pandas as pd
import datetime
orderamt = pd.read_excel('orderamt.xlsx')
#orderamt['dt'] = orderamt['dt'].apply(lambda x: datetime.datetime.strptime(x, '%Y-%m-%d'))#为了便于日期加减,将dt转换为datetime64[ns]的格式,视情况运行该句

#分别构造两个dateframe用于关联
orderamt_plus_1 = orderamt.copy()
orderamt_plus_7 = orderamt.copy()

orderamt_plus_1['dt'] = orderamt_plus_1['dt'] + datetime.timedelta(days=1)
orderamt_plus_7['dt'] = orderamt_plus_7['dt'] + datetime.timedelta(days=7)
orderamt_1 = pd.merge(orderamt, orderamt_plus_1, on=['dt'],how='left')
orderamt_1_7 = pd.merge(orderamt_1, orderamt_plus_7, on=['dt'],how='left')
orderamt_all = orderamt_1_7[['id_x', 'dt', 'amt_x', 'amt_y', 'amt']]

方法二:应用shift函数,直接选取前面n行的方法:

代码语言:javascript
复制
orderamt = pd.read_excel('orderamt.xlsx')
orderamt['ld_amt'] = orderamt['amt'].shift(1)
orderamt['lw_amt'] = orderamt['amt'].shift(7)
orderamt

这样得到的效果和SQL方式是一致的。如果要计算百分比,同样是稍微加工即可:

代码语言:javascript
复制
#接方法一代码
orderamt_all['ld_pct'] = (orderamt_all['amt_x'] - orderamt_all['amt_y']) / orderamt_all['amt_y']
orderamt_all['lw_pct'] = (orderamt_all['amt_x'] - orderamt_all['amt']) / orderamt_all['amt']
orderamt_all
代码语言:javascript
复制
#接方法二代码
orderamt['ld_pct'] = (orderamt['amt'] - orderamt['ld_amt']) / orderamt['ld_amt']
orderamt['lw_pct'] = (orderamt['amt'] - orderamt['lw_amt']) / orderamt['lw_amt']
orderamt

在pandas中,还有专门的计算同环比的函数pct_change。

方法三:使用pandas的pct_change()函数计算

代码语言:javascript
复制
orderamt = pd.read_excel('orderamt.xlsx')
orderamt['ld_pct'] = orderamt['amt'].pct_change()
orderamt['lw_pct'] = orderamt['amt'].pct_change(7)
orderamt

上面的代码中,我们都没有用百分比的形式保留结果,这里提供一种方式。

代码语言:javascript
复制
#接方法三,方法一二类似
orderamt['ld_pct'] = orderamt['ld_pct'].apply(lambda x: format(x, '.2%'))
orderamt['lw_pct'] = orderamt['lw_pct'].apply(lambda x: format(x, '.2%'))
orderamt

至此,我们完成了SQL和pandas中对于周同比和日环比计算的过程。

◆ ◆ ◆ ◆ ◆

小结

本篇文章中,我们使用SQL和pandas的多种方法对常见的周同比和日环比进行计算。在同样的思路指导下,SQL和pandas实现的方式各有特色,代码并不复杂,但值得细细品味。

推荐阅读:

1.一场pandas与SQL的巅峰大战

2.一场pandas与SQL的巅峰大战(二)

3.一场pandas与SQL的巅峰大战(三)

4.常用Hive函数的学习和总结

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 超哥的杂货铺 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档