注目キーワード
  1. Python
  2. コンペ

【完全版】pandasで複数条件を使ったデータ抽出|query・isin・AND/OR条件の使い方解説

  • 2023年8月15日
  • 2025年9月6日
  • Python
  • 15573回
  • 0件

この記事で分かること:
• pandasで複数条件を指定する基本的な方法
• AND条件・OR条件の正しい書き方
• queryメソッドとlocの使い分け
• よくあるエラーと対処法

pandasでデータ分析をしていると「複数の条件を同時に満たす行だけを抽出したい」という場面が頻繁に出てきます。この記事では、pandas初心者でも理解できるよう、具体例を交えながら複数条件でのデータ抽出方法を徹底解説します。

pandasで複数条件を使う基本(AND・OR)

pandasで複数条件を指定する際は、必ず各条件を括弧で囲むことが重要です。

基本的な書き方

AND条件(&):すべての条件を満たす行を抽出

import pandas as pd

# サンプルデータの作成
df = pd.DataFrame({
    'name': ['田中', '佐藤', '鈴木', '高橋', '伊藤'],
    'age': [25, 30, 35, 40, 28],
    'salary': [400, 500, 600, 700, 450],
    'department': ['営業', 'IT', '営業', '管理', 'IT']
})

# 年齢が30以上かつ給与が500以上の社員を抽出
result = df[(df['age'] >= 30) & (df['salary'] >= 500)]
print(result)

OR条件(|):いずれかの条件を満たす行を抽出

# 年齢が25以下または給与が600以上の社員を抽出
result = df[(df['age'] <= 25) | (df['salary'] >= 600)]
print(result)

⚠️ 重要な注意点:

  • 各条件は必ず括弧で囲む(df['age'] >= 30)
  • AND条件には&を使用(andではない)
  • OR条件には|を使用(orではない)

複数条件と括弧の優先順位

3つ以上の条件を組み合わせる場合、括弧の使い方で結果が変わります。

# 例1:(A または B) かつ C
result1 = df[((df['age'] <= 30) | (df['salary'] >= 600)) & (df['department'] == '営業')]

# 例2:A または (B かつ C)
result2 = df[(df['age'] <= 30) | ((df['salary'] >= 600) & (df['department'] == '営業'))]

💡 可読性を高めるコツ:

  • 長い条件は変数に分けて記述
  • 改行を使って見やすくする
# 可読性の高い書き方
young_condition = df['age'] <= 30
high_salary_condition = df['salary'] >= 600
sales_condition = df['department'] == '営業'

result = df[
    (young_condition | high_salary_condition) & 
    sales_condition
]

locとqueryの違い・使い分け

pandasで複数条件を指定する方法は主に2つあります:locqueryメソッドです。

比較表

項目 loc query
書き方 Python構文そのまま 文字列ベース
可読性 複雑になりがち 直感的で読みやすい
パフォーマンス 高速 やや低速(大きなデータでは差が出る)
変数利用 直接利用可能 @記号が必要

loc を使った複数条件指定

# locを使った基本的な書き方
result = df.loc[(df['age'] >= 30) & (df['salary'] >= 500)]

# 特定の列のみを抽出
result = df.loc[(df['age'] >= 30) & (df['salary'] >= 500), ['name', 'age']]

query を使った複数条件指定

# queryを使った基本的な書き方
result = df.query('age >= 30 & salary >= 500')

# より複雑な条件
result = df.query('age >= 30 & salary >= 500 & department == "営業"')

# 変数を使う場合(@記号を使用)
min_age = 30
result = df.query('age >= @min_age')

🔍 使い分けの指針:

  • query推奨:条件が複雑で可読性を重視する場合
  • loc推奨:パフォーマンスを重視する場合、変数を多用する場合

よくあるエラーと対処法

pandas初心者が複数条件で躓きがちなエラーと解決方法を解説します。

1. ValueError: The truth value of a Series is ambiguous

エラーの原因:括弧を忘れてandorを使用

# ❌ エラーが発生する書き方
# result = df[df['age'] >= 30 and df['salary'] >= 500]  # エラー!

# ✅ 正しい書き方
result = df[(df['age'] >= 30) & (df['salary'] >= 500)]

