Pandas数据分析 - 第三章:DataFrame 对象详解

第三章:DataFrame 对象详解

📋 章节概述

本章深入讲解 Pandas DataFrame 对象的高级用法,包括行列操作、数据选择、索引管理、条件筛选、数据转换等核心功能。通过本章学习,你将掌握 DataFrame 的完整操作技能。

🎯 学习目标

  1. 掌握 DataFrame 的行列操作(增删改查)
  2. 深入理解 loc/iloc 在 DataFrame 中的高级用法
  3. 学会设置、重置和修改索引
  4. 掌握条件筛选和过滤技巧
  5. 理解 DataFrame 的数据对齐机制
  6. 学会使用 apply 和 applymap 进行数据转换

📊 知识结构图

DataFrame 详解
创建与结构
列操作
行操作
数据选择
索引管理
条件筛选
数据转换
字典创建
列表创建
NumPy创建
选择列
添加列
修改列
删除列
选择行
添加行
修改行
删除行
loc

标签索引
iloc

位置索引
布尔索引
set_index
reset_index
rename
单条件
多条件
query
apply
applymap
map

python 复制代码
import pandas as pd
import numpy as np

3.1 DataFrame 结构解析

DataFrame 是 Pandas 最重要的数据结构,可以理解为:

  • 一个 Excel 工作表
  • 一个 SQL 数据表
  • 多个 Series 组成的字典(共享同一个行索引)

结构组成

  • 行索引(index):每行的标签
  • 列索引(columns):每列的标签
  • 数据(values):二维数组形式的数据

DataFrame结构
行索引

Index
数据区域
列索引

Columns
列1: Series
列2: Series
列3: Series

示例1:从字典创建 DataFrame(最常用)

python 复制代码
# 方式1:从字典创建(最常用)
# 字典的 key 成为列名,value 成为该列数据
df_dict = pd.DataFrame({
    "姓名": ["张伟", "李娜", "王强", "刘洋", "陈静"],
    "部门": ["技术部", "销售部", "技术部", "人事部", "财务部"],
    "薪资": [12000, 15000, 18000, 8000, 9000],
    "入职日期": pd.to_datetime(["2026-01-15", "2026-02-20", "2026-03-10", "2026-01-05", "2026-02-01"])
})
df_dict

| | 姓名 | 部门 | 薪资 | 入职日期 |
| 0 | 张伟 | 技术部 | 12000 | 2026-01-15 |
| 1 | 李娜 | 销售部 | 15000 | 2026-02-20 |
| 2 | 王强 | 技术部 | 18000 | 2026-03-10 |
| 3 | 刘洋 | 人事部 | 8000 | 2026-01-05 |

4 陈静 财务部 9000 2026-02-01

示例2:从列表创建 DataFrame

python 复制代码
# 方式2:从列表的列表创建
df_list = pd.DataFrame(
    data=[["E001", "张伟", 28], ["E002", "李娜", 32], ["E003", "王强", 25]],
    columns=["工号", "姓名", "年龄"],
    index=["row1", "row2", "row3"]  # 自定义行索引
)
df_list

| | 工号 | 姓名 | 年龄 |
| row1 | E001 | 张伟 | 28 |
| row2 | E002 | 李娜 | 32 |

row3 E003 王强 25

示例3:从 NumPy 数组创建 DataFrame

python 复制代码
# 方式3:从 NumPy 数组创建
np.random.seed(42)  # 设置随机种子保证可重复
df_numpy = pd.DataFrame(
    data=np.random.randn(4, 3),  # 4行3列的标准正态分布数据
    columns=["A", "B", "C"],
    index=["第1行", "第2行", "第3行", "第4行"]
)
df_numpy.round(2)

| | A | B | C |
| 第1行 | 0.50 | -0.14 | 0.65 |
| 第2行 | 1.52 | -0.23 | -0.23 |
| 第3行 | 1.58 | 0.77 | -0.47 |

第4行 0.54 -0.46 -0.47

示例4:DataFrame 基本属性

python 复制代码
print("DataFrame 基本属性:")
print(f"  shape(形状): {df_dict.shape}  -> (行数, 列数)")
print(f"  index(行索引): {list(df_dict.index)}")
print(f"  columns(列索引): {list(df_dict.columns)}")
print(f"  dtypes(数据类型):")
print(df_dict.dtypes)
print(f"\n  values(数据值,NumPy数组):")
print(df_dict.values)
复制代码
DataFrame 基本属性:
  shape(形状): (5, 4)  -> (行数, 列数)
  index(行索引): [0, 1, 2, 3, 4]
  columns(列索引): ['姓名', '部门', '薪资', '入职日期']
  dtypes(数据类型):
姓名                 str
部门                 str
薪资               int64
入职日期    datetime64[us]
dtype: object

  values(数据值,NumPy数组):
[['张伟' '技术部' 12000 Timestamp('2026-01-15 00:00:00')]
 ['李娜' '销售部' 15000 Timestamp('2026-02-20 00:00:00')]
 ['王强' '技术部' 18000 Timestamp('2026-03-10 00:00:00')]
 ['刘洋' '人事部' 8000 Timestamp('2026-01-05 00:00:00')]
 ['陈静' '财务部' 9000 Timestamp('2026-02-01 00:00:00')]]

3.2 列操作(增删改查)

列操作
选择列
添加列
修改列
删除列
df单括号col

返回Series
df双括号col

返回DataFrame
直接赋值
assign方法
整列修改
apply修改
del删除
pop删除
drop删除

python 复制代码
# 创建基础数据框
df = pd.DataFrame({
    "姓名": ["张伟", "李娜", "王强", "刘洋", "陈静"],
    "部门": ["技术部", "销售部", "技术部", "人事部", "财务部"],
    "基本工资": [10000, 12000, 15000, 7000, 8000]
})
df

| | 姓名 | 部门 | 基本工资 |
| 0 | 张伟 | 技术部 | 10000 |
| 1 | 李娜 | 销售部 | 12000 |
| 2 | 王强 | 技术部 | 15000 |
| 3 | 刘洋 | 人事部 | 7000 |

4 陈静 财务部 8000

3.2.1 选择列

python 复制代码
# 选择单列(返回 Series)
name_col = df["姓名"]  # 或 df.姓名(不推荐)
print(f"类型: {type(name_col)}")
name_col
复制代码
类型: <class 'pandas.Series'>





