Python | データ処理:フィルタリング

Python
スポンサーリンク
  1. 概要(フィルタリングは「欲しい行だけを、短く正確に抜く」ための基本)
  2. 基本のブールインデックス(単一条件・複数条件・安全な書き方)
    1. 最小例(単一条件で行を抜く)
    2. 複数条件の結合(& と | と括弧が必須)
  3. 行・列を同時に扱うloc/iloc(明確な抽出と可読性)
    1. 行は条件、列は名前で同時指定(loc)
    2. 位置ベースで抽出(iloc)
  4. 文字列・カテゴリのフィルタ(contains・startswith・カテゴリ化)
    1. 部分一致や前方一致で抽出
    2. 複数値の集合で抽出(isin)
    3. カテゴリ型で順序や性能を改善
  5. 日時のフィルタ(範囲・月/曜日指定・文字列スライス)
    1. 範囲抽出の基本(to_datetime→昇順→範囲)
    2. 曜日・月で抽出
  6. 範囲・集合・欠損の扱い(between・isin・isna)
    1. betweenで閉区間抽出(可読性が高い)
    2. 欠損の抽出・否定(isna・notna)
  7. queryの使いどころ(SQL風に読みやすく)
    1. 日本語列名でもスッキリ書ける
  8. 条件付き代入とmask/where(抽出だけでなく「置換」も型に)
    1. whereで条件置換(Falseを値で埋める)
    2. maskで逆(Trueを値で置換)
  9. グループ・重複・トップNのフィルタ(現場で頻出の型)
    1. グループ条件でフィルタ(filter)
    2. 重複を落とす・重複の抽出(duplicated)
    3. トップN行の抽出(nlargest/nsmallest)
  10. つまずき対策の深掘り(演算子、NaN、dtype、性能)
    1. & と | と括弧を必ず使う
    2. NaNは比較で落ちる(必ずisna/notnaを使う)
    3. dtypeを先に整える(文字列数値はto_numeric)
    4. 大規模データはベクトル化を徹底
  11. 例題(現場でそのまま使えるフィルタの型)
    1. 複合条件で安全に抽出(年齢×得点)
    2. 文字列と集合の組み合わせ(店舗A/C、名前が“to”を含む)
    3. 日付で月次範囲+曜日抽出
  12. まとめ(「ブールインデックス」「&|と括弧」「型を整える」。文字列・日時・集合メソッドを使い分ける)

概要(フィルタリングは「欲しい行だけを、短く正確に抜く」ための基本)

pandasのフィルタリングは、条件式でTrue/Falseのマスクを作り、Trueの行だけを抽出するのが基本形です。重要なのは「ブールインデックス」「複数条件の結合(&と|と括弧)」「文字列・日時・範囲・集合の専用メソッド」、そして「欠損の扱い」。これらを型として覚えると、実務の抽出が一気に短く正確になります。


基本のブールインデックス(単一条件・複数条件・安全な書き方)

最小例(単一条件で行を抜く)

import pandas as pd

df = pd.DataFrame({
    "name": ["A","B","C","D"],
    "age":  [25, 30, 22, 28],
    "score":[85, 90, 78, 88]
})

adults = df[df["age"] >= 25]
print(adults)
Python

列に対する条件式(>=、==、!=、<、>)でTrue/FalseのSeriesを作り、Trueの行のみ残します。

複数条件の結合(& と | と括弧が必須)

cond = (df["age"] >= 25) & (df["score"] >= 85)
selected = df[cond]
print(selected)
Python

and/orは使えません。&(かつ)、|(または)を使い、各条件を必ず括弧で囲みます。括弧がないと演算子の優先順位で意図が崩れます。


行・列を同時に扱うloc/iloc(明確な抽出と可読性)

行は条件、列は名前で同時指定(loc)

subset = df.loc[df["age"] >= 25, ["name","score"]]
print(subset)
Python

locは「行の条件、列名の配列」を同時に指定できます。列を減らして見やすくするのが定石です。

位置ベースで抽出(iloc)

head_two = df.iloc[:2, :]     # 先頭2行
middle_col = df.iloc[:, 1]    # 2列目(0始まり)
Python

データの位置で切るならiloc。列名が未整備でも安全です。


文字列・カテゴリのフィルタ(contains・startswith・カテゴリ化)

部分一致や前方一致で抽出

s = pd.Series(["tokyo", "osaka", "kyoto", "toyama"])
has_to = s[s.str.contains("to", na=False)]
starts_t = s[s.str.startswith("to", na=False)]
Python

strアクセサは正規表現にも対応します。na=Falseで欠損時の誤爆を回避。

複数値の集合で抽出(isin)

df2 = pd.DataFrame({"store": ["A","B","C","A","B"], "sales": [100,120,90,110,130]})
picked = df2[df2["store"].isin(["A","C"])]
Python

「この集合に属するか」を一発で書けます。否定は~(ビット否定)を使います。

カテゴリ型で順序や性能を改善

cat = pd.CategoricalDtype(categories=["Low","Medium","High"], ordered=True)
df3 = pd.DataFrame({"level": ["High","Low","Medium","Low"]})
df3["level"] = df3["level"].astype(cat)
high_or_more = df3[df3["level"] >= "Medium"]
Python

順序ありカテゴリにすると、比較演算が安全・高速になります。


