[Python]Numpyの参照、抽出、結合


# １箇所を指定してアクセスする
## 一次元の場合
`X[index]`で指定する。最初のデータのindexは0になる。（Matlabの場合は1なので混乱する)

```python
In [1]: import numpy as np

In [2]: X = np.arange(10)

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

In [4]: print X[0]
0

In [5]: print X[2]
2
```
最後のデータ数えて指定したいときは`X[-index]`とする。C言語などのように`X[len(X)-1]`としなくてもよい。
最後のデータのIndexは-1となり、最初から指定する時は0からなので若干混乱しがち。

```python
In [6]: print X[-1]
9
```
## 二次元の場合
多次元の場合は、カンマ（,）で区切ってそれぞれを指定する。指定の仕方は一次元の時と同じ。

```python
In [17]: X = np.arange(25).reshape(5,5)

In [18]: print X
[[ 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]]

In [19]: print X[3,2]
17

In [20]: print X[-1,-2]
23
```

# 範囲を指定してアクセスする
## 一次元の場合

範囲を指定してアクセスする場合は、`X[start:end:step]`のように指定する。
このときendは含まれないので注意が必要。(Matlabではendは含まれる。）
startを省略すると最初からになり、endを省略すると最後までになり、stepを省略するとstepが1になる。

```python
In [7]: print X[1:3]
[1 2]

In [8]: print X[3:]
[3 4 5 6 7 8 9]

In [9]: print X[:3]
[0 1 2]

In [10]: print X[:]
[0 1 2 3 4 5 6 7 8 9]

In [11]: print X[::]
[0 1 2 3 4 5 6 7 8 9]

In [12]: print X[::2]
[0 2 4 6 8]
```

start,endにマイナスのIndexを指定してもよい。またstepをマイナスにするとデータが最後から取得される。

```python
In [13]: print X[-3:-1]
[7 8]

In [14]: print X[-3:]
[7 8 9]

In [15]: print X[:-3]
[0 1 2 3 4 5 6]

In [16]: print X[::-1]
[9 8 7 6 5 4 3 2 1 0]
```
## 二次元の場合
多次元の場合は、カンマ（,）で区切ってそれぞれを指定する。指定の仕方は一次元の時と同じ。

```python
In [57]: X = np.arange(25).reshape(5,5)

In [58]: print X
[[ 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]]

In [59]: print X[1:3,0:2]
[[ 5  6]
 [10 11]]

In [60]: print X[1:3,::-1]
[[ 9  8  7  6  5]
 [14 13 12 11 10]]
```
# 行を抽出する
X[row], X[row,], X[row,:]の３つの方法の結果は同じになる。
ただしX[row,]は後述の列を抽出するときにX[,col]ができないのでおすすめしない。
rowの部分は、１箇所指定でも、範囲指定でもよい。

```python
In [21]: print X[1]
[5 6 7 8 9]

In [22]: print X[1,]
[5 6 7 8 9]

In [23]: print X[1,:]
[5 6 7 8 9]
```
# 列を抽出する
X[:,col]で指定した列が取り出せるが、取り出した結果は下記の通り１次元のnumpy arrayになる。
Matlabだと同様に列を抽出すると列ベクトルになるのでそのまま行列演算に使えるが、
numpyの場合は抽出した結果が１次元のnumpy arrayになるので、この結果を行列演算に使うときは注意が必要。

```python
In [24]: print X[:,1]
[ 1  6 11 16 21]
```

# 条件を満たすデータを取り出す
X < 3とすると条件を満たす箇所がTrue,満たさない箇所がFalseとなるnumpy arrayが返される。

```python

In [1]: import numpy as np

In [2]: X = np.arange(24,-1,-1).reshape(5,5)

In [3]: print X
[[24 23 22 21 20]
 [19 18 17 16 15]
 [14 13 12 11 10]
 [ 9  8  7  6  5]
 [ 4  3  2  1  0]]

In [4]: X < 3
Out[4]: 
array([[False, False, False, False, False],
       [False, False, False, False, False],
       [False, False, False, False, False],
       [False, False, False, False, False],
       [False, False,  True,  True,  True]], dtype=bool)

In [5]: X % 2 == 0
Out[5]: 
array([[ True, False,  True, False,  True],
       [False,  True, False,  True, False],
       [ True, False,  True, False,  True],
       [False,  True, False,  True, False],
       [ True, False,  True, False,  True]], dtype=bool)
```
`X[X<3]`や`X[X%2==0]`とすると、条件を満たす箇所の値が返される。

```python
In [6]: X[X<3]
Out[6]: array([2, 1, 0])

In [7]: X[X%2==0]
Out[7]: array([24, 22, 20, 18, 16, 14, 12, 10,  8,  6,  4,  2,  0])
```

# 条件を満たすデータを書き換える

`X[X%2==0]=0`とすると、Trueの箇所だけが書き換えられる。

```python
In [8]: X[X%2==0]=0

In [9]: print X
[[ 0 23  0 21  0]
 [19  0 17  0 15]
 [ 0 13  0 11  0]
 [ 9  0  7  0  5]
 [ 0  3  0  1  0]]
```
[]の中は式でなくても、書き換える場所がTrueになっているnumpy arrayであればよい。

```python
In [10]: X = np.arange(24,-1,-1).reshape(5,5)

In [11]: cond = X%2==0

In [12]: print cond
[[ True False  True False  True]
 [False  True False  True False]
 [ True False  True False  True]
 [False  True False  True False]
 [ True False  True False  True]]

In [13]: X[cond]=0

In [14]: print X
[[ 0 23  0 21  0]
 [19  0 17  0 15]
 [ 0 13  0 11  0]
 [ 9  0  7  0  5]
 [ 0  3  0  1  0]]
```

# 指定した行、列の値を取り出す。
##行を指定する場合

```python
In [34]: X = np.arange(24,-1,-1).reshape(5,5)

In [35]: print X
[[24 23 22 21 20]
 [19 18 17 16 15]
 [14 13 12 11 10]
 [ 9  8  7  6  5]
 [ 4  3  2  1  0]]

In [36]: X[[1,3],:]
Out[36]: 
array([[19, 18, 17, 16, 15],
       [ 9,  8,  7,  6,  5]])
```
##列を指定する場合

```python
In [37]: X[:,[0,2]]
Out[37]: 
array([[24, 22],
       [19, 17],
       [14, 12],
       [ 9,  7],
       [ 4,  2]])
```
行を指定する場合と列を指定する場合を合わせると下記のようになる。
これは1行０列目と３行２列目のデータが取り出されている。

```python
In [38]: X[[1,3],[0,2]]
Out[38]: array([19,  7])
```

１行目か３行目でかつ０列目、２列目のデータを取り出す場合下記のように`np.ix_`を使う。
np.ix_では行番号と列番号が入ったnumpy arrayのtupleが返される。

```python
In [39]: X[np.ix_([1,3],[0,2])]
Out[39]: 
array([[19, 17],
       [ 9,  7]])

In [40]: np.ix_([1,3],[1,2])
Out[40]: 
(array([[1],
        [3]]), array([[1, 2]]))
```

# 0以外の場所を抽出する
Matlabなんかだとfindを使うが、numpyの場合はnonzero()を使用する。または、np.whereでも良い。

```python
In [44]: X = np.arange(24,-1,-1).reshape(5,5)

In [45]: i,j=X.nonzero()

In [46]: print i
[0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4]

In [47]: print j
[0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3]

In [48]: X[i,j]
Out[48]: 
array([24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,
        7,  6,  5,  4,  3,  2,  1])
```

```python
In [51]: i,j=np.where(X!=0)

In [52]: print i
[0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4]

In [53]: print j
[0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3]

In [54]: X[i,j]
Out[54]: 
array([24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,
        7,  6,  5,  4,  3,  2,  1])
```

# numpy arrayを結合する。
##縦に結合する
vstackを使う

```python
In [76]: X = np.arange(5)

In [77]: Y = np.arange(4,-1,-1)

In [78]: print X
[0 1 2 3 4]

In [79]: print Y
[4 3 2 1 0]

In [80]: np.vstack((X,Y))
Out[80]: 
array([[0, 1, 2, 3, 4],
       [4, 3, 2, 1, 0]])
```

##横に結合する
hstackを使う

```python
In [81]: np.hstack((X,Y))
Out[81]: array([0, 1, 2, 3, 4, 4, 3, 2, 1, 0])
```

X,Yを列ベクトルにして横に結合する場合は下記のようになる。

```python
In [82]: X.reshape(len(X),1)
Out[82]: 
array([[0],
       [1],
       [2],
       [3],
       [4]])

In [83]: Y.reshape(len(Y),1)
Out[83]: 
array([[4],
       [3],
       [2],
       [1],
       [0]])

In [84]: np.hstack((X.reshape(len(X),1),Y.reshape(len(Y),1)))
Out[84]: 
array([[0, 4],
       [1, 3],
       [2, 2],
       [3, 1],
       [4, 0]])
```

##一次元numpy arrayのtransposeの注意点
X.transposeでも良さそうだが、一次元のnumpy arrayをtransposeしても何も起きない。
二次元にしてからtransposeすると列ベクトルにできる。
transposeは転置の意味。

```python
In [87]: X.transpose()
Out[87]: array([0, 1, 2, 3, 4])

In [88]: X.reshape(1,len(X))
Out[88]: array([[0, 1, 2, 3, 4]])

In [89]: X.reshape(1,len(X)).transpose()
Out[89]: 
array([[0],
       [1],
       [2],
       [3],
       [4]])
```

##画像の結合
行列を結合は画像をくっつけたりするのにも使える。

```lang:ipython
In [102]: from skimage import data

In [103]: from skimage import io

In [104]: image = data.lena()

In [105]: image.shape
Out[105]: (512, 512, 3)

In [106]: patch1 = image[200:200+32,200:200+32,:]

In [107]: patch2 = image[300:300+32,300:300+32,:]

In [108]: patch12 = np.hstack((patch1,patch2))
```
image
![20160104_1.png](https://qiita-image-store.s3.amazonaws.com/0/100523/357b6e94-0a89-a78b-5dd2-d3085ba3d740.png)￼

patch1
![20160104_2.png](https://qiita-image-store.s3.amazonaws.com/0/100523/9b75f516-7efe-a449-029a-679e9a2dff44.png)

patch2
![20160104_3.png](https://qiita-image-store.s3.amazonaws.com/0/100523/0f5d6f58-be96-6f95-8777-5ea422a0f386.png)

patch12
![20160104_4.png](https://qiita-image-store.s3.amazonaws.com/0/100523/9c5127c8-ab03-82d5-70cd-e85bf8e742a5.png)