0    张伟
1    李娜
2    王强
3    刘洋
4    陈静
Name: 姓名, dtype: str
python 复制代码
# 选择多列(返回 DataFrame)
subset = df[["姓名", "部门"]]
print(f"类型: {type(subset)}")
subset
复制代码
类型: <class 'pandas.DataFrame'>

| | 姓名 | 部门 |
| 0 | 张伟 | 技术部 |
| 1 | 李娜 | 销售部 |
| 2 | 王强 | 技术部 |
| 3 | 刘洋 | 人事部 |

4 陈静 财务部

3.2.2 添加新列

python 复制代码
df_new = df.copy()

# 方式1:直接赋值(标量值)
df_new["绩效奖金"] = 2000
print("方式1 - 直接赋值标量:")
df_new[["姓名", "绩效奖金"]]
复制代码
方式1 - 直接赋值标量:

| | 姓名 | 绩效奖金 |
| 0 | 张伟 | 2000 |
| 1 | 李娜 | 2000 |
| 2 | 王强 | 2000 |
| 3 | 刘洋 | 2000 |

4 陈静 2000
python 复制代码
# 方式2:赋值 Series 或列表
df_new["项目数"] = [3, 5, 4, 2, 3]
print("方式2 - 赋值列表:")
df_new[["姓名", "项目数"]]
复制代码
方式2 - 赋值列表:

| | 姓名 | 项目数 |
| 0 | 张伟 | 3 |
| 1 | 李娜 | 5 |
| 2 | 王强 | 4 |
| 3 | 刘洋 | 2 |

4 陈静 3
python 复制代码
# 方式3:基于现有列计算
df_new["总薪资"] = df_new["基本工资"] + df_new["绩效奖金"]
print("方式3 - 基于现有列计算:")
df_new[["姓名", "基本工资", "绩效奖金", "总薪资"]]
复制代码
方式3 - 基于现有列计算:

| | 姓名 | 基本工资 | 绩效奖金 | 总薪资 |
| 0 | 张伟 | 10000 | 2000 | 12000 |
| 1 | 李娜 | 12000 | 2000 | 14000 |
| 2 | 王强 | 15000 | 2000 | 17000 |
| 3 | 刘洋 | 7000 | 2000 | 9000 |

4 陈静 8000 2000 10000
python 复制代码
# 方式4:使用 assign() 方法(返回新 DataFrame,链式操作)
df_assigned = df_new.assign(
    税后薪资=lambda x: x["总薪资"] * 0.9,  # 假设税率10%
    评级=lambda x: np.where(x["总薪资"] >= 15000, "A", "B")
)
print("方式4 - 使用 assign() 方法:")
df_assigned[["姓名", "总薪资", "税后薪资", "评级"]]
复制代码
方式4 - 使用 assign() 方法:

| | 姓名 | 总薪资 | 税后薪资 | 评级 |
| 0 | 张伟 | 12000 | 10800.0 | B |
| 1 | 李娜 | 14000 | 12600.0 | B |
| 2 | 王强 | 17000 | 15300.0 | A |
| 3 | 刘洋 | 9000 | 8100.0 | B |

4 陈静 10000 9000.0 B

3.2.3 修改列

python 复制代码
df_modify = df_new.copy()

print("修改前 - 基本工资:")
print(df_modify["基本工资"].tolist())

# 方式1:直接修改整列
df_modify["基本工资"] = df_modify["基本工资"] * 1.1  # 涨薪10%
print("\n修改后 - 基本工资(涨薪10%):")
print(df_modify["基本工资"].tolist())
复制代码
修改前 - 基本工资:
[10000, 12000, 15000, 7000, 8000]

修改后 - 基本工资(涨薪10%):
[11000.0, 13200.000000000002, 16500.0, 7700.000000000001, 8800.0]
python 复制代码
# 方式2:使用 apply 方法(更灵活)
df_modify["部门"] = df_modify["部门"].apply(lambda x: x.replace("部", "部门"))
print("使用 apply 修改部门名称:")
print(df_modify["部门"].tolist())
复制代码
使用 apply 修改部门名称:
['技术部门', '销售部门', '技术部门', '人事部门', '财务部门']

3.2.4 删除列

python 复制代码
print(f"原始列: {list(df_new.columns)}")

# 方式1:使用 del(原地删除)
df_del = df_new.copy()
del df_del["项目数"]
print(f"方式1 - del 删除后: {list(df_del.columns)}")

# 方式2:使用 pop()(原地删除,返回被删除的列)
df_pop = df_new.copy()
popped_col = df_pop.pop("绩效奖金")
print(f"方式2 - pop 删除后: {list(df_pop.columns)}")
print(f"  被删除的列: {popped_col.tolist()}")

# 方式3:使用 drop()(返回新 DataFrame,推荐)
df_dropped = df_new.drop(columns=["项目数", "总薪资"])
print(f"方式3 - drop 删除后: {list(df_dropped.columns)}")
print(f"  原 DataFrame 列数: {len(df_new.columns)}")
复制代码
原始列: ['姓名', '部门', '基本工资', '绩效奖金', '项目数', '总薪资']
方式1 - del 删除后: ['姓名', '部门', '基本工资', '绩效奖金', '总薪资']
方式2 - pop 删除后: ['姓名', '部门', '基本工资', '项目数', '总薪资']
  被删除的列: [2000, 2000, 2000, 2000, 2000]
方式3 - drop 删除后: ['姓名', '部门', '基本工资', '绩效奖金']
  原 DataFrame 列数: 6

3.3 行操作(增删改查)

行操作
选择行
添加行
修改行
删除行
loc标签
iloc位置
loc新增
concat
loc修改
drop方法

python 复制代码
# 创建带自定义索引的数据框
df_indexed = pd.DataFrame({
    "姓名": ["张伟", "李娜", "王强", "刘洋", "陈静"],
    "部门": ["技术部", "销售部", "技术部", "人事部", "财务部"],
    "薪资": [12000, 15000, 18000, 8000, 9000]
}, index=["E001", "E002", "E003", "E004", "E005"])
df_indexed

| | 姓名 | 部门 | 薪资 |
| E001 | 张伟 | 技术部 | 12000 |
| E002 | 李娜 | 销售部 | 15000 |
| E003 | 王强 | 技术部 | 18000 |
| E004 | 刘洋 | 人事部 | 8000 |

