Copy

MIDORIAck ソフトウェア材料の倉庫

Contents ♪

Python numpy
2025.04.28
numpyの配列はnumpy.ndarray
import numpy as np

nd = np.array([1, 2, 3])
print(type(nd))     # numpy.ndarray
np.array()で作ったnumpyの配列のタイプを表示してみる。
numpy.ndarrayは配列を扱うnumpyの根幹。
2025.04.28
等差数列を生成する arange
import numpy as np

# 等差数列を生成する。
narr = np.arange(8)
print(narr)                 # [0 1 2 3 4 5 6 7]
narr = np.arange(3, 9)
print(narr)                 # [3 4 5 6 7 8]
narr = np.arange(1, 9, 2)
print(narr)                 # [1 3 5 7]
narr = np.arange(0, 3.0, 0.5)
print(narr)                 # [0.  0.5 1.  1.5 2.  2.5]

narr = np.arange(1, 5, 1, dtype=np.float64)
print(narr)                 # [1. 2. 3. 4.]
                            # dtype=出力型
                            # 上は、numpy.float64を指定しているが、通常のfloatなどでもよい。
arange()は引数で指定する開始から停止の手前までの等差数列を作成する。
スライスの指定の仕方と同じである。
dtypeに出力する数値型を指定できる。
等差数列 = numpy.arange(開始, 停止, 間隔, dtype=出力型)
2025.04.28
線形に変化する数列を生成する linspace
import numpy as np

narr = np.linspace(0.0, 5.0, 6)
print(narr)         # [0. 1. 2. 3. 4. 5.]

narr = np.linspace(0.0, 5.0, 3)
print(narr)         # [0.  2.5 5. ]
numpy.linspace()は、線形に変化する数列を作成する。
[start, .., stop] = linspace(start, stop, num)
startからstopまでの線形に変化する間をnum分割した各点の値をサンプリングする。
linspace()メソッドでのstopはスライスのstopとは異なり、stopの値が配列に含まれる。
2025.04.28
添字・スライスによるndarrayの参照
import numpy as np

narr = np.array([[10, 20, 30, 40], [11, 22, 33, 44]])

print(narr[0, 0])       # 10
print(narr[1, 2])       # 33
# リストやタプルとは違う。リストやタプルはarr[1][2]のようにする。

print(narr[0, 2::])     # [30 40]
print(narr[-1, 1::])    # [22 33 44]

narr = np.array([[10, 20, 30, 40], [11, 22, 33, 44], [100, 200, 300, 400]])
print(narr[0:2, 2::])   # [[30 40] [33 44]]
                        # 平方の配列から部分的な矩形のように取り出すことができる。

print(narr[:, 1:2])     # [[ 20] [ 22] [200]]
                        # 全ての行から2列を取り出す

narr = np.array([[10, 20], [30, 40], [50, 60], [70, 80]])
print(narr[[0, 2, 3]])
# [[10 20] [50 60] [70 80]]
# 添字を指定するリストで取り出す

narr = np.array([[10, 20, 30], [11, 22, 33]])
narr[1, 0:2] = 100
# スライスの要素への代入
print(narr) # [[ 10  20  30] [100 100  33]]
numpy.ndarrayの配列は、標準のタプル・リストのようなarr[i]のような添字での参照や、スライスによる部分配列へのアクセスができるが、標準のタプルやリストとは異なるところがある。
標準での多次元配列の添字はarr[次元][次元]であるが、ndarrayではnarr[次元, 次元]である。スライスもarr[添字][スライス]ではなくnarr[添字, スライス]のようになる。
ndarrayの配列もリストのようにスライスが参照する要素への代入ができる。
2025.04.28
配列をコピーする copy
import numpy as np

narr = np.arange(5)
arr1 = np.copy(narr)
arr1[2] *= 10
print(narr)         # [0 1 2 3 4]
arr2 = narr
arr2[2] *= 10
print(narr)         # [ 0  1 20  3  4]

# ndarrayの変数の代入では参照の代入になるので、
# 代入先の変更は代入元の変更にもなる。
# copy()では、実体のコピーが作成される。

narr1 = np.array([[1, 2], [3, 4]])
narr2 = np.array([[5, 6], [7, 8]])

np.copyto(narr1, narr2)
print(narr1)        # [[5 6] [7 8]]
numpy.copy()は、配列のコピーを生成する。
コピー = numpy.copy(配列)
ndarray配列の変数の代入は参照の代入であり、代入された側は代入した側と同じ実体を参照するのでコピーではない。
numpy.copyto()は既存の配列の要素間でのコピーを行う(引数の方向に注意)。
numpy.copyto(コピー先, コピー元)
2025.04.28
配列への参照を返す asarray
import numpy as np

narr = np.arange(5)
narr_r = np.asarray(narr)
narr[2] *= 10
print(narr, narr_r)     # [ 0  1 20  3  4] [ 0  1 20  3  4]
numpy.asarray(配列)は、既存の配列の実体への参照を返す。
ただしこの振る舞いは、配列変数の代入でも同様である。
配列への参照 = numpy.asarray(配列) 
2025.04.28
配列の全要素へ演算する(スカラー演算)
import numpy as np

narr = np.array([1, 2, 3])
narr *= 10          # 配列の各要素を*10の乗算
print(narr)         # [10 20 30]

narr = np.array([[1, 2, 3], [11, 22, 33]])
narr *= 10
print(narr)         # [[ 10  20  30] [110 220 330]]

