100 numpy exerices から便利なものをまとめてみた(1-50)

100 numpy exerices から便利なものをまとめてみました。ただし、51番目以降の難易度が高く半分までしか進めませんでした。51番以降はもう少しスキルアップしてから挑戦したいと考えています。

## NO.4 配列のサイズを求めよ
配列のサイズは、numpyのndarray[^1]属性から導き出すことができます。

| 属性             |意味                | 
|:-----------------|:------------------|
| size             | 配列の数           |
| itemsize         | 配列1要素のサイズ   |
| nbytes           | 配列の大きさ       |
| shape            | 各次元の要素数[^2] |
| dtype            | 配列のデータ型[^2] |
```
np_array = np.ones(10)   # 10個の配列を作成
# 配列サイズの求め方その1
array_size = np_array.size * np_array.itemsize
print(array_size)
80
# 配列サイズの求め方その2
print(np_array.nbytes)
80
```

[^1]: ndarrayとは何ぞやについては以下が参考になりました。
      https://deepage.net/features/numpy-ndarray.html
[^2]: 直接は関係ありませんがが、ndarrayという括りでよく使うかなと思っていたので記載しました。

## NO.8 配列の中身を反転
以下の形式で配列内の計算がされるため、これを利用して順序を逆転させることができます。
array[start:end:step]
stepにマイナス値を指定すると逆順となります。

```
# 1次元配列の場合
tmp_np = np.arange(0,10)  # 0-9の配列作成
print(tmp_np)
[0 1 2 3 4 5 6 7 8 9]
print(tmp_np[::-1])
[9 8 7 6 5 4 3 2 1 0]

# 2次元配列の場合
tmp_np = np.arange(10).reshape(2,5) # 2*5の配列を作成
print(tmp_np)
[[0 1 2 3 4]
 [5 6 7 8 9]]
print(tmp_np[::-1, ::-1])
[[9 8 7 6 5]
 [4 3 2 1 0]]
```

## NO.10 0でない項目を抽出

NO.4に続き、ndarrayの属性を使うことで0でない項目を抽出することができます。

```
tmp_np = np.array([1,2,0,0,4,0])
print(tmp_np[tmp_np.nonzero()])
[1 2 4]
```

## NO.11 3*3の単位行列を作成

numpyのeye()またはidentity()を使うことで単位行列を簡単に作成できます。
eye()は、eye(行数, [列数], [対角成分の値], [データ型])のような指定ができるため、identity()より複雑なことができる点が異なる。

```
print(np.eye(3,3,1))
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
print(np.identity(4))
[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]]
```

## NO.15 境界に1・内部に0を設定した2次元配列を作成

配列内を以下のように指定することで値を
[X:-A, Y:-B]
X:行列の行のスタートとなる値
A:行列の行のエンドとなる値。マイナス値の場合は、最後から数えた値になる。
Y:行列の列のスタートとなる値
B:行列の列のエンドとなる値。マイナス値の場合は、最後から数えた値になる。

```
tmp_np = np.ones((7,7))
tmp_np[1:-1,1:-1] = 0
print(tmp_np)
[[1. 1. 1. 1. 1. 1. 1.]
 [1. 0. 0. 0. 0. 0. 1.]
 [1. 0. 0. 0. 0. 0. 1.]
 [1. 0. 0. 0. 0. 0. 1.]
 [1. 0. 0. 0. 0. 0. 1.]
 [1. 0. 0. 0. 0. 0. 1.]
 [1. 1. 1. 1. 1. 1. 1.]]
```


## NO.16 ある配列の周りに0の配列を埋める

numpyのpad()のconstantモードを使うことで配列の周りに0を埋めることができます。
pad(配列, パディングの数, パッドの種類, パッドの種類特有の引数)
```
tmp_np = np.ones((5,5))
tmp_np = np.pad(tmp_np, 1, 'constant')
print(tmp_np)
[[0. 0. 0. 0. 0. 0. 0.]
 [0. 1. 1. 1. 1. 1. 0.]
 [0. 1. 1. 1. 1. 1. 0.]
 [0. 1. 1. 1. 1. 1. 0.]
 [0. 1. 1. 1. 1. 1. 0.]
 [0. 1. 1. 1. 1. 1. 0.]
 [0. 0. 0. 0. 0. 0. 0.]]
```

pad()のこれ以外の使い方

