第 4 章 时间统计
有某商超订单数据表 orders.csv,其数据列为:
| 列名 | 含义 |
|---|---|
| orderID | 订单号 |
| userID | 用户 ID |
| orderTime | 订单时间 |
| amount | 订单金额 |
此表包含 2022-2024 年共三年的商超订单数据。
4.1 按年、月统计销售额
由于只需要最终统计表,故不需要先增加包含年和月的计算列。可以直接对 orders 用年月表达式作为分组表达式。
第一步: 打开 orders 表:

第二步: 在 orders 表上,使用分组表达式year(orderTime):Year以及month(orderTime):Month,设置分组字段:

再设置销售额聚合表达式:

单击OK后,得到了按年月分组统计的销售额:

知识点:month 函数用于取得指定日期所在的月份。详细用法请参考:https://d.raqsoft.com.cn:6443/esproc/func/month.html
4.2 销售额环比增长率
环比增长率 (MoM, Month-over-Month Growth Rate)是指某一指标(如销售额、用户数、GDP 等)在相邻两个统计周期(通常按月或季度)之间的增长比率 ,用于衡量短期内的变化趋势。
计算公式:环比增长率 =(本期数值−上期数值)/ 上期数值
通过环比增长率的公式可以看到,要计算的比值得在时间上是有序的,4.1 节中 groupTime 表已经按年月有序,就只需直接使用计算列计算即可。
第一步: 在 groupTime 表上单击计算列,并使用表达式
(TotalAmount-TotalAmount[-1])/TotalAmount[-1]设置计算列:

第二步: 单击OK,计算出环比增长率:

4.3 同比增长率
同比增长率 (YoY, Year-over-Year Growth Rate)是指某一指标(如销售额、利润、GDP 等)在相同统计周期但不同年份之间的增长比率 ,用于消除季节性影响,反映长期趋势。
计算公式:同比增长率 =(本期数值−去年同期数值)/ 去年同期数值
3.6 节中,我们介绍了将数据分组成明细表,然后在明细表上计算子表后再合并的方法。本节介绍另一种解法,不按月份分组成明细,直接在计算表达式中判断相邻关系。先将相同月份的年度数据排到一起,方便相邻年份引用。
第一步: 在 groupTime 表上,选中 Month 列表头,单击左移列,将 Month 移到前面,这样查看同比数据比较直观:

第二步: 再对 groupTime 表按 Month , Year 排升序:

得到相同月份下,年度相邻的结果:

第三步: 使用公式if(Year[-1]==Year-1 && Month[-1]==Month, (TotalAmount-TotalAmount[-1])/TotalAmount[-1], null) 计算同比值,该公式的含义为当相邻两行为相同月份且年份相邻时,则计算(TotalAmount-TotalAmount[-1])/TotalAmount[-1]同比值,否则为 null:

单击OK后,得到同比计算结果:

4.4 五日移动平均
移动平均是一种用于分析时间序列数据的统计方法,通过计算特定时间窗口内数据的平均值来平滑短期波动,帮助观察长期趋势。它广泛应用于金融(如股票分析)、经济学、气象学、质量控制等领域。
计算公式:MAn=(p1+p2+⋯+pn)/n
其中 pn 为第 n 天的数据(如收盘价),n 为窗口大小(如 5 天)。
第一步: 在 orders 表上,以表达式date(orderTime):Date将日期去掉时间部分,按天设置分组:

如图设置聚合值,统计按天汇总的销售额 Amount :

单击OK后,得到按日期分组的销售额表:

第二步: 对 groupDate 表增加计算列,计算列的表达式设置为Amount[-2:2].avg():

单击OK后,得到五日移动平均结果:

知识点:什么是 Amount[-2:2] 3.8 节中,我们知道可以使用 [n] 来引用以当前行为中心的相对位置引用,这里使用 [b:e] 语法定义起始位置到结束位置的引用范围,返回范围中的值序列。Amount[-2:2] 表示以当前行为中心,向前取 2 行、向后取 2 行(包含当前行本身)构成的值序列。
4.5 工作日 vs 周末销售对比
实现思路:将数据按日统计后,分别算出日期所属星期几,然后分别选出周六日以及工作日的数据,再各自求平均销售额,即可获得两者数据的对比。
第一步: 对 groupDate 表增加计算列,计算列的表达式设置为day@w(Date):

单击OK,得到包含星期数的数据:

第二步: 从 groupDate 中选出周末的数据,使用表达式weekDay==1 || weekDay==7过滤:

单击OK,得到周末的数据表:

第三步: 在数据表 groupDate 上单击如图集合运算:

如图设置结果表名,运算符选差集,并选中目标表dataWeekend:

该步的含义为,计算 groupDate 跟 dataWeekend 的差集,也就是从 groupDate 中去掉周末的数据,留下的自然是工作日数据:

第四步: 在手写命令区分别计算dataWeekend.avg(Amount)和dataWorkdays.avg(Amount):


