CSVを読み込んだあとに、次のように思うことはありませんか。
- 商品名に「Pro」を含む行だけ見たい
- 住所に「東京」を含むデータだけ抽出したい
- カテゴリ名に特定の文字が入っている行だけ確認したい
- 欠損値が混じっていて、文字列検索がうまくいかない
このように、完全一致ではなく「文字列の一部を含む行」を抽出したいときに使うのが、pandasの str.contains() です。
pandasで「contains」のように文字列を含む行を探したい場合は、str.contains() を使います。
結論から言うと、基本形は次のように書きます。
df[df["列名"].str.contains("探したい文字", na=False)]
na=False を付けると、欠損値がある行を False として扱えます。
そのため、欠損値が混じる列でも、初心者が安全に抽出しやすくなります。
この記事では、pandasの str.contains() を使って文字列を含む行を抽出する方法を、Google Colabで試しやすいサンプルで解説します。
あわせて、isin() や query() との違い、na=False の意味、よくあるミスも整理します。
この記事でわかること
この記事では、次の内容を学べます。
str.contains()で文字列を含む行を抽出する方法- 完全一致と部分一致の違い
na=Falseを付ける理由- 特定の文字を含まない行を抽出する方法
- 大文字・小文字を無視して検索する方法
regex=Falseを使って記号をそのまま検索する方法isin()、query()、replace()との使い分け- 抽出後に
head()やvalue_counts()で確認する流れ
Pandas DataFrame入門シリーズの中での位置づけ
str.contains() は、DataFrameを読み込んだあとに、必要な行を探す・抽出するための操作です。
データ分析の流れで見ると、次のような位置づけになります。
- CSVを読み込む
head()やinfo()で中身を確認するstr.contains()で文字列を含む行を抽出する- 必要に応じて
replace()やfillna()で前処理する value_counts()やgroupby()で集計する
つまり、str.contains() は「確認したあと、必要なデータだけ取り出す」ための実用的な操作です。
str.contains()は文字列を含む行を抽出したいときに使う
str.contains() は、Seriesの各要素に対して「指定した文字列を含むかどうか」を調べます。
基本形は次のとおりです。
df[df["列名"].str.contains("探したい文字", na=False)]
ポイントは、df.str.contains() ではなく、文字列が入っている列を指定してから使うことです。
df["商品名"].str.contains("Pro", na=False)
この結果は、各行が条件に合うかどうかを表す True / False のデータになります。
それを df[...] の中に入れることで、条件に合う行だけを取り出せます。
最初は、次の3つをセットで覚えると分かりやすいです。
| 目的 | 書き方 |
|---|---|
| 文字を含む行を抽出する | df[df["列名"].str.contains("文字", na=False)] |
| 文字を含まない行を抽出する | df[~df["列名"].str.contains("文字", na=False)] |
| 大文字・小文字を無視する | df[df["列名"].str.contains("文字", case=False, na=False)] |
サンプルデータを作成する
まずは、商品名・住所・カテゴリ・メモを含む小さなDataFrameを作ります。
実務ではCSVから読み込むことが多いですが、ここではGoogle Colabでそのまま試せるように、サンプルデータを直接作成します。
import pandas as pd
import numpy as np
df = pd.DataFrame({
"商品名": [
"Basic Pen",
"Pro Notebook",
"Pro Mouse",
"Mini Stand",
"Desk Pro Max",
"Standard Keyboard",
"ProCase",
"USB-C Cable"
],
"住所": [
"東京都新宿区",
"大阪府大阪市",
"東京都渋谷区",
"神奈川県横浜市",
"東京近郊",
"北海道札幌市",
np.nan,
"京都府京都市"
],
"カテゴリ": [
"文房具",
"PC周辺機器",
np.nan,
"家具",
"PC周辺機器",
"PC周辺機器",
"アクセサリ",
"ケーブル"
],
"価格": [120, 98000, 4500, 3200, 128000, 8500, 2400, 1600],
"メモ": [
"初回入荷",
"Pro対象",
"在庫確認",
"セール対象",
"PRO表記あり",
np.nan,
"proの小文字あり",
"記号A+Bを含む"
]
})
df
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 0 | Basic Pen | 東京都新宿区 | 文房具 | 120 | 初回入荷 |
| 1 | Pro Notebook | 大阪府大阪市 | PC周辺機器 | 98000 | Pro対象 |
| 2 | Pro Mouse | 東京都渋谷区 | NaN | 4500 | 在庫確認 |
| 3 | Mini Stand | 神奈川県横浜市 | 家具 | 3200 | セール対象 |
| 4 | Desk Pro Max | 東京近郊 | PC周辺機器 | 128000 | PRO表記あり |
| 5 | Standard Keyboard | 北海道札幌市 | PC周辺機器 | 8500 | NaN |
| 6 | ProCase | NaN | アクセサリ | 2400 | proの小文字あり |
| 7 | USB-C Cable | 京都府京都市 | ケーブル | 1600 | 記号A+Bを含む |
このDataFrameには、あえて次のようなデータを入れています。
| 列名 | 目的 |
|---|---|
| 商品名 | 「Pro」を含む商品を抽出する例に使う |
| 住所 | 「東京」を含む住所を抽出する例に使う |
| カテゴリ | 欠損値がある場合の na=False を説明するために使う |
| メモ | 大文字小文字や記号検索の注意点を説明するために使う |
このように、str.contains() は商品名、住所、カテゴリ、メモ欄など、文字列が入っている列でよく使います。
商品名に「Pro」を含む行を抽出する
まずは、商品名に Pro を含む行だけを抽出してみます。
df[df["商品名"].str.contains("Pro", na=False)]
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 1 | Pro Notebook | 大阪府大阪市 | PC周辺機器 | 98000 | Pro対象 |
| 2 | Pro Mouse | 東京都渋谷区 | NaN | 4500 | 在庫確認 |
| 4 | Desk Pro Max | 東京近郊 | PC周辺機器 | 128000 | PRO表記あり |
| 6 | ProCase | NaN | アクセサリ | 2400 | proの小文字あり |
上のコードでは、次の流れで処理しています。
df["商品名"]で商品名の列を取り出す.str.contains("Pro", na=False)で「Proを含むか」を調べるdf[...]でTrueになった行だけを抽出する
処理前と処理後のイメージは次のとおりです。
| 状態 | 内容 |
|---|---|
| 処理前 | すべての商品が表示されている |
| 条件 | 商品名に Pro を含むか調べる |
| 処理後 | Pro Notebook、Pro Mouse、Desk Pro Max、ProCase などが残る |
ここで重要なのは、str.contains() は完全一致ではなく部分一致だという点です。
そのため、ProCase や Desk Pro Max のように、文字列の一部に Pro が入っていれば抽出対象になります。
完全一致・部分一致・候補リスト・置換の違い
初心者が迷いやすいのは、==、isin()、str.contains()、replace() の使い分けです。
最初に判断基準を整理しておきます。
| やりたいこと | 使う方法 | 例 |
|---|---|---|
| ある値と完全に一致する行を抽出したい | == |
商品名が Pro Mouse の行 |
| 複数の候補のどれかに完全一致する行を抽出したい | isin() |
カテゴリが 家具 または ケーブル の行 |
| 文字列の一部を含む行を抽出したい | str.contains() |
商品名に Pro を含む行 |
| 条件式を文字列として書きたい | query() |
価格 >= 5000 のような条件を書く |
| 値そのものを置き換えたい | replace() / str.replace() |
PC周辺機器 を パソコン関連 に直す |
query() は条件式をすっきり書ける便利な方法ですが、文字列の部分一致を学び始めた段階では、まず df[df["列名"].str.contains("文字", na=False)] の形で理解するのがおすすめです。
str.contains() は、値を変更する処理ではありません。
条件に合う行を「取り出す」ための処理です。
# 完全一致:商品名が「Pro Mouse」と完全に一致する行
df[df["商品名"] == "Pro Mouse"]
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 2 | Pro Mouse | 東京都渋谷区 | NaN | 4500 | 在庫確認 |
# 候補リスト:カテゴリが「家具」または「ケーブル」の行
df[df["カテゴリ"].isin(["家具", "ケーブル"])]
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 3 | Mini Stand | 神奈川県横浜市 | 家具 | 3200 | セール対象 |
| 7 | USB-C Cable | 京都府京都市 | ケーブル | 1600 | 記号A+Bを含む |
# 部分一致:商品名に「Pro」を含む行
df[df["商品名"].str.contains("Pro", na=False)]
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 1 | Pro Notebook | 大阪府大阪市 | PC周辺機器 | 98000 | Pro対象 |
| 2 | Pro Mouse | 東京都渋谷区 | NaN | 4500 | 在庫確認 |
| 4 | Desk Pro Max | 東京近郊 | PC周辺機器 | 128000 | PRO表記あり |
| 6 | ProCase | NaN | アクセサリ | 2400 | proの小文字あり |
この3つは似ていますが、役割が違います。
==は1つの値との完全一致isin()は複数候補との完全一致str.contains()は文字列の一部一致
「Proを含む商品名」のように、文字列の一部を探したい場合は、str.contains() が自然です。
住所に「東京」を含む行を抽出する
次に、住所列に 東京 を含む行だけを抽出します。
住所や店舗名、商品名、カテゴリ名などは、完全一致よりも「一部に含まれるか」で探したい場面がよくあります。
df[df["住所"].str.contains("東京", na=False)]
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 0 | Basic Pen | 東京都新宿区 | 文房具 | 120 | 初回入荷 |
| 2 | Pro Mouse | 東京都渋谷区 | NaN | 4500 | 在庫確認 |
| 4 | Desk Pro Max | 東京近郊 | PC周辺機器 | 128000 | PRO表記あり |
この例では、東京都新宿区、東京都渋谷区、東京近郊 のように、住所の一部に 東京 を含む行が抽出されます。
処理前後のイメージは次のとおりです。
| 行 | 住所 | 東京を含むか |
抽出結果 |
|---|---|---|---|
| 0 | 東京都新宿区 | True | 残る |
| 1 | 大阪府大阪市 | False | 残らない |
| 2 | 東京都渋谷区 | True | 残る |
| 3 | 神奈川県横浜市 | False | 残らない |
| 4 | 東京近郊 | True | 残る |
| 6 | 欠損値 | False扱い | 残らない |
na=False を付けているため、住所が欠損している行は False として扱われます。
na=Falseを付ける理由
str.contains() を使うときに、初心者がつまずきやすいのが na=False です。
検索対象の列に欠損値がある場合、str.contains() の判定結果にも欠損値が混じることがあります。
この判定結果をそのままDataFrameの抽出条件に使うと、列の型や欠損値の扱いによってはエラーになることがあります。
# na=False を付けない場合の判定結果
mask = df["カテゴリ"].str.contains("PC")
mask
| カテゴリ | |
|---|---|
| 0 | False |
| 1 | True |
| 2 | NaN |
| 3 | False |
| 4 | True |
| 5 | True |
| 6 | False |
| 7 | False |
上の結果を見ると、カテゴリ が欠損している行では、判定結果にも欠損値が混じっています。
この状態でDataFrameの抽出条件に使うと、列の型や欠損値の扱いによってはエラーになることがあります。
そのため、初心者向けには na=False を付けておく書き方がおすすめです。
# na=False を付けると、欠損値は False として扱われる
df[df["カテゴリ"].str.contains("PC", na=False)]
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 1 | Pro Notebook | 大阪府大阪市 | PC周辺機器 | 98000 | Pro対象 |
| 4 | Desk Pro Max | 東京近郊 | PC周辺機器 | 128000 | PRO表記あり |
| 5 | Standard Keyboard | 北海道札幌市 | PC周辺機器 | 8500 | NaN |
na=False の意味は、次のように考えると分かりやすいです。
| 書き方 | 欠損値がある行の扱い | 初心者向けの使いやすさ |
|---|---|---|
str.contains("PC") |
欠損値が判定結果に残ることがある | エラーや混乱につながりやすい |
str.contains("PC", na=False) |
欠損値を False として扱う |
安全に抽出しやすい |
「欠損値の行は、検索文字を含まないものとして扱いたい」場合は、na=False を付けるのが自然です。
特に、次のような実務データでは na=False を付けておくと安心です。
- 商品名や住所に空欄がある
- メモ欄に未入力の行がある
- CSVを読み込んだ直後で、欠損値の有無をまだ確認できていない
特定の文字を含まない行を抽出する
str.contains() の前に ~ を付けると、条件を反転できます。
つまり、「Proを含む行」ではなく、Proを含まない行を抽出できます。
df[~df["商品名"].str.contains("Pro", na=False)]
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 0 | Basic Pen | 東京都新宿区 | 文房具 | 120 | 初回入荷 |
| 3 | Mini Stand | 神奈川県横浜市 | 家具 | 3200 | セール対象 |
| 5 | Standard Keyboard | 北海道札幌市 | PC周辺機器 | 8500 | NaN |
| 7 | USB-C Cable | 京都府京都市 | ケーブル | 1600 | 記号A+Bを含む |
~ は「ではない」という意味で使います。
~df["商品名"].str.contains("Pro", na=False)
この条件は、「商品名に Pro を含まない」という意味になります。
ただし、na=False を付け忘れると、欠損値が混じる列ではうまく反転できないことがあります。
~ と一緒に使う場合も、基本的には na=False を付けておくと安心です。
大文字・小文字を無視して検索する
英字を含むデータでは、Pro、PRO、pro のように表記が混じることがあります。
デフォルトでは、大文字と小文字は区別されます。
# デフォルトでは大文字・小文字を区別する
df[df["メモ"].str.contains("pro", na=False)]
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 6 | ProCase | NaN | アクセサリ | 2400 | proの小文字あり |
上の例では、小文字の pro を含む行だけが抽出されます。
大文字・小文字を区別せずに検索したい場合は、case=False を使います。
# case=False で大文字・小文字を区別せずに検索
df[df["メモ"].str.contains("pro", case=False, na=False)]
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 1 | Pro Notebook | 大阪府大阪市 | PC周辺機器 | 98000 | Pro対象 |
| 4 | Desk Pro Max | 東京近郊 | PC周辺機器 | 128000 | PRO表記あり |
| 6 | ProCase | NaN | アクセサリ | 2400 | proの小文字あり |
case=False を使うと、Pro、PRO、pro のような表記ゆれをまとめて検索できます。
ただし、case=False は「抽出時に大文字小文字を無視する」だけです。
データ自体を書き換える処理ではありません。表記そのものをそろえたい場合は、replace() や文字列処理を使う流れになります。
記号をそのまま探したいときはregex=Falseを付ける
str.contains() は、デフォルトでは検索文字を正規表現として扱います。
正規表現とは、文字列のパターンを表す書き方です。便利ですが、初心者のうちは +、.、? などの記号を検索するときに、意図しない結果になることがあります。
たとえば、メモ欄から A+B という文字をそのまま探したい場合、+ が正規表現の特別な記号として解釈されることがあります。
記号を普通の文字として探したいときは、regex=False を付けると安全です。
# 「A+B」という文字をそのまま探したい場合
df[df["メモ"].str.contains("A+B", regex=False, na=False)]
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 7 | USB-C Cable | 京都府京都市 | ケーブル | 1600 | 記号A+Bを含む |
今回の記事では、正規表現の詳しい書き方には深入りしません。
初心者のうちは、次のように覚えておくと十分です。
| 場面 | 書き方 |
|---|---|
| 普通の文字を含むか調べる | str.contains("東京", na=False) |
+ や . などの記号をそのまま探す |
str.contains("A+B", regex=False, na=False) |
| 正規表現を使って複数パターンを探す | 慣れてから学べばよい |
まずは、na=False と regex=False の役割を分けて理解しましょう。
na=False:欠損値をFalseとして扱うregex=False:検索文字を正規表現ではなく、普通の文字として扱う
str.contains()を複数条件と組み合わせる方法
str.contains() は、ほかの条件と組み合わせることもできます。
たとえば、商品名に Pro を含み、価格が5000円以上の商品だけを抽出してみます。
df[
df["商品名"].str.contains("Pro", na=False)
& (df["価格"] >= 5000)
]
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 1 | Pro Notebook | 大阪府大阪市 | PC周辺機器 | 98000 | Pro対象 |
| 4 | Desk Pro Max | 東京近郊 | PC周辺機器 | 128000 | PRO表記あり |
ここでは、2つの条件を & でつないでいます。
- 商品名に
Proを含む - 価格が5000円以上
複数条件の詳しい書き方や query() の使い方は条件抽出の記事で扱う内容なので、この記事では深追いしません。
str.contains() は、あくまで「文字列を含むかどうかの条件を作る」と理解しておくと整理しやすいです。
抽出後に確認・前処理・集計へつなげる
str.contains() で行を抽出したら、そこで終わりではありません。
抽出したデータを確認し、必要に応じて前処理や集計につなげます。
たとえば、Pro を含む商品だけを取り出したあと、カテゴリごとの件数を確認してみます。
pro_items = df[df["商品名"].str.contains("Pro", na=False)]
pro_items.head()
| 商品名 | 住所 | カテゴリ | 価格 | メモ | |
|---|---|---|---|---|---|
| 1 | Pro Notebook | 大阪府大阪市 | PC周辺機器 | 98000 | Pro対象 |
| 2 | Pro Mouse | 東京都渋谷区 | NaN | 4500 | 在庫確認 |
| 4 | Desk Pro Max | 東京近郊 | PC周辺機器 | 128000 | PRO表記あり |
| 6 | ProCase | NaN | アクセサリ | 2400 | proの小文字あり |
pro_items["カテゴリ"].value_counts(dropna=False)
| count | |
|---|---|
| PC周辺機器 | 2 |
| NaN | 1 |
| アクセサリ | 1 |
このように、str.contains() はデータ分析の流れの中で、次のように使えます。
| 流れ | 使う操作の例 |
|---|---|
| データを読み込む | read_csv() |
| 中身を確認する | head()、info() |
| 必要な行を探す | str.contains() |
| 値の表記ゆれを直す | replace() |
| 欠損値を確認・処理する | isnull()、fillna() |
| 件数を見る | value_counts() |
| グループごとに集計する | groupby() |
str.contains() は、確認と前処理、集計をつなぐための「対象データを探す操作」と考えると分かりやすいです。
よくあるミスと対処法
str.contains() では、次のようなミスが起きやすいです。
| よくあるミス | 原因 | 対処 |
|---|---|---|
df.str.contains() と書いてしまう |
DataFrame全体には直接使えない | df["列名"].str.contains() と書く |
| 欠損値が混じって抽出できない | 判定結果に欠損値が混じる | na=False を付ける |
| 完全一致のつもりで使ってしまう | str.contains() は部分一致 |
完全一致なら == や isin() を使う |
| 記号検索で意図しない結果になる | デフォルトで正規表現扱い | regex=False を付ける |
| 抽出しただけなのに元データが変わったと思う | 抽出は行を取り出す処理 | 値の変更は replace() などを使う |
query() と混同する |
query() は条件式の書き方、str.contains() は文字列判定 |
文字列の部分一致はまず str.contains() で考える |
特に、最初は次の2点を押さえるだけでも十分です。
- 欠損値がありそうな列では
na=Falseを付ける - 完全一致ではなく、文字列の一部を探すときに
str.contains()を使う
この記事で深入りしない発展内容
str.contains() は正規表現と組み合わせると、より複雑な文字列検索もできます。
ただし、この記事では初心者が最初に使いやすいように、1列から特定の文字を含む行を抽出する基本に絞っています。
次の内容は便利ですが、最初から深く覚えなくても大丈夫です。
- 複雑な正規表現パターン
- 複数列をまたぐ文字列検索
str.extract()やstr.match()の詳しい使い方- 大量データでの高速化
- 自然言語処理やテキストマイニング
まずは、str.contains("文字", na=False) の基本形を使えるようになることを優先しましょう。
まとめ
この記事では、pandasの str.contains() を使って、文字列を含む行を抽出する方法を解説しました。
大切なポイントは次のとおりです。
- 文字列の一部を含む行を抽出したいときは
str.contains()を使う - 基本形は
df[df["列名"].str.contains("文字", na=False)] - 完全一致なら
==やisin()、部分一致ならstr.contains()と使い分ける - 欠損値が混じる列では
na=Falseを付けると安全 - 含まない行を抽出したいときは
~を使う - 大文字・小文字を無視したい場合は
case=Falseを使う - 記号をそのまま検索したい場合は
regex=Falseを使う - 抽出後は
head()やvalue_counts()で確認すると次の分析につなげやすい
str.contains() は、商品名・住所・カテゴリ・メモ欄など、文字列データを扱うときによく使います。
まずは str.contains("文字", na=False) の基本形を覚え、必要に応じて ~、case=False、regex=False を加えていきましょう。
次に読みたい関連記事
この記事の内容は、次の記事とあわせて読むと理解しやすくなります。
- Pandas DataFrame入門|作り方・基本操作をわかりやすく解説
- Google Colab CSV 読み込み&保存入門|pandasでread_csvとto_csvを解説
- pandas 条件抽出(filtering)入門|AND/OR・query関数・複数条件の指定方法
- pandas isinの使い方と仕組み|リスト・複数条件・not isinを解説
- pandas replace()の使い方|値の置換・表記ゆれ・欠損値変換を解説
- pandas value_counts()の使い方|件数集計・割合表示・欠損値の数え方を解説
- pandas fillna()の使い方|欠損値を0・平均値・中央値で埋める方法
まずDataFrameの基本やCSV読み込みを確認し、そのあと条件抽出・isin・replace・value_countsへ進むと、文字列データの確認から前処理までの流れがつながりやすくなります。
str.contains()とisin()の違いは何ですか?
str.contains() は、文字列の一部を含むかどうかを調べる部分一致の方法です。
一方、isin() は、指定した候補リストのどれかに完全一致するかを調べる方法です。
商品名に Pro を含む行を探すなら str.contains()、カテゴリが 家具 または ケーブル のように決まった値に一致する行を探すなら isin() が向いています。
na=Falseはいつ付ければよいですか?
検索対象の列に欠損値がある可能性があるときは、基本的に付けておくと安心です。na=False は、「欠損値の行は検索文字を含まないものとして扱う」という意味です。
初心者のうちは、まず str.contains("文字", na=False) の形を基本にすると安全です。
大文字と小文字を区別せずに検索できますか?
できます。case=False を使います。df[df["メモ"].str.contains("pro", case=False, na=False)]
このように書くと、Pro、PRO、pro などをまとめて検索できます。
特定の文字を含まない行を抽出できますか?
できます。~ を使って条件を反転します。df[~df["商品名"].str.contains("Pro", na=False)]
このコードは、商品名に Pro を含まない行を抽出します。
str.contains()で正規表現を使わないようにできますか?
できます。regex=False を使います。df[df["メモ"].str.contains("A+B", regex=False, na=False)]+ や . などの記号を、そのままの文字として検索したい場合に役立ちます。
str.contains()とquery()はどちらを使えばよいですか?
初心者のうちは、まず df[df["列名"].str.contains("文字", na=False)] の形をおすすめします。query() は条件を文字列として書ける便利な方法ですが、文字列メソッドを組み合わせると書き方が少し難しくなります。
まずは通常の条件抽出に慣れてから、必要に応じて query() を使うと理解しやすいです。
コメント