Pandas 過濾資料

過濾(filter)是指根據條件篩選出符合的資料列。這是資料分析中最常用的操作之一。

範例資料

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
    'age': [25, 30, 35, 28, 32],
    'city': ['Taipei', 'Tokyo', 'Seoul', 'Taipei', 'Tokyo'],
    'salary': [50000, 60000, 70000, 55000, 65000]
})

基本條件過濾

比較運算

# 選取 age > 30 的資料
result = df[df['age'] > 30]
print(result)

輸出:

      name  age   city  salary
2  Charlie   35  Seoul   70000
4      Eva   32  Tokyo   65000

背後的原理是布林索引(Boolean indexing):

# 條件運算會產生布林 Series
print(df['age'] > 30)
0    False
1    False
2     True
3    False
4     True
Name: age, dtype: bool

常見比較運算子

df[df['age'] > 30]     # 大於
df[df['age'] >= 30]    # 大於等於
df[df['age'] < 30]     # 小於
df[df['age'] <= 30]    # 小於等於
df[df['age'] == 30]    # 等於
df[df['age'] != 30]    # 不等於

多條件過濾

使用 &(AND)、|(OR)、~(NOT)組合多個條件。

注意:每個條件必須用括號包起來。

AND 條件

# age > 25 且 salary > 55000
result = df[(df['age'] > 25) & (df['salary'] > 55000)]

OR 條件

# age < 26 或 age > 33
result = df[(df['age'] < 26) | (df['age'] > 33)]

NOT 條件

# age 不大於 30
result = df[~(df['age'] > 30)]

複雜條件組合

# (age > 25 且 city == 'Taipei') 或 salary > 65000
result = df[((df['age'] > 25) & (df['city'] == 'Taipei')) | (df['salary'] > 65000)]

字串條件過濾

等於特定值

result = df[df['city'] == 'Taipei']

包含特定文字

result = df[df['name'].str.contains('a')]  # 名字包含 'a'

開頭或結尾

result = df[df['name'].str.startswith('A')]
result = df[df['name'].str.endswith('e')]

不區分大小寫

result = df[df['name'].str.lower() == 'alice']
# 或
result = df[df['name'].str.contains('alice', case=False)]

isin() 過濾

檢查值是否在給定的列表中:

# city 在 ['Taipei', 'Tokyo'] 中
result = df[df['city'].isin(['Taipei', 'Tokyo'])]

排除特定值:

# city 不在 ['Seoul'] 中
result = df[~df['city'].isin(['Seoul'])]

between() 過濾

選取範圍內的值:

# age 在 25 到 32 之間(包含邊界)
result = df[df['age'].between(25, 32)]

query() 方法

使用類似 SQL 的語法過濾:

# 基本用法
result = df.query('age > 30')

# 多條件
result = df.query('age > 25 and salary > 55000')
result = df.query('age < 26 or age > 33')

# 字串比較
result = df.query('city == "Taipei"')

# 使用變數(加 @)
min_age = 30
result = df.query('age > @min_age')

query() 的好處是語法更直覺,不需要重複寫 df['欄位']

過濾空值

# 選取 age 不是空值的列
result = df[df['age'].notna()]

# 選取 age 是空值的列
result = df[df['age'].isna()]

使用 loc 過濾

loc 可以同時過濾列和選取欄位:

# 過濾 age > 30,只選取 name 和 salary 欄位
result = df.loc[df['age'] > 30, ['name', 'salary']]

取得過濾後的索引

# 取得符合條件的索引
indices = df[df['age'] > 30].index
print(indices)  # Index([2, 4], dtype='int64')

過濾後重設索引

過濾後索引可能不連續,可以重設:

result = df[df['age'] > 30].reset_index(drop=True)