如何在numpy中反转排列(permutation)数组?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (25)

例如,给定一个自索引(不确定这是否是正确的术语)numpy数组:

a = np.array([3, 2, 0, 1])

这代表了permutation:

0 => 3
1 => 2
2 => 0
3 => 1

我试图在python中生成一个数组来表示逆转换,而不是“手动”执行,也就是说,我想要一个泡泡溶液。在上述情况下,我希望得到的结果是:

array([2, 3, 1, 0])

相当于

0 <= 3                0 => 2
1 <= 2       or       1 => 3
2 <= 0                2 => 1
3 <= 1                3 => 0
提问于
用户回答回答于

置换的逆pnp.arange(n)是索引的数组:

p[s] == np.arange(n)

np.argsort返回:

>>> p = np.array([3, 2, 0, 1])
>>> np.argsort(p)
array([2, 3, 1, 0])
>>> p[np.argsort(p)]
array([0, 1, 2, 3])
用户回答回答于

这只是一个具有恒定内存要求的单程线性时间算法:

from __future__ import print_function
import numpy as np

p = np.array([3, 2, 0, 1])
s = np.empty(p.size, dtype=np.int32)
for i in np.arange(p.size):
    s[p[i]] = i

print('s =', s)

以上代码打印

 s = [2 3 1 0]

或者

import numpy as np

def np_argsort(p):
    return np.argsort(p)

def np_fancy(p):
    s = np.zeros(p.size, p.dtype) # np.zeros is better than np.empty here, at least on Linux
    s[p] = xrange(p.size) 
    return s

def create_input(n):
    np.random.seed(31)
    indices = np.arange(n, dtype = np.int32)
    return np.random.permutation(indices)

从我的IPython笔记本上看:

p = create_input(700000)
%timeit np_argsort(p)
10 loops, best of 3: 72.7 ms per loop
%timeit np_fancy(p)
10 loops, best of 3: 70.2 ms per loop

def np_put(p):
    n = p.size
    s = np.zeros(n, dtype = np.int32)
    i = np.arange(n, dtype = np.int32)
    np.put(s, p, i) # s[p[i]] = i 
    return s

这给了n = 700 000(与上述相同大小):

p = create_input(700000)
%timeit np_put(p)
100 loops, best of 3: 12.8 ms per loop

np.argsort仍然击败np.put较小的方法n

p = create_input(1210)
%timeit np_argsort(p)
10000 loops, best of 3: 25.1 µs per loop
%timeit np_fancy(p)
10000 loops, best of 3: 118 µs per loop
%timeit np_put(p)
10000 loops, best of 3: 25 µs per loop

也用以下Cython如下:

import numpy as np
cimport numpy as np

def in_cython(np.ndarray[np.int32_t] p):    
    cdef int i
    cdef int[:] pmv
    cdef int[:] smv 
    pmv = p
    s = np.empty(p.size, dtype=np.int32)
    smv = s
    for i in xrange(p.size):
        smv[pmv[i]] = i
    return s

计时:

p = create_input(700000)
%timeit in_cython(p)
100 loops, best of 3: 2.59 ms per loop

所以,np.put解决方案的速度仍然不够快(对于这个输入大小,运行了12.8ms;argSort使用了72.7 ms)。

扫码关注云+社区