narr = np.zeros(5)
print(narr + 5)     # [5. 5. 5. 5. 5.]
数値とndarray配列を数値演算すると、配列要素の全てに対し演算を行う(ブロードキャスト)。これは行列式で言うところのスカラー演算である。
ndarray * nは、ndarray配列の要素全てに「* n」が演算された結果になる。
2025.04.28
配列同士の演算
import numpy as np

narr1 = np.array([1, 2, 3])
narr2 = np.array([5, 6, 7])

print(narr1 + narr2)    # [ 6  8 10]
print(narr2 - narr1)    # [4 4 4]
print(narr2 / narr1)    # [5.  3.  2.33333333]
print(narr1 * narr2)    # [ 5 12 21]        ※アダマール積
配列同士の数値演算は、双方の配列の要素対要素で当該演算が行われる。
2025.04.28
配列のべき乗・平方根 power sqrt
import numpy as np

narr = np.arange(5, dtype=float)
narr = np.power(narr, 2)
print(narr)             # [ 0.  1.  4.  9. 16.]
                        # べき乗
narr = np.sqrt(narr)
print(narr)             # [0. 1. 2. 3. 4.]
numpy.power()は、配列の各要素に対しべき乗を演算した結果を返す。
同様にnumpy.sqrt()は平方根を返す。
[べき乗, べき乗, ...] = numpy.power(配列)
[平方根, 平方根, ...] = numpy.sqrt(配列)
2025.04.28
ラジアン変換 radians degrees
import numpy as np

rad = np.radians([0, 30, 60, 90])
print(rad)
# [0.         0.52359878 1.04719755 1.57079633]
# 角度からラジアンに変換

print(np.sin(rad))
# [0.        0.5       0.8660254 1.       ]
# ラジアンを指定する三角関数

deg = np.degrees(rad)
print(deg)
# [ 0. 30. 60. 90.] ラジアンから角度に変換

print(np.deg2rad(180))      # 3.141592653589793
print(np.rad2deg(3.1416))   # 180.00042091829943
                            # 単純な角度とラジアンの変換関数。
numpy.radians()は、配列の各要素が角度[deg]を表す数値とした場合のラジアンへの変換を返す。
numpy.degrees()はその逆で、ラジアンを表す配列要素を角度へ変換する。
[rad, rad, ...] = numpy.radians([deg, deg, ...])
[deg, deg, ...] = numpy.degrees([rad, rad, ...])
また、単一の数値をラジアン・角度に相互変換するメソッドも用意されている。
rad = numpy.deg2rad(deg)
deg = numpy.rad2deg(rad)
numpyの三角関数はラジアンを使う。
2025.04.28
指数・対数 exp log
import numpy as np

narr = np.arange(5)
narr = np.exp(narr)
print(narr)
# [ 1.          2.71828183  7.3890561  20.08553692 54.59815003]
# 底eの指数関数

narr = np.log(narr)
print(narr)
# [0. 1. 2. 3. 4.]
# 底eの対数関数
numpy.exp()、numpy.log()はそれぞれ配列要素に対し底eの指数、底eの対数を返す。
[指数, 指数, ...] = numpy.exp(配列)
[対数, 対数, ...] = numpy.log(配列)
同様に、底2にはlog2()、底10にはlog10()のようなメソッドが用意されている。
2025.04.28
数値演算に使う定数 numpy.piなど
import numpy as np

print(np.pi)        # 3.141592653589793 円周率
print(np.nan)       # nan 非数値
print(np.inf)       # inf 無限大
print(np.e)         # 2.718281828459045 自然対数
numpyには数値演算で使う定数が定義されている。
2025.04.28
numpy定義の数値型
Pythonの整数型はシステムアーキテクチャとは関係なくビット数の制限がないが、numpyでは固定ビットによるC言語的にメモリ上に整列した数値データとして扱うことができる。
numpyは以下の数値型を定義している。
numpy.byte  numpy.ubyte
numpy.int8  numpy.uint8
numpy.int16 numpy.uint16
numpy.int32 numpy.uint32
numpy.int64 numpy.uint64
numpy.float16
numpy.float32
numpy.float64
次のようにnumpyの浮動小数点型のキャストにより精度が変化する。
import numpy as np

print(np.float16(1.23456789))
# 1.234
print(np.float32(1.23456789))
# 1.23456789
2025.04.28
行列の積を求める dot
import numpy as np

# numpy.dot() 行列の積
# 双方の対応する要素の積の和

narr1 = np.array([2, 3])
narr2 = np.array([7, 8])
print(np.dot(narr1, narr2))
# 38    ⇒(2*7)+(3*8) 

arr1 = [2, 3]
arr2 = (7, 8)
print(np.dot(arr1, arr2))
# 38        ndarrayに限らず、リストやタプルなどの配列的なデータを受け入れる。
numpy.dot()は行列の積を返す。
行列の積 = numpy.dot(行列1, 行列2)
行列は、numpy.ndarray配列でも通常のリストなどの配列でもよい。
2025.04.28
逆行列を求める linalg.inv
import numpy as np

narr = np.array([[2, 3], [4, 5]])
ninv = np.linalg.inv(narr)
print(ninv)
# [[-2.5  1.5] [ 2.  -1. ]]

print(np.dot(narr, ninv))
# [[1. 0.] [0. 1.]]
numpy.linalg.inv(行列)は、行列の逆行列を求める。
元の行列と逆行列の内積は対角成分が1の行列になる。
逆行列 = numpy.linalg.inv(行列)
2025.04.28
配列の形状を調べる shape
import numpy as np

