pivot@s 聚合时第 3 参数的用法

开门见山,关于 pivot@s 聚合时第 3 参数的用法,我有 3 个问题恳请大佬们给予指导。如下:

1、3 参聚合时可否引用 2 参中的变量名;

2、3 参聚合值可否进一步运算,支持复杂聚合表达式;

3、3 参聚合时不能引用 #n 来表示字段,只能用字段名。

实战场景如下所示,需要把左边的表格变成右上角的表格,行转列再聚合汇总。类似场景的聚合还是很多的,涉及到分类聚合的都可以用 pivot 实现 reshape and aggregate。

imagepng

为方便测试,以下数据可以复制使用:

月份	水果(价格)	数量
一月	山楂(5)	10
一月	山楂(5.5)	8
一月	西瓜(5.5)	20
一月	梨(5)	10
一月	梨(6)	6
一月	苹果(5)	10
一月	苹果(4.51)	20
二月	西瓜(5)	30
二月	山楂(5)	10
二月	西瓜(6)	10
二月	菠萝(5)	10
二月	苹果(6)	8
二月	苹果(8)	20

这样的 reshape & aggregate 需求,似乎没有比 spl 的 pivot@s 更方便快捷的方法了,VBA 字典套字典,需要一定的基础和想象力,Power Query 虽然可以在 UI 界面点击,小白可以不写代码完成操作,无奈步骤太多,pandas 的 dataframe 结构对我而言有点不友好,在 pivot_table 之前需要对源数据重构(以下写法来自某学习群的一位 Python 佬):

df.iloc[:,[0,2]].join(df[[*df][1]].str.extract('(?P<水果>\D+)((?P<b>[\d.]+)').astype({'b':float})).eval('c=数量*b').pivot_table('c','月份','水果',sum).fillna(0)

imagepng

目前来看,spl 中的 pivot@s 是最简洁的,可以用以下语句实现 (此帖用 EXCEL 插件,IDE 一样的效果):

=spl("=E(?).pivot@s(月份;#2.split@rp(""(|)"")(1),(~.(#2.split@rp(""(|)"")(2))**~.(#3)).sum())",B2:D15)

imagepng

此时,pivot@s()的第 3 参数用 ~.fx() 这种写法,其中的波浪线 ~ 表示引用当前组,可以看到语句简洁,"一行流" 风格 (Python 佬常说的一行代码解决问题,说着玩😄)。

当然,我求助绝不是为了吹牛好玩,我想的是上述语句能不能更简洁。请注意观察上图语句中标有颜色的部分,#2.split@rp(““(|)””),2 参 3 参都涉及到了这部分,且重复写了。所以,我就琢磨,能不能在 2 参的位置引入变量名,令 x=#2.split@rp(““(|)””),供 3 参调用。再一个,pivot@s 的第 3 参数不仅支持 ~.fx() 还支持聚合函数,于是就有了以下写法:

imagepng

可以看到,3 参虽然能引用 2 参中的变量名,但结果跟预期的不一样,3 参聚合时显示的都是源数据最后一行的价格,但 3 参能聚合原本存在的列,比如聚合第 3 列的数量,结果是符合预期的:

imagepng

那 pivot@s 中的 3 参是不是只支持简单聚合,还能否对聚合值进行进一步计算呢,尝试了一下,结果不符合预期,如下所示:

imagepng

所以,初步得出 pivot@s 中的 3 参只支持简单聚合,引用变量时结果会不符合预期。无意中还发现一个问题,3 参聚合时不能用 #n 表示某列,会抛出索引越界的错误,只能用字段名表示,如下截图:

imagepng

spl 中,涉及到聚合的除了 pivot@s 之外,还有 groups,group@s,这两个函数在聚合时,可以引用变量名且支持复杂聚合表达式,结果都是符合预期的。为了简单起见,还是拿本帖数据源中一月份的数据用 groups 和 group@s 举例如下:

imagepng

group@s 时也是一样的操作,结果符合预期:

imagepng

我的想法是这样的,在 spl 中分组聚合函数就这几个 groups,group@s,pivot@s,常用且实用。就拿 pivot 这个函数来说,以我目前所了解到的能用 pivot 的编程语言,没有比 spl 的 pivot 更简洁好用的了,所以,恳请大佬们考虑一下帖子开头的 3 个小问题,看看能否把 pivot@s 的 3 参优化一下,跟 groups 和 group@s 函数保持语法统一?我想要的写法是这样的 (目前结果不符合预期):

=spl("=E(?).pivot@s(月份;(x=#2.split@rp(""(|)""))(1),sum(x(2)*数量))",B2:D15)

或者

=spl("=E(?).pivot@s(月份;(x=#2.split@rp(""(|)""))(1),sum(x(2)*#3))",B2:D15)

关于 pivot@s 目前想到的就这些,具体还得恳请大佬们得闲时出手指点为盼。

期待好消息……🙏 🙏