NumPy配列ndarrayの下三角行列・上三角行列を抽出・生成(tril, triu, tri)

Modified: | Tags: Python, NumPy

対角線より上の成分が0である行列を下三角行列、対角線より下の成分が0である行列を上三角行列という。

NumPy配列ndarrayから下三角行列・上三角行列を抽出(取得)するにはnumpy.tril(), numpy.triu()、下三角行列・上三角行列を新たに生成するにはnumpy.tri()を使う。

ここでは以下の内容について説明する。

  • NumPy配列ndarrayから下三角行列を抽出(取得): numpy.tril()
  • NumPy配列ndarrayから上三角行列を抽出(取得): numpy.triu()
  • 下三角行列と上三角行列を相互に変換
  • 下三角行列・上三角行列を生成: numpy.tri()

対角行列を生成したり対角成分を抽出したりするにはnumpy.diag()を使う。

numpy.tril()numpy.triu()を利用して対称行列を生成することもできる。

NumPy配列ndarrayから下三角行列を抽出(取得): numpy.tril()

numpy.tril()の引数にnumpy.ndarrayを指定すると、対角線より上の成分を0としたnumpy.ndarrayが返される。ビューではなく、元のnumpy.ndarrayとメモリを共有しないコピー。

import numpy as np

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

print(np.tril(a))
# [[ 0  0  0  0]
#  [ 4  5  0  0]
#  [ 8  9 10  0]
#  [12 13 14 15]]

第二引数kで境界となる対角線の位置を指定可能。正の値だと上側(右側)、負の値だと下側(左側)に移動する。

print(np.tril(a, k=2))
# [[ 0  1  2  0]
#  [ 4  5  6  7]
#  [ 8  9 10 11]
#  [12 13 14 15]]

print(np.tril(a, k=-1))
# [[ 0  0  0  0]
#  [ 4  0  0  0]
#  [ 8  9  0  0]
#  [12 13 14  0]]

正方行列でなくてもOK。考え方は正方行列の場合と同じ。

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

print(np.tril(a))
# [[ 0  0  0  0]
#  [ 4  5  0  0]
#  [ 8  9 10  0]]

print(np.tril(a, k=-1))
# [[0 0 0 0]
#  [4 0 0 0]
#  [8 9 0 0]]

3次元以上の配列の場合、最後の2つの軸(次元)に対して処理が適用される。

print(np.tril(np.arange(32).reshape(2, 4, 4)))
# [[[ 0  0  0  0]
#   [ 4  5  0  0]
#   [ 8  9 10  0]
#   [12 13 14 15]]
# 
#  [[16  0  0  0]
#   [20 21  0  0]
#   [24 25 26  0]
#   [28 29 30 31]]]

print(np.tril(np.arange(16).reshape(1, 1, 4, 4)))
# [[[[ 0  0  0  0]
#    [ 4  5  0  0]
#    [ 8  9 10  0]
#    [12 13 14 15]]]]

NumPy配列ndarrayから上三角行列を抽出(取得): numpy.triu()

numpy.triu()の引数にnumpy.ndarrayを指定すると、対角線より下の成分を0としたnumpy.ndarrayが返される。

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

print(np.triu(a))
# [[ 0  1  2  3]
#  [ 0  5  6  7]
#  [ 0  0 10 11]
#  [ 0  0  0 15]]

numpy.tril()と同じく第二引数kを指定可能。

print(np.triu(a, k=2))
# [[0 0 2 3]
#  [0 0 0 7]
#  [0 0 0 0]
#  [0 0 0 0]]

print(np.triu(a, k=-1))
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 0  9 10 11]
#  [ 0  0 14 15]]

正方行列でない場合や3次元以上の配列の場合もnumpy.tril()と同様。

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

print(np.triu(a))
# [[ 0  1  2  3]
#  [ 0  5  6  7]
#  [ 0  0 10 11]]

