【実践編】NumPy `numpy.diagflat()` 関数でできること:対角線操作を超えた高度なテクニック
numpy.diagflat(a, k=0)
k
: (オプション) 対角線オフセット。デフォルトは0
で、主対角線を意味します。正の値は主対角線より上の対角線、負の値は主対角線より下の対角線に対応します。a
: 入力データ。1次元配列またはスカラ値である必要があります。
戻り値
2次元配列。入力された a
が1次元配列の場合は、a
が k
番目の対角線要素として配置された2次元配列が返されます。a
が2次元配列の場合は、その k
番目の対角線が抽出された1次元配列が返されます。
例
1次元配列を主対角線に配置
import numpy as np
# 入力データ
data = np.array([1, 2, 3, 4, 5])
# 対角線化
result = np.diagflat(data)
print(result)
出力:
[[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]]
2次元配列の対角線を抽出
# 入力データ
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 1番目の対角線抽出
result = np.diagflat(data, k=1)
print(result)
出力:
[2 5 8]
# 入力データ
data = np.array([1, 2, 3, 4, 5])
# 主対角線より1つ上の対角線に配置
result1 = np.diagflat(data, k=1)
# 主対角線より2つ下の対角線に配置
result2 = np.diagflat(data, k=-2)
print(result1)
print(result2)
出力:
[[0 1 0 0 0]
[0 0 2 0 0]
[0 0 0 3 0]
[0 0 0 0 4]
[0 0 0 0 5]]
[[5 0 0 0 0]
[0 4 0 0 0]
[0 0 3 0 0]
[0 0 0 2 0]
[0 0 0 0 1]]
numpy.diagflat()
関数は、行列の対角化など、様々な用途に使用できます。- 対角線要素以外にも要素を配置したい場合は、
numpy.fill_diagonal()
関数を使用することもできます。 numpy.diagflat()
関数は、対角線要素のみを操作するため、メモリ効率性に優れています。
1次元配列を様々な対角線に配置
import numpy as np
# 入力データ
data = np.array([1, 2, 3, 4, 5])
# 主対角線
result1 = np.diagflat(data)
# 主対角線より1つ上の対角線
result2 = np.diagflat(data, k=1)
# 主対角線より2つ下の対角線
result3 = np.diagflat(data, k=-2)
print("主対角線:")
print(result1)
print("\n主対角線より1つ上の対角線:")
print(result2)
print("\n主対角線より2つ下の対角線:")
print(result3)
出力
主対角線:
[[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]]
主対角線より1つ上の対角線:
[[0 1 0 0 0]
[0 0 2 0 0]
[0 0 0 3 0]
[0 0 0 4 0]
[0 0 0 0 5]]
主対角線より2つ下の対角線:
[[5 0 0 0 0]
[0 4 0 0 0]
[0 0 3 0 0]
[0 0 0 2 0]
[0 0 0 0 1]]
2次元配列の対角線を抽出
import numpy as np
# 入力データ
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 0番目の対角線
result1 = np.diagflat(data)
# 1番目の対角線
result2 = np.diagflat(data, k=1)
# 2番目の対角線
result3 = np.diagflat(data, k=2)
print("0番目の対角線:")
print(result1)
print("\n1番目の対角線:")
print(result2)
print("\n2番目の対角線:")
print(result3)
出力
0番目の対角線:
[[1 0 0]
[0 5 0]
[0 0 9]]
1番目の対角線:
[2 6 8]
2番目の対角線:
[3 7]
対角線要素の演算
import numpy as np
# 入力データ
data = np.array([1, 2, 3, 4, 5])
# 主対角線要素を2倍する
result1 = np.diagflat(data * 2)
# 主対角線より1つ上の対角線に平方根を配置
result2 = np.diagflat(np.sqrt(data), k=1)
print("主対角線要素を2倍:")
print(result1)
print("\n主対角線より1つ上の対角線に平方根:")
print(result2)
主対角線要素を2倍:
[[2 0 0 0 0]
[0 4 0 0 0]
[0 0 6 0 0]
[0 0 0 8 0]
[0 0 0 0 10]]
主対角線より1つ上の対角線に平方根:
[[0 1 0 0 0]
[0 0 1.4142135623730951 0 0]
[0 0 1.7320508075688772 0 0]
[0 0 0 2 0]
[0 0 0 0
以下に、numpy.diagflat()
の代替方法として検討すべきいくつかオプションを紹介します。
np.fill_diagonal() 関数
np.fill_diagonal()
関数は、指定した値を2次元配列の対角線要素に配置するために使用されます。numpy.diagflat()
関数と異なり、対角線以外の要素も同時に操作することができます。
import numpy as np
# 入力データ
data = np.array([1, 2, 3, 4, 5])
# 主対角線に1を配置
result1 = np.array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
np.fill_diagonal(result1, 1)
# 主対角線より1つ上の対角線に2を配置
result2 = np.array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
np.fill_diagonal(result2, 2, k=1)
print("主対角線に1を配置:")
print(result1)
print("\n主対角線より1つ上の対角線に2を配置:")
print(result2)
出力
主対角線に1を配置:
[[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]]
主対角線より1つ上の対角線に2を配置:
[[0 2 0 0 0]
[0 0 2 0 0]
[0 0 0 2 0]
[0 0 0 0 2]
[0 0 0 0 0]]
ループによる要素操作
シンプルなケースであれば、ループを用いて要素を操作する方法も有効です。
import numpy as np
# 入力データ
data = np.array([1, 2, 3, 4, 5])
# 主対角線に1を配置
n = len(data)
result1 = np.zeros((n, n))
for i in range(n):
result1[i, i] = 1
# 主対角線より1つ上の対角線に2を配置
result2 = np.zeros((n, n))
for i in range(1, n):
result2[i - 1, i] = 2
print("主対角線に1を配置:")
print(result1)
print("\n主対角線より1つ上の対角線に2を配置:")
print(result2)
出力
主対角線に1を配置:
[[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]]
主対角線より1つ上の対角線に2を配置:
[[0 2 0 0 0]
[0 0 2 0 0]
[0 0 0 2 0]
[0 0 0 0 2]
[0 0 0 0 0]]
scipy.sparse モジュールの利用
疎行列を扱う場合は、scipy.sparse
モジュールの diags()
関数を使用することができます。
import numpy as