【NumPy】numpy配列をn分割するnp.array_split(配列 , 個数)
numpyで配列をn分割するnp.array_split(配列 , 個数)
配列をn個に分割したいとき、np.array_split()
を使うと便利です。
【実行環境】
- Android
- Termux
- Python3.9
- Jupyter Notebook
1次元配列の場合
まずは簡単な例から。1~10まで並んだ配列を2分割してみます。
余りの出ない分割の場合
要素数10個の配列を、2や5で分割する場合は共に余りが出ないので、同じ要素数のグループに均等に分割できますよね。
2等分します。
# 元の配列 a = np.arange(1,11) print(a) # 2分割 np.array_split(a, 2)
[ 1 2 3 4 5 6 7 8 9 10]
[array([1, 2, 3, 4, 5]), array([ 6, 7, 8, 9, 10])]
要素数が5個ずつ、2等分されました。
余りの出る分割の場合
10の3等分だと、個数は
10 ÷ 3 = 3 余り 1
ですので、余りをどこかのグループに入れて、個数を(3, 3, 4)みたいにグループ分けしなくちゃいけませんが、これも自動でやってくれます。
print(a) # 3分割 np.array_split(a, 3)
[ 1 2 3 4 5 6 7 8 9 10]
[array([1, 2, 3, 4]), array([5, 6, 7]), array([ 8, 9, 10])]
先頭のグループに余りが追加されて要素数が4つに、残り2グループは要素数3つ、全体が3分割されました。
では、要素数が11個の配列を3等分する場合はどうなる?
11 ÷ 3 = 3 余り 2
なので、要素数が(5, 3, 3)にするか、余り2を2グループに1つずつ入れて(4, 4, 3)になれば3等分できる。
では、やっていただきます。numpyさん、お願いします。
a11 = np.arange(1,12) print(a11) # 要素数11を3等分 np.array_split(a11, 3)
[ 1 2 3 4 5 6 7 8 9 10 11]
[array([1, 2, 3, 4]), array([5, 6, 7, 8]), array([ 9, 10, 11])]
(4,4,3)の要素数で3分割されました。
要素数を超した分割を指定した場合
分割数を、元の配列数を超えて指定するとどうなるか。2個を3等分していただきます。エラーが出るだろうけど
# 要素数を超えた分割指定 np.array_split([1,2], 3)
[array([1]), array([2]), array([], dtype=int64)]
お、エラーは出さず、律儀に空の配列を含んだ3分割がされました。
各分割をそれぞれ変数に代入できるか(できる)
指定分割数だけ変数を用意すると、各変数に代入できるんじゃないか。やってみましょう。
# 変数に代入できるか? 3等分する x, y, z = np.array_split([5,6,7], 3) # 変数を出力 print(x, y, z)
[5] [6] [7]
出来ますね。
2次元配列のn分割
元の配列が2次元配列になるとどうだろう?
5行4列の配列を2等分する。
# 見やすいように表示する from pprint import pprint # 5行4列の2次元配列生成 ad2 = np.arange(1,21).reshape(5,4) print(ad2) # 2等分 np.array_split(ad2, 2)
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[13 14 15 16]
[17 18 19 20]]
[array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]]),
array([[13, 14, 15, 16],
[17, 18, 19, 20]])]
2次元配列を2等分しました。行で分割されています。
n分割します。
print('元の配列\n', ad2) print() # n等分 for i in range(6): print(f'【{i+1}等分】') pprint(np.array_split(ad2, i+1)) print('-'*30)
元の配列
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[13 14 15 16]
[17 18 19 20]]
【1等分】
[array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20]])]
------------------------------
【2等分】
[array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]]),
array([[13, 14, 15, 16],
[17, 18, 19, 20]])]
------------------------------
【3等分】
[array([[1, 2, 3, 4],
[5, 6, 7, 8]]),
array([[ 9, 10, 11, 12],
[13, 14, 15, 16]]),
array([[17, 18, 19, 20]])]
------------------------------
【4等分】
[array([[1, 2, 3, 4],
[5, 6, 7, 8]]),
array([[ 9, 10, 11, 12]]),
array([[13, 14, 15, 16]]),
array([[17, 18, 19, 20]])]
------------------------------
【5等分】
[array([[1, 2, 3, 4]]),
array([[5, 6, 7, 8]]),
array([[ 9, 10, 11, 12]]),
array([[13, 14, 15, 16]]),
array([[17, 18, 19, 20]])]
------------------------------
【6等分】
[array([[1, 2, 3, 4]]),
array([[5, 6, 7, 8]]),
array([[ 9, 10, 11, 12]]),
array([[13, 14, 15, 16]]),
array([[17, 18, 19, 20]]),
array([], shape=(0, 4), dtype=int64)]
------------------------------
n分割後の形状確認
Numpy配列の形状を確認するときは配列.shape
でできます。
分割後の各配列が同一形状とは限らないので、各配列ごとに形状を取得する必要があります。
分割全体をそのまま形状確認するとエラーになる例。
# 1次元配列生成 a11 = np.arange(1,12) print(a11) # 要素数11を3等分 np.array_split(a11, 3) # 配列の形状確認 np.array_split(a11, 3).shape
[ 1 2 3 4 5 6 7 8 9 10 11]
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/data/data/com.termux/files/usr/tmp/ipykernel_8750/3673819837.py in <module>
7
8 # 配列の形状確認
----> 9 np.array_split(a11, 3).shape
AttributeError: 'list' object has no attribute 'shape'
「リストオブジェクトはshapeの属性がない」と怒られました。
分割したらリストに各配列を格納しているようです。上でやったように変数で各配列を取り出した際も、リストを変数で分けて取り出したわけね。
分割後の各配列の形状を確認します。ついでに型も確認します。
# 1次元配列生成 a11 = np.arange(1,12) print('元の配列') print(a11) print(type(a11)) print('-'*20) # 要素数11を3等分 print('3等分後') pprint(np.array_split(a11, 3)) print('-'*20) # 配列の形状確認 all_a = np.array_split(a11, 3) print('分割後の各配列の形状と型') for i in all_a: print(i.shape) print(type(i)) # 型確認 print('-'*20)
元の配列
[ 1 2 3 4 5 6 7 8 9 10 11]
<class 'numpy.ndarray'>
--------------------
3等分後
[array([1, 2, 3, 4]), array([5, 6, 7, 8]), array([ 9, 10, 11])]
--------------------
分割後の各配列の形状と型
(4,)
<class 'numpy.ndarray'>
--------------------
(4,)
<class 'numpy.ndarray'>
--------------------
(3,)
<class 'numpy.ndarray'>
--------------------
3次元配列で上記と同じようにn分割させようとしたらエラーが出ました。画像の配列が3次元ですけど、構造とかがぶっちゃけ捉えにくい。よくわからないので一旦放置します。
以上です。