E005 陈静 财务部 9000

3.3.1 选择行

python 复制代码
# 使用 loc 选择行(按标签)
print("选择单行:")
print(df_indexed.loc["E001"])
print("\n选择多行:")
df_indexed.loc["E001":"E003"]
复制代码
选择单行:
姓名       张伟
部门      技术部
薪资    12000
Name: E001, dtype: object

选择多行:

| | 姓名 | 部门 | 薪资 |
| E001 | 张伟 | 技术部 | 12000 |
| E002 | 李娜 | 销售部 | 15000 |

E003 王强 技术部 18000
python 复制代码
# 使用 iloc 选择行(按位置)
print("选择第一行:")
print(df_indexed.iloc[0])
print("\n选择前3行:")
df_indexed.iloc[0:3]
复制代码
选择第一行:
姓名       张伟
部门      技术部
薪资    12000
Name: E001, dtype: object

选择前3行:

| | 姓名 | 部门 | 薪资 |
| E001 | 张伟 | 技术部 | 12000 |
| E002 | 李娜 | 销售部 | 15000 |

E003 王强 技术部 18000

3.3.2 添加新行

python 复制代码
# 方式1:使用 loc 添加(推荐)
df_add = df_indexed.copy()
df_add.loc["E006"] = ["赵敏", "技术部", 13000]
print("方式1 - 使用 loc 添加新行:")
df_add.tail(3)
复制代码
方式1 - 使用 loc 添加新行:

| | 姓名 | 部门 | 薪资 |
| E004 | 刘洋 | 人事部 | 8000 |
| E005 | 陈静 | 财务部 | 9000 |

E006 赵敏 技术部 13000
python 复制代码
# 方式2:使用 concat 添加多行
df_add2 = df_indexed.copy()
new_rows = pd.DataFrame({
    "姓名": ["周杰", "吴刚"],
    "部门": ["销售部", "人事部"],
    "薪资": [11000, 9500]
}, index=["E006", "E007"])
df_concat = pd.concat([df_add2, new_rows])
print("方式2 - 使用 concat 添加多行:")
df_concat.tail(4)
复制代码
方式2 - 使用 concat 添加多行:

| | 姓名 | 部门 | 薪资 |
| E004 | 刘洋 | 人事部 | 8000 |
| E005 | 陈静 | 财务部 | 9000 |
| E006 | 周杰 | 销售部 | 11000 |

E007 吴刚 人事部 9500

3.3.3 修改行

python 复制代码
df_modify_row = df_indexed.copy()

print("修改前 E001:")
print(df_modify_row.loc["E001"])

df_modify_row.loc["E001"] = ["张伟(已更新)", "技术部", 15000]
print("\n修改后 E001:")
print(df_modify_row.loc["E001"])
复制代码
修改前 E001:
姓名       张伟
部门      技术部
薪资    12000
Name: E001, dtype: object

修改后 E001:
姓名    张伟(已更新)
部门        技术部
薪资      15000
Name: E001, dtype: object

3.3.4 删除行

python 复制代码
print(f"原始行数: {len(df_indexed)}")

# 使用 drop 删除行
df_drop_row = df_indexed.drop(index=["E004", "E005"])
print(f"删除后行数: {len(df_drop_row)}")
df_drop_row
复制代码
原始行数: 5
删除后行数: 3

| | 姓名 | 部门 | 薪资 |
| E001 | 张伟 | 技术部 | 12000 |
| E002 | 李娜 | 销售部 | 15000 |

E003 王强 技术部 18000

3.4 loc 和 iloc 高级用法

loc 和 iloc 对比总结

特性 loc iloc
索引方式 标签索引 位置索引
切片规则 左闭右闭 左闭右开
支持类型 字符串、数字、布尔 整数
布尔索引 支持 支持

记忆口诀

  • loc = label-based(标签)
  • iloc = integer-based(整数位置)

数据选择
loc

标签索引

左闭右闭
iloc

位置索引

左闭右开
布尔索引

条件筛选
df.loc标签切片

包含终点
df.iloc位置切片

不含终点

python 复制代码
# 创建示例数据
df_demo = pd.DataFrame({
    "A": [1, 2, 3, 4, 5],
    "B": [10, 20, 30, 40, 50],
    "C": [100, 200, 300, 400, 500]
}, index=["a", "b", "c", "d", "e"])
df_demo

| | A | B | C |
| a | 1 | 10 | 100 |
| b | 2 | 20 | 200 |
| c | 3 | 30 | 300 |
| d | 4 | 40 | 400 |

e 5 50 500

3.4.1 loc 高级用法

python 复制代码
# loc['a', 'A'] - 选择单行单列
print("loc['a', 'A'] - 选择单行单列:")
print(df_demo.loc["a", "A"])
print()

# loc['a':'c', :] - 选择多行,所有列
print("loc['a':'c', :] - 选择多行,所有列:")
print(df_demo.loc["a":"c", :])
print()

# loc[:, 'A':'B'] - 所有行,选择多列
print("loc[:, 'A':'B'] - 所有行,选择多列:")
print(df_demo.loc[:, "A":"B"])
print()

# loc[['a','c','e'], ['A','C']] - 选择指定行和列
print("loc[['a','c','e'], ['A','C']] - 选择指定行和列:")
df_demo.loc[["a", "c", "e"], ["A", "C"]]
复制代码
loc['a', 'A'] - 选择单行单列:
1

loc['a':'c', :] - 选择多行,所有列:
   A   B    C
a  1  10  100
b  2  20  200
c  3  30  300

loc[:, 'A':'B'] - 所有行,选择多列:
   A   B
a  1  10
b  2  20
c  3  30
d  4  40
e  5  50

loc[['a','c','e'], ['A','C']] - 选择指定行和列:

| | A | C |
| a | 1 | 100 |
| c | 3 | 300 |

e 5 500

3.4.2 iloc 高级用法

python 复制代码
# iloc[0, 0] - 第1行第1列
print("iloc[0, 0] - 第1行第1列:")
print(df_demo.iloc[0, 0])
print()

# iloc[0:3, :] - 前3行,所有列
print("iloc[0:3, :] - 前3行,所有列:")
print(df_demo.iloc[0:3, :])
print()

# iloc[:, 0:2] - 所有行,前2列
print("iloc[:, 0:2] - 所有行,前2列:")
print(df_demo.iloc[:, 0:2])
print()

# iloc[[0,2,4], [0,2]] - 指定行和列(按位置)
print("iloc[[0,2,4], [0,2]] - 指定行和列(按位置):")
df_demo.iloc[[0, 2, 4], [0, 2]]
复制代码
iloc[0, 0] - 第1行第1列:
1

iloc[0:3, :] - 前3行,所有列:
   A   B    C
a  1  10  100
b  2  20  200
c  3  30  300

iloc[:, 0:2] - 所有行,前2列:
   A   B
a  1  10
b  2  20
c  3  30
d  4  40
e  5  50

iloc[[0,2,4], [0,2]] - 指定行和列(按位置):

| | A | C |
| a | 1 | 100 |
| c | 3 | 300 |

e 5 500

3.4.3 布尔索引(条件筛选)

python 复制代码
# 选择 A 列大于 2 的行
print("选择 A 列大于 2 的行:")
print(df_demo.loc[df_demo["A"] > 2])
print()

# 选择 A 列大于 2 的行的 B 列
print("选择 A 列大于 2 的行的 B 列:")
df_demo.loc[df_demo["A"] > 2, "B"]
复制代码
选择 A 列大于 2 的行:
   A   B    C
c  3  30  300
d  4  40  400
e  5  50  500

选择 A 列大于 2 的行的 B 列:





c    30
d    40
e    50
Name: B, dtype: int64

3.5 索引管理

索引管理
set_index

设置索引
reset_index

重置索引
rename

重命名
单列索引
多级索引
保留原索引
删除原索引
修改行索引名
修改列名

python 复制代码
df_base = pd.DataFrame({
    "工号": ["E001", "E002", "E003", "E004", "E005"],
    "姓名": ["张伟", "李娜", "王强", "刘洋", "陈静"],
    "部门": ["技术部", "销售部", "技术部", "人事部", "财务部"],
    "薪资": [12000, 15000, 18000, 8000, 9000]
})
print("原始数据(默认整数索引):")
df_base
复制代码
原始数据(默认整数索引):

| | 工号 | 姓名 | 部门 | 薪资 |
| 0 | E001 | 张伟 | 技术部 | 12000 |
| 1 | E002 | 李娜 | 销售部 | 15000 |
| 2 | E003 | 王强 | 技术部 | 18000 |
| 3 | E004 | 刘洋 | 人事部 | 8000 |

4 E005 陈静 财务部 9000

3.5.1 设置索引

python 复制代码
# 使用 set_index() 设置索引
df_set_idx = df_base.set_index("工号")
print("设置工号为索引后:")
df_set_idx
复制代码
设置工号为索引后:

| | 姓名 | 部门 | 薪资 |
| 工号 | | | |
| E001 | 张伟 | 技术部 | 12000 |
| E002 | 李娜 | 销售部 | 15000 |
| E003 | 王强 | 技术部 | 18000 |
| E004 | 刘洋 | 人事部 | 8000 |

E005 陈静 财务部 9000
python 复制代码
# 设置多级索引
df_multi = df_base.set_index(["部门", "工号"])
print("设置部门和工号为多级索引:")
df_multi
复制代码
设置部门和工号为多级索引:

| | | 姓名 | 薪资 |
| 部门 | 工号 | | |
| 技术部 | E001 | 张伟 | 12000 |
| 销售部 | E002 | 李娜 | 15000 |
| 技术部 | E003 | 王强 | 18000 |
| 人事部 | E004 | 刘洋 | 8000 |

财务部 E005 陈静 9000

3.5.2 重置索引

python 复制代码
# 使用 reset_index() 重置索引
df_reset = df_set_idx.reset_index()
print("重置索引后(工号变回列):")
df_reset
复制代码
重置索引后(工号变回列):

| | 工号 | 姓名 | 部门 | 薪资 |
| 0 | E001 | 张伟 | 技术部 | 12000 |
| 1 | E002 | 李娜 | 销售部 | 15000 |
| 2 | E003 | 王强 | 技术部 | 18000 |
| 3 | E004 | 刘洋 | 人事部 | 8000 |

4 E005 陈静 财务部 9000
python 复制代码
# 重置索引并删除原索引
df_reset_drop = df_set_idx.reset_index(drop=True)
print("重置索引并删除(恢复默认整数索引):")
df_reset_drop
复制代码
重置索引并删除(恢复默认整数索引):

| | 姓名 | 部门 | 薪资 |
| 0 | 张伟 | 技术部 | 12000 |
| 1 | 李娜 | 销售部 | 15000 |
| 2 | 王强 | 技术部 | 18000 |
| 3 | 刘洋 | 人事部 | 8000 |

4 陈静 财务部 9000

3.5.3 修改索引名称

python 复制代码
df_rename = df_set_idx.copy()

# 修改索引名称
df_rename.index.name = "员工编号"
print(f"索引名称: {df_rename.index.name}")

# 修改列名
df_rename.columns = ["员工姓名", "所属部门", "月薪"]
print("\n修改列名后:")
df_rename.head(3)
复制代码
索引名称: 员工编号

修改列名后:

| | 员工姓名 | 所属部门 | 月薪 |
| 员工编号 | | | |
| E001 | 张伟 | 技术部 | 12000 |
| E002 | 李娜 | 销售部 | 15000 |

E003 王强 技术部 18000
python 复制代码
# 使用 rename() 修改特定行/列名
df_renamed = df_rename.rename(
    index={"E001": "E001-主管"},
    columns={"月薪": "基本薪资"}
)
print("修改特定名称后:")
df_renamed.head(3)
复制代码
修改特定名称后:

| | 员工姓名 | 所属部门 | 基本薪资 |
| 员工编号 | | | |
| E001-主管 | 张伟 | 技术部 | 12000 |
| E002 | 李娜 | 销售部 | 15000 |

E003 王强 技术部 18000

3.6 条件筛选与过滤

条件筛选运算符

运算符 含义
& 与(and)
` `
~ 非(not)
isin() 在列表中
between() 在范围内

条件筛选
单条件
多条件
特殊方法
df列大于值
AND与
OR或
NOT非
isin
between
query

