【実践編】NumPy `numpy.diagflat()` 関数でできること:対角線操作を超えた高度なテクニック


numpy.diagflat(a, k=0)
  • k: (オプション) 対角線オフセット。デフォルトは 0 で、主対角線を意味します。正の値は主対角線より上の対角線、負の値は主対角線より下の対角線に対応します。
  • a: 入力データ。1次元配列またはスカラ値である必要があります。

戻り値

2次元配列。入力された a が1次元配列の場合は、ak 番目の対角線要素として配置された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