reshapeは要素を読む順序に従って形を作り直し、transposeは軸そのものを入れ替える。「時刻×チャンネル」を「チャンネル×時刻」へ変えたいなら、通常はtransposeまたは2次元配列の.Tを使う。要素数が同じだからといってreshapeで代用すると、チャンネルと値の対応を壊す。
最小例で確かめる
以下は説明用に作った小さなデータである。実測データや実行速度の測定結果ではない。コード全体をexample.pyとして保存すれば、入力ファイルを別途用意せずに実行できる。assertは、この例で成り立つべき形や値を確認するために入れてある。
import numpy as np
x = np.array([[10, 11, 12], [20, 21, 22]])
transposed = x.T
reshaped = x.reshape(3, 2)
print("transpose:", transposed.tolist())
print("reshape:", reshaped.tolist())
cube = np.arange(24).reshape(2, 3, 4) # 試行、時刻、チャンネル
swapped = cube.transpose(0, 2, 1)
print("axis order:", cube.shape, "->", swapped.shape)
print("known element:", int(cube[1, 2, 3]), int(swapped[1, 3, 2]))
try:
x.reshape(4, 2) # 意図的な要素数不一致
except ValueError:
print("expected: ValueError")
else:
raise AssertionError("invalid reshape was accepted")
np.testing.assert_array_equal(transposed, [[10, 20], [11, 21], [12, 22]])
np.testing.assert_array_equal(reshaped, [[10, 11], [12, 20], [21, 22]])
assert cube[1, 2, 3] == swapped[1, 3, 2] == 23
assert not np.array_equal(transposed, reshaped)
実行結果
transpose: [[10, 20], [11, 21], [12, 22]]
reshape: [[10, 11], [12, 20], [21, 22]]
axis order: (2, 3, 4) -> (2, 4, 3)
known element: 23 23
expected: ValueError
shapeだけでは軸の意味は分からない
例の最初の行は時刻0の3チャンネル、次の行は時刻1の3チャンネルだとする。転置後は第1チャンネルの10と20が同じ行になり、第2チャンネルは11と21になる。元のx[t, c]と転置後のtransposed[c, t]が対応するので、時刻とチャンネルの役割が交換されている。
reshape(3, 2)は、標準のC順序では元の要素を10、11、12、20、21、22の順に読み、その順番で2個ずつ行へ入れる。第1行が10と11になるため、同じチャンネルの時系列にはならない。両方とも(3, 2)というshapeだが、表しているデータの意味は異なる。
多次元では軸の順番を明記する
cubeのshapeは(2, 3, 4)で、試行、時刻、チャンネルの順である。transpose(0, 2, 1)なら試行軸をそのまま残し、時刻とチャンネルを交換する。結果のshapeは(2, 4, 3)になる。引数の数字は出力側へ並べる元の軸番号であり、各軸の長さを直接指定するものではない。
多次元配列の.Tは軸の順序をすべて逆転する。そのため2次元では便利でも、試行軸を先頭に保ちたい3次元データでは期待と違うことがある。軸名をコメントへ書き、代表要素の添字がどう変わるか確認するとよい。例の23が同じ測定値を指し続けることを検査している。
reshapeが適している場面
reshapeは、もともと定めた順序で並ぶ1次元のデータを時刻×チャンネルへ復元したり、連続する複数軸を一つにまとめたりするときに使える。その際は、書き出し側と読み込み側が同じ軸順・要素順を採用していることが前提になる。外部ファイルの仕様に順序が書いてあれば、それに合わせて復元する。
新しいshapeの積は要素数と一致しなければならない。ひとつの軸に-1を指定して長さを推定させることもできるが、軸の意味まで推定するわけではない。4×2へ変えようとした失敗例のように、単純な要素数の違いは例外になる。一方、意味の違いは自分で検査する必要がある。
要素順とメモリ共有も分けて考える
order=”C”とorder=”F”は、要素をどの添字順序で読み書きするかの指定である。外部データとの対応を確認せずにorderを変え、たまたま期待する見た目になったから採用する方法は避けたい。軸交換の目的が明らかならtransposeを使う方が、その意図を読み手へ伝えやすい。
transposeは一般にviewを返し、reshapeは入力の並びによってviewにもcopyにもなる。したがって変形した配列の編集が原本へ影響するかは、形の問題とは別に確認する。原本を残す必要があればcopy()を明示する。学習用には連番や軸ごとに桁を変えた値を入れて、見た目と添字の両方から対応を追うと分かりやすい。
動作確認環境と参考資料
Linux・CPython 3.12.14、NumPy 2.3.5、pandas 2.2.3、SciPy 1.17.0、Matplotlib 3.10.8の環境で掲載コードを実行した。使用するライブラリはコード冒頭のimportを参照してほしい。公式資料の最新版と、この実行確認版は区別している。数値の末尾や表の表示幅は環境によって変わることがある。
