【Python】filter関数の使い方を徹底解説!初心者でもわかる条件絞り込みの完全ガイド
Pythonプログラミングでデータの絞り込み処理を効率的に行いたい時に活躍するのが「filter関数」です。リストや配列から条件に合う要素だけを抽出したい場面で非常に便利な機能ですが、「使い方がよくわからない」「いつ使えばいいの?」と悩む方も多いでしょう。この記事では、Pythonのfilter関数の基本から実践的な活用法まで、豊富なサンプルコードとともに徹底解説します。
filter関数とは?基本概念を理解しよう
filter関数は、指定した条件(関数)に基づいてイテラブル(リスト、タプルなど)の要素を絞り込むPythonの組み込み関数です。条件に合致する要素のみを含む新しいイテレータを返します。
filter関数の基本構文
filter(function, iterable)
- function: 条件を判定する関数(TrueまたはFalseを返す)
- iterable: 絞り込み対象のデータ(リスト、タプルなど)
最もシンプルなfilter関数の例
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 偶数のみを抽出
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # 出力: [2, 4, 6, 8, 10]
filter関数の基本的な使い方
数値の絞り込み
numbers = [1, 5, 10, 15, 20, 25, 30]
# 10より大きい数を抽出
greater_than_10 = list(filter(lambda x: x > 10, numbers))
print(greater_than_10) # 出力: [15, 20, 25, 30]
# 5の倍数を抽出
multiples_of_5 = list(filter(lambda x: x % 5 == 0, numbers))
print(multiples_of_5) # 出力: [5, 10, 15, 20, 25, 30]
文字列の絞り込み
words = ["apple", "banana", "cherry", "date", "elderberry"]
# 5文字以上の単語を抽出
long_words = list(filter(lambda word: len(word) >= 5, words))
print(long_words) # 出力: ['apple', 'banana', 'cherry', 'elderberry']
# 'a'で始まる単語を抽出
a_words = list(filter(lambda word: word.startswith('a'), words))
print(a_words) # 出力: ['apple']
通常の関数を使ったfilter関数
関数を定義してfilterに渡す
def is_positive(num):
return num > 0
def is_even(num):
return num % 2 == 0
numbers = [-3, -1, 0, 2, 4, 7, 9]
# 正の数のみ抽出
positive_nums = list(filter(is_positive, numbers))
print(positive_nums) # 出力: [2, 4, 7, 9]
# 偶数のみ抽出
even_nums = list(filter(is_even, numbers))
print(even_nums) # 出力: [-2, 0, 2, 4] # 注:-2は含まれない(元データにない)
より複雑な条件関数
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
primes = list(filter(is_prime, numbers))
print(primes) # 出力: [2, 3, 5, 7, 11]
辞書とfilter関数
辞書のリストから条件に合うものを抽出
students = [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 92},
{"name": "Charlie", "score": 78},
{"name": "Diana", "score": 95}
]
# 80点以上の学生を抽出
high_scorers = list(filter(lambda s: s["score"] >= 80, students))
print(high_scorers) # 出力: [{'name': 'Alice', 'score': 85}, ...]
# 名前が'A'で始まる学生を抽出
a_names = list(filter(lambda s: s["name"].startswith("A"), students))
print(a_names) # 出力: [{'name': 'Alice', 'score': 85}]
商品データの絞り込み
products = [
{"name": "iPhone", "price": 999, "category": "electronics"},
{"name": "Book", "price": 20, "category": "books"},
{"name": "Laptop", "price": 1200, "category": "electronics"}
]
# 1000円以下の商品を抽出
affordable = list(filter(lambda p: p["price"] <= 1000, products))
print(affordable) # 出力: [{'name': 'iPhone', ...}, {'name': 'Book', ...}]
# エレクトロニクス商品を抽出
electronics = list(filter(lambda p: p["category"] == "electronics", products))
print(electronics) # 出力: [{'name': 'iPhone', ...}, {'name': 'Laptop', ...}]
None を使ったfilter関数
Falsy値の除去
# None、空文字、0、Falseなどを除去
mixed_data = [1, 0, "hello", "", None, True, False, [], [1, 2]]
# Truthy値のみを抽出
truthy_values = list(filter(None, mixed_data))
print(truthy_values) # 出力: [1, 'hello', True, [1, 2]]
# 空でない文字列のみを抽出
strings = ["apple", "", "banana", None, "cherry", ""]
non_empty_strings = list(filter(None, strings))
print(non_empty_strings) # 出力: ['apple', 'banana', 'cherry']
bool関数との組み合わせ
data = [0, 1, 2, "", "text", [], [1], {}, {"key": "value"}]
# bool()でTruthy値を明示的に判定
truthy_data = list(filter(bool, data))
print(truthy_data) # 出力: [1, 2, 'text', [1], {'key': 'value'}]
filter関数 vs リスト内包表記
パフォーマンスと可読性の比較
numbers = list(range(1000))
# filter関数を使用
evens_filter = list(filter(lambda x: x % 2 == 0, numbers))
# リスト内包表記を使用
evens_comprehension = [x for x in numbers if x % 2 == 0]
# 結果は同じ
print(evens_filter == evens_comprehension) # 出力: True
どちらを選ぶべきか
# シンプルな条件:リスト内包表記が読みやすい
evens = [x for x in range(10) if x % 2 == 0]
# 複雑な条件:filter関数が適している
def complex_condition(x):
return x > 5 and x % 3 == 0 and str(x)[0] != '1'
filtered_numbers = list(filter(complex_condition, range(50)))
複数の条件を組み合わせた絞り込み
AND条件
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 18, 20]
# 偶数かつ10以下
even_and_small = list(filter(lambda x: x % 2 == 0 and x <= 10, numbers))
print(even_and_small) # 出力: [2, 4, 6, 8, 10]
# 3の倍数かつ5より大きい
multiple_3_and_gt5 = list(filter(lambda x: x % 3 == 0 and x > 5, numbers))
print(multiple_3_and_gt5) # 出力: [6, 9, 12, 15, 18]
OR条件
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 2の倍数または3の倍数
div_2_or_3 = list(filter(lambda x: x % 2 == 0 or x % 3 == 0, numbers))
print(div_2_or_3) # 出力: [2, 3, 4, 6, 8, 9, 10]
# 5未満または8より大きい
small_or_large = list(filter(lambda x: x < 5 or x > 8, numbers))
print(small_or_large) # 出力: [1, 2, 3, 4, 9, 10]
文字列処理でのfilter関数活用
メールアドレスの検証
emails = ["user@example.com", "invalid-email", "test@test.co", "@invalid.com"]
# 有効なメールアドレスのみ抽出
def is_valid_email(email):
return "@" in email and "." in email.split("@")[-1]
valid_emails = list(filter(is_valid_email, emails))
print(valid_emails) # 出力: ['user@example.com', 'test@test.co']
テキストデータのクリーニング
text_data = ["Hello World", "", " ", "Python", None, "Data Science", " AI "]
# 空でない文字列かつ空白のみでない文字列を抽出
clean_texts = list(filter(lambda x: x and x.strip(), text_data))
print(clean_texts) # 出力: ['Hello World', 'Python', 'Data Science', ' AI ']
# さらに前後の空白を除去
cleaned = [text.strip() for text in clean_texts]
print(cleaned) # 出力: ['Hello World', 'Python', 'Data Science', 'AI']
数値データの分析での活用
統計処理での絞り込み
import statistics
scores = [85, 92, 78, 95, 67, 88, 91, 73, 82, 96]
# 平均より高いスコアを抽出
avg_score = statistics.mean(scores)
above_average = list(filter(lambda x: x > avg_score, scores))
print(f"平均: {avg_score:.1f}") # 出力: 平均: 84.7
print(above_average) # 出力: [85, 92, 95, 88, 91, 96]
# 標準偏差の範囲内のデータを抽出
std_dev = statistics.stdev(scores)
mean = avg_score
normal_range = list(filter(lambda x: abs(x - mean) <= std_dev, scores))
print(normal_range)
外れ値の除去
data = [10, 12, 13, 11, 100, 14, 15, 12, 13, 200, 11]
# 四分位範囲を使った外れ値除去
def remove_outliers(data):
q1 = sorted(data)[len(data) // 4]
q3 = sorted(data)[3 * len(data) // 4]
iqr = q3 - q1
lower = q1 - 1.5 * iqr
upper = q3 + 1.5 * iqr
return list(filter(lambda x: lower <= x <= upper, data))
clean_data = remove_outliers(data)
print(clean_data) # 出力: [10, 12, 13, 11, 14, 15, 12, 13, 11]
filterとmapの組み合わせ
データ変換と絞り込みを同時実行
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 偶数のみを抽出して2乗
squared_evens = list(map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, numbers)))
print(squared_evens) # 出力: [4, 16, 36, 64, 100]
# 文字列の長さが4以上のものを大文字に変換
words = ["cat", "dog", "elephant", "fish", "tiger"]
long_upper = list(map(str.upper, filter(lambda w: len(w) >= 4, words)))
print(long_upper) # 出力: ['ELEPHANT', 'FISH', 'TIGER']
パイプライン処理
from functools import reduce
sales_data = [
{"product": "A", "price": 100, "quantity": 5},
{"product": "B", "price": 200, "quantity": 3},
{"product": "C", "price": 50, "quantity": 10},
{"product": "D", "price": 300, "quantity": 2}
]
# 売上高が400以上の商品の合計売上を計算
high_revenue_total = reduce(
lambda x, y: x + y,
map(lambda item: item["price"] * item["quantity"],
filter(lambda item: item["price"] * item["quantity"] >= 400, sales_data))
)
print(high_revenue_total) # 出力: 1600
実践的なfilter関数の応用例
ログファイルの解析
log_entries = [
"2024-01-01 10:00:00 INFO User login successful",
"2024-01-01 10:05:00 ERROR Database connection failed",
"2024-01-01 10:10:00 WARNING Low disk space",
"2024-01-01 10:15:00 INFO Data backup completed",
"2024-01-01 10:20:00 ERROR Authentication failed"
]
# エラーログのみを抽出
error_logs = list(filter(lambda log: "ERROR" in log, log_entries))
print(error_logs)
# 特定時間以降のログを抽出
after_10_10 = list(filter(lambda log: log.split()[1] >= "10:10:00", log_entries))
print(len(after_10_10)) # 出力: 3
ファイル処理
import os
# ファイル一覧から特定の拡張子のみを抽出
files = ["document.pdf", "image.jpg", "script.py", "data.csv", "photo.png"]
# 画像ファイルのみを抽出
image_files = list(filter(lambda f: f.endswith(('.jpg', '.png', '.gif')), files))
print(image_files) # 出力: ['image.jpg', 'photo.png']
# Pythonファイルのみを抽出
python_files = list(filter(lambda f: f.endswith('.py'), files))
print(python_files) # 出力: ['script.py']
API レスポンスの処理
# API から取得したユーザーデータ
users = [
{"id": 1, "name": "Alice", "age": 25, "active": True},
{"id": 2, "name": "Bob", "age": 17, "active": False},
{"id": 3, "name": "Charlie", "age": 30, "active": True},
{"id": 4, "name": "Diana", "age": 16, "active": True}
]
# アクティブかつ成人のユーザーを抽出
adult_active_users = list(filter(lambda u: u["active"] and u["age"] >= 18, users))
print(adult_active_users)
# 名前の長さが5文字以上のユーザーを抽出
long_name_users = list(filter(lambda u: len(u["name"]) >= 5, users))
print(long_name_users) # 出力: [{'id': 1, 'name': 'Alice', ...}, ...]
filter関数のパフォーマンス最適化
ジェネレータとしての活用
# 大量のデータを扱う場合はlistに変換せず、ジェネレータのまま使用
large_numbers = range(1000000)
# メモリ効率的な処理
even_generator = filter(lambda x: x % 2 == 0, large_numbers)
# 必要な分だけ取得
first_10_evens = []
for i, num in enumerate(even_generator):
if i >= 10:
break
first_10_evens.append(num)
print(first_10_evens) # 出力: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
早期終了の活用
def find_first_match(data, condition):
"""条件に合う最初の要素を見つけて処理を終了"""
filtered = filter(condition, data)
try:
return next(filtered)
except StopIteration:
return None
numbers = [1, 3, 5, 8, 9, 12, 15]
first_even = find_first_match(numbers, lambda x: x % 2 == 0)
print(first_even) # 出力: 8
よくある間違いとその対処法
filter結果をlistに変換し忘れ
numbers = [1, 2, 3, 4, 5]
# 間違い:filterオブジェクトそのものを出力
filtered = filter(lambda x: x % 2 == 0, numbers)
print(filtered) # 出力: <filter object at 0x...>
# 正しい:listに変換
filtered_list = list(filter(lambda x: x % 2 == 0, numbers))
print(filtered_list) # 出力: [2, 4]
複数回の反復処理
numbers = [1, 2, 3, 4, 5, 6]
evens = filter(lambda x: x % 2 == 0, numbers)
# 1回目の反復
first_iteration = list(evens)
print(first_iteration) # 出力: [2, 4, 6]
# 2回目の反復(空になる)
second_iteration = list(evens)
print(second_iteration) # 出力: []
# 解決策:必要に応じて再作成
evens = list(filter(lambda x: x % 2 == 0, numbers))
条件関数の返り値
def check_positive(x):
if x > 0:
return "positive" # 間違い:文字列は常にTruthy
return "negative"
# 期待通りに動作しない
positive_nums = list(filter(check_positive, [-1, 2, -3, 4]))
print(positive_nums) # 出力: [-1, 2, -3, 4](全て含まれる)
# 正しい実装
def check_positive_correct(x):
return x > 0 # TrueまたはFalseを返す
positive_nums = list(filter(check_positive_correct, [-1, 2, -3, 4]))
print(positive_nums) # 出力: [2, 4]
filter関数を使うべき場面・避けるべき場面
使うべき場面
関数型プログラミングスタイル
# mapやreduceと組み合わせた処理
from functools import reduce
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sum_of_squares_of_evens = reduce(
lambda x, y: x + y,
map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, numbers))
)
複雑な条件関数
def is_valid_user(user):
return (user.get("active") and
user.get("age", 0) >= 18 and
"@" in user.get("email", ""))
valid_users = list(filter(is_valid_user, users))
避けるべき場面
シンプルな条件はリスト内包表記
# filter使用
evens = list(filter(lambda x: x % 2 == 0, numbers))
# リスト内包表記(推奨)
evens = [x for x in numbers if x % 2 == 0]
条件と変換を同時に行う場合
# 非効率
positive_squares = list(map(lambda x: x ** 2, filter(lambda x: x > 0, numbers)))
# 効率的
positive_squares = [x ** 2 for x in numbers if x > 0]
まとめ
Pythonのfilter関数は、データの絞り込み処理を効率的に行うための強力なツールです。重要なポイントをまとめると:
filter関数の基本
filter(function, iterable)
の構文- 条件に合致する要素のみを抽出
- イテレータを返すため、必要に応じて
list()
で変換
効果的な使用場面
- 複雑な条件による絞り込み
- 関数型プログラミングスタイル
- map()やreduce()との組み合わせ
- 大量データの効率的な処理
実践的な活用方法
- 辞書のリストから条件に合うデータを抽出
- Noneや空文字などのFalsy値の除去
- 数値データの統計的な絞り込み
- ログファイルやAPIレスポンスの処理
ベストプラクティス
- シンプルな条件はリスト内包表記を検討
- 大量データではジェネレータとして活用
- 条件関数は必ずTrueまたはFalseを返す
- 複数回の反復が必要な場合はlistに変換
filter関数をマスターすることで、Pythonでのデータ処理がより効率的で読みやすいコードになります。実際のプロジェクトで様々なパターンを試して、適切な使い分けができるようになりましょう。
■プロンプトだけでオリジナルアプリを開発・公開してみた!!
■AI時代の第一歩!「AI駆動開発コース」はじめました!
テックジム東京本校で先行開始。
■テックジム東京本校
「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。
<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。
<月1開催>放送作家による映像ディレクター養成講座
<オンライン無料>ゼロから始めるPython爆速講座