論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
フィルタリング処理
Filtering
データ前処理

🔖 キーワード索引

条件抽出boolean indexingquerywhereisin正規表現範囲指定複数条件AND/ORNULL処理

別名・略称:(なし)

💡 30秒で分かる結論

フィルタリング処理(Filtering):条件に合うデータを抽出する処理

📍 あなたが今見ているもの

「47都道府県の中から東京・大阪・神奈川だけ抜き出したい」「2020年以降のデータに絞りたい」 といった操作はデータ分析で毎日のように行います。 これがフィルタリング。 SQL なら WHERE 句、 pandas なら boolean indexing、 Excel ならオートフィルタ。 道具は違っても考え方は共通です。

🎨 直感で掴む

条件の組み立て方

目的pandas 例
単一条件df[df['消費支出'] > 300]
ANDdf[(df['年'] >= 2020) & (df['都道府県'] == '東京')]
ORdf[df['都道府県'].isin(['東京', '大阪', '愛知'])]
範囲df[df['年'].between(2020, 2023)]
部分一致df[df['品目'].str.contains('食料')]
欠損ありdf[df['col'].notna()]

📐 定義 / 数式

【フィルタリングの集合論的定義】
$$\mathcal{D}_{\text{filtered}} = \{ x \in \mathcal{D} \mid \phi(x) = \text{True} \}$$
条件述語 $\phi$ を満たす要素だけからなる部分集合

🔬 記号・式を言葉で読み解く

boolean mask
True/False の Series。 これで行を絞り込む。
&, |, ~
AND, OR, NOT。 各条件を括弧で囲む こと(演算子優先順位対策)。
query()
文字列で条件を書く。 SQL ライクに読みやすい。
isin()
リスト内のいずれかと一致するか。
欠損
NaN との比較は常に False。 必ず isna() / notna() で扱う。

🧮 実データで計算してみる

SSDSE-B-2026 から「2023 年の関東地方の県だけ抽出」する例:

手順条件
1. 年で絞るdf['年'] == 2023
2. 関東の県だけdf['都道府県'].isin(['東京', '神奈川', '埼玉', '千葉', '茨城', '栃木', '群馬'])
3. AND で結合条件 1 & 条件 2

🐍 Python 実装

SSDSE-B-2026(47 都道府県・2023 年データ)を題材にした最小コード:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)

# 単一条件: 消費支出 30 万円以上
high = df[df['消費支出'] >= 300000]

# 複数条件: 関東 7 都県のみ
kanto = ['東京', '神奈川', '埼玉', '千葉', '茨城', '栃木', '群馬']
df_kanto = df[df['都道府県'].isin(kanto)]

# query メソッドで可読性アップ
df_q = df.query('消費支出 >= 300000 and 都道府県 == "東京"')

⚠️ よくある落とし穴

⚠️ 演算子の優先順位
df['a'] > 0 & df['b'] > 0 はエラー。 → 各条件を括弧で。
⚠️ NaN との比較
df['col'] != NaN は機能しない。 → notna() を使う。
⚠️ 文字列の完全一致 vs 部分一致
== は完全一致のみ。 部分一致は str.contains
⚠️ チェイン代入の警告
df[df['a']>0]['b'] = 1 は SettingWithCopyWarning。 → df.loc[df['a']>0, 'b'] = 1
⚠️ 巨大データでのループ
for ループで 1 行ずつフィルタは遅い。 → ベクトル化操作で一気に。

🌐 関連手法・この用語を使う論文

📄 前処理を含む論文
条件抽出は分析の前処理として全論文で使われています。

🐍 Python 実装 — 完全ガイド

フィルタリングは pandas の中核操作です。 5 つの代表的なパターンを SSDSE-B-2026(都道府県別経済データ)で示します。

パターン 1: 単純な不等号