知识点:day@w 函数从日期型数据中,获得该日位于一个星期中的第几天。注意星期天返回 1,星期一返回 2,依此类推,星期六返回 7。详细用法请参考:https://d.raqsoft.com.cn:6443/esproc/func/day.html
4.6 时段销售占比
实现思路:将销售数据按小时分组汇总,然后求出小时的平均销售额,最后算出一天内的占比,从而了解一天内销售的波峰和低谷:
第一步: 重新打开 orders ,然后在分组中设置分组表达式date(orderTime):Date、hour(orderTime):Hour,按每天的时段分组:

同时设置聚合表达式sum(amount)统计销售额:

单击OK后,得到按时段统计结果:

第二步: 在 groupTime 上,再次按 Hour 分组,统计平均销售额 AvgAmount :


单击OK后,得到分时段的平均销售额:

第三步: 双击 AvgAmount 列表头,将 AvgAmount 按降序排列,可以看到销售高峰时段:

4.7 销售完成度追踪
以月均销售额作为月销售目标,要求计算 24 年 10 月份的日累计销售完成度。
先计算月均销售额。
第一步: 对 groupTime 表,再次分组,分组表达式设为year(Date):Year、month(Date):Month:

统计每月总销售额:

单击OK后,算出年度月总销售额:

第二步: 继续对 groupMonth 分组,分组表达式设为Month:

此时要计算月度平均销售额:

单击OK后,算出月度平均销售额:

再计算 24 年 10 月份的日累计销售完成度。
第三步: 从 groupTime 中过滤出 2024 年 10 月的数据,过滤表达式设为year(Date)==2024 && month(Date)==10:

单击OK后,过滤出 2024 年 10 月数据:

第四步: 将 data202410 按日期汇总,再次分组并聚合 Amount:

作为分时段的中间表不再需要,因此该分组仍然命名为 data202410 ,并将时段数据汇总:

单击OK后, data202410 按日期汇总结果:

第五步: 在 data202410 中增加计算列,分别算出累计值,同时计算累计值跟 10 月均值的占比:
计算表达式分别为: cum[-1]+Amount
cum/MonthAvg(10).AvgTotalAmount

单击OK后,算出累计值,以及日累计的完成度占比:

其中表达式MonthAvg(10).AvgTotalAmount的含义为从月均表 MonthAvg 中取第 10 行数据,再取该行中 AvgTotalAmount 列的值。
4.8 复购周期分析
我们把一天内购买多次的用户视为购买遗漏商品,或者为了优惠拆单下单,不视作复购用户,因此对其按日期求唯一。
第一步: 重新打开 orders,把订单数据按 userID、orderTime 求唯一,如图设置分组:

如果一天中有多笔订单,使用返回每组的首行,便去掉重复项了,该选项选中后,聚合已经没有意义,所以上图中聚合设置都是禁止编辑的。单击OK后,得到用户下单日结果:

后续分析只需要 groupUserDate 表,选中 orders ,单击删除图标,删除它以释放内存空间:

第二步: 在 groupUserDate 中,按 userID 分组,并选择保持明细:

单击OK后,得到 userID 的明细表:

第三步: 双击打开 1 号用户的明细表:

使用计算列表达式interval(Date[-1],Date),计算复购间隔:

interval函数用于计算两个日期的间隔,缺省返回值的单位是天。单击OK后,算出间隔值:

第一行数据没有前一行,所以间隔值为null。在过滤界面中用表达式interval!=null,去掉该行值:

第四步: 在 groupUserDate 上,使用合并明细,将所有记录合并为 allInterval :

单击OK后得到合并结果:

第五步: 现在要找出每个用户的最后下单数据,回到 groupUserDate.Details(1) ,使用界面排序,按日期降序排列。注意,明细表中只能通过图标界面的操作才会同步执行到其他明细表。如果双击列头,虽然也排序,但它只是排的当前明细表。

单击OK,排序后,最后下单的数据行就都位于第一行了:

只保留每个用户的最后下单数据,使用过滤表达式#==1,去掉其他行:

只保留最后下单的数据结果:

第六步: 回到 groupUserDate ,再使用合并明细:

单击OK,得到每个用户的最后订单表:

第七步: 在手写命令区,执行allInterval.avg(interval),算出所有用户的平均复购间隔:

该值需要在后面表达式中用到,但从命令区执行的结果都缺省无名,所以要将它命名后,方可引用,参考 3.8 节,将其命名为 AVGInterval :

在 lastInterval 上,使用过滤表达式:Date<date("2024/12/31")-AVGInterval,
找出那些超出平均下单时间,还没复购的客户。当前订单数据截止到 2024 年底,所以上面表达式计算的是 2024 年最后一天之前的平均天数。

单击OK后,得到需要对其制定召回策略的用户:

通过跟 lastInterval 中的数据行数比较,一半多的用户需要重点关注,比较符合分析预期。
