Python:对Sqlalchemy行按列分组并计算列均值
分组Sqlalchemy实体行并计算列均值的优化实现
你手里有个包含5400条Sqlalchemy实体行的生成器,想要按col1列分组,再计算每组col2列的均值,还写了一个分组函数,但想找更优的实现方式,尤其是用itertools的方案。先给你指出你写的函数里的一个bug:map_[key] = map_[key].append(value)这行有问题——列表的append()方法是原地修改列表,返回的是None,这会导致后续你取map_[key]时拿到的是None,而不是你想要的列表。
下面给你几个更优的实现方案:
方案一:用collections.defaultdict简化分组逻辑
这个写法比你原来的try-except更简洁,还能避免上述bug,同时可以直接完成均值计算:
from collections import defaultdict def group_by_col1_calculate_mean(rows): group_map = defaultdict(list) # 第一步:按col1分组收集col2的值 for row in rows: group_map[row.col1].append(row.col2) # 第二步:转换为均值字典 return {key: sum(values) / len(values) for key, values in group_map.items()}
方案二:用itertools.groupby实现分组
注意:itertools.groupby的特性是只对连续相同的键分组,所以必须先让数据按col1排序。如果你的Sqlalchemy查询可以直接加order_by(你的模型类.col1),那效率会更高,不用在内存里排序5400条数据。
代码示例:
from itertools import groupby def group_by_col1_with_groupby(rows): # 如果查询结果没排序,先按col1排序(已排序可跳过) sorted_rows = sorted(rows, key=lambda x: x.col1) # 按col1分组 grouped_data = groupby(sorted_rows, key=lambda x: x.col1) # 计算每组均值 mean_result = {} for col1_val, group in grouped_data: col2_values = [row.col2 for row in group] mean_result[col1_val] = sum(col2_values) / len(col2_values) return mean_result
额外优化:低内存占用的均值计算
如果数据量更大(比如远超5400条),可以不用存储所有col2的值,而是直接累加总和和计数,节省内存:
from collections import defaultdict def group_by_col1_low_memory(rows): # 用列表存[总和, 计数] group_stats = defaultdict(lambda: [0, 0]) for row in rows: group_stats[row.col1][0] += row.col2 group_stats[row.col1][1] += 1 # 转换为均值 return {key: total / count for key, (total, count) in group_stats.items()}
各方案适用场景
defaultdict写法:最直观、代码简洁,适合你的5400条数据场景,上手快。itertools.groupby:适合已排序的数据,或者能让Sqlalchemy返回排序结果的情况,分组效率更高。- 低内存方案:数据量极大时优先选,内存占用比前两种小很多。
内容的提问来源于stack exchange,提问作者NicWorkAccount
相关产品推荐
相关产品推荐

