np.array_splitとsplit・hsplit・vsplit・dsplitの違い|NumPy配列を分割する方法を実行結果で解説

NumPyの配列を「同じ数ずつ」ではなく「だいたい同じ数ずつ」分けたいときはnp.array_splitを使います。np.splitは割り切れないとValueErrorになり、np.hsplitは列方向(axis=1)、np.vsplitは行方向(axis=0)、np.dsplitは3次元目(axis=2)に分けるnp.splitの省略形です。

この記事では、5つの分割関数の違いを一覧表で整理したうえで、array_splitの端数の配り方、分割位置をインデックスで指定する方法、1次元配列でのhsplitの動き、分割結果が元の配列と同じメモリを共有する「ビュー」になる注意点まで、実行結果つきで説明します。コードはPython 3.12・NumPy 2.5.4で実行しました(2026年10月15日確認)。

5つの分割関数の違い(早見表)

どの関数も「配列を軸に沿って切り分け、部分配列のリストを返す」点は同じです。違いは、分ける軸が決まっているかどうかと、割り切れないときにエラーにするかどうかです。

関数 分ける軸 整数で割り切れないとき 使える配列
np.split(a, n, axis=0) 引数axisで指定(既定は0) ValueError 1次元以上
np.array_split(a, n, axis=0) 引数axisで指定(既定は0) 先頭側に1個ずつ多く配って分割 1次元以上
np.hsplit(a, n) axis=1(列)。1次元配列だけはaxis=0 ValueError 1次元以上
np.vsplit(a, n) axis=0(行) ValueError 2次元以上
np.dsplit(a, n) axis=2(奥行き) ValueError 3次元以上

軸の説明は公式リファレンスのnumpy.hsplit・numpy.vsplit・numpy.dsplitに沿っています。hsplit・vsplit・dsplitにはaxis引数がなく、割り切れない数を渡すとsplitと同じくエラーになります。割り切れない分割を特定の軸で行いたいときは、np.array_split(a, n, axis=1)のようにarray_splitへaxisを渡します。

np.array_split:割り切れなくても分割できる

検索でいちばん多く調べられているのがこの関数です。10個の要素を3つに分けてみます。

import numpy as np

a = np.arange(10)
print(np.array_split(a, 3))
print(np.array_split(a, 4))

実行結果:

[array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8, 9])]
[array([0, 1, 2]), array([3, 4, 5]), array([6, 7]), array([8, 9])]

端数は「先頭のグループから1個ずつ多く」配られます。公式リファレンス(numpy.array_split)の説明では、長さlの配列をn個に分けると、l % n個の部分配列がl//n + 1個の要素を持ち、残りがl//n個になります。10を4つに分けると、10 % 4 = 2個のグループが3要素、残り2個のグループが2要素です。

「最後のグループだけ少なくなる」のではない点に注意してください。たとえば7要素を3つに分けると[0, 1, 2]・[3, 4]・[5, 6]となり、多くなるのは先頭側です。

大きなデータを決まった数のバッチに分ける

実務でよく使うのは、データを「n個のかたまり」に分けて順番に処理する場面です。103件を4つに分けると、各バッチの件数と先頭・末尾の値は次のようになります。

import numpy as np

data = np.arange(103)
for i, batch in enumerate(np.array_split(data, 4)):
    print(i, len(batch), batch[0], batch[-1])

実行結果:

0 26 0 25
1 26 26 51
2 26 52 77
3 25 78 102

「4個ずつ」に分けたいとき

array_splitの整数引数は「いくつに分けるか(個数)」で、「何個ずつ」ではありません。1グループの大きさを固定したいときは、区切り位置をrangeで作って渡すか、スライスで切ります。どちらも同じ結果です。

import numpy as np

data = np.arange(10)
batches = [data[i:i + 4] for i in range(0, len(data), 4)]
print(batches)
print(np.array_split(data, range(4, len(data), 4)))

実行結果:

