NumPy
前回、Pandasのgroupbyでキーによるグルーピングをして統計値を算出する方法を紹介しました。

今回はNumPyでndarrayを分割するsplit、array_split、hsplit、vsplit、dsplitを紹介します。
それでは始めていきましょう。
np.split
まずはndarrayを等分に、もしくは分割するインデックスを指定して分割するnp.splitです。
「np.split(ndarray, 数値)」とすることでndarrayを指定した値に等分割することができます。
import numpy as np
data = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print(np.split(data, 2))
実行結果
[array([0, 1, 2, 3, 4]), array([5, 6, 7, 8, 9])]
この際、引数として与えるndarrayはリストではダメでエラーとなります。
import numpy as np
data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(np.split(data, 2))
実行結果
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/numpy/lib/shape_base.py:859, in split(ary, indices_or_sections, axis)
858 try:
--> 859 len(indices_or_sections)
860 except TypeError:
(中略)
AttributeError: 'list' object has no attribute 'shape'
また指定する数値はndarrayを余りなく等分割できる値でないとエラーとなります。
import numpy as np
data = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print(np.split(data, 3))
実行結果
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[15], line 5
1 import numpy as np
3 data = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
----> 5 print(np.split(data, 3))
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/numpy/lib/shape_base.py:864, in split(ary, indices_or_sections, axis)
862 N = ary.shape[axis]
863 if N % sections:
--> 864 raise ValueError(
865 'array split does not result in an equal division') from None
866 return array_split(ary, indices_or_sections, axis)
ValueError: array split does not result in an equal division
数値をリストで与えるとそのインデックス位置で分割されます。
import numpy as np
data = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
print(np.split(data, [2, 6]))
実行結果
[array([0, 1]), array([2, 3, 4, 5]), array([6, 7, 8])]
二次元ndarrayの場合、オプション引数として「axis=軸方向」を与えると任意の軸方向で分割することができます(デフォルトは0)。
import numpy as np
data = np.array([[0, 1, 2, 3, 4, 5, 6, 7], [8, 7, 6, 5, 4, 3, 2, 1]])
print(np.split(data, 2, axis=0))
実行結果
[array([[0, 1, 2, 3, 4, 5, 6, 7]]), array([[8, 7, 6, 5, 4, 3, 2, 1]])]
import numpy as np
data = np.array([[0, 1, 2, 3, 4, 5, 6, 7], [8, 7, 6, 5, 4, 3, 2, 1]])
print(np.split(data, 2, axis=1))
実行結果
[array([[0, 1, 2, 3],
[8, 7, 6, 5]]), array([[4, 5, 6, 7],
[4, 3, 2, 1]])]
np.array_split
np.splitでは指定した数値で等分割できない場合はエラーとなりました。
それでもなるべく分割して欲しいという場合、「np.array_split」を使うと、エラーとならずみ分割できます。
使い方は「np.array_split(ndarray, 数値)」です。
import numpy as np
data = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print(np.array_split(data, 3))
実行結果
[array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8, 9])]
余りが出る場合、前方のndarrayから一つずつ追加されていきます。
そのため上の例では最初のndarrayが後の二つのndarrayよりも要素が一つ多くなっています。
import numpy as np
data = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print(np.array_split(data, 7))
実行結果
[array([0, 1]), array([2, 3]), array([4, 5]), array([6]),
array([7]), array([8]), array([9])]
こちらの例では7分割しようとすると3余るため、前方のndarrayから3つのndarrayで要素数が一つ多くなっています。
np.hsplit、np.vsplit、np.dsplit
np.hsplitは横方向、np.vsplitは縦方向、np.dsplitは深さ方向にndarrayを等分割します。
まずnp.hsplitですが、使い方はこれまでと同じで「np.hsplit(ndarray, 数値)」です。
import numpy as np
data = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print(np.hsplit(data, 2))
実行結果
[array([0, 1, 2, 3, 4]), array([5, 6, 7, 8, 9])]
import numpy as np
data = np.array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]])
print(np.hsplit(data, 2))
実行結果
[array([[0, 1, 2, 3, 4],
[9, 8, 7, 6, 5]]), array([[5, 6, 7, 8, 9],
[4, 3, 2, 1, 0]])]
あくまでも等分割するのでやはり余りが出る場合はエラーとなります。
import numpy as np
data = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
print(np.hsplit(data, 2))
実行結果
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[31], line 5
1 import numpy as np
3 data = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
----> 5 print(np.hsplit(data, 2))
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/numpy/lib/shape_base.py:940, in hsplit(ary, indices_or_sections)
938 return split(ary, indices_or_sections, 1)
939 else:
--> 940 return split(ary, indices_or_sections, 0)
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/numpy/lib/shape_base.py:864, in split(ary, indices_or_sections, axis)
862 N = ary.shape[axis]
863 if N % sections:
--> 864 raise ValueError(
865 'array split does not result in an equal division') from None
866 return array_split(ary, indices_or_sections, axis)
ValueError: array split does not result in an equal division
次にnp.vsplitですが、こちらも使い方はこれまでと同じで「np.vsplit(ndarray, 数値)」です。
import numpy as np
data = np.array([[0, 1, 2, 3, 4,], [5, 6, 7, 8, 9], [9, 8, 7, 6, 5], [4, 3, 2, 1, 0]])
print(np.vsplit(data, 2)[0])
print(np.vsplit(data, 2)[1])
実行結果
[[0 1 2 3 4]
[5 6 7 8 9]]
[[9 8 7 6 5]
[4 3 2 1 0]]
np.vsplitは2次元目を分割するので最低2次元のndarrayである必要があります。
そのため1次元のndarrayの場合はエラーとなります。
import numpy as np
data = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print(np.vsplit(data, 2))
実行結果
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[36], line 5
1 import numpy as np
3 data = np.array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
----> 5 print(np.vsplit(data, 2))
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/numpy/lib/shape_base.py:989, in vsplit(ary, indices_or_sections)
987 if _nx.ndim(ary) < 2:
988 raise ValueError('vsplit only works on arrays of 2 or more dimensions')
--> 989 return split(ary, indices_or_sections, 0)
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/numpy/lib/shape_base.py:864, in split(ary, indices_or_sections, axis)
862 N = ary.shape[axis]
863 if N % sections:
--> 864 raise ValueError(
865 'array split does not result in an equal division') from None
866 return array_split(ary, indices_or_sections, axis)
ValueError: array split does not result in an equal division
最後にnp.dsplitですが、こちらも使い方はこれまでと同じで「np.dsplit(ndarray, 数値)」です。
import numpy as np
data = np.array([[[1, 2, 3, 4], [5, 6, 7, 8]],
[[9, 10, 11, 12], [13, 14, 15, 16]],
[[17, 18, 19, 20], [21, 22, 23, 24]]])
print(np.dsplit(data, 2))
実行結果
[array([[[ 1, 2],
[ 5, 6]],
[[ 9, 10],
[13, 14]],
[[17, 18],
[21, 22]]]), array([[[ 3, 4],
[ 7, 8]],
[[11, 12],
[15, 16]],
[[19, 20],
[23, 24]]])]
np.vsplitは三次元目を分割するので、2次元以下のndarrayの場合はエラーとなります。
import numpy as np
data = np.array([[0, 1, 2, 3, 4,], [5, 6, 7, 8, 9], [9, 8, 7, 6, 5], [4, 3, 2, 1, 0]])
print(np.dsplit(data, 2))
実行結果
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[43], line 5
1 import numpy as np
3 data = np.array([[0, 1, 2, 3, 4,], [5, 6, 7, 8, 9], [9, 8, 7, 6, 5], [4, 3, 2, 1, 0]])
----> 5 print(np.dsplit(data, 2))
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/numpy/lib/shape_base.py:1033, in dsplit(ary, indices_or_sections)
994 """
995 Split array into multiple sub-arrays along the 3rd axis (depth).
996
(...)
1030 array([], shape=(2, 2, 0), dtype=float64)]
1031 """
1032 if _nx.ndim(ary) < 3:
-> 1033 raise ValueError('dsplit only works on arrays of 3 or more dimensions')
1034 return split(ary, indices_or_sections, 2)
ValueError: dsplit only works on arrays of 3 or more dimensions
次回はNumPyで配列の形状を変えるブロードキャスト(np.broadcast_to、np.broadcast_arrays)を紹介します。
ではでは今回はこんな感じで。
コメント