🎯 目的:SSDSE-B-2026 から「消費支出 ≥ 30 万円の都道府県」を抽出し、 高消費水準の県が全 47 都道府県のうち何件・どの県かを把握する。 ブールマスクの最基本パターン。
📥 入力data/raw/SSDSE-B-2026.csv (UTF-8、 2 行ヘッダ、 列:年・都道府県コード・都道府県・総人口・消費支出・可処分所得)。 閾値 300,000 円。
1
2
3
4
5
6
7
8
9
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
df.columns = ['年', '都道府県コード', '都道府県', '総人口', '消費支出', '可処分所得']  # 簡略化

# 消費支出が 30 万円以上の県
high = df[df['消費支出'] >= 300000]
print(f'対象県数: {len(high)} / {len(df)}')
print(high[['都道府県', '消費支出']].head())
📤 出力 対象県数: 18 / 47 都道府県 消費支出 0 東京都 340000 1 神奈川県 325000 2 埼玉県 310000 3 千葉県 305000 4 愛知県 315000
💬 解釈:18 / 47 ≒ 38 % の県が高消費水準。 ブール Series df['消費支出'] >= 300000 は要素ごと True/False の 47 個の系列で、 df[ ... ][] 内に渡すと True の行だけが取り出される。 pandas の最重要イディオム。

パターン 2: 複数条件(AND / OR / NOT)

🎯 目的:SSDSE-B-2026 で「関東 7 都県 かつ 2023 年」(AND)、 「消費 30 万 or 所得 50 万以上」(OR)、 「関東以外」(NOT)を組み合わせて、 ビット演算子 & | ~ の使い分けを理解する。
📥 入力:関東 7 都県リスト、 年=2023、 消費 30 万円・所得 50 万円の閾値。 各条件は別々のブールマスクとして組み立てる。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# AND: 関東 7 都県 かつ 2023 年
kanto = ['東京都', '神奈川県', '埼玉県', '千葉県', '茨城県', '栃木県', '群馬県']
mask_a = df['都道府県'].isin(kanto)
mask_b = df['年'] == 2023
df_subset = df[mask_a & mask_b]

# OR: 消費支出 30 万円以上 または 可処分所得 50 万円以上
df_or = df[(df['消費支出'] >= 300000) | (df['可処分所得'] >= 500000)]

# NOT: 関東以外
df_not = df[~df['都道府県'].isin(kanto)]
📤 出力 df_subset (AND): 7 行 × 6 列 # 関東 7 都県 × 2023 年 df_or (OR): 27 行 × 6 列 # 消費 OR 所得の閾値超え df_not (NOT): 40 行 × 6 列 # 47 - 7 = 40 県
💬 解釈:Python の and / or / not はスカラ用で Series には使えないのが落とし穴。 pandas では必ず & / | / ~ を使い、 演算子優先順位の関係で各条件を () で囲むのが鉄則。 .isin() はリスト判定の最短記法。

パターン 3: query() で SQL ライク

1
2
3
4
5
6
7
8
9
# query は文字列で条件を書けるので、 列名が多いときに可読性が高い
df_q = df.query('消費支出 >= 300000 and 都道府県 == "東京都"')

# 変数参照は @ プレフィックス
threshold = 350000
df_q2 = df.query('消費支出 >= @threshold')

# 範囲指定
df_q3 = df.query('300000 <= 消費支出 <= 500000')

パターン 4: 文字列フィルタと正規表現

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 部分一致 ("県" を含む)
df_str = df[df['都道府県'].str.contains('県', na=False)]

# 始まり ("北" で始まる)
df_start = df[df['都道府県'].str.startswith(('北', '東'))]

# 正規表現
df_re = df[df['都道府県'].str.match(r'^(東|大|京).*[都府]$')]

# 大文字小文字を無視
df_ci = df[df['都道府県'].str.contains('TOKYO', case=False, na=False)]

パターン 5: 欠損を扱う安全フィルタ

1
2
3
4
5
6
7
8
9
# NaN との比較は常に False になる罠を回避
df_safe = df[df['消費支出'].notna() & (df['消費支出'] >= 300000)]

# 行に欠損があれば除外
df_complete = df.dropna(subset=['消費支出', '可処分所得'])

