query() 方法,让你能够以最自然的方式获取所需数据。
import pandas as pd
import numpy as np
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六', '陈七', '周八'],
'年龄': [28, 35, 42, 29, 31, 38],
'工资': [8000, 12000, 15000, 9500, 11000, 13500],
'部门': ['技术', '销售', '技术', '管理', '销售', '技术'],
'入职年份': [2020, 2018, 2015, 2021, 2019, 2017]
})
print(df)
布尔索引是 Pandas 最基本的筛选方式,通过传入一个布尔型 Series(与 DataFrame 长度相同)来选取对应位置为 True 的行。
df[df['年龄'] > 30] # 年龄大于30
df[df['部门'] == '技术'] # 部门为技术
# 年龄大于30且部门为技术
df[(df['年龄'] > 30) & (df['部门'] == '技术')]
# 工资小于10000或部门为管理
df[(df['工资'] < 10000) | (df['部门'] == '管理')]
# 年龄不大于30(取反)
df[~(df['年龄'] > 30)]
注意:每个条件必须用括号括起来,因为 &、| 的优先级高于比较运算符。
isin() 进行成员筛选当需要筛选列值属于某个集合时,isin() 非常方便。
# 筛选部门为技术或销售的行
df[df['部门'].isin(['技术', '销售'])]
# 筛选年龄为28、35、38的行
df[df['年龄'].isin([28, 35, 38])]
between() 进行区间筛选between() 用于筛选数值在某个闭区间内的行,包含左右边界。
# 筛选工资在9000到13000之间
df[df['工资'].between(9000, 13000)]
# 也可用于日期、字符串等可比较类型
df[df['姓名'].between('王', '赵')] # 按字典序
通过 .str 访问器可以使用字符串方法进行筛选。
# 筛选姓名以“张”开头的行
df[df['姓名'].str.startswith('张')]
# 筛选姓名包含“五”的行
df[df['姓名'].str.contains('五')]
# 筛选部门长度大于等于2的行
df[df['部门'].str.len() >= 2]
query() 方法query() 提供了一种类似 SQL 的字符串表达式语法,使代码更简洁。
# 筛选年龄大于30且部门为技术
df.query('年龄 > 30 and 部门 == "技术"')
# 使用变量
min_wage = 10000
df.query('工资 >= @min_wage and 入职年份 < 2020')
# 复杂条件
df.query('(年龄 > 30 or 工资 > 12000) and 部门 != "管理"')
有时需要根据行索引或列索引进行筛选。
# 设置姓名列为索引
df_indexed = df.set_index('姓名')
# 根据索引值筛选
df_indexed.loc[['张三', '王五']]
# 根据索引条件筛选(需先重置索引或使用 index 属性)
df[df.index.isin([0, 2, 4])] # 筛选行索引为0,2,4的行
结合 .loc[] 可以在筛选行的同时选择特定列。
# 筛选年龄大于30的行,并只保留姓名和工资列
df.loc[df['年龄'] > 30, ['姓名', '工资']]
# 使用 query 配合列选择
df.query('年龄 > 30').loc[:, ['姓名', '工资']]
import pandas as pd
# 员工数据
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六', '陈七', '周八', '吴九'],
'年龄': [28, 35, 42, 29, 31, 38, 45],
'工资': [8000, 12000, 15000, 9500, 11000, 13500, 18000],
'部门': ['技术', '销售', '技术', '管理', '销售', '技术', '管理'],
'入职年份': [2020, 2018, 2015, 2021, 2019, 2017, 2014]
})
# 需求1:筛选年龄大于30且工资低于15000的员工
df1 = df[(df['年龄'] > 30) & (df['工资'] < 15000)]
print("年龄>30且工资<15000:\n", df1)
# 需求2:筛选部门为技术或管理,且入职年份在2018年之后的员工
df2 = df[df['部门'].isin(['技术', '管理']) & (df['入职年份'] > 2018)]
print("\n技术或管理,且入职年份>2018:\n", df2)
# 需求3:筛选姓名包含“五”或“七”的员工,只保留姓名和部门
df3 = df[df['姓名'].str.contains('五|七')][['姓名', '部门']]
print("\n姓名含五或七:\n", df3)
# 需求4:使用query筛选工资在10000-16000之间且部门不是销售
df4 = df.query('10000 <= 工资 <= 16000 and 部门 != "销售"')
print("\n工资在10000-16000之间且非销售:\n", df4)
(df['年龄'] > 30) & (df['工资'] < 15000),不能写成 df['年龄'] > 30 & df['工资'] < 15000。
str.contains() 对于大数据集可能较慢,考虑使用正则或提前处理。
query() 中使用外部变量需加 @ 前缀,如 @min_wage。
df[df['年龄'].isna() | (df['年龄'] > 30)]。
query() 提高可读性。&、|,不要用 and、or(除非在 query 中)。.loc[] 进行赋值,避免链式索引警告。