[array([0, 1, 2, 3]), array([4, 5, 6, 7]), array([8, 9])]
[array([0, 1, 2, 3]), array([4, 5, 6, 7]), array([8, 9])]

np.split:等分割できないとエラーになる

np.splitに整数を渡すと「その数に等分」します。割り切れない場合はエラーで止まるので、データの件数がそろっていることを確かめたい場面ではむしろ安全です。

import numpy as np

a = np.arange(10)
try:
    np.split(a, 3)
except ValueError as e:
    print("ValueError:", e)
print(np.split(a, 5))

実行結果:

ValueError: array split does not result in an equal division
[array([0, 1]), array([2, 3]), array([4, 5]), array([6, 7]), array([8, 9])]

分割位置をリストで指定する

2つめの引数に昇順の整数のリストを渡すと、その位置で区切ります。[3, 7]ならa[:3]・a[3:7]・a[7:]の3つです。この指定方法はsplit・array_split・hsplit・vsplit・dsplitのすべてで共通です。

import numpy as np

a = np.arange(10)
parts = np.split(a, [3, 7])
for p in parts:
    print(p)
print(np.split(a, [3, 20]))

実行結果:

[0 1 2]
[3 4 5 6]
[7 8 9]
[array([0, 1, 2]), array([3, 4, 5, 6, 7, 8, 9]), array([], dtype=int64)]

配列の長さを超える位置を指定してもエラーにはならず、空の配列が返ります(numpy.splitの公式説明どおり)。後続の処理で空配列を想定していないと思わぬ結果になるので、件数を確認してから使いましょう。

シャッフルしたインデックスを学習・検証・テスト用に分ける

分割位置の指定は、データを6:2:2に分けるような場面で便利です。

import numpy as np

rng = np.random.default_rng(0)
idx = rng.permutation(10)
train, valid, test = np.split(idx, [6, 8])
print(idx)
print(train, valid, test)

実行結果:

[4 6 2 7 3 5 9 0 8 1]
[4 6 2 7 3 5] [9 0] [8 1]

機械学習で本格的にデータを分けるときは、scikit-learnのtrain_test_splitや交差検証の仕組みを使うのが一般的です。

np.hsplit:列方向(横)に分割する

hsplitの「h」はhorizontal(水平)で、2次元配列なら列で切ります。np.split(x, n, axis=1)と同じです。

import numpy as np

x = np.arange(12).reshape(3, 4)
print(x)
left, right = np.hsplit(x, 2)
print(left)
print(right)
print(np.hsplit(x, [1]))

実行結果:

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[[0 1]
 [4 5]
 [8 9]]
[[ 2  3]
 [ 6  7]
 [10 11]]
[array([[0],
       [4],
       [8]]), array([[ 1,  2,  3],
       [ 5,  6,  7],
       [ 9, 10, 11]])]

np.hsplit(x, [1])は「最初の1列と残り」に分ける書き方で、表形式のデータで先頭列(IDやラベル)と特徴量を切り離すときに使えます。結果は2次元のまま(形が(3, 1))なので、1次元にしたいときはleft.ravel()などで変換します。

1次元配列に使うとaxis=0で分割される

1次元配列には「列」がないため、hsplitはaxis=0で分割します。一方vsplitは2次元以上の配列にしか使えません。

import numpy as np

v = np.arange(6)
print(np.hsplit(v, 3))
try:
    np.vsplit(v, 3)
except ValueError as e:
    print("ValueError:", e)

実行結果:

[array([0, 1]), array([2, 3]), array([4, 5])]
ValueError: vsplit only works on arrays of 2 or more dimensions

np.vsplit:行方向(縦)に分割する

vsplitの「v」はvertical(垂直)で、行で切ります。np.split(x, n, axis=0)と同じです。最後の1行だけ切り離す例です。

import numpy as np

x = np.arange(12).reshape(4, 3)
top, bottom = np.vsplit(x, [3])
print(top)
print(bottom)

実行結果:

[[0 1 2]
 [3 4 5]
 [6 7 8]]
