note.nkmk.me

NumPy配列ndarrayの形状を変換するreshapeの使い方と-1の意味

Date: 2018-08-09 / tags: Python, NumPy

NumPy配列ndarrayの形状を変換するにはnumppy.ndarrayreshape()メソッドかnumpy.reshape()関数を使う。

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

  • ndarray.reshape()メソッドの使い方
  • numpy.reshape()関数の使い方
  • 変換順序を指定: 引数order
  • -1による形状の指定
  • reahape()が返すのはビュー

NumPy配列ndarrayの形状や次元数などを確認したい場合は以下の記事を参照。

以下の一次元のNumPy配列ndarrayを例とする。

import numpy as np

a = np.arange(24)

print(a)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]

print(a.shape)
# (24,)

print(a.ndim)
# 1
スポンサーリンク

ndarray.reshape()メソッドの使い方

numppy.ndarrayreshape()メソッドの第一引数に変換後の形状をリストやタプルで指定する。

a_4_6 = a.reshape([4, 6])

print(a_4_6)
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(a_4_6.shape)
# (4, 6)

print(a_4_6.ndim)
# 2

a_2_3_4 = a.reshape([2, 3, 4])

print(a_2_3_4)
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
# 
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

print(a_2_3_4.shape)
# (2, 3, 4)

print(a_2_3_4.ndim)
# 3

元の配列と要素数が一致する形状でないとエラーValueErrorとなる。

# a_5_6 = a.reshape([5, 6])
# ValueError: cannot reshape array of size 24 into shape (5,6)

リストやタプルではなく、各次元の値を順に指定してもOK。

print(a.reshape(4, 6))
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(a.reshape(2, 3, 4))
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
# 
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

numpy.reshape()関数の使い方

numpy.reshape()関数では、第一引数に元のnumpy.ndarray、第二引数に変換したい形状をリストやタプルで指定する。元の配列と要素数が一致する形状でないとエラーValueErrorとなる。

print(np.reshape(a, [4, 6]))
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(np.reshape(a, [2, 3, 4]))
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
# 
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

# print(np.reshape(a, [5, 6]))
# ValueError: cannot reshape array of size 24 into shape (5,6)

numpy.reshape()関数の第二引数には必ずリストやタプルを指定する。numppy.ndarrayreshape()メソッドのように各次元の値を順に指定するとエラーValueErrorとなる。

print(a.reshape(4, 6))
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

# print(np.reshape(a, 4, 6))
# ValueError: cannot reshape array of size 24 into shape (4,)

変換順序を指定: 引数order

変換順序を引数orderで指定する。order='C'がC言語方式でorder='F'がFORTRAN方式。デフォルトはorder='C'

以下のように結果が異なる。

print(a.reshape([4, 6], order='C'))
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(a.reshape([4, 6], order='F'))
# [[ 0  4  8 12 16 20]
#  [ 1  5  9 13 17 21]
#  [ 2  6 10 14 18 22]
#  [ 3  7 11 15 19 23]]

print(a.reshape([2, 3, 4], order='C'))
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
# 
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

print(a.reshape([2, 3, 4], order='F'))
# [[[ 0  6 12 18]
#   [ 2  8 14 20]
#   [ 4 10 16 22]]
# 
#  [[ 1  7 13 19]
#   [ 3  9 15 21]
#   [ 5 11 17 23]]]

numpy.reshape()関数でも同様に指定可能。

print(np.reshape(a, [4, 6], order='F'))
# [[ 0  4  8 12 16 20]
#  [ 1  5  9 13 17 21]
#  [ 2  6 10 14 18 22]
#  [ 3  7 11 15 19 23]]

numppy.ndarrayreshape()メソッドは上述のように形状を各次元の値を順に指定することを許可しているので、引数orderを指定する場合はキーワードを明示しないとエラーTypeErrorとなる。

numpy.reshape()関数では第三引数がorderとなるのでキーワードは省略可。

# print(a.reshape([4, 6], 'F'))
# TypeError: 'list' object cannot be interpreted as an integer

print(np.reshape(a, [4, 6], 'F'))
# [[ 0  4  8 12 16 20]
#  [ 1  5  9 13 17 21]
#  [ 2  6 10 14 18 22]
#  [ 3  7 11 15 19 23]]

-1による形状の指定

形状の指定では-1を使うことができる。

以下、numppy.ndarrayreshape()メソッドを例とするがnumpy.reshape()関数でも同様。

-1とした次元の長さは他の次元の指定値から推測されて自動的に決定される。サイズの大きい配列の形状を変換するときに便利。

print(a.reshape([4, -1]))
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(a.reshape([2, -1, 4]))
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
# 
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

-1を指定できるのは一つの次元に対してのみ。二つ以上の次元に指定するとエラーValueError

# print(a.reshape([2, -1, -1]))
# ValueError: can only specify one unknown dimension

また、条件を満たす値が存在しない場合もエラーValueErrorとなる。

# print(a.reshape([2, -1, 5]))
# ValueError: cannot reshape array of size 24 into shape (2,newaxis,5)

reahape()が返すのはビュー

numppy.ndarrayreshape()メソッドもnumpy.reshape()関数もコピーではなくビュー(参照)を返すので注意。

以下、numppy.ndarrayreshape()メソッドを例とするがnumpy.reshape()関数でも同様。

以下のように、元のオブジェクトを変更するとreshape()メソッドが返したビューオブジェクトも変更される。

a_4_6 = a.reshape([4, 6])
print(a_4_6)
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

a[0] = 100
print(a)
# [100   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17
#   18  19  20  21  22  23]

print(a_4_6)
# [[100   1   2   3   4   5]
#  [  6   7   8   9  10  11]
#  [ 12  13  14  15  16  17]
#  [ 18  19  20  21  22  23]]

逆の場合も同様。reshape()メソッドが返したビューオブジェクトを変更すると元のオブジェクトも変更される。

a_4_6[0, 0] = 0
print(a_4_6)
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(a)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]

コピーを取得したい場合はcopy()メソッドを使う。この場合、それぞれのオブジェクトに変更を加えても他方のオブジェクトは影響されない。

a_4_6_copy = a.reshape([4, 6]).copy()

print(a_4_6_copy)
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

a[0] = 100
print(a)
# [100   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17
#   18  19  20  21  22  23]

print(a_4_6_copy)
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

a_4_6_copy[0, 0] = 200
print(a_4_6_copy)
# [[200   1   2   3   4   5]
#  [  6   7   8   9  10  11]
#  [ 12  13  14  15  16  17]
#  [ 18  19  20  21  22  23]]

print(a)
# [100   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17
#   18  19  20  21  22  23]
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事