如何用Numpy高效实现同形状ndarray间的元组计数?
用Numpy高效统计多数组同索引元组的出现次数
核心问题说明
你遇到的distribution[img, avg] += 1失效问题,本质是Numpy处理重复索引时,只会对每个唯一索引执行一次累加操作,不会自动统计重复出现的次数。下面提供两种优雅的Numpy原生解决方案:
方案1:np.bincount(最高效简洁)
将两个数组的索引组合成唯一整数编码,通过bincount统计频次后重塑为目标形状:
import numpy as np from torch.nn.functional import avgpool2d img = np.random.randint(0, 2, (64, 64)) avg = avgpool2d(img, kernel_size=3, padding=1).numpy() * 9 avg = avg.astype(np.int32) # 把(i,j)二维索引编码为一维整数:i * 9 + j encoded = img.flat * 9 + avg.flat # 统计每个编码的出现次数,minlength确保覆盖所有可能的编码值 counts = np.bincount(encoded, minlength=18) # 重塑为(2,9)的分布矩阵 distribution = counts.reshape(2, 9)
bincount是Numpy中统计整数频次的最优方法,时间复杂度O(n),完全规避循环。
方案2:np.unique结合return_counts
直接提取所有唯一的(i,j)元组并获取对应频次,再填充到结果数组:
import numpy as np from torch.nn.functional import avgpool2d img = np.random.randint(0, 2, (64, 64)) avg = avgpool2d(img, kernel_size=3, padding=1).numpy() * 9 avg = avg.astype(np.int32) # 将两个数组的扁平化结果堆叠为N×2的元组矩阵 pairs = np.stack([img.flat, avg.flat], axis=1) # 获取唯一元组及对应出现次数 unique_pairs, counts = np.unique(pairs, axis=0, return_counts=True) # 初始化分布矩阵并赋值 distribution = np.zeros((2, 9), dtype=np.int32) distribution[unique_pairs[:, 0], unique_pairs[:, 1]] = counts
这种方法更直观,适合需要查看所有唯一元组的场景,性能略逊于bincount但足以应对绝大多数需求。
扩展:N元组的通用统计方法
针对N个数组(如arr1, arr2, arr3)的场景,可采用两种通用思路:
- 编码法:计算每个元组的唯一整数编码,例如
encoded = arr1.flat * (size2*size3) + arr2.flat * size3 + arr3.flat,再用bincount统计。 - 堆叠法:通过
np.stack([arr1, arr2, arr3], axis=-1).reshape(-1, N)将所有元组转为二维数组,再用np.unique(..., axis=0, return_counts=True)统计。
内容的提问来源于stack exchange,提问作者illus
相关产品推荐
相关产品推荐