[[ 9 10 11]]

np.dsplit:3次元目(奥行き)で分割する

dsplitの「d」はdepth(奥行き)で、axis=2で切ります。高さ×幅×チャンネルの画像データを、色のチャンネルごとに分けるときがわかりやすい例です。

import numpy as np

img = np.arange(2 * 2 * 3).reshape(2, 2, 3)  # 高さ2×幅2×チャンネル3
r, g, b = np.dsplit(img, 3)
print(r.shape)
print(r[:, :, 0])
r2, g2, b2 = np.unstack(img, axis=2)
print(r2.shape)
print(r2)

実行結果:

(2, 2, 1)
[[0 3]
 [6 9]]
(2, 2)
[[0 3]
 [6 9]]

dsplitの結果は形が(2, 2, 1)で、3次元目が長さ1のまま残ります。2次元の配列として受け取りたいときは、NumPy 2.1で追加されたnp.unstackが便利です。unstackは指定した軸を取り除いて分割し、リストではなくタプルを返します。2次元配列にdsplitを使うと「dsplit only works on arrays of 3 or more dimensions」というValueErrorになります。

注意:分割結果は元の配列と同じメモリを見ている

公式リファレンスにあるとおり、np.splitが返す部分配列は元の配列の「ビュー」です。部分配列を書き換えると、元の配列も変わります。

import numpy as np

a = np.arange(6)
first, second = np.split(a, 2)
first[0] = 100
print(a)
print(np.shares_memory(a, first))
safe = [p.copy() for p in np.split(a, 2)]
safe[0][1] = -1
print(a)

実行結果:

[100   1   2   3   4   5]
True
[100   1   2   3   4   5]

元のデータを残したまま部分配列を加工したい場合は、.copy()でコピーしてから書き換えます。コピーを書き換えた2回目の出力では、元の配列は変わっていません。

分割と結合の対応

分割した配列は、対応する結合関数で元に戻せます。

分割 元に戻す結合
np.split(a, n, axis=k)・np.array_split np.concatenate(parts, axis=k)
np.hsplit np.hstack
np.vsplit np.vstack
np.dsplit np.dstack
np.unstack np.stack

よくある質問

Q. np.splitとnp.array_splitの違いは何ですか?

分割数を整数で渡したときに、割り切れないとnp.splitはValueErrorになり、np.array_splitは先頭のグループから1個ずつ多く配って分割します。分割位置をリストで渡す使い方は同じです。

Q. np.array_splitで「n個ずつ」に分けるには?

整数引数は分割する個数なので、区切り位置を渡します。np.array_split(data, range(n, len(data), n)) とすると、先頭からn個ずつに分かれ、最後のグループだけ少なくなります。

Q. np.hsplitとnp.vsplitはどちらが列で分けますか?

hsplitが列(axis=1)、vsplitが行(axis=0)です。hsplitは横に並んだ列を切り分ける、vsplitは縦に積まれた行を切り分ける、と覚えると迷いません。

Q. 割り切れない数でhsplitを使いたいときは?

hsplitには端数を許す仕組みがないため、np.array_split(x, n, axis=1) を使います。vsplitの代わりならaxis=0、dsplitの代わりならaxis=2です。

まとめ

NumPyの分割は、割り切れない分割ならnp.array_split、件数がそろっていることを前提にするならnp.split、軸を名前で表したいならhsplit(列)・vsplit(行)・dsplit(奥行き)と使い分けます。分割位置はリストでも指定でき、結果は元の配列のビューなので、書き換えるときは.copy()を忘れないようにしましょう。配列操作はテックジムのAIエンジニア養成コース(16章で機械学習とディープラーニングを学ぶコース)でも、第0章「データ分析入門とデータ可視化」から前処理の土台として繰り返し使います。


NumPy|結合・分割の関連記事

複数の配列をつなぐ・分けるための関数の記事です。

NumPy全体の使い方は「NumPyの使い方」、「NumPy関数一覧」でまとめています。

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら