【Python】二次元配列を自在に操れ。【初期化・参照・抽出・計算・転置】

# はじめに
Pythonを学ぶ上で避けては通れない**二次元配列の操作（初期化・参照・抽出・計算・転置）** をまとめました。
(※numpyモジュールのインストールが必要。macの場合は、terminalから`pip3 install numpy`でインストール可能。windowsの場合は、こちらを参考に、、[WindowsでPython3, numpy, pandas, matplotlibなどインストール](https://qiita.com/mojaie/items/241eb7006978e6962d05))
基本的に以下のようなコードでコードと出力結果を記載します。

```ex.py
code = 'コード'
# 出力結果
```

# リストの初期化
例として、２行３列`[[0, 0, 0], [0, 0, 0]]`の２次元配列を次の２通りの方法で作成する。

### 1. リスト内包表記を使って二次元配列を作る

```ex1.py
a = [[0 for j in range(3)] for i in range(2)]
print(a)
# [[0, 0, 0], [0, 0, 0]]

a[0][0] = 1
print(a)
# [[1, 0, 0], [0, 0, 0]]
```
### 2. numpyモジュールを使って二次元配列を作る

```ex2.py
import numpy as np

a = np.zeros((2, 3))
print(a)
# [[0, 0, 0],
#  [0, 0, 0]]

print(a)
a[0][0] = 1
# [[1, 0, 0], 
#  [0, 0, 0]]
```

# 一次元の配列を二次元に変換
例：0~5までの数字を2行3列の二次元配列に代入する場合
 **(※-1を使うとその次元のサイズは他の次元から自動的に算出される。)**

```ex.py
import numpy as np

#0~5までの配列を自動生成
a = np.arange(6)
print(a)
# [0 1 2 3 4 5]

#一次元配列aを二次元配列に変換
print(a.reshape(2, 3))
# [[0 1 2]
#  [3 4 5]]

print(a.reshape(-1, 3))
# [[0 1 2]
#  [3 4 5]]

print(a.reshape(2, -1))
# [[0 1 2]
#  [3 4 5]]
```

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

多次元の場合は、カンマ（,）で区切ってそれぞれを指定する。指定の仕方は一次元の時と同じ。

```ex.py
import numpy as np

a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

#a[行の範囲,　列の範囲]
print(a[:3, 1:3])
# [[1 2]
#  [5 6]
#  [9, 10]

print(a[:, 1])
# [[1] 
#  [5]
#  [9]]
```

# 条件を満たすデータを取り出す

```ex.py
import numpy as np

a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

#条件を満たす箇所がTrue,満たさない箇所がFalseとなるnumpy arrayが返される。
print(a > 5)
# [[False False False False]
#  [False False  True  True]
#  [ True  True  True  True]]

#条件を満たす箇所の値が返される。
print( a[a > 5] )
# [ 6  7  8  9 10 11]
```

# 各列・各行の最大値を求める
第二引数`axis`を指定すると、各軸に沿って最大値となるインデックスが返される。
例えば`axis=0`とすると各列ごとの最大値の行番号が返される。各列の最大値そのものは`np.max()`で`axis=0`とすると得られる。(axis=1とすると行ごとの最大値の列番号が返される。)

```ex.py
import numpy as np

a = np.array([[20, 50, 30], [60, 40, 10]])
print(a)
# [[20 50 30]
#  [60 40 10]]

#axis=1とすると列ごとの最大値の列番号が返される。
print(np.argmax(a, axis=0))
# [1 0 0]

#列ごとの最大値
print(np.max(a, axis=0))
# [60 50 30]


#同様にaxis=1とすると行ごとの最大値の列番号が返される。
print(np.argmax(a, axis=1))
# [1 0]

#行ごとの最大値
print(np.max(a, axis=1))
# [50 60]
```

同様に以下の応用が可能である。
・`numpy.sum()`: 合計
・`numpy.mean()`: 平均
・`numpy.min()`: 最小 / `numpy.max()`: 最大
・そのほか（`numpy.std()`: 標準偏差 / `numpy.var()`: 分散など）


# 二次元配列（行列）の転置
### T属性（.T）
`T`属性で元の二次元配列（行列）の転置行列を取得できる。


```ex1.py
import numpy as np

import numpy as np

a = np.arange(6).reshape(2, 3)
print(a)
# [[0 1 2]
#  [3 4 5]]

a_T = a.T
print(a_T)
# [[0 3]
#  [1 4]
#  [2 5]]
```

・T属性が返すのは元の配列のビュー（参照）であり、いずれかの要素を変更するともう一方の要素も変更される。
・2つの`ndarray`が同じメモリのデータを参照している（片方がもう片方のビューである）かどうかは`np.shares_memory()`で確認できる。

```ex2.py
print(np.shares_memory(a, a_T))
# True

a_T[0, 1] = 100
print(a_T)
# [[  0 100]
#  [  1   4]
#  [  2   5]]

print(a)
# [[  0   1   2]
#  [100   4   5]]
```

別々のデータとして処理したい場合はcopy()でコピーを作成する。

```ex3.py
a_T_copy = a.T.copy()
print(a_T_copy)
# [[0 3]
#  [1 4]
#  [2 5]]

print(np.shares_memory(a, a_T_copy))
# False

a_T_copy[0, 1] = 100
print(a_T_copy)
# [[  0 100]
#  [  1   4]
#  [  2   5]]

print(a)
# [[0 1 2]
#  [3 4 5]]
```



# 最後に
Python入門としておすすめの参考書をピックアップしました。
君もPythonマスターになろう!!
<a target="_blank" href="https://www.amazon.co.jp/%25E5%25AE%259F%25E8%25B7%25B5%25E5%258A%259B%25E3%2582%2592%25E8%25BA%25AB%25E3%2581%25AB%25E3%2581%25A4%25E3%2581%2591%25E3%2582%258B-Python%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8-%25E3%2582%25AF%25E3%2582%25B8%25E3%2583%25A9%25E9%25A3%259B%25E8%25A1%258C%25E6%259C%25BA/dp/4839960240/ref=sr_1_1?adgrpid=56067694929&amp;gclid=CjwKCAiA0JKfBhBIEiwAPhZXD4cYthncm_x1N-8XZBt0oTXElVBue7NvUUlkW9tAvi4tNzYYjMtg2xoCyUQQAvD_BwE&amp;hvadid=618680433332&amp;hvdev=c&amp;hvlocphy=1009306&amp;hvnetw=g&amp;hvqmt=e&amp;hvrand=486049685057603636&amp;hvtargid=kwd-334061639888&amp;hydadcr=27294_14598076&amp;jp-ad-ap=0&amp;keywords=%25E5%25AE%259F%25E8%25B7%25B5%25E5%258A%259B%25E3%2582%2592%25E8%25BA%25AB%25E3%2581%25AB%25E3%2581%25A4%25E3%2581%2591%25E3%2582%258B+python%25E3%2581%25AE%25E6%2595%2599%25E7%25A7%2591%25E6%259B%25B8&amp;qid=1675943159&amp;sr=8-1&_encoding=UTF8&tag=sho11hei12-22&linkCode=ur2&linkId=022621387e463616da1274bc9105547e&camp=247&creative=1211">実践力を身につける Pythonの教科書</a>
<a target="_blank" href="https://www.amazon.co.jp/%25E3%2582%2588%25E3%2581%258F%25E3%2582%258F%25E3%2581%258B%25E3%2582%258BPython%25E5%2585%25A5%25E9%2596%2580-%25E5%25AF%258C%25E5%25A3%25AB%25E9%2580%259A%25E3%2583%25A9%25E3%2583%25BC%25E3%2583%258B%25E3%2583%25B3%25E3%2582%25B0%25E3%2583%25A1%25E3%2583%2587%25E3%2582%25A3%25E3%2582%25A2/dp/4938927993/ref=sr_1_1_sspa?__mk_ja_JP=%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A&amp;keywords=Python%25E5%2585%25A5%25E9%2596%2580&amp;qid=1675942677&amp;sr=8-1-spons&amp;psc=1&amp;spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUEyTjVCOUZKSDRCRjZQJmVuY3J5cHRlZElkPUEwMzM5MDg0MlFOS0QxNDZDVTBZRiZlbmNyeXB0ZWRBZElkPUE2MEg3MktFR0FUWEwmd2lkZ2V0TmFtZT1zcF9hdGYmYWN0aW9uPWNsaWNrUmVkaXJlY3QmZG9Ob3RMb2dDbGljaz10cnVl&_encoding=UTF8&tag=sho11hei12-22&linkCode=ur2&linkId=10f3cd88ab01574392075bb958292f73&camp=247&creative=1211">よくわかるPython入門</a>