| パッドの種類     |意味                                                       | 
|:----------------|:---------------------------------------------------------|
| edge            | 行と列の最小値番目または最大値番目の値を外側に詰める          |
| linar_ramp      | 行と列に指定した数分の行と列を外側に詰める。その際、一番外側が0になるようにする。ただし、end_valuesを指定した場合、その値が一番外側に設定される。      |                     
| maximum         | 行または列の最大値を外側に詰める       |
| reflect         | 行と列の最小値番目または最大値番目を中心に対称となる値を外側に詰める。最小値番目または最大値番目の値は対象外|
| symmetric       | 行と列の最小値番目または最大値番目を含めて対称となる値を外側に詰める。最小値番目または最大値番目の値も対象|
| wrap            | 行と列の最小値番目または最大値番目とは反対の値から外側に詰める。|

```
# edge
tmp_np = np.arange(16).reshape(4,4)
tmp_np = np.pad(tmp_np, (1,0), mode='edge')
print(Z)
   # 1行目および1列目が追加される
[[ 0  0  1  2  3]
 [ 0  0  1  2  3]
 [ 4  4  5  6  7]
 [ 8  8  9 10 11]
 [12 12 13 14 15]]

# linear_ramp
Z = np.ones((4,4)) * 10
Z = np.pad(Z, (1,2), mode='linear_ramp')
print(Z)
[[ 0.   0.   0.   0.   0.   0.   0. ]
 [ 0.  10.  10.  10.  10.   5.   0. ]
 [ 0.  10.  10.  10.  10.   5.   0. ]
 [ 0.  10.  10.  10.  10.   5.   0. ]
 [ 0.  10.  10.  10.  10.   5.   0. ]
 [ 0.   5.   5.   5.   5.   2.5  0. ]
 [ 0.   0.   0.   0.   0.   0.   0. ]]
Z = np.ones((4,4)) * 10
Z = np.pad(Z, (1,2), mode='linear_ramp', end_values=(2,3))
print(Z)
[[ 2.    2.    2.    2.    2.    2.5   3.  ]
 [ 2.   10.   10.   10.   10.    6.5   3.  ]
 [ 2.   10.   10.   10.   10.    6.5   3.  ]
 [ 2.   10.   10.   10.   10.    6.5   3.  ]
 [ 2.   10.   10.   10.   10.    6.5   3.  ]
 [ 2.    6.5   6.5   6.5   6.5   4.75  3.  ]
 [ 2.    3.    3.    3.    3.    3.    3.  ]]

# maximum
Z = np.ones((4,4)) * 10
Z[2][2] = 29
Z[3][3] = 22
Z = np.pad(Z, (1,1), mode='maximum')
print(Z)
[[29. 10. 10. 29. 22. 29.]
 [10. 10. 10. 10. 10. 10.]
 [10. 10. 10. 10. 10. 10.]
 [29. 10. 10. 29. 10. 29.]
 [22. 10. 10. 10. 22. 22.]
 [29. 10. 10. 29. 22. 29.]]

# reflect
Z = np.ones((4,4)) * 10
Z[0][0] = 14
Z[3][3] = 16
Z[2][2] = 29
Z[1][1] = 22
print(Z)
[[14. 10. 10. 10.]
 [10. 22. 10. 10.]
 [10. 10. 29. 10.]
 [10. 10. 10. 16.]]
Y = np.pad(Z, (3,3), mode='reflect')
print(Y)
[[16. 10. 10.  10. 10. 10. 16.  10. 10. 10.]
 [10. 29. 10.  10. 10. 29. 10.  29. 10. 10.]
 [10. 10. 22.  10. 22. 10. 10.  10. 22. 10.]
              -----------------
 [10. 10. 10. |14. 10. 10. 10.| 10. 10. 14.]
 [10. 10. 22. |10. 22. 10. 10.| 10. 22. 10.]
 [10. 29. 10. |10. 10. 29. 10.| 29. 10. 10.]
 [16. 10. 10. |10. 10. 10. 16.| 10. 10. 10.]
              -----------------
 [10. 29. 10.  10. 10. 29. 10.  29. 10. 10.]
 [10. 10. 22.  10. 22. 10. 10.  10. 22. 10.]
 [10. 10. 10.  14. 10. 10. 10.  10. 10. 14.]]

# symmetric
Y = np.pad(Z, (3,3), mode='symmetric')
print(Y)
[[29. 10. 10.  10. 10. 29. 10.  10. 29. 10.]
 [10. 22. 10.  10. 22. 10. 10.  10. 10. 22.]
 [10. 10. 14.  14. 10. 10. 10.  10. 10. 10.]
              -----------------
 [10. 10. 14. |14. 10. 10. 10.| 10. 10. 10.]
 [10. 22. 10. |10. 22. 10. 10.| 10. 10. 22.]
 [29. 10. 10. |10. 10. 29. 10.| 10. 29. 10.]
 [10. 10. 10. |10. 10. 10. 16.| 16. 10. 10.]
              -----------------
 [10. 10. 10.  10. 10. 10. 16.  16. 10. 10.]
 [29. 10. 10.  10. 10. 29. 10.  10. 29. 10.]
 [10. 22. 10.  10. 22. 10. 10.  10. 10. 22.]]

# wrap
Y = np.pad(Z, (3,3), mode='wrap')
print(Y)
[[22. 10. 10.  10. 22. 10.  10. 10. 22. 10.]
 [10. 29. 10.  10. 10. 29.  10. 10. 10. 29.]
 [10. 10. 16.  10. 10. 10.  16. 10. 10. 10.]
              -------------
 [10. 10. 10. |14. 10. 10.| 10. 14. 10. 10.]
 [22. 10. 10. |10. 22. 10.| 10. 10. 22. 10.]
 [10. 29. 10. |10. 10. 29.| 10. 10. 10. 29.]
 [10. 10. 16. |10. 10. 10.| 16. 10. 10. 10.]
              -------------
 [10. 10. 10.  14. 10. 10.  10. 14. 10. 10.]
 [22. 10. 10.  10. 22. 10.  10. 10. 22. 10.]
 [10. 29. 10.  10. 10. 29.  10. 10. 10. 29.]]
```

