[python3] すぐに使える numpy の使い方まとめ

# はじめに
numpyは、pythonで配列の計算をするためのライブラリです。配列同士の計算が、高速にできる特徴があります。1次元(ベクトル)、2次元(マトリックス)、3次元(テンソル)配列の直感的な演算処理ができます。

numpyと似たpythonライブラリで有名なpandasがあります。(pandasの中でもnumpyは使われています）
[[python3] 非IT業務でも使える pandas の基本的な使い方](https://qiita.com/saira/items/3fcfc73b967744bec124)
numpyとの違いは、ざっくり下記のような感じでしょうか。numpyは数字だけを扱うのに特化しているイメージですね。pandasは様々なデータ形式や欠損値への処理が可能なので、機械学習などにおいては、元データをpandasで呼び出して整形、numpyで数値処理 => 機械学習ライブラリへといった流れになるのでは無いでしょうか。

|  | numpy | pandas |
|:-:|:-:|:-:|
| 扱うデータ  |  数値  | 様々（数値、文字列、時系列)  |
| 計算速度  | 高速  | numpyよりは遅い  |
|  得意な処理 | 配列演算処理  | データ整形、欠損値処理  |


# インストール

```console:
$ pip3 install numpy
```

# インポート
npとしてインポートするのが慣例。

```python:
import numpy as np
```


# numpy アレイの作成
### pythonリストから作成
単純にpythonリストを渡して、numpyアレイを作成する。

```python:1次元配列
my_list = [1, 3, 4, 10]
np.array(my_list)

# =>  array([1, 3, 4, 10])
```


```python:2次元配列
my_matrix = [[1, 3, 4], [9, 2, 3], [2, 5, 9]]
np.array(my_matrix)

# =>  array([[1, 3, 4],
#            [9, 2, 3],
#            [2, 5, 9]])
```


## numpy関数を使う
### np.arange()
pythonのrange()と同じような働きをする、arange()。np.arange(start, end, (step))。

```python:np.arange()

np.arange(0, 11)
# =>  array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

np.arange(0, 11, 2)
# =>  array([0, 2, 4, 6, 8, 10])
```

### np.zeros() / np.ones()
0のみ、1のみの要素を持つ配列の作成

```python:np.zeros()
np.zeros(4)
# => array([0., 0., 0., 0.,])

np.zeros((3, 2))
# =>  array([[0., 0.],
#            [0., 0.],
#            [0., 0.]])
```

```python:np.ones()
np.ones(3)
# =>  array([1., 1., 1.])
```

### np.linspace()
始まりと終わりの数字を指定して、均等に分割する。np.arange(start, end, 分割数)。

```python:
np.linspace(0,10,3)
# =>  array([ 0.,  5., 10.])

np.linspace(0, 10, 10)
# =>  array([ 0.        ,  1.11111111,  2.22222222,  3.33333333,  4.44444444,
#             5.55555556,  6.66666667,  7.77777778,  8.88888889, 10.        ])
```

### np.eye()

```python:
np.eye(3)
# => array([[1., 0., 0.],
#           [0., 1., 0.],
#           [0., 0., 1.]])
```

## random関数
numpyには、ランダムな数値配列を生成する方法が多数ある。
### .rand()
与えられた形状配列を作成して、0~1の一様分布からランダムに数値をサンプリングする。

```python:
np.random.rand(3)
# =>  array([0.07713379, 0.17275998, 0.57856427])

np.random.rand(4, 4)
# =>  array([[0.1793304 , 0.46509954, 0.29201518, 0.44933199],
#            [0.72024083, 0.69927245, 0.5703159 , 0.15318234],
#            [0.25567981, 0.99377745, 0.39728105, 0.25397251],
#            [0.77973278, 0.79301535, 0.12647443, 0.9207554 ]])
```

### .randn()
"正規分布”からサンプリングする。一様分布からサンプリングするrand()とは異なる。

```python:
np.random.randn(2)
# =>  array([-0.77946845, -0.61496784])

np.random.randn(3, 3)
# =>  array([[ 0.6605953 , -1.59772636,  0.48223159],
#            [ 0.97797005,  1.52575177,  0.50617422],
#            [-1.00068423, -0.40814908, -2.22607208]])
```

### .randint()
ランダムに整数を取り出す。注意点として、指定するstart値は含まれるが、end値は含まれない。
例) np.random.randint(2, 8) => 2~7の中からサンプリング。

```python:
np.random.randint(1, 100)
# =>  25

np.random.randint(1, 100, 5)
# =>  array([73, 14, 66, 88,  2])
```

## numpyアトリビュート、メソッドを使う

下記のような2つの配列を定義する。

```python:
arr = np.arange(25)
# =>  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])
ranarr = np.random.randint(0,50,10)
# =>  array([ 9, 13, 45, 25, 27, 22,  2, 29, 21,  9])
```

### reshape()
同じデータを使用した、新しい形状の配列を返す。

```python:
arr.reshape(5, 5)
# =>  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]])
```

### shape
配列の形状を確認する。メソッドでは無いので、()はつけない。

```python:
arr.shape
# =>  (25,)
arr.reshape(5, 5).shape
# =>  (5, 5)
```

## 要素の取り出し

```python:
arr = np.arange(0, 11)
arr
# =>  array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10])

arr[5]
# =>  5

arr[1:5]
# =>  array([1, 2, 3, 4])
```


## Broadcasting

```python:
arr[0:5] = 100
arr
# =>  array([100, 100, 100, 100, 100,   5,   6,   7,   8,   9,  10])
```


## Selection
```python:
arr = np.arange(1,11)
arr
# =>  array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])

arr > 4
# =>  array([False, False, False, False,  True,  True,  True,  True,  True, True])

bool_arr = arr > 4
arr[bool_arr]
# =>  array([ 5,  6,  7,  8,  9, 10])
```

## 配列演算
pythonのlistとは異なり、配列同士の演算が容易に可能。

```python:
arr = np.arange(0,11)
arr
# =>  array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10])

arr + arr
# =>  array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18, 20])

arr * arr 
# =>  array([  0,   1,   4,   9,  16,  25,  36,  49,  64,  81, 100])

arr**4
# =>  array([    0,     1,    16,    81,   256,   625,  1296,  2401,  4096,  6561, 10000])
```
Numpyには多くの配列関数が付属している。配列全体で操作を実行するために使用できる。

```python:
# 各要素のルートを取得
np.sqrt(arr)
# =>  array([0.        , 1.        , 1.41421356, 1.73205081, 2.        ,
#            2.23606798, 2.44948974, 2.64575131, 2.82842712, 3.        ,
#            3.16227766])

# 指数関数
np.exp(arr)
# =>  array([1.00000000e+00, 2.71828183e+00, 7.38905610e+00, 2.00855369e+01,
#            5.45981500e+01, 1.48413159e+02, 4.03428793e+02, 1.09663316e+03,
#            2.98095799e+03, 8.10308393e+03, 2.20264658e+04])

# sin
np.sin(arr)
# =>  array([ 0.        ,  0.84147098,  0.90929743,  0.14112001, -0.7568025 ,
#            -0.95892427, -0.2794155 ,  0.6569866 ,  0.98935825,  0.41211849,
#            -0.54402111])


# log
np.log(arr)
# =>  array([      -inf, 0.        , 0.69314718, 1.09861229, 1.38629436,
#            1.60943791, 1.79175947, 1.94591015, 2.07944154, 2.19722458,
#            2.30258509])
```