ValueError: setting an array element with a sequence の原因と直し方[NumPy]
NumPyを使っているとこれが出ることがある。
ValueError: setting an array element with a sequence.新しいバージョンではもう少し親切な文言になることもある。
ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions.言っているのは、数値が入るはずの場所に列(リストや配列)が来ている、ということになる。NumPyの配列は全要素が同じ型で、形も長方形でなければならないので、そこから外れると拒否される。
1. 長さが揃っていない入れ子リスト
いちばん多い原因になる。
import numpy as npa = np.array([[1, 2, 3], [4, 5]]) # ValueError3個と2個で長さが違うので、長方形の配列にできない。NumPyの古いバージョンではdtype=objectの配列が黙って作られていたが、いまはエラーになる。
対処は目的によって3つに分かれる。
長さを揃えるのが本筋になる。足りない分を埋める。
rows = [[1, 2, 3], [4, 5]]n = max(len(r) for r in rows)a = np.array([r + [0] * (n - len(r)) for r in rows])欠損として扱いたいならnp.nanで埋める。ただしnanは浮動小数点なので、配列全体がfloatになる。
a = np.array([r + [np.nan] * (n - len(r)) for r in rows])どうしても不揃いのまま持ちたいなら、明示的にobject配列にする。ただし数値演算の高速化は効かなくなる。
a = np.empty(len(rows), dtype=object)a[:] = rows2. 配列の1要素にリストを代入している
形が合っているつもりでも、代入先が数値ひとつのときに起きる。
a = np.zeros(3)a[0] = [1, 2] # ValueErroraはfloatが3個並んだ配列なので、1要素にリストは入らない。2次元が必要なら最初からそう作る。
a = np.zeros((3, 2))a[0] = [1, 2] # OKスライスの形を確認するのが早い。
print(a.shape, a[0].shape)3. dtypeを指定したが中身が合わない
数値のdtypeを指定した配列に、文字列や列が混ざっている場合になる。
a = np.array([1, 2, [3, 4]], dtype=float) # ValueErrorデータの出どころを疑ったほうがいい。CSVやJSONから読んだ値に、想定外の入れ子が混ざっていることが多い。
for i, v in enumerate(data): if not np.isscalar(v): print(i, type(v), v)これで犯人の位置が分かる。
4. pandasの列にリストが入っている
DataFrameの列の中身がリストになっていると、valuesやto_numpyで取り出した時点で問題になる。
df["tags"] = [[1, 2], [3], [4, 5, 6]]np.array(df["tags"].to_list()) # ValueError列を展開するか、長さを揃える。
df = df.explode("tags") # 行に展開する同じ性質の問題はdrop_duplicatesやgroupbyでも起きる。そちらはunhashable type: ‘list’にまとめた。
5. 機械学習ライブラリに渡すとき
scikit-learnやPyTorchに特徴量を渡すときによく出る。サンプルごとに特徴の数が違うと、この時点で弾かれる。
X = [[1.0, 2.0], [3.0], [4.0, 5.0]]model.fit(X, y) # ValueError系列の長さが可変なら、パディングして長さを揃えるか、そもそも固定長の特徴に変換する設計にする必要がある。
形を先に確認する習慣
原因が読めないときは、渡す直前で形を出してしまうのが確実になる。
print(type(data), len(data))print([len(r) if hasattr(r, "__len__") else "scalar" for r in data][:20])長さの一覧を見れば、どこだけ違うかが一目で分かる。要素数が多いなら集計する。
from collections import Counterprint(Counter(len(r) for r in data))📘 特徴量の形をそろえる作業そのものについては、Kaggleで勝つデータ分析の技術。
まとめ
・原因は「数値が入る場所に列が来ている」こと。NumPyの配列は長方形で同じ型である必要がある
・不揃いな入れ子リストが最頻の原因。0やnanで埋めて長さを揃えるのが本筋
・どうしても不揃いのまま持つならdtype=object。ただし高速化は効かなくなる
・1要素への代入で出る場合は、配列の次元が足りていない。shapeを確認する
・pandasの列にリストが入っている場合はexplodeで展開する
・渡す直前に長さの一覧をCounterで数えると、犯人がすぐ分かる
※本記事にはアフィリエイト広告を含みます。