SPL:次序相关的分组
有些时候,数据的次序在分组时是有意义的。我们有时会把具有相同字段值或者同时满足某些条件的相邻记录分到同一组。比如蝉联奥运会金牌榜第一名届数最长的国家是哪个,某支股票的收盘价最多连续上涨了几天等等。这就需要用到有序分组了。
1. 连续相同值分组
对有序集合进行分组时,当分组字段的值发生变化时重新分组。
【例 1】 根据奥运会奖牌榜统计表,求总成绩蝉联第一名届数最长的国家及其奖牌信息。部分数据如下:
Game | Nation | Gold | Silver | Copper |
30 | USA | 46 | 29 | 29 |
30 | China | 38 | 27 | 23 |
30 | UK | 29 | 17 | 19 |
30 | Russia | 24 | 26 | 32 |
30 | Korea | 13 | 8 | 7 |
… | … | … | … | … |
在 SPL 中函数 A.group() 的选项 @o,当字段值发生变化时重新分组。
SPL脚本如下:
A | |
1 | =T("Olympic.txt") |
2 | =A1.sort@z(GAME,GOLD,SILVER,COPPER) |
3 | =A2.group@o1(GAME) |
4 | =A3.group@o(NATION) |
5 | =A4.maxp(~.len()) |
A1:导入奥运会奖牌榜。
A2:按第几届和奖牌数(金、银、铜)降序排列。
A3:每届取一名,因为有序也就是每届的第一名。
A4:当国家改变时重新分组。
A5:选出成员数量最多的一组,也就是蝉联次数最多的。
2. 按相邻条件分组
对有序集合进行分组时,当分组条件的计算结果为 true 时重新分组。
【例 2】 上证指数 2020 年收盘价最长连续上涨了多少天?(首个交易日指数上涨)。部分数据如下:
DATE | CLOSE | OPEN | VOLUME | AMOUNT |
2020/01/02 | 3085.1976 | 3066.3357 | 292470208 | 3.27197122606E11 |
2020/01/03 | 3083.7858 | 3089.022 | 261496667 | 2.89991708382E11 |
2020/01/06 | 3083.4083 | 3070.9088 | 312575842 | 3.31182549906E11 |
2020/01/07 | 3104.8015 | 3085.4882 | 276583111 | 2.88159227657E11 |
2020/01/08 | 3066.8925 | 3094.2389 | 297872553 | 3.06517394459E11 |
… | … | … | … | … |
在 SPL 中函数 A.group() 的选项 @i,当条件发生变化时重新分组。
SPL脚本如下:
A | |
1 | =T("SSEC.csv") |
2 | =A1.select(year(DATE)==2020).sort(DATE) |
3 | =A2.group@i(CLOSE<CLOSE[-1]) |
4 | =A3.max(~.len()) |
A1:导入上证指数表。
A2:选出 2020 年的记录,并按日期升序排列。
A3:当收盘价小于前日收盘价时重新分组。
A4:计算连续上涨的最大天数。
3. 按序号分组
有些时候,我们能够直接或者间接的获取分组序号(成员应该分配到第几组),这种情况下我们可以直接按照分组序号进行分组。
【例 3】 根据员工的入职时间平均分成三组(有余数的顺序分配到某一组),并统计每组的平均工资。部分数据如下:
ID | NAME | BIRTHDAY | ENTRYDATE | DEPT | SALARY |
1 | Rebecca | 1974/11/20 | 2005/03/11 | R&D | 7000 |
2 | Ashley | 1980/07/19 | 2008/03/16 | Finance | 11000 |
3 | Rachel | 1970/12/17 | 2010/12/01 | Sales | 9000 |
4 | Emily | 1985/03/07 | 2006/08/15 | HR | 7000 |
5 | Ashley | 1975/05/13 | 2004/07/30 | R&D | 16000 |
… | … | … | … | … | … |
在 SPL 中函数 A.group() 的选项 @n,用于按序号分组,具有相同序号的记录被分到同一组(序号为 N 的成员分配到第 N 组,N 从 1 开始)。
SPL脚本如下:
A | |
1 | =T("Employee.csv").sort(ENTRYDATE) |
2 | =A1.group@n((#-1)*3\A1.len()+ 1) |
3 | =A2.new(#:GROUP_NO, ~.avg(SALARY):AVG_SALARY) |
A1:导入员工表,并按照入职日期排序。
A2:通过排序后的行号计算出所属的分组序号,并按序号分组。
A3:统计每组的平均工资。