628 文字
3 分
Pandas で and が使えず & が要る理由

Understat から取ってきたセリエAの選手データで「ミランの選手」かつ「5 得点以上」を絞り込もうとして、素直にこう書きました。

df[df["team_title"] == "AC Milan" and df["goals"] >= 5]
ValueError: The truth value of a Series is ambiguous.
Use a.empty, a.bool(), a.item(), a.any() or a.all().

and は「全体で 1 つ」を求める#

Python の and は、左右のオブジェクトを真偽値 1 つに変換してから判定します。ところが df["team_title"] == "AC Milan" が返すのは真偽値ではなく、行数と同じ長さの bool の Series です。

print(df["team_title"] == "AC Milan")
0 False
1 False
2 False
...
585 False
Name: team_title, Length: 586, dtype: bool

586 行ぶんの True/False が並んだこれを、and は「Yes か No のどちらか 1 つ」に決めようとします。1 つでも True があれば True なのか、全部 True でなければ False なのか。決めようがないので Pandas は判断を拒否し、ambiguous(あいまい)だと言ってきます。エラーメッセージが a.any() や a.all() を勧めてくるのは、「全体で 1 つに畳むならどちらの意味か明示しろ」ということです。

& は「行ごとに 1 つ」#

一方、こちらが本当にやりたいのは全体を畳むことではなく、1 行ずつ「両方の条件を満たすか」を判定することです。それをやるのが & です。

df[(df["team_title"] == "AC Milan") & (df["goals"] >= 5)]
player_name team_title position goals
Rafael Leão AC Milan F S 9
Christian Pulisic AC Milan F S 8
Christopher Nkunku AC Milan F S 7
Adrien Rabiot AC Milan M S 6
Strahinja Pavlovic AC Milan D S 5

& は 2 つの bool Series を要素ごとに突き合わせ、結果もまた bool の Series で返します。df[...] はそれを行の選択に使います。or に対応するのが |、not に対応するのが ~ で、対応関係は同じです。

なお各条件を丸カッコで囲んでいるのは飾りではありません。& は == や >= より結合が強いため、囲まないと意図と違う順序で評価されます。

まとめ#

& は and の代替品ではなく、そもそも別の演算です。and が「まとめて 1 つの答え」を出すのに対し、& は「行ごとに答え」を出す。Pandas の絞り込みで欲しいのは常に後者です。

データの取得元については Pythonでサッカー分析を学ぼうとしたら、無料のxGが消えていた に書きました。

Pandas で and が使えず & が要る理由
https://blog.c12o.net/posts/pandas-and-vs-ampersand/
作者
Seu (c12o)
公開日
2026-08-02
ライセンス
CC BY-NC-SA 4.0