3.3 有序分组
3.3.1 按位置分组
员工每 10 个分一组,把姓氏的众数作为该组的姓氏
SPL
A | |
---|---|
1 | =file(“EMPLOYEE.csv”).import@tc() |
2 | =A1.group((#-1)\10).new(#:GID,~.mode(SURNAME):SURNAME) |
SPL 利用”#”来得到分组键,不需要单独计算一列分组键
SQL
SELECT GRP, SURNAME
FROM (
SELECT CEIL(rownum/10) AS grp, SURNAME, COUNT(*) AS count,
ROW_NUMBER() OVER (PARTITION BY CEIL(rownum/10) ORDER BY COUNT(*) DESC) AS rn
FROM EMPLOYEE
GROUP BY CEIL(rownum/10), SURNAME)
WHERE rn = 1;
Python
emp=pd.read_csv('../EMPLOYEE.csv')
pos_seq=[i//10foriinrange(len(emp))]
group_surname=emp.groupby(pos_seq)['SURNAME'].apply(lambdax:x.value_counts().idxmax())
Python 是衍生出一列,然后根据衍生列分组。
3.3.2 按序号分组
员工分成 10 组,把姓氏的众数作为该组的姓氏
SPL
A | |
---|---|
1 | =file(“EMPLOYEE.csv”).import@tc() |
2 | =A1.group@n(#%10+1).new(#:GID,~.mode(SURNAME):SURNAME) |
@n 选项是按序号分组,这时要保证分组键值是自然数且从 1 开始,能提高分组效率。
SQL
SQL 没有类似的方法提高分组效率。
Python
Python 没有类似的方法提高分组效率。
3.3.3 值变化分组
找出序列中的连续数字序列
SPL
A | B | |
---|---|---|
1 | [7,5,5,7,13,15,16,17,13,5,6,7,8,17,6,10,11,11,18,15] | |
2 | =A1.group@o(~-#).select(~.len()>1) | /[[15,16,17],[5,6,7,8],[10,11]] |
groups@o() 方法依次扫描整个序列,当分组键值和上一个成员的分组键相同时,则将该成员加入到当前的分组子集,如果分组键值发生变化了,则产生一个新的分组子集。
SQL
SQL 中没有现成的方法来完成这个任务。
Python
lst=[7,5,5,7,13,15,16,17,13,5,6,7,8,17,6,10,11,11,18,15]
diffs=[j-ifori,jinenumerate(lst)]
groups=pd.Series(diffs).diff().ne(0).cumsum()
g_list=pd.Series(lst).groupby(groups).agg(list)
result=g_list[g_list.apply(lambdax:len(x)>1)].tolist()
Python 还是要烧脑去构造一个衍生列来分组。
3.3.4 条件变化分组
股票最长连续上涨天数
SPL
A | |
---|---|
1 | =file(“STOCK.csv”).import@tc() |
2 | =A1.group@i(CLOSING<=CLOSING[-1]).max(~.len())-1 |
group@i() 的分组键是个表达式,每当计算出 true 时则产生一个新的分组子集,也就是满足某个条件时就重新分一组。因为分组的第 1 条记录并不上涨,所以最后要减 1。
SQL
SQL 中没有现成的方法来完成这个任务。
Python
stock = pd.read_csv('../STOCK.csv')
stock['UP'] = stock['CLOSING'].diff() > 0
up_streak = stock.groupby((~stock['UP']).cumsum())['UP'].cumsum().where(stock['UP'], 0)
max_streak = up_streak.max()
Python 还是老方法,构造一个衍生列来完成计算。