# fillna() で代入してからフィルタ
df_fill = df.fillna({'消費支出': 0})
df_fill_ok = df_fill[df_fill['消費支出'] >= 300000]

🔬 性能比較 — どの書き方が速いか

書き方可読性速度推奨度
df[df['x']>0]速い◎ 標準
df.query('x > 0')○ 列数多時
df.loc[df['x']>0]速い◎ 列も指定可
for ループ遅い× 避ける
df.apply(lambda r: ...)遅い△ 複雑な条件のみ

🔑 鉄則: ベクトル化(&, |, .isin, .str.contains)を最優先。 100 万行のデータでも 1 秒未満。

⚠️ よくある落とし穴 — 追加 5 つ

⚠️ in 演算子 vs isin()
df['都道府県'] in ['東京','大阪']列全体が in として評価され予期せぬ動作。 必ず .isin([...]) を使う。
⚠️ str アクセサと NaN
df['col'].str.contains('A') は NaN 行で NaN を返し、 boolean indexing でエラー。 na=False を付ける。
⚠️ コピー vs ビュー
フィルタ結果はビューになり得る。 後で書き換えるなら .copy() を明示。
⚠️ index の混乱
フィルタ後は元の index が残り、 連番ではなくなる。 .reset_index(drop=True) で振り直し。
⚠️ 浮動小数の == 比較
df['x'] == 0.1 は誤判定の温床。 np.isclose や範囲指定を使う。

🔎 深掘り解説 — なぜ「ベクトル化」が速いのか

pandas のフィルタが for ループより 100 倍以上速い理由は、 内部で NumPy の C 実装を呼び出しているから。 Python レベルでは for ループ 1 回ごとにオブジェクト生成・型チェックが走るが、 NumPy は連続メモリ上の値を直接 C 関数で処理する。 これは「ベクトル化(vectorization)」と呼ばれ、 データサイエンスの基本原則の 1 つ。

行数for ループboolean mask速度比
10,000~100 ms~1 ms100×
100,000~1 s~5 ms200×
1,000,000~10 s~50 ms200×

📊 さらに polarsDuckDB を使えば、 数千万行レベルでも 1 秒未満で完了する世界が広がる。

🎯 ツール別フィルタ早見表 — Excel / SQL / pandas / R / Power Query

操作ExcelSQLpandasR (dplyr)Power Query
不等号オートフィルタWHERE x > 0df[df.x>0]filter(x>0)Table.SelectRows
複数条件 AND複数オートフィルタWHERE A AND B(A) & (B)filter(A, B)複数 SelectRows
in リストテキストフィルタ「複数選択」WHERE x IN (...)df.x.isin([...])x %in% c(...)List.Contains
範囲 between「指定の範囲内」x BETWEEN a AND bdf.x.between(a,b)between(x, a, b)範囲指定
部分一致「を含む」LIKE '%X%'str.contains('X')str_detectText.Contains
欠損除外「空白セル」を非表示IS NOT NULLnotna()!is.na(x)null を除去

💡 道具は違っても考え方は同じ:「条件を boolean に変換し、 True の行だけ残す」。

🧪 練習問題(SSDSE-B-2026 で手を動かす)

  1. Q1. 「総人口 100 万人以上 かつ 高齢化率 30%未満」の都道府県を抽出してください。
  2. Q2. 「東日本(北海道〜中部)」と「西日本(近畿〜九州)」の 2 グループに分け、 それぞれの可処分所得平均を比較してください。 ヒント: .isin().groupby()
  3. Q3. 都道府県名に「県」が含まれない自治体(東京都・大阪府・京都府・北海道)だけ抽出する正規表現を書いてください。 ヒント: str.contains(r'(都|府|道)$')
  4. Q4. 消費支出が欠損していない行に限定し、 消費支出が中央値以上の県を抽出してください。
  5. Q5. query() を使い、 消費支出 / 可処分所得 >= 0.8 となる「貯蓄余力の小さい県」を抽出してください。
解答例(クリックで展開)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# Q1
df_q1 = df[(df['総人口'] >= 1_000_000) & (df['高齢化率'] < 30)]

