70
68

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Pythonその4Advent Calendar 2020

Day 9

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

Last updated at Posted at 2020-02-11

はじめに

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

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

リストの初期化

例として、2行3列[[0, 0, 0], [0, 0, 0]]の2次元配列を次の2通りの方法で作成する。

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マスターになろう!!
実践力を身につける Pythonの教科書
よくわかるPython入門

70
68
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
70
68

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?