print(np.triu(a, k=-1))
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 0  9 10 11]]
print(np.triu(np.arange(16).reshape(1, 1, 4, 4)))
# [[[[ 0  1  2  3]
#    [ 0  5  6  7]
#    [ 0  0 10 11]
#    [ 0  0  0 15]]]]

下三角行列と上三角行列を相互に変換

下三角行列と上三角行列は互いの転置行列なので、Ttranspose()を使って相互に変換できる。

a_tril = np.tril(np.arange(16).reshape(4, 4))
print(a_tril)
# [[ 0  0  0  0]
#  [ 4  5  0  0]
#  [ 8  9 10  0]
#  [12 13 14 15]]

print(a_tril.T)
# [[ 0  4  8 12]
#  [ 0  5  9 13]
#  [ 0  0 10 14]
#  [ 0  0  0 15]]

print(a_tril.T.T)
# [[ 0  0  0  0]
#  [ 4  5  0  0]
#  [ 8  9 10  0]
#  [12 13 14 15]]

下三角行列・上三角行列を生成: numpy.tri()

numpy.tri()は対角線より上の成分が0、それ以外の成分が1の下三角行列を生成する。

第一引数Nに整数値を指定するとNN列の正方行列(二次元配列)が生成される。

デフォルトはデータ型dtypefloat

print(np.tri(4))
# [[1. 0. 0. 0.]
#  [1. 1. 0. 0.]
#  [1. 1. 1. 0.]
#  [1. 1. 1. 1.]]

print(type(np.tri(4)))
# <class 'numpy.ndarray'>

print(np.tri(4).dtype)
# float64
source: numpy_tri.py

データ型は引数dtypeで指定できる。

print(np.tri(4, dtype=int))
# [[1 0 0 0]
#  [1 1 0 0]
#  [1 1 1 0]
#  [1 1 1 1]]

print(np.tri(4, dtype=int).dtype)
# int64
source: numpy_tri.py

numpy.tril(), numpy.triu()と同様に引数kを指定可能。

print(np.tri(4, k=1))
# [[1. 1. 0. 0.]
#  [1. 1. 1. 0.]
#  [1. 1. 1. 1.]
#  [1. 1. 1. 1.]]

print(np.tri(4, k=-1))
# [[0. 0. 0. 0.]
#  [1. 0. 0. 0.]
#  [1. 1. 0. 0.]
#  [1. 1. 1. 0.]]
source: numpy_tri.py

第二引数Mを指定するとNM列となる。

print(np.tri(3, 4))
# [[1. 0. 0. 0.]
#  [1. 1. 0. 0.]
#  [1. 1. 1. 0.]]

print(np.tri(3, 4, k=-1))
# [[0. 0. 0. 0.]
#  [1. 0. 0. 0.]
#  [1. 1. 0. 0.]]
source: numpy_tri.py

上三角行列を生成する関数はない。上三角行列を生成したい場合は下三角行列をTtranspose()で転置する。

print(np.tri(4).T)
# [[1. 1. 1. 1.]
#  [0. 1. 1. 1.]
#  [0. 0. 1. 1.]
#  [0. 0. 0. 1.]]
source: numpy_tri.py

あくまでもnumpy.tri()で下三角行列を生成してから転置しているだけなので、引数Mや引数kを指定する際は注意。

print(np.tri(3, 4).T)
# [[1. 1. 1.]
#  [0. 1. 1.]
#  [0. 0. 1.]
#  [0. 0. 0.]]

print(np.tri(4, k=1).T)
# [[1. 1. 1. 1.]
#  [1. 1. 1. 1.]
#  [0. 1. 1. 1.]
#  [0. 0. 1. 1.]]

print(np.tri(4, k=-1).T)
# [[0. 1. 1. 1.]
#  [0. 0. 1. 1.]
#  [0. 0. 0. 1.]
#  [0. 0. 0. 0.]]
source: numpy_tri.py

関連カテゴリー

関連記事