使用第二个数组中的顺序就地排序numpy数组

时间:2018-10-21 14:39:32

标签: python numpy numpy-ndarray

让两个ndarray:形状为A的{​​{1}}和形状为(n, *m)的{​​{1}}。有没有一种方法可以使用对B进行排序的顺序来对(n, )进行就地排序?

使用np.argsort很容易将AB进行排序,但这不是就地完成的:

A

评论:

  • BA = A[np.argsort(B)] 具有不同的dtype,而A可以具有多个二维。因此,无法将它们堆叠在一起以使用B
  • A占用了大量空间,这就是为什么需要对其进行就地排序的原因。因此,任何需要ndarray.sort()占用两倍空间的解决方案都将无法达到这个目的。
  • 此问题的标题“ Re-arranging numpy array in place”听起来似乎很相关,但是问题本身并不十分清楚,答案与我的问题不符。

2 个答案:

答案 0 :(得分:1)

如果您可以预先将 private void LoadLineChart() { seriesCollection = new SeriesCollection { new ColumnSeries { Title = "1988", Values = new ChartValues<double> { 10, 50, 39, 50, 5, 10, 15, 20, 25, 30, 35, 40, 9, 18, 27, 36, 2, 4, 6, 8, 10, 12, 14, 16, 3, 6, 9, 12, 14, 17, 21 } } }; //adding series will update and animate the chart automatically seriesCollection.Add(new ColumnSeries { Title = "1989", Values = new ChartValues<double> { 12, 71, 41, 21, 9, 6, 3, 61, 41, 21, 01, 8, 6, 4, 2, 63, 72, 81, 9, 04, 53, 03, 52, 02, 51, 01, 5, 05, 93, 05, 01 } }); **LineChart.Series = seriesCollection;** } 设置为结构化数组,其数据类型由形状为A的子数组和相同类型的标量(例如{{ 1}}),则可以相对于(m, )对它进行就地排序。例如:

np.int32

答案 1 :(得分:1)

这是一个解决方案,可以通过遵循索引数组中的循环来工作。可以选择使用pythran对其进行编译,如果行较小(10个元素为80x),则可以大大提高速度;如果行较大(1000个元素为30%),则可以提供较小的速度。

要使其与pythran兼容,我必须对其进行一些简化,因此它仅接受2D数组,并且仅沿轴0排序。

代码:

import numpy as np

#pythran export take_inplace(float[:, :] or int[:, :], int[:])

def take_inplace(a, idx):
    n, m = a.shape
    been_there = np.zeros(n, bool)
    keep = np.empty(m, a.dtype)
    for i in range(n):
        if been_there[i]:
            continue
        keep[:] = a[i]
        been_there[i] = True
        j = i
        k = idx[i]
        while not been_there[k]:
            a[j] = a[k]
            been_there[k] = True
            j = k
            k = idx[k]
        a[j] = keep

使用编译版本运行样本。如上所示,仅对于较小的行才需要编译,对于较大的行,纯python应该足够快。

>>> from timeit import timeit
>>> import numpy as np
>>> import take_inplace
>>> 
>>> a = np.random.random((1000, 10))
>>> idx = a[:, 4].argsort()
>>>
>>> take_inplace.take_inplace(a, idx)
>>>
# correct
>>> np.all(np.arange(1000) == a[:, 4].argsort())
True
>>>
# speed
>>> timeit(lambda: take_inplace.take_inplace(a, idx), number=1000)
0.011950935004279017
>>>
# for comparison
>>> timeit(lambda: a[idx], number=1000)
0.02985276997787878