You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以向量化方式实现numpy数组的行分组均值计算?

向量化解决方案:按分组计算行均值

问题背景

给定分组索引列表:

outer_list = [[0], [1, 2], [1, 2], [3, 5], [4], [3, 5]]

其中每个子列表对应父列表中该索引所属的分组(例如索引1和2同属一组,索引3和5同属一组)。同时有一个numpy矩阵val_mat:

val_mat = np.arange(2*6).reshape(2, 6)

需求是对每行数据,将同一分组内的元素替换为该分组的行均值,最终得到均值矩阵。

当前实现通过遍历outer_list计算均值,在处理10k×500k规模矩阵时耗时约2分钟,需要更高效的向量化实现。

向量化实现步骤

1. 生成分组标签数组

首先将重复的分组映射为唯一ID,生成每个索引对应的分组标签:

import numpy as np

outer_list = [[0], [1, 2], [1, 2], [3, 5], [4], [3, 5]]
# 将子列表转为元组(可哈希),用于去重
group_tuples = [tuple(lst) for lst in outer_list]
# 获取唯一分组并生成每个索引的分组ID
unique_groups, group_ids = np.unique(group_tuples, return_inverse=True)

此时group_ids为array([0, 1, 1, 2, 3, 2]),代表每个索引对应的分组编号。

2. 向量化计算分组均值

利用np.bincount实现高效的分组求和与计数,进而计算均值并映射回原索引位置:

val_mat = np.arange(2*6).reshape(2, 6)

# 计算每个分组的元素个数
group_counts = np.bincount(group_ids)

# 对每行计算分组均值并生成结果矩阵
mean_vals = np.zeros_like(val_mat)
for i in range(val_mat.shape[0]):
    row = val_mat[i]
    # 分组求和
    group_sums = np.bincount(group_ids, weights=row)
    # 分组均值
    group_means = group_sums / group_counts
    # 将均值映射到对应索引位置
    mean_vals[i] = group_means[group_ids]

3. 进一步优化:避免行循环(可选)

如果想彻底去掉行循环,可以利用广播和矩阵运算实现:

# 构建分组计数的广播矩阵:(n_groups, n_cols)
count_matrix = group_counts[group_ids][np.newaxis, :]
# 构建分组求和矩阵:(n_rows, n_groups)
sum_matrix = np.dot(val_mat, np.eye(len(group_counts))[group_ids])
# 计算均值矩阵
mean_vals = sum_matrix / count_matrix

注:该方法在分组数量极大时(如50万组),np.eye会生成超大矩阵,内存可能不足,此时优先选择带行循环的版本(行循环的开销远小于原方法的50万次切片操作)。

效果对比

原方法需要遍历50万次分组并执行切片运算,向量化方法仅需几次numpy内置操作,处理10k×500k矩阵的耗时可大幅降低(通常能压缩到数十秒甚至更短)。

内容的提问来源于stack exchange,提问作者user354621

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 05:38:11