PythonでExcelの表から特定の言葉を含む行を抽出する手順|商品名や備考に入った語で絞り込む
Excelの表から、備考や商品名に特定の言葉を含む行だけを、pandasのstr.containsで抜き出す手順を解説します。空欄・大文字と小文字・括弧などの記号でつまずく点を、架空の問い合わせの明細で試しました。
目次
この記事でわかること
- 備考や商品名に特定の言葉を含む行だけを取り出す方法(str.contains)
- 空欄のセルを「含まない」として扱う書き方(na=False)
- 括弧や点のような記号を、文字のまま探す書き方(regex=False)
- 大文字と小文字、全角と半角、数字のセルでつまずく点
Excelの問い合わせの明細から「返品」と書かれた行だけを見たいとき、検索で1件ずつ拾ってコピーしていくと、件数が増えるほど手間がかかり、拾い忘れも起きます。この記事では、pandasで明細を読み込んで、備考の列に決めた言葉がある行だけを選び、別のファイルに保存するところまでを、実際に動かした結果を添えて紹介します。
拠り所は、pandas 3.1.0の公式の資料のSeries.str.containsと、文字のデータの扱い方をまとめたユーザーガイドです。2026年11月4日に原文を読みました。商品名や問い合わせの内容は、どれも試すために用意した架空のものです。
先に結論: str.containsで真偽の列を作り、それで行を選ぶ
列にstr.contains("返品", regex=False, na=False)を使うと、言葉を含む行がTrueになる真偽の列ができます。 それを表の[ ]に渡すと、Trueの行だけが残ります。記号を文字のまま探すregex=Falseと、空欄を含まない扱いにするna=Falseは、毎回付けておくと安心です。
| やりたいこと | 書き方 | 試した明細での結果 |
|---|---|---|
| 言葉を含む行を選ぶ | str.contains("返品", regex=False, na=False) | 10行から3行 |
| 大文字と小文字を区別しない | case=Falseを足す | 「usb」で1行から3行 |
| 言葉を含まない行を選ぶ | 結果の前に~を付ける | 7行 |
| 空欄のセルを含まない扱いにする | na=False | 備考が空欄の1行は選ばれない |
str.containsのしくみ
pandasの資料では、str.containsを、型や正規表現が文字列の中に含まれるかを調べ、結果を真偽(TrueとFalse)の列で返すものとしています。ユーザーガイドの説明では、似た働きのmatchは文字列の先頭から、fullmatchは文字列の全体が一致するかを見るのに対し、containsは文字列のどの位置にあっても一致とみなします。
引数のcaseは大文字と小文字を区別するかで、初めの設定はTrue(区別する)です。regexは探す語を正規表現として読むかで、初めの設定はTrueです。Falseにすると、渡した語をそのままの文字として探します。資料の例でも、正規表現の「.0」は「どれか1文字の後に0」と読まれるため、「40」にも一致すると注意しています。
空欄や数字のセルの扱い
pandas 3.0からは、文字の列を読み込むと、文字用の型(str)になります。ユーザーガイドによると、この型の空の値はNaNです。str.containsの資料では、空の値の結果をnaの引数で決め、何も渡さないときは列の型によって変わるとしています。str型ならFalse、いろいろな値が混ざったobject型ならNaNになります。
文字と数字のセルが混ざった列は、object型として読み込まれます。数字のセルは文字列ではないため、結果にNaNが入り、その結果で行を選ぼうとするとエラーで止まります。na=Falseを付けると、空欄も数字も「含まない」として扱われます。数字のセルも文字として調べたいときは、先にastype(str)で文字に直します。
手順: 問い合わせの明細から「返品」を含む行を書き出す
次のコードは、架空の問い合わせの明細 toiawase.xlsx を読み込み、備考の列に「返品」を含む行を toiawase_henpin.xlsx に書き出します。元の toiawase.xlsx は書きかえません。ファイルの名前と探す言葉は、自分の明細のものに書きかえてください。
import pandas as pd
toiawase = pd.read_excel("toiawase.xlsx") # 読むだけで、上書きはしない
word = "返品"
# 記号も文字のまま探し、空欄のセルは「含まない」として扱う
found = toiawase["備考"].str.contains(word, regex=False, na=False)
hits = toiawase[found]
print("読み込んだ行:", len(toiawase))
print(f"「{word}」を含む行:", int(found.sum()))
print(hits[["受付日", "商品名", "備考"]].to_string(index=False))
hits.to_excel("toiawase_henpin.xlsx", index=False)
foundは、行ごとにTrueかFalseが入った列です。sumでTrueの数を数えられるので、書き出す前に件数を画面に出し、見つけた行の中身と見比べます。xlsxの読み書きには、pandasのほかにopenpyxlが要ります。
試した結果
受付日・商品名・型番・備考の4列で、データの行が10行の架空の明細で動かしました。備考には「返品したい」「交換の相談」「返品ではなく修理を希望」などを入れ、1行は空欄にしました。型番の列には、「C-150」のような文字と、2041のような数字を混ぜました。
- 「読み込んだ行: 10」「「返品」を含む行: 3」と表示されました
- 見つかったのは、USBケーブル(1.5m)・USB-C充電器・キーボードの3行でした
- キーボードの備考は「返品ではなく修理を希望」で、返品の依頼ではありませんが、「返品」の2文字を含むため選ばれました
- 備考が空欄のマウスの行は、選ばれませんでした
- toiawase_henpin.xlsx は4列・3行で、受付日の古い順に並んでいました
- 元の toiawase.xlsx は、実行の前と後でハッシュ値が一致しました
動かしたのは手元のMacで、pandasの版は3.1.0です(Pythonは3.12.15、openpyxlは3.1.5)。書き出したファイルはExcelのアプリでは開かず、openpyxlで読み直して中身を見ました。
自分で絞り込んでよいか、相談するかの判断
目安は、「言葉が入っているかどうかで、行の扱いを決めてよいか」です。返品の問い合わせを先に読みたい、ある商品の行だけを集計したい、のように人が後で中身を読む使い方なら、上のコードで絞り込んでかまいません。
言葉を含むかどうかだけで、返金や在庫の処理を自動で進めるような使い方は、先に相談します。試した結果のように「返品ではなく」のような否定の文も選ばれますし、書く人によって「返却」「戻し」のような別の言い方もあります。抜き出した行は必ず目で確かめ、どの言葉で探すかを明細を作っている人とそろえておきます。
つまずきやすいところ
- 否定の文の行まで選ばれる: 「返品」で探すと、「返品ではなく修理を希望」の行も入りました。str.containsは言葉の意味ではなく文字の並びを見ます。件数だけで判断せず、選ばれた行を読みます
- 括弧の付いた語が、別の行にも一致する: regexを付けずに商品名を「(1.5m)」で探すと、括弧の無い「ケーブル1.5m」の行にも一致して2行になり、正規表現の括弧についての警告(UserWarning)も出ました。regex=Falseにすると、括弧付きの1行だけになりました
- 全角の「USB」が見つからない: case=Falseで「usb」を探すと、USBケーブル・usbハブ・USB-C充電器の3行になりましたが、全角で書かれた「USBメモリ」は入りませんでした。全角の文字を半角に直すなら、PythonでExcelの表の文字の前後の空白と全角・半角をそろえる手順を先に使います
- 数字のセルが混ざった列でエラーになる: 型番の列をna=Falseなしで調べると、数字のセルの結果がNaNになり、行を選ぶところで、空の値を含む真偽の列では行を選べないというエラー(ValueError)が出ました。na=Falseを付けるか、astype(str)で文字に直してから調べます
- 日付の列には使えない: 受付日の列にstr.containsを使うと、.strは文字列の値にしか使えないというエラー(AttributeError)が出ました。日付で行を選ぶときは、文字ではなく日付として比べます
- 等しい値や一覧の値で選びたい: 「返品」と完全に同じ値の行や、決めた商品の一覧に入る行を選ぶときは、PythonでExcelの表から条件に合う行を抽出する手順のやり方が向いています
- 行ではなく、セルの中の番号だけがほしい: 行を選ぶのではなく、セルの文字列から型番や番号の部分だけを取り出すなら、PythonでExcelの文字列から番号やコードを抽出する手順を見てください
まとめ
- 言葉を含む行は、str.containsで真偽の列を作り、表の[ ]に渡して選びます
- regex=Falseで記号を文字のまま探し、na=Falseで空欄や数字のセルを「含まない」として扱います
- 大文字と小文字はcase=Falseでそろえられますが、全角と半角は先にそろえます
- 文字の並びだけを見るので、選ばれた行の中身と件数を確かめてから書き出します
よくある質問
このコードを動かすと、元のExcelのファイルは書きかわりますか?
書きかわりません。コードは問い合わせの明細を読み込むだけで、見つけた行は toiawase_henpin.xlsx という別のファイルに入れます。試したときも、元の toiawase.xlsx のハッシュ値は実行の前後で一致しました。
「返品」か「交換」のどちらかを含む行を、まとめて抜き出せますか?
できます。regexを初めの設定(True)のままにして、語を「|」でつなぎます。pandasの資料にも、2つの語のどちらかを含むかを調べる例があります。試した明細では、str.contains("返品|交換", na=False)で5行が見つかりました。
言葉を含まない行のほうを抜き出したいときは、どうしますか?
str.containsの結果の前に「~」を付けると、真と偽が入れかわります。試した明細で「返品」を含まない行を選ぶと、7行でした。備考が空欄の行も、含まない側に入ります。
商品名と備考のどちらかに言葉がある行を探せますか?
列ごとにstr.containsで真偽の列を作り、「|」でつないで行を選びます。試した明細で「ケーブル」を商品名か備考に含む行を探すと、商品名に入っている3行が選ばれました。
言葉で始まる型番だけを選ぶには、どうしますか?
str.containsは文字列のどこにあっても一致するので、型番「AC-65」も「C-」を含むと判定されます。先頭だけを見るときはstr.startswithを使います。試した明細では、文字に直した型番の列でC-150とC-151の2行だけが選ばれました。