python 复制代码
# 创建员工数据
df_employees = pd.DataFrame({
    "姓名": ["张伟", "李娜", "王强", "刘洋", "陈静", "赵敏", "周杰", "吴刚"],
    "部门": ["技术部", "销售部", "技术部", "人事部", "财务部", "技术部", "销售部", "人事部"],
    "职位": ["工程师", "销售经理", "高级工程师", "HR专员", "会计", "工程师", "销售代表", "HR经理"],
    "薪资": [12000, 15000, 18000, 8000, 9000, 13000, 11000, 10000],
    "工龄": [2, 3, 1, 4, 2, 3, 2, 5],
    "绩效评分": [4.5, 4.8, 4.9, 4.2, 4.0, 4.6, 4.3, 4.7]
})
df_employees

| | 姓名 | 部门 | 职位 | 薪资 | 工龄 | 绩效评分 |
| 0 | 张伟 | 技术部 | 工程师 | 12000 | 2 | 4.5 |
| 1 | 李娜 | 销售部 | 销售经理 | 15000 | 3 | 4.8 |
| 2 | 王强 | 技术部 | 高级工程师 | 18000 | 1 | 4.9 |
| 3 | 刘洋 | 人事部 | HR专员 | 8000 | 4 | 4.2 |
| 4 | 陈静 | 财务部 | 会计 | 9000 | 2 | 4.0 |
| 5 | 赵敏 | 技术部 | 工程师 | 13000 | 3 | 4.6 |
| 6 | 周杰 | 销售部 | 销售代表 | 11000 | 2 | 4.3 |

7 吴刚 人事部 HR经理 10000 5 4.7

3.6.1 单条件筛选

python 复制代码
# 薪资大于 12000 的员工
print("薪资大于 12000 的员工:")
high_salary = df_employees[df_employees["薪资"] > 12000]
high_salary[["姓名", "部门", "薪资"]]
复制代码
薪资大于 12000 的员工:

| | 姓名 | 部门 | 薪资 |
| 1 | 李娜 | 销售部 | 15000 |
| 2 | 王强 | 技术部 | 18000 |

5 赵敏 技术部 13000
python 复制代码
# 技术部的员工
print("技术部的员工:")
tech_dept = df_employees[df_employees["部门"] == "技术部"]
tech_dept[["姓名", "职位", "薪资"]]
复制代码
技术部的员工:

| | 姓名 | 职位 | 薪资 |
| 0 | 张伟 | 工程师 | 12000 |
| 2 | 王强 | 高级工程师 | 18000 |

5 赵敏 工程师 13000

3.6.2 多条件筛选

python 复制代码
# 技术部且薪资大于 13000 的员工(与 &)
print("技术部且薪资大于 13000 的员工:")
result = df_employees[(df_employees["部门"] == "技术部") & (df_employees["薪资"] > 13000)]
result[["姓名", "部门", "薪资"]]
复制代码
技术部且薪资大于 13000 的员工:

| | 姓名 | 部门 | 薪资 |

2 王强 技术部 18000
python 复制代码
# 销售部或绩效评分 >= 4.8 的员工(或 |)
print("销售部或绩效评分 >= 4.8 的员工:")
result2 = df_employees[(df_employees["部门"] == "销售部") | (df_employees["绩效评分"] >= 4.8)]
result2[["姓名", "部门", "绩效评分"]]
复制代码
销售部或绩效评分 >= 4.8 的员工:

| | 姓名 | 部门 | 绩效评分 |
| 1 | 李娜 | 销售部 | 4.8 |
| 2 | 王强 | 技术部 | 4.9 |

6 周杰 销售部 4.3
python 复制代码
# 非技术部的员工(非 ~)
print("非技术部的员工:")
non_tech = df_employees[~(df_employees["部门"] == "技术部")]
non_tech[["姓名", "部门"]]
复制代码
非技术部的员工:

| | 姓名 | 部门 |
| 1 | 李娜 | 销售部 |
| 3 | 刘洋 | 人事部 |
| 4 | 陈静 | 财务部 |
| 6 | 周杰 | 销售部 |

7 吴刚 人事部

3.6.3 使用 isin 和 between

python 复制代码
# 使用 isin() 筛选
print("部门为技术部或销售部的员工:")
selected = df_employees[df_employees["部门"].isin(["技术部", "销售部"])]
selected[["姓名", "部门"]]
复制代码
部门为技术部或销售部的员工:

| | 姓名 | 部门 |
| 0 | 张伟 | 技术部 |
| 1 | 李娜 | 销售部 |
| 2 | 王强 | 技术部 |
| 5 | 赵敏 | 技术部 |

6 周杰 销售部
python 复制代码
# 使用 between() 筛选
print("薪资在 10000 到 15000 之间的员工:")
middle_salary = df_employees[df_employees["薪资"].between(10000, 15000)]
middle_salary[["姓名", "薪资"]]
复制代码
薪资在 10000 到 15000 之间的员工:

| | 姓名 | 薪资 |
| 0 | 张伟 | 12000 |
| 1 | 李娜 | 15000 |
| 5 | 赵敏 | 13000 |
| 6 | 周杰 | 11000 |

7 吴刚 10000

3.6.4 使用 query() 方法

python 复制代码
# 使用 query() 进行筛选
print("薪资大于 12000 且绩效 >= 4.5:")
query_result = df_employees.query("薪资 > 12000 and 绩效评分 >= 4.5")
query_result[["姓名", "薪资", "绩效评分"]]
复制代码
薪资大于 12000 且绩效 >= 4.5:

| | 姓名 | 薪资 | 绩效评分 |
| 1 | 李娜 | 15000 | 4.8 |
| 2 | 王强 | 18000 | 4.9 |

5 赵敏 13000 4.6
python 复制代码
# 使用变量查询
min_salary = 12000
query_result2 = df_employees.query("薪资 > @min_salary")  # @符号引用外部变量
print(f"薪资大于 {min_salary} 的员工:")
query_result2[["姓名", "薪资"]]
复制代码
薪资大于 12000 的员工:

| | 姓名 | 薪资 |
| 1 | 李娜 | 15000 |
| 2 | 王强 | 18000 |

5 赵敏 13000

3.7 apply 和 applymap 数据转换

数据转换方法对比