2. 括弧不足によるエラー

# ❌ 括弧が不足している
# result = df[df['age'] >= 30 & df['salary'] >= 500]  # エラー!

# ✅ 各条件を括弧で囲む
result = df[(df['age'] >= 30) & (df['salary'] >= 500)]

3. NaN値が含まれる場合の注意点

# NaN値を含むサンプルデータ
df_with_nan = df.copy()
df_with_nan.loc[0, 'age'] = None

# NaN値は条件に一致しない
result = df_with_nan[(df_with_nan['age'] >= 30) & (df_with_nan['salary'] >= 500)]

# NaN値を除外してから条件指定
result = df_with_nan.dropna().loc[(df_with_nan.dropna()['age'] >= 30) & 
                                  (df_with_nan.dropna()['salary'] >= 500)]

実用的な複数条件パターン集

実際のデータ分析でよく使われる複数条件のパターンを紹介します。

数値範囲での抽出

# 年齢が25歳以上35歳以下の社員
result = df[(df['age'] >= 25) & (df['age'] <= 35)]

# betweenメソッドを使った書き方(両端含む)
result = df[df['age'].between(25, 35)]

# betweenメソッドで片端除外
result = df[df['age'].between(25, 35, inclusive='left')]  # 25<=age<35

複数値の一致(isin)

# 特定の部署の社員を抽出
target_departments = ['営業', 'IT']
result = df[df['department'].isin(target_departments)]

# 複数条件とisinの組み合わせ
result = df[(df['age'] >= 30) & (df['department'].isin(target_departments))]

文字列条件の複数指定

# 名前に特定の文字を含む社員(サンプルデータを拡張)
df_extended = pd.DataFrame({
    'name': ['田中太郎', '佐藤花子', '鈴木一郎', '高橋美咲', '伊藤健太'],
    'age': [25, 30, 35, 40, 28],
    'email': ['tanaka@example.com', 'sato@example.com', 'suzuki@gmail.com', 
              'takahashi@example.com', 'ito@yahoo.com']
})

# 名前に「太郎」を含み、メールアドレスが「example.com」で終わる
result = df_extended[
    (df_extended['name'].str.contains('太郎')) & 
    (df_extended['email'].str.endswith('example.com'))
]

否定条件(NOT)

# チルダ(~)を使った否定条件
# 営業部でない社員
result = df[~(df['department'] == '営業')]

# 複数条件での否定
# 年齢30未満でかつ営業部でない社員
result = df[(df['age'] < 30) & ~(df['department'] == '営業')]

パフォーマンス改善のコツ

大きなデータセットで複数条件を扱う際のパフォーマンス改善方法を紹介します。

1. Boolean indexingの最適化

# 条件を変数に格納してからフィルタリング
age_condition = df['age'] >= 30
salary_condition = df['salary'] >= 500
department_condition = df['department'] == '営業'

# 一度に全条件を評価
final_condition = age_condition & salary_condition & department_condition
result = df[final_condition]

2. queryメソッドの活用

# 複雑な条件はqueryメソッドが高速な場合がある
result = df.query('age >= 30 & salary >= 500 & department == "営業"')

# 数値計算を含む条件
result = df.query('age * 1.1 > 33 & salary / age > 15')

3. データ型の最適化

# カテゴリ型に変換してメモリ使用量とパフォーマンスを改善
df['department'] = df['department'].astype('category')

# 整数型の最適化
df['age'] = df['age'].astype('int8')  # 年齢は0-255で十分

応用テクニック

複数DataFrameでの条件抽出

# 別のDataFrameの条件を参照
df_targets = pd.DataFrame({
    'department': ['営業', 'IT'],
    'min_salary': [450, 550]
})

# 部署ごとの最低給与条件を満たす社員を抽出
result_list = []
for _, row in df_targets.iterrows():
    dept_result = df[
        (df['department'] == row['department']) & 
        (df['salary'] >= row['min_salary'])
    ]
    result_list.append(dept_result)

final_result = pd.concat(result_list, ignore_index=True)

日付・時間での複数条件

