この記事で分かること:
• 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つあります:locとqueryメソッドです。
比較表
| 項目 | 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
エラーの原因:括弧を忘れてandやorを使用
# ❌ エラーが発生する書き方 # 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ではandやorではなく、&や|を使用する必要があります。また、各条件は必ず括弧で囲んでください。これは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ではなく&/|、括弧必須 - パフォーマンス:データ型最適化、条件の変数化
- 実践応用:ビジネスデータ分析での活用方法
💡 次のステップ:
- 基本操作の習得:この記事のコードを実際に動かしてみる
- 応用練習:自分のデータで複数条件抽出を試す
- パフォーマンス最適化:大きなデータセットでの最適化に挑戦
- 関連技術の学習:groupbyやmergeと組み合わせた高度な分析
複数条件抽出は pandas の基本中の基本です。この記事の内容をマスターすれば、データ分析の効率が大幅に向上するはずです。ぜひ実際のプロジェクトで活用してみてください。
【関連記事】
Pandasのaggによる集計テクニック: 基本的な使い方、applyとの違い、条件付きカウント (count ifのような使い方)、最初の値の取得 (first value)など