# Q2
east = ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県',
        '茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県',
        '新潟県','富山県','石川県','福井県','山梨県','長野県','岐阜県','静岡県','愛知県']
df['地方'] = df['都道府県'].apply(lambda x: '東日本' if x in east else '西日本')
print(df.groupby('地方')['可処分所得'].mean())

# Q3
df_q3 = df[df['都道府県'].str.contains(r'(都|府|道)$', regex=True)]

# Q4
med = df['消費支出'].median()
df_q4 = df[df['消費支出'].notna() & (df['消費支出'] >= med)]

# Q5
df_q5 = df.query('消費支出 / 可処分所得 >= 0.8')

🔬 高度なテクニック — 3 つの実践パターン

① 動的なフィルタ(条件をリストで管理)

1
2
3
4
5
6
7
8
conditions = {
    '消費支出 >= 300000': df['消費支出'] >= 300000,
    '高齢化率 < 30': df['高齢化率'] < 30,
    '関東': df['都道府県'].isin(['東京都', '神奈川県', '埼玉県', '千葉県'])
}
mask = pd.concat(conditions.values(), axis=1).all(axis=1)
df_subset = df[mask]
print(f'条件を満たす県: {len(df_subset)}')

② グループ内フィルタ(groupby + filter)

1
2
3
# 地方ごとに、 平均消費支出が 30 万円以上の地方だけ残す
df['地方'] = df['都道府県'].map(prefecture_to_region)
df_filtered = df.groupby('地方').filter(lambda g: g['消費支出'].mean() >= 300000)

③ 上位 N 件抽出(nlargest / nsmallest)

1
2
3
4
5
6
7
8
# 高齢化率トップ 5
top5 = df.nlargest(5, '高齢化率')[['都道府県', '高齢化率']]

# 消費支出ボトム 3
bot3 = df.nsmallest(3, '消費支出')[['都道府県', '消費支出']]

# ソートしてから head() でも同じ結果
top5_alt = df.sort_values('高齢化率', ascending=False).head(5)

📊 公的データでの応用例 — 3 つのケース

課題データフィルタ条件
過疎地域の経済分析SSDSE-B-2026総人口 < 100 万 & 高齢化率 > 30
大都市圏の比較SSDSE-B-2026都道府県.isin(['東京都','大阪府','愛知県'])
基準年比較e-Stat 時系列年.isin([2010, 2015, 2020])

フィルタリングは EDA の最初の一歩。 「適切に絞り込めるか」が分析の質を決めます。

✅ フィルタリングを書く前のチェックリスト

  1. 条件はベクトル化できているか(for ループになっていないか)
  2. 複数条件は各々を括弧で囲み& / | で結合したか
  3. 欠損値notna() / na=False で安全に除外したか
  4. 結果がコピービューか意識しているか(書き換えるなら .copy())
  5. 必要なら .reset_index(drop=True)index を振り直したか
  6. 条件式が正しいか、 必ず件数(len)と head() で確認したか
  7. 条件のロジック(AND / OR)が要求通りか、 ベン図でイメージできるか
  8. 除外ではなく抽出のロジックになっているか確認したか

📐 集合論で見るフィルタリング — AND/OR の正体

フィルタリングは集合演算そのもの。 2 条件 $A, B$ について:

$$A \cap B = \{x : \phi_A(x) \land \phi_B(x)\} \quad \text{(AND)}$$ $$A \cup B = \{x : \phi_A(x) \lor \phi_B(x)\} \quad \text{(OR)}$$ $$A^c = \{x : \neg \phi_A(x)\} \quad \text{(NOT)}$$
集合演算数式pandasSQL
積集合$A \cap B$(A) & (B)A AND B
和集合$A \cup B$(A) | (B)A OR B
差集合$A \setminus B$(A) & ~(B)A AND NOT B
補集合$A^c$~(A)NOT A

⚖️ ド・モルガンの法則:$\neg(A \land B) = \neg A \lor \neg B$ → pandas でも ~((A) & (B))(~A) | (~B)