narr = np.array([[100, 200, 300], [11, 22, 33]])
print(narr.shape)           # (配列の構成を表す)各次元数をタプルで示す。
print(np.shape(narr))
print(np.shape(narr[1]))
# (2, 3)
# (2, 3)
# (3,)

print(np.shape(([10, 20, 30], [40, 50, 60])))   # 標準のリスト・タプル
# (2, 3)
print(np.shape(10))     # 配列でない場合は
# ()

print(np.ndim(narr))    # 2     次元数
print(narr.ndim)        # 2
print(np.ndim(10))      # 0
print(np.size(narr))    # 6     全体の要素数
print(narr.size)        # 6
numpy.shape()は、配列の次元の構成(形状)をタプルで返す。
numpy.ndarray配列に限らないタプルやリストなどの配列の次元構造を解析する。
(1次元数, 2次元数, ...) = numpy.shape(配列)
numpy.ndarrayのshapeプロパティは、そのndarray配列の次元構成(形状)保持している。
numpy.ndarray.shape ⇒ (1次元数, 2次元数, ...)
numpy.ndim()、numpy.size()はそれぞれ(トップレベルの)次元数、(全体の)要素数を返す。
次元数  = numpy.ndim()
        = numpy.ndarray.ndim
要素数  = numpy.size()
        = numpy.ndarray.size
2025.04.28
配列形状をリシェイプする reshape
import numpy as np

narr = np.arange(8)
print(narr)             # [0 1 2 3 4 5 6 7]
narr = np.reshape(narr, (2, 4))
print(narr)             # [[0 1 2 3] [4 5 6 7]]
narr = np.reshape(narr, (8, ))
print(narr)             # [0 1 2 3 4 5 6 7]
try:
    narr = np.reshape(narr, (3, 2))
    print(narr)             # [0 1 2 3 4 5 6 7]
except ValueError:
    print("Error. cannot reshape")      # Error. cannot reshape
                                        # 次元・要素数の総数が合わない

narr.shape = (4, 2)
print(narr)             # [[0 1] [2 3] [4 5] [6 7]]
                        # shapeプロパティに配列の形として代入する方法。

narr = np.ravel(narr)
print(narr)             # [0 1 2 3 4 5 6 7]
                        # ravelは1次元に平滑化する。

narr = narr.reshape((2, 4))     # ndarrayのメソッドでも同じことができる
                                # 自身をリシェイプするのではなくリシェイプした配列を返す
print(narr.reshape(-1))         # [0 1 2 3 4 5 6 7]
                                # -1は次元数を減らす
numpy.reshape()は、指定する形状(次元の構造を表すタプル)に従って配列をリシェイプ(次元構造を変更)した配列を返す。
リシェイプした配列 = numpy.reshape(配列, (1次元数, 2次元数, ...))
また、numpy.ndarrayのshapeプロパティへ形状のタプルを代入することで、その配列をリシェイプさせることができる。
numpy.ndarray.shape = (1次元数, 2次元数, ...)
numpy.ndarray.reshape()メソッドにより当該ndarray配列をリシェイプした配列を返す。この場合はそれ自身のndarray配列を変更するのではなく、リシェイプした配列を生成した返す。
リシェイプした配列 = numpy.ndarray.reshape((1次元数, 2次元数, ...))
配列の要素数が、形状が示す次元の構成に合わずリシェイプできない場合はValueError例外になる。
reshape()に負数を指定すると、対象の配列から負数が示す次元数を減らした平滑化を行う。2次元配列にreshape(-1)とすれば1次元配列へ平滑化が行われる。
numpy.ravel()は、配列を1次元に平滑化する。
1次元配列 = numpy.ravel(配列)
2025.04.28
行・列を逆転させる flip
import numpy as np

narr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(np.flip(narr, axis=0))
# [[7 8 9]
#  [4 5 6]
# [1 2 3]]
# 行の上下が逆転する。

print(np.flip(narr, axis=1))
# [[3 2 1]
#  [6 5 4]
#  [9 8 7]]
# 列の左右が逆転する。

print(np.flip(narr))
# [[9 8 7]
#  [6 5 4]
#  [3 2 1]]
# axisの指定がない場合は上下左右が逆転する。
numpy.flip()は、配列を逆転させる。
逆転した配列 = numpy.flip(配列, axis=軸)
逆転する方向をaxisで指定する。指定がない場合は行と列の両方が逆転する。
2025.04.28
行列を回転させる roll
import numpy as np

narr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(np.roll(narr, 1, axis=0))
# [[7 8 9]
#  [1 2 3]
#  [4 5 6]]
# 1行回転する。
print(np.roll(narr, -1, axis=0))
# [[4 5 6]
#  [7 8 9]
#  [1 2 3]]
# 1行逆回転する。
print(np.roll(narr, 2, axis=1))
# [[2 3 1]
#  [5 6 4]
# [8 9 7]]
# 2列回転する
print(np.roll(narr, 1))
# [[9 1 2]
# [3 4 5]
# [6 7 8]])
# axisの指定がない場合は平滑化した状態でのシフトのようになる
numpy.roll()は、配列を回転させる。
回転というのは、行列が行か列の方向に環状になっているものとして循環することである。
回転した配列 = numpy.roll(配列, 回転数, axis=軸)
回転数が正の整数ならば、行方向は下へ、列方向は右への回転になる。
回転する方向をaxisで指定する。指定がない場合は平滑化した状態でシフトしたようになる。
2025.04.28
行と列を入れ替える transpose
import numpy as np