方法 作用 适用对象
apply() 按行/列应用函数 DataFrame/Series
applymap() 逐元素应用函数 DataFrame
map() 值映射 Series

数据转换
apply

按行/列
applymap

逐元素
map

Series映射
axis=0

按列
axis=1

按行

3.7.1 apply 方法(按行或按列应用函数)

python 复制代码
df_apply = df_employees.copy()

# 对列应用函数(默认 axis=0)
print("计算每列的数值范围(max-min):")
range_result = df_apply[["薪资", "工龄", "绩效评分"]].apply(lambda x: x.max() - x.min())
range_result
复制代码
计算每列的数值范围(max-min):





薪资      10000.0
工龄          4.0
绩效评分        0.9
dtype: float64
python 复制代码
# 对行应用函数(axis=1)
print("计算每个员工的综合得分(薪资/1000 + 工龄 + 绩效*10):")
df_apply["综合得分"] = df_apply.apply(
    lambda row: row["薪资"] / 1000 + row["工龄"] + row["绩效评分"] * 10,
    axis=1
).round(2)
df_apply[["姓名", "薪资", "工龄", "绩效评分", "综合得分"]]
复制代码
计算每个员工的综合得分(薪资/1000 + 工龄 + 绩效*10):

| | 姓名 | 薪资 | 工龄 | 绩效评分 | 综合得分 |
| 0 | 张伟 | 12000 | 2 | 4.5 | 59.0 |
| 1 | 李娜 | 15000 | 3 | 4.8 | 66.0 |
| 2 | 王强 | 18000 | 1 | 4.9 | 68.0 |
| 3 | 刘洋 | 8000 | 4 | 4.2 | 54.0 |
| 4 | 陈静 | 9000 | 2 | 4.0 | 51.0 |
| 5 | 赵敏 | 13000 | 3 | 4.6 | 62.0 |
| 6 | 周杰 | 11000 | 2 | 4.3 | 56.0 |

7 吴刚 10000 5 4.7 62.0

3.7.2 applymap 方法(逐元素应用函数)

python 复制代码
# 对 DataFrame 所有元素应用函数
df_numeric = df_demo.copy()
print("原始数据:")
print(df_numeric)

print("\n所有元素格式化(保留1位小数):")
# Pandas 3.0+ 使用 map 替代 applymap
formatted = df_numeric.map(lambda x: f"{x:.1f}")
formatted
复制代码
原始数据:
   A   B    C
a  1  10  100
b  2  20  200
c  3  30  300
d  4  40  400
e  5  50  500

所有元素格式化(保留1位小数):

| | A | B | C |
| a | 1.0 | 10.0 | 100.0 |
| b | 2.0 | 20.0 | 200.0 |
| c | 3.0 | 30.0 | 300.0 |
| d | 4.0 | 40.0 | 400.0 |

e 5.0 50.0 500.0

3.7.3 map 方法(Series 专用)

python 复制代码
# 使用 map 进行值映射
print("部门名称映射为英文:")
dept_map = {"技术部": "Tech", "销售部": "Sales", "人事部": "HR", "财务部": "Finance"}
df_apply["部门英文"] = df_apply["部门"].map(dept_map)
df_apply[["姓名", "部门", "部门英文"]]
复制代码
部门名称映射为英文:

| | 姓名 | 部门 | 部门英文 |
| 0 | 张伟 | 技术部 | Tech |
| 1 | 李娜 | 销售部 | Sales |
| 2 | 王强 | 技术部 | Tech |
| 3 | 刘洋 | 人事部 | HR |
| 4 | 陈静 | 财务部 | Finance |
| 5 | 赵敏 | 技术部 | Tech |
| 6 | 周杰 | 销售部 | Sales |

7 吴刚 人事部 HR
python 复制代码
# 使用 map 进行条件映射
print("根据薪资分级:")
df_apply["薪资等级"] = df_apply["薪资"].map(
    lambda x: "高" if x >= 15000 else "中" if x >= 10000 else "低"
)
df_apply[["姓名", "薪资", "薪资等级"]]
复制代码
根据薪资分级:

| | 姓名 | 薪资 | 薪资等级 |
| 0 | 张伟 | 12000 | 中 |
| 1 | 李娜 | 15000 | 高 |
| 2 | 王强 | 18000 | 高 |
| 3 | 刘洋 | 8000 | 低 |
| 4 | 陈静 | 9000 | 低 |
| 5 | 赵敏 | 13000 | 中 |
| 6 | 周杰 | 11000 | 中 |

7 吴刚 10000

3.8 实战案例:员工绩效管理系统

场景描述

你是一家公司的 HR 经理,需要管理员工的绩效数据。你需要完成以下任务:

  1. 创建完整的员工绩效数据表
  2. 计算绩效奖金(基于绩效评分和项目数)
  3. 筛选高绩效员工(用于年终评优)
  4. 按部门统计绩效情况
  5. 生成员工绩效报告

员工绩效管理
创建数据
计算奖金
筛选员工
部门统计
绩效评级
生成报告

步骤1:创建员工绩效数据表

python 复制代码
# 创建员工绩效数据
hr_df = pd.DataFrame({
    "工号": ["E001", "E002", "E003", "E004", "E005", "E006", "E007", "E008", "E009", "E010"],
    "姓名": ["张伟", "李娜", "王强", "刘洋", "陈静", "赵敏", "周杰", "吴刚", "郑华", "孙丽"],
    "部门": ["技术部", "销售部", "技术部", "人事部", "财务部", "技术部", "销售部", "人事部", "技术部", "销售部"],
    "职位": ["工程师", "销售经理", "高级工程师", "HR专员", "会计", "工程师", "销售代表", "HR经理", "架构师", "销售总监"],
    "基本工资": [12000, 15000, 18000, 8000, 9000, 13000, 11000, 10000, 20000, 22000],
    "项目数": [3, 5, 4, 2, 3, 4, 6, 3, 5, 7],
    "绩效评分": [4.5, 4.8, 4.9, 4.2, 4.0, 4.6, 4.3, 4.7, 4.8, 4.9],
    "客户满意度": [88, 92, 95, 85, 82, 90, 87, 91, 94, 96]
})

print("员工绩效数据表:")
hr_df
复制代码
员工绩效数据表:

