2011-05-27 74 views
26

类似于this answer,我有一双3D numpy的阵列,ab的,我要通过的a值来的b的条目进行排序。与this answer不同,我只想沿阵列的一个轴进行排序。排序由另一个阵列的numpy的阵列,沿特定轴

我的numpy.argsort()文件的天真阅读:

Returns 
------- 
index_array : ndarray, int 
    Array of indices that sort `a` along the specified axis. 
    In other words, ``a[index_array]`` yields a sorted `a`. 

使我相信,我可以做我的排序与下面的代码:

import numpy 

a = numpy.zeros((3, 3, 3)) 
a += numpy.array((1, 3, 2)).reshape((3, 1, 1)) 
print "a" 
print a 
""" 
[[[ 1. 1. 1.] 
    [ 1. 1. 1.] 
    [ 1. 1. 1.]] 

[[ 3. 3. 3.] 
    [ 3. 3. 3.] 
    [ 3. 3. 3.]] 

[[ 2. 2. 2.] 
    [ 2. 2. 2.] 
    [ 2. 2. 2.]]] 
""" 
b = numpy.arange(3*3*3).reshape((3, 3, 3)) 
print "b" 
print b 
""" 
[[[ 0 1 2] 
    [ 3 4 5] 
    [ 6 7 8]] 

[[ 9 10 11] 
    [12 13 14] 
    [15 16 17]] 

[[18 19 20] 
    [21 22 23] 
    [24 25 26]]] 
""" 
print "a, sorted" 
print numpy.sort(a, axis=0) 
""" 
[[[ 1. 1. 1.] 
    [ 1. 1. 1.] 
    [ 1. 1. 1.]] 

[[ 2. 2. 2.] 
    [ 2. 2. 2.] 
    [ 2. 2. 2.]] 

[[ 3. 3. 3.] 
    [ 3. 3. 3.] 
    [ 3. 3. 3.]]] 
""" 

##This isnt' working how I'd like 
sort_indices = numpy.argsort(a, axis=0) 
c = b[sort_indices] 
""" 
Desired output: 

[[[ 0 1 2] 
    [ 3 4 5] 
    [ 6 7 8]] 

[[18 19 20] 
    [21 22 23] 
    [24 25 26]] 

[[ 9 10 11] 
    [12 13 14] 
    [15 16 17]]] 
""" 
print "Desired shape of b[sort_indices]: (3, 3, 3)." 
print "Actual shape of b[sort_indices]:" 
print c.shape 
""" 
(3, 3, 3, 3, 3) 
""" 

什么是应该做的正确方法?

回答

20

您仍然必须为其他两个维度提供索引才能正常工作。

>>> a = numpy.zeros((3, 3, 3)) 
>>> a += numpy.array((1, 3, 2)).reshape((3, 1, 1)) 
>>> b = numpy.arange(3*3*3).reshape((3, 3, 3)) 
>>> sort_indices = numpy.argsort(a, axis=0) 
>>> static_indices = numpy.indices((3, 3, 3)) 
>>> b[sort_indices, static_indices[1], static_indices[2]] 
array([[[ 0, 1, 2], 
     [ 3, 4, 5], 
     [ 6, 7, 8]], 

     [[18, 19, 20], 
     [21, 22, 23], 
     [24, 25, 26]], 

     [[ 9, 10, 11], 
     [12, 13, 14], 
     [15, 16, 17]]]) 

numpy.indices计算阵列的每个轴的索引时通过其它两个轴(或n - 1轴,其中n =轴的总数)“扁平”。换句话说,这个(对于长篇帖子道歉):

>>> static_indices 
array([[[[0, 0, 0], 
     [0, 0, 0], 
     [0, 0, 0]], 

     [[1, 1, 1], 
     [1, 1, 1], 
     [1, 1, 1]], 

     [[2, 2, 2], 
     [2, 2, 2], 
     [2, 2, 2]]], 


     [[[0, 0, 0], 
     [1, 1, 1], 
     [2, 2, 2]], 

     [[0, 0, 0], 
     [1, 1, 1], 
     [2, 2, 2]], 

     [[0, 0, 0], 
     [1, 1, 1], 
     [2, 2, 2]]], 


     [[[0, 1, 2], 
     [0, 1, 2], 
     [0, 1, 2]], 

     [[0, 1, 2], 
     [0, 1, 2], 
     [0, 1, 2]], 

     [[0, 1, 2], 
     [0, 1, 2], 
     [0, 1, 2]]]]) 

这些是每个轴的标识索引;当用于索引b时,他们重新创建b。

>>> b[static_indices[0], static_indices[1], static_indices[2]] 
array([[[ 0, 1, 2], 
     [ 3, 4, 5], 
     [ 6, 7, 8]], 

     [[ 9, 10, 11], 
     [12, 13, 14], 
     [15, 16, 17]], 

     [[18, 19, 20], 
     [21, 22, 23], 
     [24, 25, 26]]]) 

作为替代numpy.indices,你可以使用numpy.ogrid,作为unutbu建议。由于ogrid生成的对象较小,为了一致起见,我将创建所有三个坐标轴,但请注意unutbu的注释,以便通过生成两个坐标轴来完成此操作。

>>> static_indices = numpy.ogrid[0:a.shape[0], 0:a.shape[1], 0:a.shape[2]] 
>>> a[sort_indices, static_indices[1], static_indices[2]] 
array([[[ 1., 1., 1.], 
     [ 1., 1., 1.], 
     [ 1., 1., 1.]], 

     [[ 2., 2., 2.], 
     [ 2., 2., 2.], 
     [ 2., 2., 2.]], 

     [[ 3., 3., 3.], 
     [ 3., 3., 3.], 
     [ 3., 3., 3.]]]) 
+0

非常好,谢谢! – Andrew 2011-05-28 14:01:46

+2

我喜欢这个回答。为了节省一些内存,可以将'static_indices'改为'static_indices = np.ogrid [0:a.shape [1],0:a.shape [2]]'。这将产生更小的数组,但是会通过利用广播与'np.indices'做同样的事情。它可以像这样使用:'b [sort_indices,static_indices [1],static_indices [2]]'。 – unutbu 2011-05-28 16:26:20

+1

Err,'b [sort_indices,static_indices [0],static_indices [1]]'而不是。 – unutbu 2011-05-28 17:01:13