narr = np.array([[10, 20, 30], [11, 22, 33]])
print(np.transpose(narr))       # [[10 11] [20 22] [30 33]]
print(narr.T)                   # [[10 11] [20 22] [30 33]]

narr = np.array([1, 2, 3])
print(narr.T)
# [1 2 3]   一次元配列の場合は変化なし。
numpy.transpose()は配列(行列)の行と列を入れ替えた(転置した)配列を返す。
転換配列 = numpy.transpose(行列)
10 20 30    ⇒  10 11
11 22 33        20 22
                30 33
また、numpy.ndarrayのTプロパティは、元の行列の転置した状態を参照できる。
2025.04.28
独立した配列に分割する split
import numpy as np

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

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

narr = np.arange(10)
narr = np.hsplit(narr, 2)
print(narr)
# [array([0, 1, 2, 3, 4]), array([5, 6, 7, 8, 9])]
# 水平方向(列)を分割する。

narr = np.array([[1, 2], [3, 4], [5, 6], [7, 8]])
narr = np.vsplit(narr, 2)
print(narr)
# [array([[1, 2], [3, 4]]),
#  array([[5, 6], [7, 8]])]
# 垂直方向(行)を分割する。分割した配列の個々がndarrayオブジェクトである。
numpy.split()は、配列を独立したndarrayに分割する。
リシェイプのように行や列に分割するのではなく、個々の独立した配列に分割する。
[配列, 配列, ...] = numpy.split(配列, 分割)
分割
    数値で指定: その数での等分に分割
    リストで指定: 要素をその数で分割
結果は、分割されたndarrayオブジェクトのリストが返る。
numpy.hsplit()、numpy.vsplit()は、それぞれ水平方向、垂直方向へ分割する。
[配列, 配列, ...] = numpy.hsplit(配列, 分割)
[配列, 配列, ...] = numpy.vsplit(配列, 分割)
2025.04.28
指定する形状の配列を作成する ones zeros full random
import numpy as np

# 全ての要素が数値1.0の配列を作成する。

narr = np.ones((5, ))
print(narr)             # [1. 1. 1. 1. 1.]
                        # 全て1の値からなる配列を生成する。

narr = np.ones((5, ), dtype=int)
print(narr)             # [1 1 1 1 1]
                        # dtype=出力型 デフォルトは浮動小数点の1.0。

narr = np.ones((4, 3))
print(narr)             # [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.]]

# 全ての要素が数値0.0の配列を作成する。
narr = np.zeros((4, ))  # [0. 0. 0. 0.]
print(narr)
narr = np.zeros((2, 3))
print(narr)             # [[0. 0. 0.] [0. 0. 0.]]

# 全ての要素が指定値の配列を作成する。
narr = np.full((3, 2), 100)
print(narr)             # [[100 100] [100 100] [100 100]]

narr = np.full((3, ), np.nan)
print(narr)             # [nan nan nan]

narr = np.random.random((5, ))
print(narr)             # [nan nan nan]
# [0.18682439 0.60394027 0.45201599 0.50787037 0.88682388]
# 0.0〜1.0の乱数の配列を作成する。

narr = np.array([[1, 2], [3, 4]])
narr = np.zeros_like(narr)
print(narr)             # [[0 0] [0 0]]
                        # _like()は既に存在する配列の形状だけを引き継いで生成する。
                        # zeros_like()と同様に、ones_like()、full_like()がある。
numpy.ones()、.zeros()、.fill()、.random.random()はそれぞれ要素が全て1.0、全て0、全て指定値、乱数で指定された形状のndarray配列を生成する。
[1.0 1.0 ...] = numpy.ones(形状)
[0 0 ...] = numpy.zeros(形状)
[値, 値, ...] = numpy.fill(形状, 値)
[乱数, 乱数, ...] = numpy.random.random(形状)
0や1はデフォルトは浮動小数点で0.0、1.0で生成される。dtypeで数値型を指定すれば指定した型で生成する。
それぞれ〜_like()という関数がある。それらは引数に形状ではなく既存の配列を指定する。指定された配列の形状を解析してその形状と同じ単一値のndarray配列を生成する。
2025.04.28
行・列の挿入 insert
import numpy as np

narr = np.arange(5)
print(np.insert(narr, 0, 10))
# [10  0  1  2  3  4]
print(np.insert(narr, [0, 3, 5], 10))       # 挿入位置のリスト
# [10  0  1  2 10  3  4 10]
print(np.insert(narr, [0, 3], [10, 20]))    # 挿入位置のリストと要素
# [10  0  1  2 20  3  4]

narr = np.array([[10, 20, 30], [11, 22, 33]])
print(np.insert(narr, 1, [1, 2, 3]))
# [10  1  2  3 20 30 11 22 33]
print(np.insert(narr, 1, [1, 2, 3], axis=0))    # 行の挿入
# [[10 20 30] [ 1  2  3] [11 22 33]]
print(np.insert(narr, 2, [1, 2], axis=1))       # 列の挿入
# [[10 20  1 30]
#  [11 22  2 33]]
numpy.insert()は、配列に要素を挿入する。
挿入した配列 = numpy.insert(配列, 挿入位置, 挿入する配列, axis=軸)
挿入位置: 数値で指定、リストで指定
挿入位置は一つの値をインデックスで指定する場合はその位置に、リストで指定する場合はリストのそれぞれの位置に挿入する。
insert()はデフォルトでは対象の配列を平滑化する。配列が行列の場合は、行と列のどちらかに対しなのかをaxisで指定する必要がある。
2025.04.28
行・列の追加 append
import numpy as np
narr = np.arange(5)
print(np.append(narr, 10))
# [ 0  1  2  3  4 10]
print(np.append(narr, [10, 20]))    # リストの要素を追加
# [ 0  1  2  3  4 10 20]

