Pandas フィルタリングと条件検索
データフィルタリングはデータ分析で最もよく使われる操作の一つです。Pandas は豊富な条件検索機能を提供しており、さまざまな条件に基づいてデータを抽出できます。この節では、さまざまなデータフィルタリング方法を詳しく説明します。
基本条件フィルタリング
単一条件フィルタリング
例
import pandas as pd
# サンプルデータを作成
df = pd.DataFrame({
"氏名": ["佐藤", "鈴木", "高橋", "田中", "伊藤"],
"年齢": [25, 30, 28, 35, 22],
"都市": ["北京", "上海", "広州", "北京", "深セン"],
"給与": [12000, 15000, 11000, 18000, 9000],
"部門": ["技術", "営業", "技術", "運営", "技術"]
})
print("元のデータ:")
print(df)
print()
# 等しい条件でフィルタリング
print("都市が北京と等しい:")
print(df[df["都市"] == "北京"])
print()
# 等しくない条件でフィルタリング
print("都市が北京と等しくない:")
print(df[df["都市"] != "北京"])
print()
# 大なり小なり
print("給与が12000より大きい:")
print(df[df["給与"] > 12000])
print()
# 文字列条件
print("氏名が「藤」を含む:")
print(df[df["氏名"].str.contains("藤")])
# サンプルデータを作成
df = pd.DataFrame({
"氏名": ["佐藤", "鈴木", "高橋", "田中", "伊藤"],
"年齢": [25, 30, 28, 35, 22],
"都市": ["北京", "上海", "広州", "北京", "深セン"],
"給与": [12000, 15000, 11000, 18000, 9000],
"部門": ["技術", "営業", "技術", "運営", "技術"]
})
print("元のデータ:")
print(df)
print()
# 等しい条件でフィルタリング
print("都市が北京と等しい:")
print(df[df["都市"] == "北京"])
print()
# 等しくない条件でフィルタリング
print("都市が北京と等しくない:")
print(df[df["都市"] != "北京"])
print()
# 大なり小なり
print("給与が12000より大きい:")
print(df[df["給与"] > 12000])
print()
# 文字列条件
print("氏名が「藤」を含む:")
print(df[df["氏名"].str.contains("藤")])
複数条件の組み合わせ
例
import pandas as pd
df = pd.DataFrame({
"氏名": ["佐藤", "鈴木", "高橋", "田中", "伊藤"],
"年齢": [25, 30, 28, 35, 22],
"都市": ["北京", "上海", "広州", "北京", "深セン"],
"給与": [12000, 15000, 11000, 18000, 9000],
"部門": ["技術", "営業", "技術", "運営", "技術"]
})
# AND 条件:& 記号を使用
print(北京 かつ 給与>10000:)
print(df[(df["都市"] == "北京") & (df["給与"] > 10000)])
print()
# OR 条件:| 記号を使用
print("技術部門 または 給与>15000:")
print(df[(df["部門"] == "技術") | (df["給与"] > 15000)])
print()
# NOT 条件:~ 記号を使用
print("技術部門ではない:")
print(df[~(df["部門"] == "技術")])
print()
# 複雑な組み合わせ
print("(北京 かつ 年齢>25)または(上海):")
print(df[((df["都市"] == "北京") & (df["年齢"] > 25)) | (df["都市"] == "上海")])
df = pd.DataFrame({
"氏名": ["佐藤", "鈴木", "高橋", "田中", "伊藤"],
"年齢": [25, 30, 28, 35, 22],
"都市": ["北京", "上海", "広州", "北京", "深セン"],
"給与": [12000, 15000, 11000, 18000, 9000],
"部門": ["技術", "営業", "技術", "運営", "技術"]
})
# AND 条件:& 記号を使用
print(北京 かつ 給与>10000:)
print(df[(df["都市"] == "北京") & (df["給与"] > 10000)])
print()
# OR 条件:| 記号を使用
print("技術部門 または 給与>15000:")
print(df[(df["部門"] == "技術") | (df["給与"] > 15000)])
print()
# NOT 条件:~ 記号を使用
print("技術部門ではない:")
print(df[~(df["部門"] == "技術")])
print()
# 複雑な組み合わせ
print("(北京 かつ 年齢>25)または(上海):")
print(df[((df["都市"] == "北京") & (df["年齢"] > 25)) | (df["都市"] == "上海")])
複数条件を組み合わせる場合、各条件を括弧で囲み、条件間は
&(かつ)、|(または)で接続し、Python のand、orキーワードは使用できません。
isin と where
isin によるフィルタリング
例
import pandas as pd
df = pd.DataFrame({
"氏名": ["佐藤", "鈴木", "高橋", "田中", "伊藤"],
"都市": ["北京", "上海", "広州", "北京", "深セン"],
"部門": ["技術", "営業", "技術", "運営", "技術"]
})
# リスト内でフィルタリング
print("都市が北京または上海:")
print(df[df["都市"].isin(["北京", "上海"])])
print()
# リストに含まれない
print("都市が北京でも上海でもない:")
print(df[~df["都市"].isin(["北京", "上海"])])
print()
# 複数列の isin
df2 = pd.DataFrame({
"都市": ["北京", "上海"],
"部門": ["技術", "営業"]
})
print("都市と部門を同時に満たす:")
print(df[df[["都市", "部門"]].isin(df2).all(axis=1)])
df = pd.DataFrame({
"氏名": ["佐藤", "鈴木", "高橋", "田中", "伊藤"],
"都市": ["北京", "上海", "広州", "北京", "深セン"],
"部門": ["技術", "営業", "技術", "運営", "技術"]
})
# リスト内でフィルタリング
print("都市が北京または上海:")
print(df[df["都市"].isin(["北京", "上海"])])
print()
# リストに含まれない
print("都市が北京でも上海でもない:")
print(df[~df["都市"].isin(["北京", "上海"])])
print()
# 複数列の isin
df2 = pd.DataFrame({
"都市": ["北京", "上海"],
"部門": ["技術", "営業"]
})
print("都市と部門を同時に満たす:")
print(df[df[["都市", "部門"]].isin(df2).all(axis=1)])
where 条件
例
import pandas as pd
import numpy as np
df = pd.DataFrame({
"A": [1, 5, 3, 7],
"B": [4, 2, 8, 3]
})
# where: 条件を満たす値は保持し、満たさない値は NaN または指定値に設定
print("値が3より大きいものは保持し、他は0に設定:")
result = df.where(df > 3, 0)
print(result)
print()
# 別の DataFrame を条件として使用
other = pd.DataFrame({
"A": [True, False, True, False],
"B": [False, True, False, True]
})
print("条件 DataFrame に基づいてフィルタリング:")
print(df.where(other, -1))
import numpy as np
df = pd.DataFrame({
"A": [1, 5, 3, 7],
"B": [4, 2, 8, 3]
})
# where: 条件を満たす値は保持し、満たさない値は NaN または指定値に設定
print("値が3より大きいものは保持し、他は0に設定:")
result = df.where(df > 3, 0)
print(result)
print()
# 別の DataFrame を条件として使用
other = pd.DataFrame({
"A": [True, False, True, False],
"B": [False, True, False, True]
})
print("条件 DataFrame に基づいてフィルタリング:")
print(df.where(other, -1))
文字列フィルタリング
例
import pandas as pd
df = pd.DataFrame({
"氏名": ["佐藤", "鈴木", "高橋", "田中", "山本"],
"都市": ["北京市", "上海市", "広州市", "深セン市", "杭州市"],
"メール": ["[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]"]
})
# 含む
print("都市が「北京」を含む:")
print(df[df["都市"].str.contains("北京")])
print()
# 先頭/末尾
print("メールが sato で始まる:")
print(df[df["メール"].str.startswith("zhang")])
print()
# 正規表現マッチング
print("メールのユーザー名の長さが4より大きい:")
print(df[df["メール"].str.extract(r"(\w+)@")[0].str.len() > 4])
print()
# 複数パターンのマッチング
print("都市が 北、上、広、深 で始まる:")
print(df[df["都市"].str.contains("^北|^上|^広|^深")])
df = pd.DataFrame({
"氏名": ["佐藤", "鈴木", "高橋", "田中", "山本"],
"都市": ["北京市", "上海市", "広州市", "深セン市", "杭州市"],
"メール": ["[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]"]
})
# 含む
print("都市が「北京」を含む:")
print(df[df["都市"].str.contains("北京")])
print()
# 先頭/末尾
print("メールが sato で始まる:")
print(df[df["メール"].str.startswith("zhang")])
print()
# 正規表現マッチング
print("メールのユーザー名の長さが4より大きい:")
print(df[df["メール"].str.extract(r"(\w+)@")[0].str.len() > 4])
print()
# 複数パターンのマッチング
print("都市が 北、上、広、深 で始まる:")
print(df[df["都市"].str.contains("^北|^上|^広|^深")])
数値範囲フィルタリング
例
import pandas as pd
df = pd.DataFrame({
"氏名": ["佐藤", "鈴木", "高橋", "田中", "伊藤"],
"年齢": [25, 30, 28, 35, 22],
"給与": [12000, 15000, 11000, 18000, 9000]
})
# 範囲フィルタリング
print("年齢が25-30の間(含む):")
print(df[df["年齢"].between(25, 30)])
print()
# 分位数フィルタリング
q1 = df["給与"].quantile(0.25)
q3 = df["給与"].quantile(0.75)
print(f"給与が25%-75%の間({q1}-{q3}):")
print(df[df["給与"].between(q1, q3)])
print()
# 最小/最大N件
print("給与が最も高い3件:")
print(df.nlargest(3, "給与"))
print()
print("給与が最も低い2件:")
print(df.nsmallest(2, "給与"))
df = pd.DataFrame({
"氏名": ["佐藤", "鈴木", "高橋", "田中", "伊藤"],
"年齢": [25, 30, 28, 35, 22],
"給与": [12000, 15000, 11000, 18000, 9000]
})
# 範囲フィルタリング
print("年齢が25-30の間(含む):")
print(df[df["年齢"].between(25, 30)])
print()
# 分位数フィルタリング
q1 = df["給与"].quantile(0.25)
q3 = df["給与"].quantile(0.75)
print(f"給与が25%-75%の間({q1}-{q3}):")
print(df[df["給与"].between(q1, q3)])
print()
# 最小/最大N件
print("給与が最も高い3件:")
print(df.nlargest(3, "給与"))
print()
print("給与が最も低い2件:")
print(df.nsmallest(2, "給与"))
時系列データのフィルタリング
例
import pandas as pd
# 時系列データを作成
df = pd.DataFrame({
"日付": pd.date_range("2024-01-01", periods=10, freq="D"),
"売上": [100, 120, 90, 150, 200, 180, 110, 130, 170, 190]
})
df = df.set_index("日付")
print("時系列データ:")
print(df)
print()
# 日付でフィルタリング
print("2024-01-05 のデータ:")
print(df.loc["2024-01-05"])
print()
# 日付範囲フィルタリング
print("2024-01-03 から 2024-01-07:")
print(df.loc["2024-01-03":"2024-01-07"])
print()
# truncate を使用(より効率的なスライス)
print("truncate によるフィルタリング:")
print(df.truncate(before="2024-01-03", after="2024-01-07"))
# 時系列データを作成
df = pd.DataFrame({
"日付": pd.date_range("2024-01-01", periods=10, freq="D"),
"売上": [100, 120, 90, 150, 200, 180, 110, 130, 170, 190]
})
df = df.set_index("日付")
print("時系列データ:")
print(df)
print()
# 日付でフィルタリング
print("2024-01-05 のデータ:")
print(df.loc["2024-01-05"])
print()
# 日付範囲フィルタリング
print("2024-01-03 から 2024-01-07:")
print(df.loc["2024-01-03":"2024-01-07"])
print()
# truncate を使用(より効率的なスライス)
print("truncate によるフィルタリング:")
print(df.truncate(before="2024-01-03", after="2024-01-07"))
query メソッド
queryこのメソッドは、より簡潔なSQLスタイルのフィルタリング方法を提供します。
例
import pandas as pd
df = pd.DataFrame({
"氏名": ["張三", "李四", "王五", "趙六"],
"年齢": [25, 30, 28, 35],
"都市": ["北京", "上海", "広州", "北京"],
"給与": [12000, 15000, 11000, 18000]
})
# query メソッドを使用
print(年齢>26 かつ 都市='北京':)
print(df.query(年齢 > 26 and 都市 == '北京'))
print()
# 変数を使用
min_age = 26
city = "北京"
print(f年齢>{min_age} かつ 都市={city}:)
print(df.query(年齢 > @min_age and 都市 == @city))
print()
# 列名にスペースがある場合はバッククォートが必要
df2 = df.rename(columns={"氏名": "氏 名"})
print(列名にスペースがある場合:)
print(df2.query(`氏 名` == '張三'))
df = pd.DataFrame({
"氏名": ["張三", "李四", "王五", "趙六"],
"年齢": [25, 30, 28, 35],
"都市": ["北京", "上海", "広州", "北京"],
"給与": [12000, 15000, 11000, 18000]
})
# query メソッドを使用
print(年齢>26 かつ 都市='北京':)
print(df.query(年齢 > 26 and 都市 == '北京'))
print()
# 変数を使用
min_age = 26
city = "北京"
print(f年齢>{min_age} かつ 都市={city}:)
print(df.query(年齢 > @min_age and 都市 == @city))
print()
# 列名にスペースがある場合はバッククォートが必要
df2 = df.rename(columns={"氏名": "氏 名"})
print(列名にスペースがある場合:)
print(df2.query(`氏 名` == '張三'))
よくある質問
1、条件の組み合わせでエラーが発生する
複数条件のフィルタリングでは、括弧を使用して優先順位を明確にし、次を使用してください&、|ではなくand、or。
2、文字列に空値が含まれる
使用str.contains前には空値を処理する必要があります:df[df["列"].str.contains("x", na=False)]
3、インデックスのフィルタリング
DataFrame にカスタムインデックスがある場合は、注意が必要ですlocとilocの違い。
その他の拡張複雑な複数条件のクエリについては、
queryメソッドの構文は自然言語に近く、コードが読みやすくなります。データ量が多い場合は、locブール配列と組み合わせた方が通常はquery速い。