ValueError: If using all scalar values, you must pass an index の原因と直し方[pandas]
辞書からDataFrameを作ろうとしてこれが出ることがある。
ValueError: If using all scalar values, you must pass an index再現はとても簡単になる。
import pandas as pddf = pd.DataFrame({"name": "田中", "age": 30}) # ValueErrorなぜ怒られるのか
pd.DataFrameに辞書を渡すと、キーが列名、値がその列の中身として解釈される。値がリストなら、その長さが行数になる。
pd.DataFrame({"name": ["田中", "佐藤"], "age": [30, 25]})# 2行の表ができるところが値がスカラー(文字列や数値そのもの)だと、pandasは行数を決められない。1行なのか、100行に同じ値を並べるのか判断がつかない。だから「全部スカラーなら、行数を決めるindexを渡してほしい」と言ってくる。
つまり足りないのは行数の情報になる。
直し方1. リストで包む(推奨)
いちばん素直な方法になる。1行のDataFrameを作りたいなら、各値をリストに入れる。
df = pd.DataFrame({"name": ["田中"], "age": [30]})長さが揃っていれば何行でも作れる。ここで長さが違うと別のエラーになるので、揃えておく。
直し方2. 辞書をリストに入れる
1行ぶんの辞書として渡す書き方もある。こちらのほうが意味が読みやすいことが多い。
df = pd.DataFrame([{"name": "田中", "age": 30}])この形は複数行への拡張が自然になる。
rows = [ {"name": "田中", "age": 30}, {"name": "佐藤", "age": 25},]df = pd.DataFrame(rows)APIのレスポンスやDBの取得結果を貯めていく処理では、この形がいちばん扱いやすい。キーが揃っていない行があっても、無い列は欠損として埋めてくれる。
直し方3. indexを渡す
エラーメッセージが言っているとおりの対処になる。
df = pd.DataFrame({"name": "田中", "age": 30}, index=[0])行数はindexの長さで決まるので、同じ値を複数行に並べることもできる。
df = pd.DataFrame({"name": "田中", "age": 30}, index=[0, 1, 2])# 同じ内容が3行できる直し方4. from_dictを使う
キーを行にしたい場合はfrom_dictが便利になる。
d = {"田中": 30, "佐藤": 25}df = pd.DataFrame.from_dict(d, orient="index", columns=["age"])orient="index"で辞書のキーが行のラベルになる。既定のorient="columns"はキーが列名になるので、目的に応じて選ぶ。
直し方5. Seriesにする
そもそも1次元でよければ、DataFrameである必要はない。
s = pd.Series({"name": "田中", "age": 30})集計結果を1件だけ持ちたいときは、Seriesのほうが素直なことが多い。あとからto_frame().Tで1行のDataFrameにもできる。
df = s.to_frame().T混在しているときの注意
スカラーとリストが混ざっている場合は、このエラーは出ない。スカラーのほうがリストの長さに合わせて自動で複製される。
pd.DataFrame({"name": ["田中", "佐藤"], "dept": "営業"})# dept は2行とも「営業」になるこれは便利だが、意図しない複製が起きることもある。1件だけのつもりが、別の列の長さに引きずられて増えることがあるので、作ったあとにshapeを確認しておくと安心になる。
print(df.shape)ループで溜めるときの定石
1件ずつconcatやappendでつなぐのは遅いので、リストに溜めて最後に一度だけDataFrameにする書き方が定石になる。
rows = []for item in items: rows.append({"id": item.id, "name": item.name})df = pd.DataFrame(rows)この形なら、そもそも今回のエラーに出会わない。行数はリストの長さで自然に決まる。
なおDataFrame.appendはすでに廃止されているので、古い記事を参考にしている場合は注意したい。詳細はpandasのappendが使えなくなった話に書いた。
📘 DataFrameの組み立て方を実戦の文脈で学ぶなら、Kaggleで勝つデータ分析の技術。
まとめ
・値が全部スカラーだと行数が決まらないので、pandasがindexを要求している
・1行なら各値をリストで包むか、辞書自体をリストに入れる
・index=[0]を渡す方法もある。indexの長さぶん同じ内容が並ぶ
・キーを行にしたいならfrom_dict(orient="index")
・スカラーとリストが混ざるとスカラーが自動複製される。作成後にshapeを確認する
・ループで溜めるときはリストに貯めて最後に一度だけDataFrame化するのが速くて安全
※本記事にはアフィリエイト広告を含みます。