narr = np.array([[10, 20, 30], [11, 22, 33]])
print(np.append(narr, [1, 2, 3]))
# [10 20 30 11 22 33  1  2  3]
print(np.append(narr, [[1, 2, 3]], axis=0)) # 追加する配列に形状を合わせる必要がある
# [[10 20 30] [11 22 33] [ 1  2  3]]
print(np.append(narr, [[1], [2]], axis=1))  # 列に追加
# [[10 20 30  1]
# [11 22 33  2]]
numpy.append()は、配列に要素を末尾に追加する。
追加した配列 = numpy.append(追加する配列, axis=軸)
append()はデフォルトでは対象の配列を平滑化する。配列が行列の場合は、行と列のどちらかに対しなのかをaxisで指定する必要がある。また行列の場合は、追加する配列は追加元と次元が揃っている必要がある。
2025.04.28
行・列の削除 delete
import numpy as np

narr = np.arange(5)
print(np.delete(narr, 2))           # [0 1 3 4]
print(np.delete(narr, [1, 3]))      # [0 2 4]
print(np.delete(narr, -1))          # [0 1 2 3]

narr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=int)
print(np.delete(narr, 1))
# [1 3 4 5 6 7 8 9]
print(np.delete(narr, 1, axis=0))       # 行の削除
# [[1 2 3]
#  [7 8 9]]
print(np.delete(narr, 1, axis=1))       # 列の削除
# [[1 3]
#  [4 6]
#  [7 9]]
print(np.delete(narr, [0, 2], axis=1))  # 0と2の列を削除
# [[2]
#  [5]
#  [8]]
numpy.delete()は、配列の要素を削除する。
削除した配列 = numpy.delete(配列, 削除位置, axis=軸)
削除位置: 数値で指定、リストで指定
delete()はデフォルトでは対象の配列を平滑化する。配列が行列の場合は、行と列のどちらかに対しなのかをaxisで指定する必要がある。
2025.04.28
行・列の積み上げ stack vstack
import numpy as np

narr1 = np.array([1, 2, 3])
narr2 = np.array([4, 5, 6])
narr = np.stack((narr1, narr2))
print(narr)         # [[1 2 3] [4 5 6]]
narr = np.stack((narr1, narr2), axis=1)
print(narr)
# [[1 4]
#  [2 5]
#  [3 6]]

narr = np.vstack((narr1, narr2))
print(narr)
# [[1 2 3]
#  [4 5 6]]
#   stack()のaxis=0と同様である。
narr = np.vstack((narr, [7, 8, 9]))
print(narr)
# [[1 2 3]
#  [4 5 6]
#  [7 8 9]]
#   更に垂直方向に行を追加できる。

narr = np.hstack((narr1, narr2))
print(narr)         # [1 2 3 4 5 6]
                    # 水平方向へ列を追加する。
numpy.stack()は、複数の配列を積み上げて一つの配列を生成する。
スタック配列 = numpy.stack((配列1, 配列2, ...), axis=軸)
axisはデフォルト0で、1を指定した場合は列方向に積み上げる。
numpy.vstack()は、行列の末尾に行を追加する。
行列 = numpy.vstack(行, 行)
行列 = numpy.vstack(行列, 行)
指定する配列が行と行ならばnumpy.stack()と同じであるが、行列に行を指定すると、行列の末尾に行を追加になる。
2025.04.28
切り捨て・四捨五入 floor round etc.
import numpy as np

narr = np.array([-1.0, -0.8, -0.5, -0.3, 0.0, +0.2, +0.5, +0.8, +1.0])
print(narr)
print(np.floor(narr))
print(np.trunc(narr))
print(np.ceil(narr))
print(np.round(narr))
print(np.rint(narr))
print(np.fix(narr))

# [-1. -0.8 -0.5 -0.3 0. 0.2 0.5 0.8 1. ]       元の値
# [-1. -1. -1. -1.  0.  0.  0.  0.  1.]         小数点以下切り捨て(小さい方の整数へ)
# [-1. -0. -0. -0.  0.  0.  0.  0.  1.]         小数点以下切り捨て(単純な切り捨て)
# [-1. -0. -0. -0.  0.  1.  1.  1.  1.]         小数点以下切り上げ
# [-1. -1. -0. -0.  0.  0.  0.  1.  1.]         四捨五入
# [-1. -1. -0. -0.  0.  0.  0.  1.  1.]         四捨五入(整数を求める)
# [-1. -0. -0. -0.  0.  0.  0.  0.  1.]         0に近い方の整数を選択する

narr = np.array([-0.241, -0.251, +0.241, +0.251])
print(np.round(narr, decimals=1))       # 小数点以下2位で
# [-0.2 -0.3  0.2  0.3]

narr = np.array([-241, -251, +241, +251])
print(np.round(narr, decimals=-2))      # 小数点上2桁目で
# [-200 -300  200  300]
numpy.floor()は配列の各要素に対する小数点以下切り捨て、numpy.round()は四捨五入である。
切り捨て・切り上げ・四捨五入には以下のメソッドがある。
numpy.floor(配列)   小数点以下切り捨て(小さい方の整数へ)
numpy.trunc(配列)   小数点以下切り捨て(単純な切り捨て)
numpy.ceil(配列)    小数点以下切り上げ
numpy.round(配列)   四捨五入
numpy.rint(配列)    四捨五入(整数を求める)
numpy.fix(配列)     0に近い方の整数を選択する
decimalsには四捨五入を行う小数点以下の桁を指定できる。デフォルトは0で小数点以下の四捨五入であり結果が整数になる。decimalsが負数の場合は小数点から上の桁の指定になる。
around()というメソッドがあるが、これは単にround()の別名である。
2025.04.28
最大値・最小値 max min
import numpy as np

