Pandas query() 方法詳解
query()
是 Pandas 中一個非常強大的方法,它允許你使用字符串表達式來篩選數據行。這種方法比傳統的布爾索引更簡潔、更易讀。
基本語法
df.query(expr, inplace=False, **kwargs)
expr
: 查詢字符串表達式inplace
: 是否原地修改 DataFrame (默認為 False)**kwargs
: 其他關鍵字參數
- 對于大型 DataFrame,
query()
?通常比布爾索引快,因為它在底層使用了 numexpr 庫- 但對于小型 DataFrame,傳統布爾索引可能更快
基本用法
1. 簡單條件查詢
import pandas as pddf = pd.DataFrame({'A': range(1, 6),'B': range(10, 60, 10),'C': ['a', 'b', 'c', 'd', 'e']
})# 查詢 A 列大于 2 的行
result = df.query('A > 2')
2. 多條件查詢
# AND 條件
df.query('A > 2 & B < 50')# OR 條件
df.query('A > 4 | B == 20')# 使用括號明確優先級
df.query('(A > 2) & (B < 50)')
3. 字符串條件查詢
# 等于
df.query('C == "a"')# 不等于
df.query('C != "a"')# 包含在列表中
df.query('C in ["a", "b", "c"]')# 不包含在列表中
df.query('C not in ["a", "b"]')
高級用法
1. 使用變量 (@符號)
min_val = 3
max_val = 5df.query('A >= @min_val & A <= @max_val')
2. 列名包含空格或特殊字符
df = pd.DataFrame({'A value': [1, 2, 3], 'B@value': [4, 5, 6]})# 使用反引號包裹列名
df.query('`A value` > 1 & `B@value` < 6')
3. 使用 DataFrame 屬性
# 查詢索引
df.query('index > 2')# 查詢列長度
df.query('A.str.len() > 1') # 如果A是字符串列
4. 使用函數
# 使用內置函數
df.query('A.abs() > 2') # 絕對值# 使用自定義函數
def my_func(x):return x * 2df.query('A > @my_func(2)')
性能考慮
- 對于大型 DataFrame,
query()
通常比布爾索引快,因為它在底層使用了 numexpr 庫 - 但對于小型 DataFrame,傳統布爾索引可能更快
與傳統布爾索引的比較
# 傳統布爾索引
df[(df['A'] > 2) & (df['B'] < 50)]# query 方法
df.query('A > 2 & B < 50')
query() 的優勢在于:
- 語法更簡潔
- 不需要重復寫 DataFrame 名稱
- 對于復雜條件更易讀
注意事項
- 表達式必須返回布爾值
- 列名中的特殊字符需要用反引號包裹
- 使用變量時需要用 @ 符號
- 表達式中的字符串需要用雙引號包裹
實際應用示例
# 創建示例數據
data = {'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],'age': [25, 30, 35, 40, 45],'salary': [50000, 60000, 70000, 80000, 90000],'department': ['HR', 'IT', 'IT', 'Finance', 'HR']
}
df = pd.DataFrame(data)# 查詢年齡在30-40之間且部門為IT或HR的員工
result = df.query('(age >= 30 & age <= 40) & department in ["IT", "HR"]')# 查詢薪資高于平均薪資的員工
avg_salary = df['salary'].mean()
result = df.query('salary > @avg_salary')
query()
方法是 Pandas 中非常實用的功能,特別適合需要編寫復雜篩選條件的場景,能夠顯著提高代碼的可讀性和簡潔性。