Numpy argsort与Scipy.stats rankdata对比探究
关于numpy.argsort()与scipy.stats.rankdata()的疑问解答
嘿,我来帮你拆解这几个实际使用中容易纠结的问题~
一、核心用途的本质区别
这俩函数的定位完全不同,核心功能没有重叠:
numpy.argsort():它的核心是返回数组排序后的元素索引。简单说就是告诉你“按从小到大排序的话,原数组里的元素分别在哪些位置”。比如对数组[3, 1, 2],argsort()会返回[1, 2, 0]——意思是排序后的第一个元素是原数组索引1的1,第二个是索引2的2,第三个是索引0的3。它只负责给出排序的索引逻辑,不关心元素的“排名”计算。scipy.stats.rankdata():它的核心是计算每个元素在数组中的排名。直接返回和原数组长度相同的数组,每个位置的值是对应元素的排名。还是拿[3, 1, 2]举例,默认method='average'时会返回[3.0, 1.0, 2.0];如果有重复值,比如[2, 1, 2],它还能通过不同的method参数(比如min/max/dense)处理重复元素的排名逻辑——这是argsort做不到的,因为argsort只会给重复元素分配不同的索引,不会统一它们的排名。
简单总结:argsort是“找排序索引”,rankdata是“算元素排名”,这是本质上的功能差异。
二、性能优势差异(针对大小数组)
性能得分场景来看:
- 小数组(长度<1000):两者的差异几乎可以忽略,哪怕
rankdata内部会做更多逻辑处理,在小数组规模下完全感知不到速度差别。 - 大数组(长度>10万甚至百万):
numpy.argsort()的性能会明显更优。原因很简单:argsort是numpy底层用高度优化的C语言实现的排序算法(一般是快速排序或归并排序,根据数组类型自动选择),而rankdata的内部实现其实依赖于argsort,还要额外处理排名逻辑(比如重复值的分组、排名计算),相当于在argsort的基础上多了一层计算,所以大数组下速度会慢不少。
你可以用timeit自己测试验证:
import numpy as np from scipy.stats import rankdata import timeit # 生成100万元素的随机数组 arr = np.random.rand(1_000_000) # 测试argsort平均时间 argsort_avg = timeit.timeit(lambda: np.argsort(arr), number=10) / 10 # 测试rankdata平均时间 rankdata_avg = timeit.timeit(lambda: rankdata(arr), number=10) / 10 print(f"argsort平均耗时: {argsort_avg:.4f}s") print(f"rankdata平均耗时: {rankdata_avg:.4f}s")
跑出来的结果大概率是argsort快2-5倍左右,具体取决于你的硬件配置。
三、导入rankdata的内存开销
单独导入rankdata的内存开销非常小,不用过度担心:
- 如果你用
from scipy.stats import rankdata,Python只会加载scipy.stats模块中与rankdata相关的部分,而不是整个scipy库。整个scipy.stats模块加载后的内存占用大概在几MB级别(具体取决于Python和scipy版本,一般不会超过10MB),这在现代电脑或服务器上几乎可以忽略。 - 要是你在极端内存受限的环境(比如嵌入式设备),可能需要留意,但这类场景下通常也不会用到scipy这类库。
另外,建议直接从scipy.stats导入单个函数,而不是导入整个scipy,能减少一点不必要的内存占用。
内容的提问来源于stack exchange,提问作者Boreal Coder
相关产品推荐
相关产品推荐

