如何高效计算11k×12k二维数组/数据框的元素行列高值总数?
高效统计数组每行每列中更大元素总数的优化方案
问题描述
我有一个形状为11k×12k的DataFrame(或二维NumPy数组),需要对每个元素统计其所在行和列中数值更大的元素总数。示例如下:
原数组
array([[1, 3, 1, 5, 3], [3, 7, 3, 2, 1], [2, 3, 1, 8, 9]])
行维度统计结果(每行中比当前元素大的个数)
3 1 3 0 1 1 0 1 3 4 3 2 4 1 0
列维度统计结果(每列中比当前元素大的个数)
2 1 1 1 1 0 0 0 2 2 1 1 1 0 0
总高值统计结果(行+列的总数)
5 2 4 1 2 1 0 1 5 6 4 3 5 1 0
现有代码能实现功能,但处理该规模数据耗时约1小时:
dfT = df.T rows = df.apply(lambda x: np.sum(df>x),axis=1) cols = dfT.apply(lambda x: np.sum(dfT>x),axis=1).T output = rows+cols
我也试过用NumPy拆分子数组合并结果,效率没明显提升:
np.sum(matrix > matrix[:,None], axis=1)
请问有没有更高效的实现方式?
优化方案
核心思路:用排序+索引映射减少重复计算
原方法的问题在于对每个元素都做全行列的比较,时间复杂度为O(M*N*(M+N)),对于11k×12k的规模,计算量会达到约3e12次操作,速度极慢。
我们可以通过排序后计算排名的方式优化,时间复杂度降到O(M*N log(M)) + O(M*N log(N)),大幅减少计算量。
具体实现
1. 行维度统计优化
对每行单独降序排序,通过二分查找定位元素位置,直接得到该行中比当前元素大的个数:
import numpy as np def count_row_greater(matrix): # 每行降序排序 sorted_rows = np.sort(matrix, axis=1)[:, ::-1] # 用二分查找找每个元素在降序数组中第一个小于等于它的位置,即为更大元素的数量 row_counts = np.array([np.searchsorted(sorted_row, val, side='right') for sorted_row, row in zip(sorted_rows, matrix)]) return row_counts
2. 列维度统计优化
同理对每列降序排序,计算每个元素在列中的更大元素数量:
def count_col_greater(matrix): # 每列降序排序 sorted_cols = np.sort(matrix, axis=0)[::-1, :] # 转置后处理,再转置回原形状 col_counts = np.array([np.searchsorted(sorted_col, val, side='right') for sorted_col, col in zip(sorted_cols.T, matrix.T)]).T return col_counts
3. 合并结果
# 假设matrix是你的NumPy数组 row_counts = count_row_greater(matrix) col_counts = count_col_greater(matrix) total_counts = row_counts + col_counts
效率提升原因
- 每行排序的时间是
O(N log N),M行总时间O(M*N log N);列同理是O(M*N log M),总时间复杂度远低于原方法。 searchsorted基于二分查找,单次操作时间O(log K),比逐元素比较的O(K)快得多。
重复元素处理
如果数组中有大量重复元素,该方法依然有效:searchsorted(side='right')会返回第一个小于当前元素的位置,刚好对应降序排列下比当前元素大的元素总数。
测试验证
用示例数组测试,输出结果与需求完全一致:
matrix = np.array([[1, 3, 1, 5, 3], [3, 7, 3, 2, 1], [2, 3, 1, 8, 9]]) row_counts = count_row_greater(matrix) col_counts = count_col_greater(matrix) total_counts = row_counts + col_counts print("行统计结果:") print(row_counts) print("\n列统计结果:") print(col_counts) print("\n总统计结果:") print(total_counts)
Pandas适配
如果使用DataFrame,只需将matrix替换为df.values,最终结果可转回DataFrame:
import pandas as pd df = pd.DataFrame(matrix) row_counts_df = pd.DataFrame(count_row_greater(df.values), index=df.index, columns=df.columns) col_counts_df = pd.DataFrame(count_col_greater(df.values), index=df.index, columns=df.columns) total_counts_df = row_counts_df + col_counts_df
内容的提问来源于stack exchange,提问作者Yasir
相关产品推荐
相关产品推荐

