Edited at

[Python]Numpyデータの並べ替え


Sort

numpy.sort(a, axis=-1, kind='quicksort', order=None)


1次元の場合

sortを使うと昇順に並ぶ。降順にしたい場合は、下記のように[::-1]を使うといい

In [3]: x = np.random.randint(0, 100, size=10)

In [4]: print x
[63 82 80 93 65 96 97 75 2 61]

In [5]: print np.sort(x)
[ 2 61 63 65 75 80 82 93 96 97]

In [6]: print np.sort(x)[::-1]
[97 96 93 82 80 75 65 63 61 2]


多次元の場合

多次元の場合は、どの軸のデータをsortするか指定する。省略した場合は、一番最後の軸になる。

In [7]: x = np.random.randint(0, 100, size=(2,10))

In [8]: print x
[[43 70 88 99 0 83 51 17 19 58]
[11 89 94 11 8 28 9 54 74 67]]

In [9]: print np.sort(x)
[[ 0 17 19 43 51 58 70 83 88 99]
[ 8 9 11 11 28 54 67 74 89 94]]

In [10]: print np.sort(x,axis=0)
[[11 70 88 11 0 28 9 17 19 58]
[43 89 94 99 8 83 51 54 74 67]]

降順にしたい場合は、1次元同様[::-1]を使うといい。

In [11]: print x

[[43 70 88 99 0 83 51 17 19 58]
[11 89 94 11 8 28 9 54 74 67]]

In [12]: print np.sort(x)[:,::-1]
[[99 88 83 70 58 51 43 19 17 0]
[94 89 74 67 54 28 11 11 9 8]]

In [13]: print np.sort(x,axis=0)[::-1]
[[43 89 94 99 8 83 51 54 74 67]
[11 70 88 11 0 28 9 17 19 58]]


argsort

numpy.argsort(a, axis=-1, kind='quicksort', order=None)

実際のデータを並べ替えたくない時は、argsortを使うとindexを返してくれる。


1次元の場合

argsortにより得られたindexを、x[index]の用にするとsortされたデータを作ることができる。

降順にしたい場合は、indexを反転させれば良い。

In [14]: x = np.random.randint(0, 100, size=10)

In [15]: print x
[16 52 64 37 50 68 5 87 99 69]

In [16]: print np.argsort(x)
[6 0 3 4 1 2 5 9 7 8]

In [17]: print x[np.argsort(x)]
[ 5 16 37 50 52 64 68 69 87 99]

In [18]: print x[np.argsort(x)[::-1]]
[99 87 69 68 64 52 50 37 16 5]


多次元の場合

多次元の場合も基本的には1次元と同じ。

ただし、得られたindexをそのままx[index]のようにしてもうまくいかないので、

下記のように一つ一つ渡してデータを取り出すと良い。


In [31]: x = np.random.randint(0, 100, size=(2,10))

In [32]: print x
[[31 72 21 18 47 33 88 12 92 19]
[55 62 19 69 43 65 95 28 20 33]]

In [33]: index = np.argsort(x)

In [34]: print index
[[7 3 9 2 0 5 4 1 6 8]
[2 8 7 9 4 0 1 5 3 6]]

In [35]: print np.array([x[0,index[0,:]],x[1,index[1,:]]])
[[12 18 19 21 31 33 47 72 88 92]
[19 20 28 33 43 55 62 65 69 95]]

In [36]: print np.array([x[0,index[0,::-1]],x[1,index[1,::-1]]])
[[92 88 72 47 33 31 21 19 18 12]
[95 69 65 62 55 43 33 28 20 19]]


transpose

numpy.transpose(a, axes=None)

転置したデータが欲しい場合は、transposeかTを使うと良い。

得られるデータは、軸が反転した形になっている。

例えば2次元データAの時には、transposeしたTAは、下記のようになる。

TA[x,y] = A[y,x]

3次元以上でも同じように変換される。

TA[x,y,z] = A[z,y,x]

In [38]: x = np.array([[0,1,2]])

In [39]: print x
[[0 1 2]]

In [40]: print x.T
[[0]
[1]
[2]]

In [41]: x = np.array(range(4)).reshape(2,2)

In [42]: print x
[[0 1]
[2 3]]

In [43]: print x.transpose()
[[0 2]
[1 3]]

下記は3次元の場合でindexを反転させて渡すと同じ値が得られるのがわかる。

In [44]: x = np.array(range(8)).reshape(2,2,2)

In [45]: xT = x.T

In [46]: print 'x', x
x [[[0 1]
[2 3]]

[[4 5]
[6 7]]]

In [47]: print 'x.T', xT
x.T [[[0 4]
[2 6]]

[[1 5]
[3 7]]]