# 日付データのサンプル
df_dates = pd.DataFrame({
    'name': ['田中', '佐藤', '鈴木'],
    'join_date': pd.to_datetime(['2020-01-15', '2019-06-20', '2021-03-10']),
    'salary': [400, 500, 450]
})

# 特定期間内の入社で給与条件を満たす社員
start_date = pd.to_datetime('2020-01-01')
end_date = pd.to_datetime('2021-12-31')

result = df_dates[
    (df_dates['join_date'] >= start_date) & 
    (df_dates['join_date'] <= end_date) & 
    (df_dates['salary'] >= 450)
]

実践演習:売上データ分析例

実際のビジネスシーンを想定した複数条件抽出の例を紹介します。

# 売上データのサンプル
sales_df = pd.DataFrame({
    'date': pd.date_range('2023-01-01', periods=100),
    'product': ['A', 'B', 'C'] * 33 + ['A'],
    'sales_amount': np.random.randint(100, 1000, 100),
    'region': ['東京', '大阪', '名古屋'] * 33 + ['東京'],
    'salesperson': ['田中', '佐藤', '鈴木', '高橋'] * 25
})

# 複数条件での分析例

# 1. 高売上の東京エリア商品Aの売上データ
high_sales_tokyo_a = sales_df[
    (sales_df['sales_amount'] >= 500) & 
    (sales_df['region'] == '東京') & 
    (sales_df['product'] == 'A')
]

# 2. 特定期間の特定営業担当の売上
target_period = sales_df['date'].between('2023-02-01', '2023-02-28')
target_salesperson = sales_df['salesperson'].isin(['田中', '佐藤'])

feb_sales = sales_df[target_period & target_salesperson]

# 3. queryを使った複雑な分析
top_performers = sales_df.query(
    'sales_amount >= 700 & region in ["東京", "大阪"] & product != "C"'
)

よくある質問(FAQ)

Q: 複数条件で「and」「or」を使うとエラーが出るのはなぜですか?

A: pandasではandorではなく、&|を使用する必要があります。また、各条件は必ず括弧で囲んでください。これはpandasがSeriesオブジェクトを扱うためです。

Q: 条件が多すぎて読みにくくなってしまいます。

A: 以下の方法で可読性を改善できます:

  • 条件を変数に分けて記述
  • queryメソッドを使用
  • 改行を使って見やすく整理
  • 関数化して再利用可能にする

Q: 大きなデータで複数条件の処理が遅いです。

A: パフォーマンス改善方法:

  • データ型を最適化(category型、適切な数値型)
  • 条件を変数に格納してから一度に評価
  • queryメソッドの活用
  • 不要な列を事前に削除

Q: NaN値がある列で条件抽出すると結果がおかしくなります。

A: NaN値は条件比較で常にFalseになります。事前にdropna()で除外するか、pd.isna()で明示的にNaN値の処理を指定してください。

まとめ:効率的な複数条件抽出をマスターしよう

pandasでの複数条件抽出について、基本から応用まで詳しく解説しました。

🎯 重要ポイントのまとめ:

  • 基本構文:各条件を括弧で囲み、&(AND)、|(OR)を使用
  • 方法の選択:可読性重視ならquery、パフォーマンス重視ならloc
  • エラー対策:and/orではなく&/|、括弧必須
  • パフォーマンス:データ型最適化、条件の変数化
  • 実践応用:ビジネスデータ分析での活用方法

💡 次のステップ:

  1. 基本操作の習得:この記事のコードを実際に動かしてみる
  2. 応用練習:自分のデータで複数条件抽出を試す
  3. パフォーマンス最適化:大きなデータセットでの最適化に挑戦
  4. 関連技術の学習:groupbyやmergeと組み合わせた高度な分析

複数条件抽出は pandas の基本中の基本です。この記事の内容をマスターすれば、データ分析の効率が大幅に向上するはずです。ぜひ実際のプロジェクトで活用してみてください。

【関連記事】

Pandasのaggによる集計テクニック: 基本的な使い方、applyとの違い、条件付きカウント (count ifのような使い方)、最初の値の取得 (first value)など

Pandasでのマルチインデックスの活用:列名の変更、データの取得、そして削除の方法

Pandasにおけるmapとapplyの違いと使い分け

最新情報をチェックしよう!