python - 结构化数组排序的性能(numpy)

标签 python arrays performance numpy sorting

我有一个包含多个字段的数组,我想根据其中两个字段进行排序。这些字段之一是二进制的,例如:

size = 100000
data = np.empty(
            shape=2 * size,
            dtype=[('class', int),
                   ('value', int),]
)

data['class'][:size] = 0
data['value'][:size] = (np.random.normal(size=size) * 10).astype(int)
data['class'][size:] = 1
data['value'][size:] = (np.random.normal(size=size, loc=0.5) * 10).astype(int)

np.random.shuffle(data)

我需要根据value对结果进行排序,对于相同的值,class=0应该先排序。这样做(a):

idx = np.argsort(data, order=['value', 'class'])
data_sorted = data[idx]

与仅对数据['value']进行排序相比,速度似乎慢了一个数量级。鉴于只有两个类,有没有办法提高速度?

通过随机实验,我注意到像这样的方法(b):

idx = np.argsort(data['value'])
data_sorted = data[idx]
idx = np.argsort(data_sorted, order=['value', 'class'], kind='mergesort')
data_sorted = data_sorted[idx]

(a) 花费的时间少约 20%。更改字段数据类型似乎也有一些效果 - float 而不是整数似乎稍微快一些。

最佳答案

最简单的方法是使用 sortorder 参数

sort(data, order=['value', 'class'])

但是,这在我的计算机上运行需要 121 毫秒,而 data['class']data['value'] 分别只需要 2.44 和 5.06 毫秒。有趣的是,sort(data, order='class') 再次花费了 135 毫秒,这表明问题出在结构化数组的排序上。

因此,您使用 argsort 对每个字段进行排序,然后对最终数组进行索引的方法似乎是正确的。但是,您需要单独对每个字段进行排序,

idx=argsort(data['class'])
data_sorted = data[idx][argsort(data['value'][idx], kind='stable')]

运行时间为 43.9 毫秒。 通过从索引中删除一个临时数组,您可以获得非常轻微的加速

idx = argsort(data['class'])
tmp = data[idx]
data_sorted = tmp[argsort(tmp['value'], kind='stable')]

运行时间为 40.8 毫秒。不太好,但如果性能至关重要的话,这是一个解决方法。

这似乎是一个已知问题: sorting numpy structured and record arrays is very slow

编辑 排序中使用的比较的源代码可以在 https://github.com/numpy/numpy/blob/dea85807c258ded3f75528cce2a444468de93bc1/numpy/core/src/multiarray/arraytypes.c.src 中看到。 。 数字类型要简单得多。尽管如此,性能上的巨大差异还是令人惊讶。

关于python - 结构化数组排序的性能(numpy),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55493274/

相关文章:

java - `scale` 中的 `BigDecimal#divide()` 越高,速度越快?

Python OpenCV - 透视变换问题

python - 如何通过引用python中pandas数据框中另一列的值来添加新列

html - 使用 Template Toolkit 在不使用多个循环的情况下勾选复选框

java - 如何删除数组中值相等的元素?

android - 确定和防止 Android 调度延迟

performance - 是否可以查看/优化 Hibernate 查询计划?

python - 具有硬边距和 C 值的支持向量机

python - 使用 Opencv Python 跟踪多个对象

javascript - 为什么我不能将这些附加数据推送到我的数组中?