## NO.25 3より大きく8以下の値を反転させる
配列の中に判定条件を記述することで簡単に表現できる。

```
Z = np.arange(11)
Z[(3 < Z) & (Z <= 8)] *= -1
print(Z)
```

## NO.29 float型変数の小数部を切り捨て、整数部は1つ増やす(マイナス値はマイナス方向に)
以下の関数を活用して実現する。
abs：絶対値を求める。(マイナス値はプラスの値になる)
ceil：切り上げ
copysign：1つめの値を2つめの値の記号に変換する
```
Z = np.random.uniform(-10,+10,10)
print(Z)
[ 8.46947289 -6.10586232 -8.63005987 -3.4328069   2.5019328  -9.56276246
  9.27694649 -5.27731758  4.28944326  0.48886696]
print (np.copysign(np.ceil(np.abs(Z)), Z))
[  9.  -7.  -9.  -4.   3. -10.  10.  -6.   5.   1.]
```

## NO.36 整数部を取り出す5つの方法

```
Z = np.random.uniform(0,10,10)
print(Z)
[0.81747492 3.36675842 5.17850242 5.47450767 1.78635686 2.17632693
 3.72501725 4.65448867 2.24464464 4.90367288]
print (Z - Z%1) # 余りを使う
[0. 3. 5. 5. 1. 2. 3. 4. 2. 4.]
print (np.floor(Z)) #  floor 切り捨て(低いほうに合わせる)
[0. 3. 5. 5. 1. 2. 3. 4. 2. 4.]
print (np.ceil(Z)-1) # ceil 切り上げ(高いほうに合わせる)
[0. 3. 5. 5. 1. 2. 3. 4. 2. 4.]
print (Z.astype(int)) # intに変換して切り捨て
[0 3 5 5 1 2 3 4 2 4]
print (np.trunc(Z)) # trunc 切り捨て
[0. 3. 5. 5. 1. 2. 3. 4. 2. 4.]
```

## NO.42 2つの配列が一致しているかを確認する

all：配列の要素全てを比較する。
array_equal：配列の要素全てを比較する。
allclose：近似値かをどうかを判断する。

```
A = np.random.random(10)
B = np.random.random(10)
print(np.all(A == B))      # 回答その1
False
print(np.array_equal(A,B)) #　回答その2
False

# おまけ(一致ではなく近似値かを調べる)
A = np.array([1.0, 1.0])
B = np.array([1.0000001, 1.0])
print(np.allclose(A,B))
True
```

## NO.48 型の最小値・最大値
iinfo(型の名称).min：型の最小値
iinfo(型の名称).max：型の最大値
```
for dtype in [np.int8, np.int32, np.int64]:
    print(np.iinfo(dtype).min)
    print(np.iinfo(dtype).max)
-128
127
-2147483648
2147483647
-9223372036854775808
9223372036854775807
```

## NO.50 配列の中からある値に一番近い値を求める
ある値(v)と配列の値をそれぞれに対して減算を行い、0に一番近い値が答えという道び方

```
Z = np.arange(100)
v = np.random.uniform(0,100)
print(v)
46.12163551806881
index = (np.abs(Z-v)).argmin()
print(Z[index])
46
```