| | 工号 | 姓名 | 部门 | 职位 | 基本工资 | 项目数 | 绩效评分 | 客户满意度 |
| 0 | E001 | 张伟 | 技术部 | 工程师 | 12000 | 3 | 4.5 | 88 |
| 1 | E002 | 李娜 | 销售部 | 销售经理 | 15000 | 5 | 4.8 | 92 |
| 2 | E003 | 王强 | 技术部 | 高级工程师 | 18000 | 4 | 4.9 | 95 |
| 3 | E004 | 刘洋 | 人事部 | HR专员 | 8000 | 2 | 4.2 | 85 |
| 4 | E005 | 陈静 | 财务部 | 会计 | 9000 | 3 | 4.0 | 82 |
| 5 | E006 | 赵敏 | 技术部 | 工程师 | 13000 | 4 | 4.6 | 90 |
| 6 | E007 | 周杰 | 销售部 | 销售代表 | 11000 | 6 | 4.3 | 87 |
| 7 | E008 | 吴刚 | 人事部 | HR经理 | 10000 | 3 | 4.7 | 91 |
| 8 | E009 | 郑华 | 技术部 | 架构师 | 20000 | 5 | 4.8 | 94 |

9 E010 孙丽 销售部 销售总监 22000 7 4.9 96

步骤2:计算绩效奖金

绩效奖金计算规则

  • 基础奖金 = 基本工资 * 0.1
  • 绩效系数 = 绩效评分 / 5.0
  • 项目奖金 = 项目数 * 500
  • 总奖金 = (基础奖金 * 绩效系数) + 项目奖金
python 复制代码
hr_df["基础奖金"] = hr_df["基本工资"] * 0.1
hr_df["绩效系数"] = hr_df["绩效评分"] / 5.0
hr_df["项目奖金"] = hr_df["项目数"] * 500
hr_df["绩效奖金"] = (hr_df["基础奖金"] * hr_df["绩效系数"] + hr_df["项目奖金"]).round(2)
hr_df["总薪资"] = hr_df["基本工资"] + hr_df["绩效奖金"]

print("绩效奖金计算结果(前5行):")
hr_df[["姓名", "基本工资", "绩效评分", "项目数", "绩效奖金", "总薪资"]].head()
复制代码
绩效奖金计算结果(前5行):

| | 姓名 | 基本工资 | 绩效评分 | 项目数 | 绩效奖金 | 总薪资 |
| 0 | 张伟 | 12000 | 4.5 | 3 | 2580.0 | 14580.0 |
| 1 | 李娜 | 15000 | 4.8 | 5 | 3940.0 | 18940.0 |
| 2 | 王强 | 18000 | 4.9 | 4 | 3764.0 | 21764.0 |
| 3 | 刘洋 | 8000 | 4.2 | 2 | 1672.0 | 9672.0 |

4 陈静 9000 4.0 3 2220.0 11220.0

步骤3:筛选高绩效员工(年终评优候选人)

python 复制代码
# 定义高绩效标准:绩效评分 >= 4.7 且 客户满意度 >= 90
high_performers = hr_df[(hr_df["绩效评分"] >= 4.7) & (hr_df["客户满意度"] >= 90)]
high_performers = high_performers.sort_values("绩效评分", ascending=False)

print("高绩效员工名单(绩效评分 >= 4.7 且 客户满意度 >= 90):")
print(high_performers[["姓名", "部门", "职位", "绩效评分", "客户满意度", "绩效奖金"]])
print(f"\n共 {len(high_performers)} 人获得年终评优资格")
复制代码
高绩效员工名单(绩效评分 >= 4.7 且 客户满意度 >= 90):
   姓名   部门     职位  绩效评分  客户满意度    绩效奖金
2  王强  技术部  高级工程师   4.9     95  3764.0
9  孙丽  销售部   销售总监   4.9     96  5656.0
1  李娜  销售部   销售经理   4.8     92  3940.0
8  郑华  技术部    架构师   4.8     94  4420.0
7  吴刚  人事部   HR经理   4.7     91  2440.0

共 5 人获得年终评优资格

步骤4:部门绩效统计

python 复制代码
dept_stats = hr_df.groupby("部门").agg({
    "绩效评分": ["mean", "max", "min"],
    "客户满意度": "mean",
    "项目数": "sum",
    "绩效奖金": "mean",
    "姓名": "count"
}).round(2)

# 简化列名
dept_stats.columns = ["平均绩效", "最高绩效", "最低绩效", "平均满意度", "总项目数", "平均奖金", "人数"]

print("部门绩效统计:")
dept_stats
复制代码
部门绩效统计:

| | 平均绩效 | 最高绩效 | 最低绩效 | 平均满意度 | 总项目数 | 平均奖金 | 人数 |
| 部门 | | | | | | | |
| 人事部 | 4.45 | 4.7 | 4.2 | 88.00 | 5 | 2056.0 | 2 |
| 技术部 | 4.70 | 4.9 | 4.5 | 91.75 | 16 | 3490.0 | 4 |
| 财务部 | 4.00 | 4.0 | 4.0 | 82.00 | 3 | 2220.0 | 1 |

销售部 4.67 4.9 4.3 91.67 18 4514.0 3

步骤5:生成员工绩效评级

绩效评级规则

  • A级:绩效评分 >= 4.8 且 客户满意度 >= 95
  • B级:绩效评分 >= 4.5 且 客户满意度 >= 88
  • C级:绩效评分 >= 4.0 且 客户满意度 >= 85
  • D级:其他
python 复制代码
def get_performance_level(row):
    score = row["绩效评分"]
    satisfaction = row["客户满意度"]
    
    if score >= 4.8 and satisfaction >= 95:
        return "A级-卓越"
    elif score >= 4.5 and satisfaction >= 88:
        return "B级-优秀"
    elif score >= 4.0 and satisfaction >= 85:
        return "C级-良好"
    else:
        return "D级-待改进"

hr_df["绩效评级"] = hr_df.apply(get_performance_level, axis=1)

print("员工绩效评级分布:")
print(hr_df["绩效评级"].value_counts())

print("\n各评级员工名单:")
for level in ["A级-卓越", "B级-优秀", "C级-良好", "D级-待改进"]:
    employees = hr_df[hr_df["绩效评级"] == level]["姓名"].tolist()
    if employees:
        print(f"  {level}: {', '.join(employees)}")