narr = np.array([12, 8, 10, 4, 7])
print(np.max(narr))     # 12
print(np.min(narr))     # 4

narr = np.array([5, 8, 10, 2])
print(np.argmax(narr))  # 2

narr = np.array([[4, 3, 1], [6, 2, 8], [9, 7, 5]])
print(np.argmax(narr, axis=1))
# [0 2 0]
# 各行の中の最大値を示すインデックスをリストで返す。
print(np.argmax(narr, axis=0))
# [2 2 1]
# 各列の中の最大値を示すインデックスをリストで返す。
numpy.max()、numpy.min()は、それぞれ配列要素の中から最大値、最小値を探して求める。
最大値 = numpy.max(配列)
最小値 = numpy.min(配列)
numpy.argmax()、numpy.argmin()は、それぞれ配列の最大値、最小値のインデックスを求める。
axisで軸(行=1・列=0)指定すると、各行毎または各列毎の最大値、最小値のインデックスをリストで返す。
最大値のidx = numpy.argmax(配列)[maxc1i, maxc2i, ..]  = numpy.argmax(配列, axis=0)列から最大値を探す[maxr1i, maxr2i, ..]  = numpy.argmax(配列, axis=1)行から最大値を探す
2025.04.28
配列をソートする sort
import numpy as np

narr = np.array([3, 5, 2, 1, 4, 5, 8])
print(np.sort(narr))
# [1 2 3 4 5 5 8]

narr = np.array([[5, 3], [2, 9], [7, 4]])
print(narr)
print(np.sort(narr, axis=1))        # [[3 5] [2 9] [4 7]]
print(np.sort(narr, axis=0))
# [[2 3]
#  [5 4]
#  [7 9]]
# axis=0の場合は、行方向に大小比較が評価され、各列のソートになる。

idxs = np.argsort(narr, axis=0)
print(idxs)
# [[1 0] [0 2] [2 1]]
# 第0列は5, 2, 7で、順位は1, 0, 2となる。先頭列の順位のみスライスで抽出してリストにし、
# そのインデックスの順に抽出すると、第0列を基準としたソートができる。
print(idxs[:, 0])       # 0列目のみの順位
# [1 0 2]
print(narr[idxs[:, 0]])
# [[2 9] [5 3] [7 4]]
numpy.sort()は、配列をソートする。
ソート = numpy.sort(配列, axis=軸)
単純な一次元配列の場合は単純なソートであるが、行列の場合はaxisでソートの基準を指定する。axis=1は列の方向に各行がソートされ、axis=0は行の方向に各列がソートされる。
各列ではなく行の配列はそのままである列を基準としてソートしたい場合は、argsort()を使った方法がある。
numpy.argsort()は、ソート結果の順位をインデックスで返す。
ソート順位 = numpy.argsort(配列, axis=軸)
ソート順位の配列は、対象の配列の形状と同じで対応する要素に順位が付けられたものである。
その順位の配列の特定の列をスライスで配列に抽出し、元の配列をその抽出した配列で参照すると、特定の列を基準にソートした結果が得られる(上の例を参照)。
2025.04.28
要素の重複を取り除く unique
import numpy as np

narr = np.array([2, 4, 3, 6, 2, 1, 3])
print(np.unique(narr))      # [1 2 3 4 6]

narr = np.array([[0, 1], [2, 3], [0, 1]])
print(np.unique(narr, axis=0))  # [[0 1] [2 3]]
# この場合axisを指定しなければ、行を平滑化した結果
# [0 1 2 3]
# が返る。
numpy.unique()は、配列の中で要素の重複を取り除き各要素が一意になる配列を返す。
一意な配列 = numpy.unique(配列, axis=軸)
行列の場合はaxisでソートの基準を指定する。axis=1は列の方向に各行の重複を調べ、axis=0は行の方向に各列で重複を調べる。
axisを指定しなければ平滑化してから処理される。
2025.04.28
配列の比較演算と存在確認 isin
import numpy as np

narr1 = np.array([1, 2, 3, 4])
narr2 = np.array([2])
narr_in = (narr1 == narr2)
print(narr_in)              # [False  True False False]
print(narr_in.all())        # False
print(narr_in.any())        # True

print(narr1 == 2)           # [False  True False False] 単純に数値の存在を確認

narr1 = np.array([[1, 2], [3, 4], [5, 6]])
narr2 = np.array([3, 4])
narr_in = (narr1 == narr2)
print(narr_in)              # [[False False] [ True  True] [False False]]
narr_in = narr_in[:, 0]     # スライスで列を抽出
print(narr_in)              # [False  True False]
print(narr_in.all())        # False
print(narr_in.any())        # True

narr1 = np.array([[1, 2, 3], [4, 5, 6]])
narr_in = np.isin(narr1, [2, 3, 4])
print(narr_in)
# [[False  True  True] [ True False False]]
2つのndarray配列を「A==B」のように比較すると、Aの中にBの要素に一致する要素が存在する場所をTrue/Falseで表すリストが返る。
numpy.isin()は、配列の中にリストなどで列挙する値と同じものを、配列の形のままTrue/Falseで返す。
一致結果の配列 = numpy.isin(配列, 検査リスト)
2025.04.28
条件一致した場所を調べる where
import numpy as np