In [48]: idx = np.array([[i//4,(i//2)%2,i%2] for i in range(8)])

In [49]: x[idx[:,0],idx[:,1],idx[:,2]]
Out[49]: array([0, 1, 2, 3, 4, 5, 6, 7])

In [50]: xT[idx[:,2],idx[:,1],idx[:,0]]
Out[50]: array([0, 1, 2, 3, 4, 5, 6, 7])


並び替える順番を指定する場合

transposeでは並び替える軸の順番を指定することができる。

下記は2,0,1の順番に変換した場合の例。

これはRGBRGBと並んでいるInterleaved配列の画像データをR, G, B のようにPlane配列にする場合に有効。

In [53]: print x

[[[0 1]
[2 3]]

[[4 5]
[6 7]]]

In [54]: print x.transpose(2,0,1)
[[[0 2]
[4 6]]

[[1 3]
[5 7]]]

In [63]: I = sp.misc.imread('./data/SIDBA/Lenna.bmp')

In [64]: r, g, b = I.transpose(2,0,1)

In [65]: np.sum(np.abs(r - I[:,:,0])) + np.sum(np.abs(g - I[:,:,1])) + np.sum(np.abs(b - I[:,:,2]))
Out[65]: 0

import matplotlib.pyplot as plt

import matplotlib.cm as cm

fig, axes = plt.subplots(ncols=4, figsize=(12,8))
axes[0].set_title('color')
axes[0].imshow(I)
axes[0].get_xaxis().set_visible(False)
axes[0].get_yaxis().set_visible(False)

axes[1].set_title('R')
axes[1].imshow(r, cmap=cm.Greys_r, vmin=0,vmax=255)
axes[1].get_xaxis().set_visible(False)
axes[1].get_yaxis().set_visible(False)

axes[2].set_title('G')
axes[2].imshow(g, cmap=cm.Greys_r, vmin=0,vmax=255)
axes[2].get_xaxis().set_visible(False)
axes[2].get_yaxis().set_visible(False)

axes[3].set_title('B')
axes[3].imshow(b, cmap=cm.Greys_r, vmin=0,vmax=255)
axes[3].get_xaxis().set_visible(False)
axes[3].get_yaxis().set_visible(False)


roll

numpy.roll(a, shift, axis=None)

配列の要素を回転させる


1次元の場合

sign
direction

+
forward

-
backward

In [88]: x = np.arange(10)

In [89]: print x
[0 1 2 3 4 5 6 7 8 9]

In [90]: print np.roll(x, 1)
[9 0 1 2 3 4 5 6 7 8]

In [91]: print np.roll(x, -1)
[1 2 3 4 5 6 7 8 9 0]


多次元の場合

axisによって、回転させる軸を選ぶことができる。

なにも指定しない場合は、flatにされた後に回転して元のshapeに戻す

In [92]: x = np.arange(20).reshape(2,10)

In [93]: print x
[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]]

In [94]: print np.roll(x, 2)
[[18 19 0 1 2 3 4 5 6 7]
[ 8 9 10 11 12 13 14 15 16 17]]

In [95]: print np.roll(x, 1, axis=0)
[[10 11 12 13 14 15 16 17 18 19]
[ 0 1 2 3 4 5 6 7 8 9]]

In [96]: print np.roll(x, 1, axis=1)
[[ 9 0 1 2 3 4 5 6 7 8]
[19 10 11 12 13 14 15 16 17 18]]


rollaxis

numpy.rollaxis(a, axis, start=0)

aの各次元の大きさを並べ替える

ex.)

aが2次元で3x4だとしたときに、4x3にするとか。

動きとしては、axisをstartの位置まで移動させます。

直感的にわかりづらいですが、一つ一つ処理を分解すると下記のような処理になります。

a.shape が(3,4,5,6)の4次元としたときに

np.rollaxis(a, axis=3, start=1)


  1. axes = list(range(a.ndim)) ... [0,1,2,3]

  2. axes.remove(axis) ... [0,1,2]

  3. axes.insert(start, axis) ... [0,3,1,2]

  4. return a.transpose(axes) ... a.shape (3,6,4,5)

これは、axis番目の次元の大きさを取り出して、start番目のところに入れるという処理になります。

In [15]: x = np.arange(3*4*5*6).reshape(3,4,5,6)

In [16]: print x.shape
(3, 4, 5, 6)

In [17]: print np.rollaxis(x, 3, 1).shape
(3, 6, 4, 5)

a.shape が(3,4,5,6)の4次元としたときに

np.rollaxis(a, axis=1, start=3)


  1. axes = list(range(a.ndim)) ... [0,1,2,3]

  2. axes.remove(axis) ... [0,2,3]

  3. axes.insert(start, axis) ... [0,2,1,3] ... 入れる場所に注意

  4. return a.transpose(axes) ... a.shape (3,5,4,6)

print np.rollaxis(x, 1, 3).shape

(3, 5, 4, 6)


swapaxes

numpy.swapaxes(a, axis1, axis2)

axis1,axis2を入れ替える

In [4]: x = np.arange(3*4).reshape(3,4)

In [5]: x
Out[5]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])

In [6]: y = np.swapaxes(x,0,1)

In [7]: y
Out[7]:
array([[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])