如何用Lambda函数实现指定列分区排序的SQL窗口功能模拟?
模拟SQL窗口函数的Lambda实现
需求说明
我正在模拟SQL查询,使用如下数据:
rows = [(1, '2021/04', 'Shop 2', 341227.53), (2, '2021/05', 'Shop 2', 315447.24), (3, '2021/06', 'Shop 1', 1845662.35), (4, '2021/04', 'Shop 2', 21487.63), (5, '2021/05', 'Shop 1', 1489774.16), (6, '2021/06', 'Shop 1', 52489.35), (7, '2021/04', 'Shop 1', 154552.82), (8, '2021/05', 'Shop 2', 6548.49), (9, '2021/06', 'Shop 2', 387779.49)]
需要生成一个模拟SQL窗口函数效果的字典:
- 按第三列(店铺名,比如
'Shop 1')分区 - 按第二列(日期,比如
'2021/06')排序 - 最终格式示例:
{ 'Shop 1': ['2021/04', '2021/05', '2021/06'], 'Shop 2': ['2021/04', '2021/05', '2021/06'] }
想通过一个接收两个参数的Lambda函数实现,示例形式如下:
window_func = lambda partition_func, order_func: ...
其中partition_func用于指定分区字段(对应数据项的第三列item[2]),order_func用于指定排序字段(对应数据项的第二列item[1])
实现代码
from itertools import groupby rows = [(1, '2021/04', 'Shop 2', 341227.53), (2, '2021/05', 'Shop 2', 315447.24), (3, '2021/06', 'Shop 1', 1845662.35), (4, '2021/04', 'Shop 2', 21487.63), (5, '2021/05', 'Shop 1', 1489774.16), (6, '2021/06', 'Shop 1', 52489.35), (7, '2021/04', 'Shop 1', 154552.82), (8, '2021/05', 'Shop 2', 6548.49), (9, '2021/06', 'Shop 2', 387779.49)] # 实现Lambda函数 window_func = lambda partition_func, order_func: { shop: sorted({row[1] for row in shop_rows}, key=lambda dt: order_func(next(r for r in rows if r[1] == dt))) for shop, shop_rows in groupby(sorted(rows, key=partition_func), key=partition_func) } # 调用示例:按店铺分区,按日期排序 result = window_func(lambda x: x[2], lambda x: x[1]) print(result)
代码说明
- 先对原始数据按分区字段排序:
sorted(rows, key=partition_func),因为groupby只能把连续相同的项归为一组,必须先排序才能正确分组 - 用
groupby按店铺分组,得到每个店铺对应的所有行数据 - 提取每个店铺的所有日期,用集合去重(如果不需要去重,把
{row[1] for row in shop_rows}改成[row[1] for row in shop_rows]即可) - 用
order_func指定的规则对日期排序,最终生成键为店铺名、值为排序后日期列表的字典
测试输出
{'Shop 1': ['2021/04', '2021/05', '2021/06'], 'Shop 2': ['2021/04', '2021/05', '2021/06']}
内容的提问来源于stack exchange,提问作者David542
相关产品推荐
相关产品推荐