narr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print(narr == 4)
# [[False False False  True] [False False False False]]
print(narr < 5)
# [[ True  True  True  True] [False False False False]]

narr = np.arange(10, 20)
print(narr)
# [10 11 12 13 14 15 16 17 18 19]
print(np.where(narr % 2 == 0))
# (array([0, 2, 4, 6, 8]),)

narr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print(np.where(narr % 3 == 0))
# (array([0, 1]), array([2, 1]))
# 最初の[0, 1]は、3で割り切れる数が0と1行で一致したことを示す。
# 次の[2, 1]は、3で割り切れる数が2と1列で一致したことを示す。

print(np.argwhere(narr % 3 == 0))
# [[0 2] [1 1]]
# argwhereは、一致した行・列の位置をリストで列挙して返す。この方がわかりやすいかもしれない。

print(np.where(narr % 3 == 0, True, False))
# [[False False  True False]
#  [False  True False False]]
# whereに追加で2つの引数を指定すると、条件に一致する要素としない要素をそれぞれに置き換える。
2つのndarray配列を「A < 値」のように比較演算すると、その条件を満たす要素の場所をTrue/Falseで表すリストが返る。
numpy.where()は、次元ごとの条件に一致した場所を次元ごとの配列で返す。
([一致した行], [一致した列]) = numpy.where(配列に対する比較演算)
numpy.argwhere()はwhere()と同じだが、分割した配列ではなくリストにまとめて返す。
[[一致した行], [一致した列]] = numpy.argwhere(配列に対する比較演算)
またwhere()は、引数に真の値と偽の値を指定すると、対象の配列の形状で、条件一致する場所をそれぞれの値に置き換えた配列が返る。
一致結果配列 = numpy.where(配列に対する比較演算, 真の値, 偽の値)
2025.04.28
合計・平均を求める sum mean
import numpy as np

narr = np.array([3.5, 2.2, 5.4, 7.1, 4.9, 1.8])
print(np.mean(narr))
# 4.15

print(np.sum(narr) / narr.size)     # 合計を総数で割ると平均になる 
# 4.15 

narr = np.array(([3, 5], [2, 7]))
print(np.mean(narr))            # 4.25      全ての要素の平均
print(np.mean(narr, axis=0))    # [2.5 6. ]  (3+2)/2、(5+7)/2
print(np.mean(narr, axis=1))    # [4.  4.5]  (3+5)/2、(2+7)/2
print(np.mean(narr, dtype=int)) # 4         整数で平均を演算する。
numpy.sum()は配列要素の合計、numpy.mean()は配列要素の平均を求める。
平均 = numpy.mean(配列)
合計 = numpy.sum(配列)
axis(軸)を指定すると、行と列のそれぞれの軸で個別に求める。
numpy.mean(配列, axis = 0)  各列の平均
numpy.mean(配列, axis = 1)  各行の平均
dtypeに数値型を指定すると、その型で演算する。デフォルトは浮動小数点である。
2025.04.28
標準偏差を求める std
import numpy as np

# numpy.std() 標準偏差を求める
narr = np.array([45, 55, 70, 35, 80, 50, 55, 90, 40, 65, 85, 30, 75])
print(np.std(narr))
# 18.755669754210167

# いわゆる学校成績の偏差値は、「((得点-平均)/標準偏差) * 10 + 50で求められる。
# 上の配列を100点満点の結果だとすると平均は60点付近。
# 60点の偏差値は、上で求めた標準偏差から約50となる。
print(((60 - np.mean(narr)) / 18.755669754210167) * 10.0 + 50.0)
# 50.205066195798764

# 分散の平方根は標準偏差である。
print(np.var(narr), np.sqrt(np.var(narr)))
# 351.77514792899404 18.755669754210167

# 不偏標準偏差・不偏分散を求める場合、母数-1の-1はddofで指定できる。
print(np.var(narr, ddof=1), np.std(narr, ddof=1))
# 381.0897435897436 19.52152001227731
numpy.std()は、配列から標準偏差を求める。
標準偏差 = numpy.std(配列)
また、numpy.var()は配列の分散を求める。分散の平方根が標準偏差である。
分散 = numpy.var(配列)
平方根 = numpy.sqrt(配列)
標準偏差 = numpy.sqrt(numpy.std(配列))
2025.04.28
ファイルへの保存と読み込み tofile fromfile
import numpy as np

narr1 = np.array([[10, 20], [11, 22]])
narr1.tofile('file.bin')
narr2 = np.fromfile('file.bin', dtype=np.int64)
print(narr2)                    # [10 20 11 22]
print(narr2.reshape((2, 2)))    # [[10 20] [11 22]]
numpy.ndarray配列のtofile()メソッドは、その配列をバイナリファイルに保存する。
fromfile()メソッドはそのファイルを読み込んでndarray配列に復元する。
numpy.ndarray.tofile(バイナリファイル名)
配列 = numpy.fromfile(ファイル名, dtyle=数値型)
tofile()はデフォルトでは配列をそのままバイナリデータで保存し、数値型と次元の形状の情報は保存しない。この場合、fromfile()ではdtypeを指定して保存時の数値型を指定しなければ正しく読み取ることができない。また形状はfromfile()では復元されない。
import numpy as np

