次の形式の配列(単なる例)を考えてみましょう。
[[ 0 1]
[ 2 3]
[ 4 5]
[ 6 7]
[ 8 9]
[10 11]
[12 13]
[14 15]
[16 17]]
形状は[9,2]です。次に、各列が次のように形状[3,3]になるように配列を変換します。
[[ 0 6 12]
[ 2 8 14]
[ 4 10 16]]
[[ 1 7 13]
[ 3 9 15]
[ 5 11 17]]
最も明白な(そして確かに「非Pythonic」)ソリューションは、適切な次元でゼロの配列を初期化し、データで満たされる2つのforループを実行することです。言語に準拠したソリューションに興味があります...
a = np.arange(18).reshape(9,2)
b = a.reshape(3,3,2).swapaxes(0,2)
# a:
array([[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[10, 11],
[12, 13],
[14, 15],
[16, 17]])
# b:
array([[[ 0, 6, 12],
[ 2, 8, 14],
[ 4, 10, 16]],
[[ 1, 7, 13],
[ 3, 9, 15],
[ 5, 11, 17]]])
numpyには、このタスクに最適なツールがあります( "numpy.reshape") リンクを変更するドキュメントへ
_a = [[ 0 1]
[ 2 3]
[ 4 5]
[ 6 7]
[ 8 9]
[10 11]
[12 13]
[14 15]
[16 17]]
`numpy.reshape(a,(3,3))`
_
「-1」トリックを使用することもできます
_`a = a.reshape(-1,3)`
_
「-1」はワイルドカードで、2番目の次元が3のときに、numpyアルゴリズムが入力する数値を決定できるようにします
そうです。これも機能します:a = a.reshape(3,-1)
そしてこれ:a = a.reshape(-1,2)
は何もしません
そしてこれ:a = a.reshape(-1,9)
は形状を(2,9)に変更します
結果の再配置には2つの方法があります(例は @ eumiro に続く)。 Einops
パッケージは、このような操作を明確に記述する強力な表記法を提供します
>> a = np.arange(18).reshape(9,2)
# this version corresponds to eumiro's answer
>> einops.rearrange(a, '(x y) z -> z y x', x=3)
array([[[ 0, 6, 12],
[ 2, 8, 14],
[ 4, 10, 16]],
[[ 1, 7, 13],
[ 3, 9, 15],
[ 5, 11, 17]]])
# this has the same shape, but order of elements is different (note that each paer was trasnposed)
>> einops.rearrange(a, '(x y) z -> z x y', x=3)
array([[[ 0, 2, 4],
[ 6, 8, 10],
[12, 14, 16]],
[[ 1, 3, 5],
[ 7, 9, 11],
[13, 15, 17]]])