1. 准备示例数据
首先,我们创建一个示例 DataFrame,用于后续所有的操作演示。
import pandas as pd
import numpy as np
# 创建一个员工信息DataFrame
data = {
'姓名': ['张三', '李四', '王五', '赵六', '钱七'],
'部门': ['销售', '技术', '技术', '市场', '销售'],
'年龄': [25, 32, 28, 45, 36],
'工资': [50000, 85000, 70000, 60000, 90000],
'入职年份': [2019, 2016, 2020, 2010, 2015]
}
df = pd.DataFrame(data)
print("原始数据集:")
print(df)
我们的 df 看起来会是这样的:
| 姓名 | 部门 | 年龄 | 工资 | 入职年份 | |
|---|---|---|---|---|---|
| 0 | 张三 | 销售 | 25 | 50000 | 2019 |
| 1 | 李四 | 技术 | 32 | 85000 | 2016 |
| 2 | 王五 | 技术 | 28 | 70000 | 2020 |
| 3 | 赵六 | 市场 | 45 | 60000 | 2010 |
| 4 | 钱七 | 销售 | 36 | 90000 | 2015 |
2. 单条件筛选
单条件筛选的核心是使用布尔序列(Boolean Series) 。我们通过对 DataFrame 的某一列施加条件判断,会得到一个由 True 和 False 组成的序列。将这个布尔序列传递给 DataFrame,Pandas 就会返回所有对应 True 的行。
2.1 基本语法:df[df[‘列名’] <条件>]
python
# 筛选出所有“技术”部门的员工
condition = df['部门'] == '技术' # 这是一个布尔序列
tech_team = df[condition] # 将布尔序列传入df
# 通常我们会直接写成一行
tech_team = df[df['部门'] == '技术']
print("技术部员工:")
print(tech_team)
输出:
| 姓名 | 部门 | 年龄 | 工资 | 入职年份 | |
|---|---|---|---|---|---|
| 1 | 李四 | 技术 | 32 | 85000 | 2016 |
| 2 | 王五 | 技术 | 28 | 70000 | 2020 |
2.2 常用的比较运算符:
==:等于!=:不等于>:大于<:小于>=:大于等于<=:小于等于
python
# 筛选出年龄大于30岁的员工
df[df['年龄'] > 30]
# 筛选出工资不等于85000的员工
df[df['工资'] != 85000]
2.3 使用 .isin() 方法进行多项匹配
当你想筛选某列的值在某个列表中出现时,用 isin() 非常方便。
python
# 筛选出部门是“销售”或“市场”的员工
df[df['部门'].isin(['销售', '市场'])]
2.4 处理空值:.isna() 和 .notna()
python
# 假设我们数据中有空值NaN
df_with_nan = df.copy()
df_with_nan.loc[2, '工资'] = np.nan
# 筛选出“工资”为空的行
df_with_nan[df_with_nan['工资'].isna()]
# 筛选出“工资”不为空的行
df_with_nan[df_with_nan['工资'].notna()]
3. 多条件筛选
多条件筛选需要将多个布尔序列进行组合。Pandas 使用以下符号进行逻辑操作:
-
& 表示逻辑与 (and) :所有条件都满足 -
| 表示逻辑或 (or) :至少一个条件满足 -
~ 表示逻辑非 (not) :取反
非常重要: 每个条件都必须用括号 () 括起来,因为 &、| 的运算优先级高于 ==、> 等比较运算符。
3.1 逻辑与 (&)
python
# 筛选出“技术部”且“年龄大于30岁”的员工
df[(df['部门'] == '技术') & (df['年龄'] > 30)]
输出:
| 姓名 | 部门 | 年龄 | 工资 | 入职年份 | |
|---|---|---|---|---|---|
| 1 | 李四 | 技术 | 32 | 85000 | 2016 |
3.2 逻辑或 (|)
python
# 筛选出“工资大于80000”或“年龄小于30岁”的员工
df[(df['工资'] > 80000) | (df['年龄'] < 30)]
输出:
| 姓名 | 部门 | 年龄 | 工资 | 入职年份 | |
|---|---|---|---|---|---|
| 0 | 张三 | 销售 | 25 | 50000 | 2019 |
| 1 | 李四 | 技术 | 32 | 85000 | 2016 |
| 4 | 钱七 | 销售 | 36 | 90000 | 2015 |
3.3 逻辑非 (~)
python
# 筛选出“不是销售部门”的员工
df[~(df['部门'] == '销售')]
# 等价于
df[df['部门'] != '销售']
4. 基于字符串方法的筛选 (.str.contains())
如果列中的值是字符串,可以使用 .str 访问器下的多种字符串方法进行模糊筛选。
python
# 筛选出姓名中包含“五”的员工 (模糊匹配)
df[df['姓名'].str.contains('五')]
# 默认是大小写敏感的,可以添加case=False参数忽略大小写
# df[df['姓名'].str.contains('Wang', case=False)]
5. 筛选后的常见操作
筛选出的结果仍然是一个 DataFrame,你可以对它进行任何对 DataFrame 的操作。
5.1 获取筛选后的行数据
方法一:使用 .loc 和 .iloc (推荐)
.loc 通过标签索引,.iloc 通过位置索引。
python
# 先筛选出技术部员工,然后获取第一行(索引为1的那行)的所有数据
tech_df = df[df['部门'] == '技术']
li_si_info = tech_df.loc[1] # 获取索引标签为1的行
print(li_si_info)
print(f"李四的工资:{li_si_info['工资']}")
# 获取筛选后第一行(无论它的索引是什么)的所有数据
first_tech_info = tech_df.iloc[0] # iloc[0] 表示第0行
print(first_tech_info)
# 组合使用:直接定位到筛选后某个单元格的值
# 获取“技术部第一个员工”的“工资”
salary = tech_df.iloc[0]['工资']
salary = tech_df.iloc[0].loc['工资'] # 另一种写法
方法二:直接再筛选 (链式操作)
虽然可行,但代码可读性较差,且可能导致 SettingWithCopyWarning,一般不推荐。
python
# 不推荐:直接链式操作
df[df['部门'] == '技术'].iloc[0]['工资']
5.2 对筛选结果进行统计
python
# 计算技术部的平均工资
tech_salary_mean = df[df['部门'] == '技术']['工资'].mean()
print(f"技术部平均工资: {tech_salary_mean}")
# 计算销售部的最高年龄
sales_max_age = df[df['部门'] == '销售']['年龄'].max()
# 统计每个部门的人数 (这本身就是一个分组操作,但筛选也常用)
df[df['年龄'] > 30]['部门'].value_counts() # 年龄大于30岁的人在各部门的分布
5.3 修改筛选后的数据
这是一个非常重要的应用场景,通常使用 .loc 来避免警告。
python
# 给所有技术部员工加薪10%
df.loc[df['部门'] == '技术', '工资'] = df.loc[df['部门'] == '技术', '工资'] * 1.1
print("加薪后的数据集:")
print(df)
6. 其他有用的筛选方法:.query()
Pandas 提供了一个非常简洁的 query() 方法,允许你使用字符串表达式进行筛选,尤其适合复杂的多条件查询。
python
# 使用query完成多条件筛选
# 在query字符串中,列名可以不用加引号,但字符串值需要加引号
tech_senior = df.query('部门 == "技术" and 年龄 > 30')
print(tech_senior)
# 变量也可以传入
dept_name = "销售"
min_salary = 60000
result = df.query('部门 == @dept_name and 工资 >= @min_salary') # 使用@来引用外部变量
print(result)
7. 总结与要点回顾
| 操作类型 | 方法/语法 | 备注 |
|---|---|---|
| 单条件 | df[df[‘列’] > 10] |
核心是生成布尔序列 |
| 多条件与 | df[(条件1) & (条件2)] |
每个条件必须用括号括起来! |
| 多条件或 | df[(条件1) \| (条件2)] |
每个条件必须用括号括起来! |
| 多条件非 | df[~(条件)] |
|
| 列表匹配 | df[df[‘列’].isin([列表])] |
非常适合检查值是否在给定列表中 |
| 空值筛选 | df[df[‘列’].isna()], df[df[‘列’].notna()] |
用于数据清洗 |
| 字符串模糊 | df[df[‘列’].str.contains(‘pattern’)] |
基于正则表达式的强大文本匹配 |
| 优雅查询 | df.query(‘列a > 100 & 列b == “x”’) |
语法简洁,适合复杂查询,可引用外部变量(@var) |
| 筛选后操作 | df_filtered.iloc[0], df_filtered[‘列’].mean() |
筛选结果是一个新DataFrame,可以对其进行任何操作 |
| 筛选后赋值 | df.loc[df[‘列’] > 10, ‘列’] = 100 |
使用 .loc 安全地修改原数据,避免 SettingWithCopyWarning |