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

# Sort
[numpy.sort(a, axis=-1, kind='quicksort', order=None)](http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.sort.html)

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

```python
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するか指定する。省略した場合は、一番最後の軸になる。

```python
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]を使うといい。

```python
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)](http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.argsort.html#numpy.argsort)
実際のデータを並べ替えたくない時は、argsortを使うとindexを返してくれる。

## 1次元の場合
argsortにより得られたindexを、x[index]の用にするとsortされたデータを作ることができる。
降順にしたい場合は、indexを反転させれば良い。

```python
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]のようにしてもうまくいかないので、
下記のように一つ一つ渡してデータを取り出すと良い。

```python

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)](http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.transpose.html#numpy.transpose)

転置したデータが欲しい場合は、transposeかTを使うと良い。
得られるデータは、軸が反転した形になっている。
例えば2次元データAの時には、transposeしたTAは、下記のようになる。
TA[x,y] = A[y,x]
3次元以上でも同じように変換される。
TA[x,y,z] = A[z,y,x]

```python
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を反転させて渡すと同じ値が得られるのがわかる。

```python
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と並んでいるInterleaveｄ配列の画像データをR, G, B のようにPlane配列にする場合に有効。

```python
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]]]
```

```python
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
```

![transpose.png](https://qiita-image-store.s3.amazonaws.com/0/100523/8aeebb14-69ae-89b9-cc08-e0815b01dfeb.png)

```python
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)](http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.roll.html)
配列の要素を回転させる

# 1次元の場合
|sign|direction|
|:---:|:----:|
|+ |forward |
|- |backward|

```python
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に戻す

```python
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)](http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.rollaxis.html#numpy.rollaxis)

aの各次元の大きさを並べ替える
ex.)
aが２次元で3x4だとしたときに、4x3にするとか。

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

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

a.shape が(3,4,5,6)の４次元としたときに
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番目のところに入れるという処理になります。

```python
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)の４次元としたときに
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)

```python
print np.rollaxis(x, 1, 3).shape
(3, 5, 4, 6)
```

# swapaxes
[numpy.swapaxes(a, axis1, axis2)](http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.swapaxes.html#numpy.swapaxes)

axis1,axis2を入れ替える

```python
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]])
```