narr1 = np.array([[10, 20], [11, 22]])
narr1.tofile('file.bin', sep=" ")
narr2 = np.fromfile('file.bin', dtype=float, sep=" ")
print(narr2)            # [10. 20. 11. 22.]
tofile()にsepで区切り文字を指定すると、その文字で区切ったテキスト形式で保存される。その場合では、fromfile()で読み込むときにdtypeで数値型を合わせる必要はない。あるいはdtypeを指定すれば読み込み後にその型に変換した配列にできる。ただしそれでも形状は復元できない。
2025.04.28
npy形式ファイルへの保存と読み込み save load
import numpy as np

narr = np.array([[10, 20], [11, 22]])
np.save('test.npy', narr)
lnarr = np.load('test.npy')
print(lnarr)            # [[10 20] [11 22]]
numpy.save()メソッドは、配列をnpy形式ファイルに保存する。
numpy.load()メソッドはそのファイルを読み込んでndarray配列に復元する。
numpy.save(ファイル.npy, 配列)
配列 = numpy.load(ファイル.npy)
npy形式ファイルには配列の形状などの情報が含まれており、load()で元の配列を復元することができる。
import numpy as np

narr1 = np.arange(5)
narr2 = np.arange(5, 10)
np.savez('test.npz', A=narr1, B=narr2)
znarr = np.load('test.npz')
print(znarr['A'], znarr['B'])   # [0 1 2 3 4] [5 6 7 8 9]
numpy.savez()は、複数の配列を.npz形式のアーカイブとして保存できる。
savez()では複数の配列に引数による名前を付ける。そして.npz形式のアーカイブをnumpy.load()で読み込んだとき、その名前をキーとした辞書として各配列が参照できる。
numpy.savez(ファイル.npz, キー1=配列1, キー2=配列2, ...)
{キー1:配列1, キー2:配列2, ...} = numpy.load(ファイル.npz)
2025.04.28
csvファイルの読み込み loadtxt
test.csv
A, B, C, D, E
1, 2, 3, 4
10, 20, 30, 40
11, 22, 33, 44
import numpy as np

narr = np.loadtxt('test.csv', delimiter=',', skiprows=1)
print(narr)
# [[ 1.  2.  3.  4.]
#  [10. 20. 30. 40.]
#  [11. 22. 33. 44.]]

narr = np.loadtxt('test.csv', delimiter=',', skiprows=2, usecols=(1, 2))
print(narr)
# [[20. 30.]
#  [22. 33.]]

narr = np.array([[1, 2, 3], [4, 5, 6]])
np.savetxt('testout.csv', narr, delimiter=',', fmt='%d')
$ cat testout.csv
1,2,3
4,5,6
numpy.loadtxt()は、行と列からなる表形式のテキストファイル(主にCSV形式)を行・列の配列に読み込む。
numpy.loadtxt(ファイル.csv, delimiter=区切り文字, skiprows=読み飛ばし行数, usecols=列リスト)
delimiterにファイルの区切り文字を指定する。delimiterのデフォルトは空白文字。CSV形式では主にdelimiterに「,」を指定することが多い。
skiprowsは行頭のタイトルなどを読み飛ばす場合に、読み飛ばし行数を指定する。
usecolsには、読み込む列番号(先頭は0)のリストを指定する(範囲ではないので全て指定する必要がある)。
numpy.savetxt()は、配列をCSV形式ファイルとして保存する。
numpy.savetxt(ファイル.csv, 配列, delimiter=区切り文字, fmt=書式)
fmtには文字列のフォーマット(formatやf"{〜}")の書式を指定する。デフォルトでは浮動小数点になるがその場合、
1.000000000000000000e+00,2.000000000000000000e+00, ..
のように書き込まれる。
2025.04.28
乱数を発生する random
import numpy as np

rnd = np.random.default_rng()   # 乱数ジェネレータ
print(rnd.random(5))
# [0.35781293 0.24662761 0.95018583 0.30841601 0.69634013]
print(rnd.random(5))
# [0.60525738 0.91076414 0.53535436 0.45136241 0.68202423]

rnd = np.random.default_rng(123)
print(rnd.random(5))
# [0.68235186 0.05382102 0.22035987 0.18437181 0.1759059 ]
print(rnd.random(5))
# [0.68235186 0.05382102 0.22035987 0.18437181 0.1759059 ]

rnd = np.random.default_rng()
print(rnd.random((3, 2)))
# [[0.44251632 0.46615929]
#  [0.3714578  0.35528137]
#  [0.03952577 0.36500791]]

rnd = np.random.default_rng()
print(rnd.integers(1, 7))
# 3
# 1〜6の整数をランダムの返す(サイコロ)。

print(rnd.integers(1, 7, (2, 3)))
# [[3 4 5] [2 6 3]]
# 同様に、生成したい行列の形をタプルで指定できる。
numpy.random.default_rng()は、乱数のジェネレーターオブジェクトを生成する。
乱数ジェネレーターのrandom()メソッドは、0.0〜1.0未満の乱数を指定する個数発生する。
乱数ジェネレータ = np.random.default_rng(シード)
乱数リスト = 乱数ジェネレータ.random(個数 or タプル)
タプルの指定: (x, y)はx行各y個の行列で生成
乱数ジェネレータはシードを指定できる。シードを指定した場合はそのシードで固定化した(何度でも同じ)乱数を発生させる。
乱数ジェネレーターのintegers()メソッドは、指定する整数範囲からランダムな整数を発生する。
整数乱数リスト = 乱数ジェネレータ.integers(最小, 最大、個数 or タプル)