isinで期待したIDが出ないときは、照合する列とリストの「値の型」を確かめ、先頭ゼロを消してよいか決める前に変換しないでください。 抽出後は行数だけでなく、依頼されたコードのうち何が見つからなかったかも確認します。
CSVやExcelの台帳から、別の一覧にある機材コードだけを選びたい人向けです。ここでは架空の貸出台帳8行を使います。返却を指示したり、実在する貸出記録を更新したりする教材ではありません。コードの一致を確認するところまでを、小さく実行します。
一次資料確認日:2026年10月18日。Series.isinとDataFrame.isinを参照しています。公式安定版の表示は3.0.6です。掲載コードはPython 3.12.14・pandas 2.2.3で実行して照合しました。現行版の全条件を実測したという意味ではありません。
isinで一致しない値を、変換前の状態から調べる
完全一致の対象を、一つの列とリストで指定する
df["機材コード"].isin(targets)は、機材コード列の各値が、候補のどれかと一致するかを行ごとに返します。返るのは真偽の列です。その判定を使ってdf.loc[mask]と書くと、対象行を選べます。選ぶことと元の表を書き換えることは、別の操作です。
検索語が名前の一部に入るかを調べる処理とは異なります。「0101」と一致するコードが必要なら、機材名に0101という文字が含まれる行まで広げません。文字を含む検索は欠損と記号を切り分けるstr.containsの練習を参照できます。
候補が一つでも、["0101"]のようにリストとして渡します。公式APIは、一つの文字列をそのまま渡すとTypeErrorになると説明しています。「一つなら角括弧を外してよい」という覚え方にはしないでください。候補の列をコピーしたつもりが、文字列一個になっていることもあります。
最初に書く期待値は、抽出後の画面の見た目ではなく、残したい行IDです。本稿はT01、T02、T04、T08を対象にします。後から件数を見て期待値を作ると、誤った処理に合わせて正解を書き換えてしまいます。依頼の意味から先に正解を決める順番にしましょう。
また、候補リストを誰が作ったか、その一覧はいつのものかを残します。昨日の返却対象を今日の台帳に照合したなら、コードの不一致以外に、一覧を作った時点の差もありえます。プログラムを直す前に、二つの表が比較可能な組かを確かめるほうが早い場面があります。
候補が空のリストの場合も、何も選ばれない結果を業務上どう扱うか決めます。「対象がない」と「対象一覧を読み込めなかった」を同じ処理にしないためです。今回は固定した3コードで練習し、ファイル読込の成功まで自動判定する仕組みは含めません。
数値101と文字列0101を、見た目だけで揃えない
公式のSeries.isinには、数値と文字列を区別する例があります。画面上では数字に見えても、数値の101と文字列の「101」は同じものとして一致しません。先頭ゼロ付きの「0101」では、型に加えて文字そのものも違います。
ここで全列を整数へ変えれば解決する、と急がないことが大切です。機材コードが四桁の識別子なら、ゼロを含む形が正規の値かもしれません。一方、単に数量を比較する列なら数値として揃えることが適切な場合もあります。型変換は目的から決める処理です。
本稿のT03は元の値が数値101です。この数字が本来0101を表していたのか、それとも別の機材なのかは、表だけでは分かりません。astype("string")で「101」に変えられても、失われたゼロの根拠にはなりません。変換後の値を使って履歴を上書きしないでください。
CSVの読込時点でゼロがなくなっていたなら、抽出より前の工程を調べます。CSVの先頭ゼロと文字化けを分けて調べる方法では、識別子をどう読み込むかを扱っています。既に消えた桁を、照合の都合だけで推測して復元する話とは分けてください。
型を確かめるときは、列のdtypeだけでなく、問題の値のtypeやreprも小さな範囲で見ます。object型の列には数値と文字列が混在することがあります。「列はobjectでした」で調査を終えると、行ごとの違いが隠れたままになります。
実データの中身を相談先へ送れない場合は、数値101と文字列0101だけで再現例を作れます。必要なのは実際の機材名ではなく、型と桁の違いです。最小例で現象を再現できれば、個人情報や社内記録を共有せずに原因を説明できます。
空白・欠損・全角文字は、別の修正候補にする
「0102」と「 0102」は同じ文字列ではありません。前者にはない空白が先頭にあります。本稿のT05が抽出されないのは、この違いによります。pandasが候補を探す際、担当者の意図を読んで空白を補正してくれるわけではありません。
空白を取り除いてよいという台帳のルールがあるなら、元の値を残した別の列にstr.strip()の結果を作り、その列で再照合できます。修正前の4行と修正後の5行を比べ、追加されたT05だけが意図した変更かを見ます。件数が増えたことだけを改善としないでください。
全角の数字や、間に入った空白はさらに別です。見た目を似せる変換を一度に何種類も適用すると、どの規則で一致したか追いにくくなります。一つの修正候補につき、該当した行IDと理由を記録すると、コードを別の台帳へ移す際にも説明を保ちやすくなります。
欠損は、候補にない正常なコードとも区別します。T06のNoneは、この教材ではコード未入力です。対象コードのどれにも一致しなかったからといって、返却の対象外だと判断する材料にはなりません。「照合できる値が入っていなかった」と伝える情報が必要です。
欠損を調べる場合はisnaなど、欠損を見る条件を別に使います。候補リストにNoneを足して照合の意味を変えるより、依頼された機材コードと未入力の検査を分けたほうが、今回の目的には合います。欠損の検査はCSVの欠損・重複を調べる練習にもつながります。
修正候補を残す際に、実際の台帳担当者への確認が終わったようには書かないでください。教材で「空白を削ると一致する」と示せることと、その修正を本番へ採用してよいことは別です。業務ルールが未確認なら、実際の更新を止めたまま結果を渡せます。
| 値の例 | 一致しない理由 | 確認してから行うこと |
|---|---|---|
| 数値101/文字列0101 | 型も桁も違う | 識別子の仕様を確認。ゼロを推測で追加しない |
| 0102/先頭に空白のある0102 | 文字列が完全には一致しない | 空白除去が許されるなら別列で修正候補を作る |
| None | コード未入力 | 対象外と決めず、未入力の件数と行IDを残す |
| 0101が複数行 | 同じコードの記録が複数ある | 行数と種類数を分け、重複削除の必要性を別に判断 |
対象コードの種類数と、台帳の行数を混同しない
依頼コードが3種類だから、抽出結果も3行になるはずだとは限りません。機材コード0101が東の拠点で2行、西の拠点で1行あり、0102が1行あれば、見つかったコードは2種類でも記録は4行です。どの単位を数えているかが異なります。
台帳の一行が「機材そのもの」なのか、「貸出一回」なのかも確認してください。同じコードが複数回使われる台帳で、抽出後に重複を削ると、一回分の履歴を消す可能性があります。今回のT01とT08は別の行IDであり、勝手に同じ記録として扱いません。
反対に、一機材一行で管理する仕様の台帳なら、同じコードの複数行は調査対象です。その場合も、抽出で解決したことにはしません。重複があったことを別の検査として報告し、どの記録を残すかを決めてから更新してください。
重複削除を使うときは、最新日を残すのか、同じ日の競合をどうするかが必要です。最新日を残す重複処理の確認は、その判断を切り分けて扱っています。isinで選んだ直後に、目的を説明せずdrop_duplicatesを足すのは避けましょう。
報告の単位は「対象コード3種類、見つかったコード2種類、台帳4行、未検出1種類」のように書けます。数字が四つ並ぶのは冗長ではなく、それぞれ違う問いへの答えです。受け取る人が、4行あるから依頼を満たしたと誤解するのを防げます。
並び順についても、依頼リストの順に自動で並ぶと想定しないでください。行の抽出と並べ替えは別です。今回の出力は元台帳の行順を保つ形にしており、依頼の優先順で出したい場合は、その仕様を追加して検算する必要があります。
複数列は「列ごとの候補」と「値の組」を分ける
拠点とコードの組で対象を指定する場合、二つの列に別々のisinを使っただけでは、依頼された組と違う行が入ることがあります。「東の0101、または西の0103」という依頼を、拠点は東か西、コードは0101か0103、と分解すると組合せが広がるためです。
この教材で西の0101であるT04は、分解した条件なら通ります。しかし依頼された二つの組の中にはありません。両方の列がそれぞれ候補内であることと、その二つが対になって候補内であることは違います。見た目の似た式でも、業務上の答えは変わります。
候補の組が少ない場合は、対応する条件を括弧でまとめてORでつなぎ、期待する行IDを確認する方法があります。次の実行例はこの書き方です。候補が多くなったら、二列をキーにした別表との結合など、保守しやすい方法を検討できます。
DataFrame全体のisinも、一列のSeries.isinと同じ結果ではありません。公式資料では、SeriesやDataFrameを値として渡す際、インデックスや列名の一致も判定に関係すると説明されています。見つけた短い式を、入力の型を変えたまま使い回さないでください。
特にdf[df.isin(...)]は、行をまとめて選ぶつもりでも、要素ごとの条件になりえます。初心者のうちは、対象の一列から真偽の列を作り、その長さと意味を説明してから行の抽出へ進むほうが、どの範囲を検査しているかを追えます。
結合を使う場合も、重複キーで件数が増えないかを別に検算します。mergeで行数が増える原因とキーの確認は、この次の段階です。isinの候補一致を、結合の件数保証やキーの一意性の証明として扱わないでください。
架空の機材台帳で、抽出と依頼側の不足を検算する
8行の台帳から、変換せずに4行を選ぶ
以下のデータは編集部が作成した架空の値です。T01からT08は台帳の行を追うためのID、機材コードは照合したい値、拠点は追加条件に使う列です。実データの行番号が変わっても追えるよう、どの列を行の識別に使うかを最初に決めます。
最初の実行では、文字の修正を一切行いません。目的は、現在入っている値をそのまま比較すると何が起きるかを知ることです。修正を入れた後の結果だけ見るより、どの差が元からあったかを説明できます。
import pandas as pd
df = pd.DataFrame({
"行ID": ["T01", "T02", "T03", "T04", "T05", "T06", "T07", "T08"],
"機材コード": ["0101", "0102", 101, "0101", " 0102", None, "0103", "0101"],
"拠点": ["東", "東", "西", "西", "東", "東", "西", "東"],
})
targets = ["0101", "0102", "0199"]
mask = df["機材コード"].isin(targets)
selected = df.loc[mask].copy()
assert selected["行ID"].tolist() == ["T01", "T02", "T04", "T08"]
found_codes = set(selected["機材コード"])
missing_targets = [code for code in dict.fromkeys(targets) if code not in found_codes]
assert found_codes == {"0101", "0102"}
assert missing_targets == ["0199"]
assert len(selected) == 4
assert df["行ID"].is_unique
print(selected[["行ID", "機材コード", "拠点"]])
print("見つからなかった依頼コード:", missing_targets)
ここでコピーを作るのは、選んだ表へ後から確認用の列を足しても、元の一覧と分けて扱うためです。サンプルはファイルを保存しないので、元の台帳ファイルを上書きする処理はありません。手元のデータに置き換える際も、最初は抽出結果だけを別に確認してください。
この結果の検算は、4行だったという一点だけではありません。行IDがT01、T02、T04、T08であること、見つかったコードは0101と0102であること、0199は見つかっていないことまでを期待値と照合します。同じ4行でも、T03が混ざっていたら今回の答えとは異なります。
コードが扱っているのは文字列と数値などの小さな混在例です。独自の拡張型、大量データの速度、実際のCSVの文字コードまでは検証していません。この範囲を実行結果に添えると、教材の成功を社内全データの検証済みという意味へ広げずに済みます。
依頼されたのに見つからない0199を、結果から拾う
抽出表には、見つかったものしか出てきません。したがって抽出表だけを読み、依頼が全部終わったと判断すると、0199が抜けていることを見逃します。依頼一覧から、実際に見つかったコードを引く方向の確認が必要です。
コードでは、候補の順番を残しつつ重複を除くため、dict.fromkeys(targets)を使いました。ここで重複を除いているのは報告用の依頼コードの一覧です。台帳の4行を削ったのではありません。同じ「重複」という言葉でも、処理している側が違います。
依頼リストに同じコードが二回あった場合、その重複に意味があるかも別に見ます。たとえば二つの拠点からそれぞれ依頼された記録なら、コードだけにまとめると依頼元が失われます。本稿はコードの種類として照合する教材であり、依頼履歴の件数を数える設計ではありません。
未検出の原因は複数あります。台帳に本当に存在しない、古い版を読んだ、別の列へ記録されている、先頭ゼロが失われた、のどれかもしれません。未検出という結果だけで「依頼者の入力ミス」と決めないでください。次に調べる順序を提示するための一覧です。
今回なら、まず0199が依頼の原資料にあるか、対象とする台帳の期間や拠点が一致するかを見ます。その次に型や空白の問題を調べます。数字の補完や似たコードへの置換を先に行うと、別の機材へ依頼を付け替えてしまうおそれがあります。
完了報告には、未検出を空欄にせず「0199の1種類」と具体的に残せます。すべて見つかった場合も、未検出0種類と書くと、検査を省いたのか、本当に0だったのかが区別できます。コードを実行した人以外にも、処理の範囲が伝わります。
空白を取り除く案と、拠点を含む案を別々に試す
次は処理の目的が二つあるため、結果を一つに混ぜません。空白除去の案は、T05を0102の候補として加えてよいかを調べるものです。拠点を含む案は、同じ0101でも東だけを選ぶという別の依頼を再現するものです。
# 空白除去を採用する前の比較用。元の列は変更しない。
clean = df["機材コード"].astype("string").str.strip()
after_strip = df.loc[clean.isin(targets), "行ID"].tolist()
assert after_strip == ["T01", "T02", "T04", "T05", "T08"]
assert set(after_strip) - set(selected["行ID"]) == {"T05"}
# 別の依頼:東の0101、または西の0103だけ。
pair_mask = ((df["拠点"] == "東") & (df["機材コード"] == "0101")) | (
(df["拠点"] == "西") & (df["機材コード"] == "0103")
)
assert df.loc[pair_mask, "行ID"].tolist() == ["T01", "T07", "T08"]
independent = df["拠点"].isin(["東", "西"]) & df["機材コード"].isin(["0101", "0103"])
assert df.loc[independent & ~pair_mask, "行ID"].tolist() == ["T04"]
# 候補1つでもリストで渡す。文字列だけを渡す形は受け付けない。
try:
df["機材コード"].isin("0101")
except TypeError:
pass
else:
raise AssertionError("単一文字列の入力確認が想定と異なります")
空白を除いた案でも、T03の数値101は対象に入りません。文字列へ変わった後も値は101であり、0101とは異なるためです。この一点を確認すると、文字列に揃えることだけで全問題が解決するわけではないと分かります。
拠点を含む案では、独立した候補条件から余分に入った行がT04だと確認しています。二つの式で件数が違ったとき、どの行が違ったかを表示すれば、括弧の書き方だけではなく、依頼の意味から説明できます。
コードを変更して練習するなら、まず対象の組を一つ追加し、増えるはずの行IDを紙に書いてから実行します。先に対象を増やしたのに出力が変わらない場合は、依頼リスト、列名、型、条件式のどこを変更したかを順番に調べてください。
抽出結果を渡すとき、四つの数字と条件を添える
今回の報告例は「対象コード3種類、抽出4行、見つかったコード2種類、未検出1種類0199」です。続けて、元の機材コードは修正していないこと、空白除去案ではT05が増えること、数値101の意味は未確認であることを添えます。
受け取る人が一覧を再利用する場合、どの台帳のどの列を使ったかも必要です。ファイル名だけでは、シートや読込条件の違いまでは分かりません。コードの実行日時、pandasの版、使った候補一覧の版を一緒に記録すると、後から同じ比較をしやすくなります。
保存が必要なら、元データと別の出力先を使い、保存後に行IDとコードを読み直して比べます。抽出が正しくても、保存後の再読込で先頭ゼロが落ちることがあります。確認する対象は、画面に表示された表から、実際に渡すファイルへ移ります。
ここで自動で未検出コードを台帳へ追加する必要はありません。照合結果が不足を示したなら、資料や担当者に戻って判断する段階です。抽出用のプログラムへ更新機能を足す場合は、更新対象、取消方法、履歴の保存まで別に設計してください。
依頼者への短い説明では、技術用語を並べるより「0101と同じ文字列の行だけを選んだ」「0199はこの台帳に見つからなかった」と書けます。相手がpandasを知らなくても、結果を採用してよい範囲や、確認が残る箇所を判断できます。
| 実行 | 結果 | 説明する判断 |
|---|---|---|
| 元のコードで完全一致 | T01・T02・T04・T08の4行 | 依頼3コード中2種類が見つかり、0199は未検出 |
| 空白除去案 | 上記にT05を加えた5行 | 空白を無視してよい規則かは別途確認 |
| 東0101/西0103の組 | T01・T07・T08の3行 | 拠点とコードを対で指定し、T04は含めない |
独学の次は、型変換の理由を説明できるかで考える
練習の到達点は、isinという名前を覚えることだけではありません。T03へゼロを足さない理由、T05を加えるなら何を確認するか、0199が結果表にないことをどの側から調べるかを、自分の言葉で説明できることです。別の台帳でも使える判断になります。
さらに試すなら、候補リストへ同じコードを二回入れる、存在する0103を追加する、先頭に空白のある候補を作る、と一条件ずつ変えられます。一度に全部変えず、どの変更がどの行を動かしたか追える形にすると、原因の切り分けの練習になります。
エラーの解消だけではなく、依頼の意味をコードへ落とすところで止まるなら、質問支援のある講座を比較する材料になります。相談時には、実データを持ち込む前に、今回のような架空の8行と「期待した行ID・実際の行ID」を用意すると、質問したい範囲が具体的になります。
Python Winnerの講座内容と受講前の確認点も選択材料になります。公式Pythonマスターには文字列処理やCSVなどの学習範囲があります。ただし、このisin課題の添削や特定ライブラリの指導が含まれるかは、申込前に個別に確認してください。
2026年10月18日に確認した公式Pythonマスターの受講料は税込297,000円、受講期間は3ヶ月、マンツーマンレッスンは30分を18回です。今回のような教材の質問を相談できるかを確認し、見積書に示される講座名、総額、支援の期限を確かめてください。専門コースとは料金が異なり、学習後の転職や収入を約束するものではありません。
よくある質問
Q. isinで一つのコードだけ選びたい場合もリストが必要ですか?
一つの文字列を候補にする場合は、角括弧で囲んだ1要素のリストにします。単一の文字列をそのまま渡すとTypeErrorになることが公式APIに記載されています。
Q. 数値101を0101へ揃えればよいですか?
四桁の識別子か、数値としての値かを確認してから決めます。元の101が0101を意味したとは表だけでは分からないため、桁を推測で追加しません。
Q. 候補が3種類なのに4行出たら間違いですか?
同じコードが台帳に複数行あれば起こります。行数とコードの種類数を分けて数え、一行が何を記録しているかを確認します。
Q. 抽出表にない対象コードはどう探しますか?
依頼リストから、抽出されたコードを除いた一覧を作ります。教材では見つからない依頼コード0199を別に記録しています。
Q. このコードは台帳を変更しますか?
教材は架空データの抽出と期待値照合だけを実行し、ファイルの読込・保存や外部送信は行いません。実データの更新には別の設計が必要です。