日時のフィルタ(範囲・月/曜日指定・文字列スライス)

範囲抽出の基本(to_datetime→昇順→範囲)

df = pd.DataFrame({
    "date": pd.to_datetime(["2025-01-01","2025-01-02","2025-01-10","2025-02-01"]),
    "sales":[100,120,80,200]
}).set_index("date").sort_index()

jan = df.loc["2025-01"]                             # 月指定(文字列スライス)
range_df = df.loc["2025-01-02":"2025-01-10"]        # 端点含む範囲
Python

DateTimeIndexなら文字列だけで自然な範囲抽出ができます。必ず日時化して並べ替えてから。

曜日・月で抽出

df = df.reset_index()
weekday = df[df["date"].dt.day_name() == "Wednesday"]
january = df[df["date"].dt.month == 1]
Python

dtアクセサで、曜日・月・時刻の属性を使った条件が書けます。


範囲・集合・欠損の扱い(between・isin・isna)

betweenで閉区間抽出(可読性が高い)

mid = df2[df2["sales"].between(100, 120, inclusive="both")]
Python

「A以上B以下」をわかりやすく書けます。

欠損の抽出・否定(isna・notna)

na_rows = df[df["score"].isna()]
valid = df[df["score"].notna()]
Python

補完の対象や除外対象を素早く切り分けます。


queryの使いどころ(SQL風に読みやすく)

日本語列名でもスッキリ書ける

df = pd.DataFrame({"年齢":[25,30,22,28], "得点":[85,90,78,88]})
out = df.query("年齢 >= 25 and 得点 >= 85")
Python

複雑な条件はqueryが読みやすいことがあります。外部変数は@varで参照できます。


条件付き代入とmask/where(抽出だけでなく「置換」も型に)

whereで条件置換(Falseを値で埋める)

df["score_clean"] = df["score"].where(df["score"] >= 80, 0)  # 80未満を0に
Python

抽出せずに“列を整形”したいときに強力です。

maskで逆(Trueを値で置換)

df["score_masked"] = df["score"].mask(df["score"] >= 90, 90)  # 90以上を90へキャップ
Python

上限・下限のキャッピングなどに使えます。


グループ・重複・トップNのフィルタ(現場で頻出の型)

グループ条件でフィルタ(filter)

g = df2.groupby("store")
# 店別で平均売上が110以上のグループだけ残す
kept = g.filter(lambda d: d["sales"].mean() >= 110)
Python

「グループ単位で条件を満たす行だけ」を残すときはfilterを使います。

重複を落とす・重複の抽出(duplicated)

unique = df.drop_duplicates(subset=["name"])
dups = df[df.duplicated(subset=["name"], keep=False)]
Python

キー重複の管理は前処理の基本です。

トップN行の抽出(nlargest/nsmallest)

top3 = df.nlargest(3, "score")
bottom2 = df.nsmallest(2, "score")
Python

ランキング系はsort_valuesより短く書けます。


つまずき対策の深掘り(演算子、NaN、dtype、性能)

& と | と括弧を必ず使う

Pythonのand/orは使えません。各条件を括弧で囲い、&(かつ)・|(または)で結合します。否定は~(ビット否定)です。

NaNは比較で落ちる(必ずisna/notnaを使う)

NaNとの比較はFalseになります。欠損を含む条件はisna/notnaで明示し、誤抽出を防ぎます。

dtypeを先に整える(文字列数値はto_numeric)

型がobjectのままだと数値比較が崩れます。to_numeric(errors=”coerce”)で数値化→NaN化→フィルタが安全です。

大規模データはベクトル化を徹底

applyやループではなく、ブールインデックス・isin・between・str.contains・dt属性・queryを使うと高速です。必要な列だけ選んでから条件を作るのも有効です。


例題(現場でそのまま使えるフィルタの型)

複合条件で安全に抽出(年齢×得点)

cond = (df["age"].between(25, 30)) & (df["score"] >= 85)
out = df.loc[cond, ["name","age","score"]]
print(out)
Python

文字列と集合の組み合わせ(店舗A/C、名前が“to”を含む)

store_pick = df2["store"].isin(["A","C"])
name_pick = s.str.contains("to", na=False)
# ブール配列は別DataFrame/Seriesでも同じ長さなら使える
Python

日付で月次範囲+曜日抽出

log = pd.DataFrame({
    "dt": pd.to_datetime(["2025-01-01","2025-01-02","2025-01-08","2025-02-01"]),
    "val":[10,20,15,30]
}).set_index("dt").sort_index()
jan_wed = log.loc["2025-01"][log.loc["2025-01"].index.day_name() == "Wednesday"]
print(jan_wed)
Python

まとめ(「ブールインデックス」「&|と括弧」「型を整える」。文字列・日時・集合メソッドを使い分ける)

フィルタリングは、ブールインデックスで行を選び、複数条件は&|で結合、各条件は括弧で安全に書くのが基本です。文字列はstr.contains/startswith、集合はisin、範囲はbetween、日時はDateTimeIndexやdt属性で自然に切る。NaNはisna/notnaで明示し、dtypeを整えてから比較する。locで列も同時に絞って可読性を上げ、必要ならquery・where・filterを併用する。この型を身につければ、初心者でも“短く、意図通り、速い”抽出が安定して書けます。

タイトルとURLをコピーしました