复制代码
员工绩效评级分布:
绩效评级
B级-优秀     5
A级-卓越     2
C级-良好     2
D级-待改进    1
Name: count, dtype: int64

各评级员工名单:
  A级-卓越: 王强, 孙丽
  B级-优秀: 张伟, 李娜, 赵敏, 吴刚, 郑华
  C级-良好: 刘洋, 周杰
  D级-待改进: 陈静

步骤6:生成综合报告

python 复制代码
report_data = {
    "员工总数": len(hr_df),
    "平均绩效评分": hr_df["绩效评分"].mean(),
    "最高绩效评分": hr_df["绩效评分"].max(),
    "平均客户满意度": hr_df["客户满意度"].mean(),
    "总项目数": hr_df["项目数"].sum(),
    "总绩效奖金": hr_df["绩效奖金"].sum(),
    "平均绩效奖金": hr_df["绩效奖金"].mean(),
    "A级员工数": len(hr_df[hr_df["绩效评级"] == "A级-卓越"]),
    "B级员工数": len(hr_df[hr_df["绩效评级"] == "B级-优秀"]),
    "最佳部门": dept_stats["平均绩效"].idxmax()
}

print(f"""
┌─────────────────────────────────────────┐
│      2026年度员工绩效综合报告            │
├─────────────────────────────────────────┤
│  员工总数:        {report_data['员工总数']:>6} 人              │
│  平均绩效评分:    {report_data['平均绩效评分']:>6.2f} 分            │
│  最高绩效评分:    {report_data['最高绩效评分']:>6.2f} 分            │
│  平均客户满意度:  {report_data['平均客户满意度']:>6.1f} %            │
│  总项目数:        {report_data['总项目数']:>6} 个              │
│  总绩效奖金:      {report_data['总绩效奖金']:>10.2f} 元        │
│  平均绩效奖金:    {report_data['平均绩效奖金']:>10.2f} 元        │
│  A级员工数:       {report_data['A级员工数']:>6} 人              │
│  B级员工数:       {report_data['B级员工数']:>6} 人              │
│  最佳绩效部门:    {report_data['最佳部门']:>10}          │
└─────────────────────────────────────────┘
""")
复制代码
┌─────────────────────────────────────────┐
│      2026年度员工绩效综合报告            │
├─────────────────────────────────────────┤
│  员工总数:            10 人              │
│  平均绩效评分:      4.57 分            │
│  最高绩效评分:      4.90 分            │
│  平均客户满意度:    90.0 %            │
│  总项目数:            42 个              │
│  总绩效奖金:        33834.00 元        │
│  平均绩效奖金:       3383.40 元        │
│  A级员工数:            2 人              │
│  B级员工数:            5 人              │
│  最佳绩效部门:           技术部          │
└─────────────────────────────────────────┘

本章小结

学习内容回顾

1. DataFrame 结构

  • 由多个 Series 组成,共享同一个行索引
  • 基本属性:shape, index, columns, dtypes, values

2. 列操作

  • 选择列:df['col']df[['col1', 'col2']]
  • 添加列:直接赋值、assign() 方法
  • 修改列:直接赋值、apply() 方法
  • 删除列:del, pop(), drop()

3. 行操作

  • 选择行:loc[label], iloc[pos]
  • 添加行:loc[new_label] = values, concat()
  • 修改行:loc[label] = values
  • 删除行:drop(index=[...])

4. loc 和 iloc

  • loc:标签索引,左闭右闭
  • iloc:位置索引,左闭右开
  • 布尔索引:df[df['col'] > value]

5. 索引管理

  • 设置索引:set_index()
  • 重置索引:reset_index()
  • 修改名称:index.name, columns, rename()

6. 条件筛选

  • 单条件:df[df['col'] > value]
  • 多条件:& (与), | (或), ~ (非)
  • 特殊方法:isin(), between(), query()

7. 数据转换

  • apply():按行/列应用函数
  • applymap():逐元素应用函数
  • map():Series 值映射

下章预告

第四章:数据读取与保存

将学习多种数据格式的读写操作,包括:

  • CSV 文件读写
  • Excel 文件读写
  • JSON 数据读写
  • SQL 数据库读写

课后练习

练习1:创建一个包含学生信息的 DataFrame(姓名、班级、语文、数学、英语成绩),然后:

  • 添加"总分"和"平均分"列
  • 筛选出平均分 >= 90 的优秀学生
  • 按班级统计平均分

练习2:基于上面的员工数据 hr_df,完成以下操作:

  • 将工号设置为索引
  • 使用 loc 查询 E003 和 E007 的信息
  • 使用 iloc 查询第 3-5 行的姓名和薪资列
  • 删除"基础奖金"和"绩效系数"列

练习3:使用 query() 方法查询:

  • 技术部且绩效评分 >= 4.5 的员工
  • 销售部或财务部且薪资 > 10000 的员工

练习4 :创建一个销售数据 DataFrame,包含产品、地区、销售额,

然后使用 apply 计算每个地区的销售占比。

相关推荐
zml.~2 小时前
Spark 数据分析:从核心原理到企业级实战全解析
大数据·数据挖掘·数据分析·spark
zml.~2 小时前
大数据分析实战:基于 Spark 的新能源汽车全链路数据分析指南
大数据·数据分析·spark·汽车
yuanmazhiwu3 小时前
计算机毕业设计:Python全国空气质量与气象监测平台 Flask框架 可视化 数据分析 机器学习 天气 深度学习 AI 空气质量分析(建议收藏)✅
人工智能·python·深度学习·数据挖掘·flask·汽车·课程设计
不会唱歌的拖拉机13 小时前
使用Pandas进行RFM分析全过程
数据分析·pandas
麦客奥德彪14 小时前
客户端 Trace Benchmark 体系设计
ios·数据分析
rainy雨16 小时前
免费且好用的精益工具在哪里?2026年精益工具清单整理
大数据·人工智能·信息可视化·数据挖掘·数据分析·精益工程
2501_9216494916 小时前
原油期货量化策略开发:历史 K 线获取、RSI、MACD 布林带计算到多指标共振策略回测
后端·python·金融·数据分析·restful
苹果二16 小时前
工业软件快问快答
人工智能·数据分析·mbse·系统工程·工业软件
wayz1119 小时前
数据分析中的异常值处理:MAD
算法·数据挖掘·数据分析