🧩 フィルタの設計パターン — 再利用しやすい書き方

パターン A: 関数化(複数箇所で使う条件)

1
2
3
4
5
6
7
8
9
def is_kanto(df):
    kanto = ['東京都', '神奈川県', '埼玉県', '千葉県', '茨城県', '栃木県', '群馬県']
    return df['都道府県'].isin(kanto)

def is_high_income(df, threshold=500000):
    return df['可処分所得'] >= threshold

# 再利用可能なフィルタ
df_target = df[is_kanto(df) & is_high_income(df, 450000)]

パターン B: パイプライン(メソッドチェーン)

1
2
3
4
5
6
result = (df
    .query('年 == 2023')
    .loc[lambda d: d['消費支出'] >= 300000]
    .loc[lambda d: d['都道府県'].str.endswith('都')]
    .reset_index(drop=True)
)

パターン C: 設定駆動型(YAML/JSON で条件管理)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
filter_config = {
    'min_population': 500_000,
    'max_aging_rate': 35.0,
    'target_regions': ['関東', '近畿']
}
mask = (
    (df['総人口'] >= filter_config['min_population']) &
    (df['高齢化率'] < filter_config['max_aging_rate']) &
    (df['地方'].isin(filter_config['target_regions']))
)
df_subset = df[mask]

💡 業務分析では「条件が頻繁に変わる」ことが多いため、 設定駆動型が保守性◎。

📖 さらに学ぶには

本サイト内

外部リソース

困ったとき / トラブルシューティング

症状原因対処
「The truth value of an array is ambiguous」エラー&/| を使うべき所で and/or を使ったand→&, or→| に置換、 各条件を ( ) で囲む
結果が空条件が矛盾、 列名タイポ、 NaN 比較条件を 1 つずつ .sum() で件数確認
SettingWithCopyWarningフィルタ結果に代入.copy().loc[] で代入
KeyError列名が違う、 全角/半角df.columns で確認
query で日本語列名エラー変数名として解釈不能バッククォートで囲む `消費支出`

🧮 もう一段深く — フィルタが返す件数を予測する

分析前に、 フィルタが返す件数を概算できると効率的。 47 都道府県データを例に。

条件期待件数論拠
関東 7 都県7固定値(地理)
高齢化率 30% 以上約 352023 年は多数の県で達成
高齢化率 25% 未満約 3沖縄・東京・神奈川 等
関東 AND 高齢化率 30% 以上3〜5茨城・栃木・群馬
関東 OR 高齢化率 30% 以上約 37包含関係(AND/OR 補完)

💡 期待件数を立てておくと、 結果が大きく違ったときに「条件式のバグ」に気付きやすい。

🎓 教育的視点 — なぜ「フィルタリング」が最初に学ぶべき操作なのか

データサイエンス教育で最初に学ぶ pandas 操作は read_csv → フィルタリング → 集計 の流れ。 これは「分析対象を絞り込む」という思考が、 探索的データ分析(EDA)の基本だから。 大量データのまま考えるのは人間の脳には無理で、 まず関心のある部分集合に絞るのが鉄則。

  1. 第 1 段階: 単一条件で絞る(df[df['x'] > 0])
  2. 第 2 段階: AND/OR を組み合わせる(多次元条件)
  3. 第 3 段階: query() / loc[] でメソッドチェーン化
  4. 第 4 段階: groupby + filter で「グループ単位の絞り込み」
  5. 第 5 段階: 関数化 → パイプライン化 → 設定駆動化

この階段を踏むことで、 「条件を1つ書く」から「分析パイプライン全体を設計する」へとレベルが上がります。 重要なのは、 各段階で同じ思考(boolean マスクの組み合わせ)を使い続けていること。 道具が変わっても本質は変わりません。

フィルタリングは、 SQL、 Excel、 BI ツール、 機械学習の前処理など、 あらゆる場面で出てくる普遍的操作。 ここを丁寧に学ぶと、 後段の学習が格段に楽になります。