SPL:按序号对齐的分组和排序
有时候我们会按照序号顺序将数据进行分组和排序,把序号相同的成员分到同一组。比如按 1 到 12 月的顺序统计上一年每个月的销售总额,按照周一到周日的顺序统计某网站的访问人次等等。
这种按指定基准对齐的分组运算,我们统称为对齐分组。按序号对齐分组是对齐分组的一种特例,其基准集合是从 1 开始的整数列。对齐分组可能会有空组,也可能有成员未分配到任何一个组中。
1. 按序号顺序排序
按指定的序号顺序将数据排序,每组保留最多一个匹配成员。适用于我们希望按照指定顺序查看或者使用数据的情况。
【例 1】 根据每日销售表,按每周一到周日的顺序查询销售记录。部分数据如下:
Week |
Day |
Amount |
5 |
Sunday |
1101.2 |
5 |
Saturday |
538.6 |
5 |
Friday |
2142.4 |
5 |
Thursday |
1456.0 |
5 |
Wednesday |
48.0 |
5 |
Tuesday |
1376.0 |
5 |
Monday |
676.0 |
4 |
Sunday |
448.0 |
4 |
Saturday |
4031.0 |
4 |
Friday |
364.8 |
… |
… |
… |
在 SPL 中函数 A.align(n,y) 用于对齐分组 ,直接划分为 n 个组(从 1 到 n),并根据分组表达式 y 直接计算出每个成员对应的组号。默认每组保留最多一个匹配成员。
SPL脚本如下:
A |
|
1 |
=T("DailySales.csv") |
2 |
["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"] |
3 |
=A1.group(Week; ~.align(7,A2.pos(Day)):WeekSales) |
4 |
=A3.conj(WeekSales) |
5 |
=A4.select(~) |
A1:查询每日销售表。
A2:定义从周一到周日的序列。
A3:销售数据按周分组时,使用函数 A.align(n,y) 将每周的销售记录,按照A2定义好的顺序进行对齐。这里值得注意的是,对齐分组可能会有空组。例如当第二周的周五和周六没有销售记录时,仍然会产生每周 7 个小组:
Week |
[2,Monday,1194.0] |
[2,Tuesday,1622.4] |
[2,Wednesday,319.2] |
[2,Thursday,802.0] |
(null) |
(null) |
[2,Sunday,2123.2] |
A4:将每周排序后的销售记录合并。
A5:从结果集中选出非空的记录。
其中A5的执行结果如下:
Week |
Day |
Amount |
1 |
Monday |
3063.0 |
1 |
Tuesday |
3868.6 |
1 |
Wednesday |
2713.5 |
1 |
Thursday |
1005.9 |
1 |
Friday |
1675.0 |
1 |
Saturday |
400.0 |
1 |
Sunday |
2018.2 |
2 |
Monday |
1194.0 |
2 |
Tuesday |
1622.4 |
2 |
Wednesday |
319.2 |
… |
… |
… |
2. 每组保留所有匹配成员
按指定的序号顺序将数据分组,每组保留所有匹配成员。适用于关心每组的成员信息,或者需要用这些成员记录继续进行统计的场景。
【例 2】 根据销售表,顺序列出 2014 年每个月的销售总额。销售表部分数据如下:
ID |
CustomerID |
OrderDate |
Amount |
10248 |
VINET |
2013/07/04 |
2440 |
10249 |
TOMSP |
2013/07/05 |
1863.4 |
10250 |
HANAR |
2013/07/08 |
1813.0 |
10251 |
VICTE |
2013/07/08 |
670.8 |
10252 |
SUPRD |
2013/07/09 |
3730.0 |
… |
… |
… |
… |
在 SPL 中函数 A.align(n,y) 的选项 @a,用于在对齐分组时每组保留所有匹配成员。
SPL脚本如下:
A |
|
1 |
=T("Sales.csv") |
2 |
=A1.select(year(ORDERDATE)==2014) |
3 |
=A2.align@a(12,month(ORDERDATE)) |
4 |
=A3.new(#:Month,~.sum(AMOUNT):AMOUNT) |
A1:查询销售表。
A2:从销售表中选出 2014 年的记录。
A3:使用函数 A.align@a(n,y),将订单表的月份按照 1 到 12 的顺序分为 12 组,选项 @a 每组保留所有匹配成员。
A4:统计每个月的销售总额。
其中A4的执行结果如下:
Month |
Amount |
1 |
66692.8 |
2 |
52207.2 |
3 |
39979.9 |
4 |
60699.39 |
… |
… |
3. 按序号重复性分组
有时候每条记录计算出的分组序号是多个,我们希望将记录按照序号数列重复性的分配到多个组中。
【例 3】 根据发帖记录表,按标签将帖子分组,并统计各个标签出现频数。发帖记录表部分数据如下:
ID |
Title |
Author |
Label |
1 |
Easy analysis of Excel |
2 |
Excel,ETL,Import,Export |
2 |
Early commute: Easy to pivot excel |
3 |
Excel,Pivot,Python |
3 |
Initial experience of SPL |
1 |
Basics,Introduction |
4 |
Talking about set and reference |
4 |
Set,Reference,Dispersed,SQL |
5 |
Early commute: Better weapon than Python |
4 |
Python,Contrast,Install |
… |
… |
… |
… |
在 SPL 中函数 A.align(n,y) 的选项 @r,用于在对齐分组时按序号重复性分组。
SPL脚本如下:
A |
|
1 |
=T("PostRecord.txt") |
2 |
=A1.conj(Label.split(",")).id() |
3 |
=A1.align@ar(A2.len(),A2.pos(Label.split(","))) |
4 |
=A3.new(A2(#):Label,~.count():Count).sort@z(Count) |
A1:查询发帖记录表。
A2:将标签按逗号分隔后合并到一个序列,获得没有重复值的全部标签。
A3:使用函数 A.align@r(n,y) 的,按照每个帖子的标签在全部标签中的定位分组,选项 @r。
A4:统计每个标签的帖子数量,按降序排列。
其中A4的执行结果如下:
Label |
Count |
SPL |
7 |
Excel |
6 |
Basics |
5 |
… |
… |