Pandas教程
# 🧭 学习路线图
我们将分为几个阶段来学习 pandas:
- 入门:了解数据结构
- 数据读取与写入
- 数据选取与过滤
- 数据清洗与预处理
- 数据聚合与分组
- 数据合并与连接
- 时间序列处理(可选)
- 可视化(可选)
# ✅ 第一阶段:了解 Pandas 的两大数据结构
Pandas 最核心的两个数据结构是:
Series
: 一维数据(类似列表)DataFrame
: 二维表格(类似 Excel 表格或数据库)
# 📌 1.1 导入 Pandas
import pandas as pd
# 📌 1.2 Series(一维数据)
import pandas as pd
data = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
print(data)
2
3
4
输出:
a 10
b 20
c 30
d 40
dtype: int64
2
3
4
5
你可以像操作字典一样访问它:
print(data['b']) # 输出 20
# 📌 1.3 DataFrame(二维表格)
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Charlie'],
'age': [25, 30, 35],
'city': ['Beijing', 'Shanghai', 'Guangzhou']
}
df = pd.DataFrame(data)
print(df)
2
3
4
5
6
7
8
9
输出:
name age city
0 Alice 25 Beijing
1 Bob 30 Shanghai
2 Charlie 35 Guangzhou
2
3
4
你可以访问行、列或单个元素:
print(df['name']) # 输出 name 列
print(df.loc[1]) # 按标签访问第2行(索引为1)
print(df.iloc[0, 2]) # 按位置访问第1行第3列
2
3
# ✅ 第二阶段:数据读取与写入(CSV、Excel、JSON)
Pandas 支持多种格式的数据读取和写出,最常见的是:
.csv
:逗号分隔文本(最常用).xlsx
:Excel 文件.json
:JSON 文件
# 📌 2.1 读取 CSV 文件
假设你有一个叫 data.csv
的文件内容如下:
name,age,city
Alice,25,Beijing
Bob,30,Shanghai
Charlie,35,Guangzhou
2
3
4
使用 Pandas 读取它:
import pandas as pd
df = pd.read_csv('data.csv')
print(df)
2
3
4
输出:
name age city
0 Alice 25 Beijing
1 Bob 30 Shanghai
2 Charlie 35 Guangzhou
2
3
4
# 📌 2.2 写出 CSV 文件
你可以把 DataFrame 写回文件:
df.to_csv('output.csv', index=False) # index=False 表示不写行索引
# 📌 2.3 读取 Excel 文件
如果你有一个 data.xlsx
:
df = pd.read_excel('data.xlsx')
print(df)
2
📌 注意:你可能需要安装
openpyxl
:pip install openpyxl
1
# 📌 2.4 写出 Excel 文件
df.to_excel('output.xlsx', index=False)
# 📌 2.5 读取 JSON 文件
假设你有一个 data.json
:
[
{"name": "Alice", "age": 25, "city": "Beijing"},
{"name": "Bob", "age": 30, "city": "Shanghai"}
]
2
3
4
读取方式:
df = pd.read_json('data.json')
print(df)
2
# 🎯 总结
格式 | 读取函数 | 写出函数 |
---|---|---|
CSV | pd.read_csv() | df.to_csv() |
Excel | pd.read_excel() | df.to_excel() |
JSON | pd.read_json() | df.to_json() |
# ✅ 第三阶段:数据的选择与过滤
这一阶段我们重点掌握:
- 选取列(列筛选)
- 选取行(按索引或条件)
- 按条件过滤数据
- 使用
loc
和iloc
精确定位数据
数据的选择与过滤代码例子,每个详解可以先看下方,然后逐步看这个代码:
import pandas as pd
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie', 'David'],
'age': [25, 30, 35, 28],
'city': ['Beijing', 'Shanghai', 'Guangzhou', 'Beijing']
})
# 选取一列
print("选取一列:")
print(type(df['name']))
print(df['name'])
# 选取多列
print("\n选取多列:")
print(type(df[['name', 'city']]))
print(df[['name', 'city']])
# 使用 `iloc`(按位置)选取行
print("\n使用 `iloc` 选取行:")
print(type(df.iloc[0]))
print(df.iloc[0]) # 选取第一行
print(type(df.iloc[0:2])) # 选取前两行
print(df.iloc[0:2]) # 选取前两行
# 使用 `loc`(按标签)选取行
print("\n使用 `loc` 选取行:")
print("设置1个列索引:")
df_t = df.set_index('name') # 将 'name' 列设置为索引
print(type(df_t.loc['Alice'])) # 选取标签为 'Alice' 的行
print(df_t.loc['Alice'])
print("设置2个列索引:")
df_t2 = df.set_index(['name', 'city'])
print(type(df_t2.loc[('Alice', 'Beijing')])) # 选取标签为 ('Alice', 'Beijing') 的行
print(df_t2.loc[('Alice', 'Beijing')])
# 使用条件筛选
print("\n使用条件筛选:")
print(type(df[df['age'] > 30])) # 筛选年龄大于30的行
print(df[df['age'] > 30])
print(type(df[df['city'] == 'Beijing'])) # 筛选城市为 'Beijing' 的行
print(df[df['city'] == 'Beijing'])
print("\n使用条件筛选(多条件):")
# 与操作(同时满足)
print(df[(df['age'] > 25) & (df['city'] == 'Beijing')])
# 或操作(满足其一)
print("\n或操作(满足其一):")
print(df[(df['age'] > 30) | (df['city'] == 'Shanghai')])
print("\n条件赋值:")
# 添加新列:是否超过30岁
df['is_old'] = df['age'] > 30
print(df)
# 删除列
print("\n删除列:")
df.drop(columns=['is_old'], inplace=True)
print(df)
# 更改某些值
print("\n更改某些值:")
df.loc[df['age'] > 30, 'city'] = 'SeniorCity'
print(df)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 🔹 3.1 选取列(Column Selection)
选取一列:
df['name']
'''
<class 'pandas.core.series.Series'>
0 Alice
1 Bob
2 Charlie
3 David
Name: name, dtype: object
'''
2
3
4
5
6
7
8
9
选取多列(放在列表中):
df[['name', 'city']]
'''
<class 'pandas.core.frame.DataFrame'>
name city
0 Alice Beijing
1 Bob Shanghai
2 Charlie Guangzhou
3 David Beijing
'''
2
3
4
5
6
7
8
9
# 🔹 3.2 选取行(Row Selection)
默认 DataFrame 是以数字作为索引(0, 1, 2...)
# 使用 iloc
(按位置)
df.iloc[0] # 第一行
df.iloc[0:2] # 第1到第2行(不包括第3行)
'''
<class 'pandas.core.series.Series'>
name Alice
age 25
city Beijing
Name: 0, dtype: object
<class 'pandas.core.frame.DataFrame'>
name age city
0 Alice 25 Beijing
1 Bob 30 Shanghai
'''
2
3
4
5
6
7
8
9
10
11
12
13
14
# 使用 loc
(按标签)
如果你自己设置了索引(比如用姓名作为索引):
df = df.set_index('name')
df.loc['Alice'] # 按标签选行
'''
<class 'pandas.core.series.Series'>
age 25
city Beijing
Name: Alice, dtype: object
'''
2
3
4
5
6
7
8
设置两个索引:
df = df.set_index(['name', 'city'])
print(type(df_t2.loc[('Alice', 'Beijing')])) # 选取标签为 ('Alice', 'Beijing') 的行
print(df_t2.loc[('Alice', 'Beijing')])
'''
<class 'pandas.core.series.Series'>
age 25
Name: (Alice, Beijing), dtype: int64
'''
2
3
4
5
6
7
8
# 🔹 3.3 条件过滤(Boolean Indexing)
# 筛选年龄大于30的人
df[df['age'] > 30]
'''
<class 'pandas.core.frame.DataFrame'>
name age city
2 Charlie 35 Guangzhou
'''
# 筛选城市是 Beijing 的人
df[df['city'] == 'Beijing']
'''
<class 'pandas.core.frame.DataFrame'>
name age city
0 Alice 25 Beijing
3 David 28 Beijing
'''
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
组合多个条件:
# 与操作(同时满足)
df[(df['age'] > 25) & (df['city'] == 'Beijing')]
'''
name age city
3 David 28 Beijing
'''
# 或操作(满足其一)
df[(df['age'] > 30) | (df['city'] == 'Shanghai')]
'''
name age city
1 Bob 30 Shanghai
2 Charlie 35 Guangzhou
'''
2
3
4
5
6
7
8
9
10
11
12
13
14
注意:逻辑运算符要用
&
(与) 和|
(或),每个条件都要用括号括起来。
# 🔹 3.4 条件赋值
# 添加新列:是否超过30岁,is_old变量名起的好像不太好,就这样吧。。。
df['is_old'] = df['age'] > 30
'''
name age city is_old
0 Alice 25 Beijing False
1 Bob 30 Shanghai False
2 Charlie 35 Guangzhou True
3 David 28 Beijing False
'''
# 删除列
df.drop(columns=['is_old'], inplace=True)
'''
name age city
0 Alice 25 Beijing
1 Bob 30 Shanghai
2 Charlie 35 Guangzhou
3 David 28 Beijing
'''
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
也可以直接更改某些值:
df.loc[df['age'] > 30, 'city'] = 'SeniorCity'
'''
name age city
0 Alice 25 Beijing
1 Bob 30 Shanghai
2 Charlie 35 SeniorCity
3 David 28 Beijing
'''
2
3
4
5
6
7
8
# 🔹 3.5 索引
# 🧠 什么是索引(Index)?
在 pandas 中,索引是用于标识数据标签的机制。它可以是数字、字符串,甚至多个列组成的多重索引(MultiIndex)。
import pandas as pd
df = pd.DataFrame({
'name': ['Alice', 'Alice', 'Bob'],
'city': ['Beijing', 'Shanghai', 'Shanghai'],
'score': [85, 90, 88]
})
print(df) # 默认是 RangeIndex
'''
name city score
0 Alice Beijing 85
1 Alice Shanghai 90
2 Bob Shanghai 88
'''
2
3
4
5
6
7
8
9
10
11
12
13
14
# 🔹 1. 单列索引(单层索引)
# 设置索引
df = df.set_index('name')
'''
city score
name
Alice Beijing 85
Alice Shanghai 90
Bob Shanghai 88
'''
2
3
4
5
6
7
8
这将 name
列作为索引,原来的行号就被替代了。
# 访问元素
df.loc['Alice']
# 🔹 2. 多列索引(多层索引 / MultiIndex)
# 设置多列为索引
df = pd.DataFrame({
'name': ['Alice', 'Alice', 'Bob'],
'city': ['Beijing', 'Shanghai', 'Shanghai'],
'score': [85, 90, 88]
})
df_multi = df.set_index(['name', 'city'])
2
3
4
5
6
此时索引是 (name, city)
的多层结构:
score
name city
Alice Beijing 85
Shanghai 90
Bob Shanghai 88
2
3
4
5
# 访问多层索引的数据
df_multi.loc[('Alice', 'Beijing')]
# 🔹 3. loc
和 iloc
的区别
方法 | 依据 | 示例 |
---|---|---|
.loc | 按“标签”查找 | df.loc['Alice'] |
.iloc | 按“位置”查找 | df.iloc[0] |
# 🔹 4. 恢复索引(reset_index
)
将索引还原为列:
df_reset = df_multi.reset_index()
# 🔹 5. 设置索引时的参数
df.set_index('col_name', inplace=True, drop=False)
参数 | 作用 |
---|---|
inplace | 是否就地修改(默认 False) |
drop | 是否从列中删除索引列(默认 True) |
# 🔹 6. 索引对象的属性和操作
df.index # 查看索引
df.index.name # 获取索引名称
df.index.names # 获取多层索引的所有名称
df.index.is_unique # 是否唯一
df.index.tolist() # 转为列表
2
3
4
5
# 🔹 7. 索引的常见用途
- 快速查找数据(相比遍历效率高)
- 数据对齐(merge、join、concat)
- 分组聚合(groupby)
- 分层结构(多维数据)
# ✅ 小结
操作 | 方法 |
---|---|
选列 | df['列名'] 或 df[['列1', '列2']] |
选行(按位置) | df.iloc[行号] |
选行(按标签) | df.loc[标签] |
条件筛选 | df[df['列'] > 某值] |
多条件筛选 | (条件1) & (条件2) |
条件修改 | df.loc[条件, '列'] = 新值 |
# ✅ 第四阶段:数据清洗与预处理
这一阶段你将学到:
- 缺失值(NaN)的处理
- 重命名列名或索引
- 删除重复数据
- 数据类型转换
- 修改列顺序、重设索引
# 🔹 4.1 缺失值处理(NaN
)
# 创建一个有缺失值的 DataFrame:
import pandas as pd
import numpy as np
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie', None],
'age': [25, None, 35, 40],
'city': ['Beijing', 'Shanghai', None, 'Guangzhou']
})
print(df)
2
3
4
5
6
7
8
9
# 查找缺失值
df.isnull() # 查看哪些位置是缺失的
df.isnull().sum() # 每列缺失值数量
2
# 删除缺失值
df.dropna() # 删除含有缺失值的行
df.dropna(axis=1) # 删除含有缺失值的列
2
# 填充缺失值
df = df.fillna(0) # 所有缺失值填 0
df['age'] = df['age'].fillna(df['age'].mean()) # 填平均值
df['name'] = df['name'].fillna('Unknown') # 填字符串
2
3
# 🔹 4.2 重命名列名或索引
df.rename(columns={'name': 'Name', 'age': 'Age'})
df.rename(index={0: 'first', 1: 'second'})
2
也可以一次性改全部列名:
df.columns = ['Name', 'Age', 'City']
# 🔹 4.3 删除重复数据
df = pd.DataFrame({
'name': ['A', 'B', 'A', 'C'],
'score': [90, 85, 90, 78]
})
df.duplicated() # 查看哪些是重复行
df.drop_duplicates() # 删除重复行
2
3
4
5
6
7
# 🔹 4.4 数据类型转换
df['age'] = df['age'].astype(int) # 转整数(前提是不能有NaN)
df['age'] = pd.to_numeric(df['age'], errors='coerce') # 自动转失败的填NaN
2
日期转换:
df['date'] = pd.to_datetime(df['date'])
# 🔹 4.5 重设索引、修改列顺序
重设索引:
df.reset_index(drop=True, inplace=True)
修改列顺序:
df = df[['city', 'name', 'age']] # 指定你想要的顺序
# ✅ 小结表格
任务 | 方法 |
---|---|
查找缺失值 | df.isnull() |
删除缺失值 | df.dropna() |
填补缺失值 | df.fillna(value) |
重命名列名 | df.rename(columns={}) |
删除重复行 | df.drop_duplicates() |
类型转换 | df['col'].astype(type) |
转日期格式 | pd.to_datetime(df['col']) |
重设索引 | df.reset_index() |
# 🧪 练习
import pandas as pd
import numpy as np
data = {
'name': ['A', 'B', 'C', None],
'score': [90, np.nan, 75, 88],
'date': ['2024-01-01', '2024-01-02', None, '2024-01-04']
}
df = pd.DataFrame(data)
# 1. 查看缺失
print(df.isnull().sum())
# 2. 用平均分填补缺失分数
df['score'] = df['score'].fillna(df['score'].mean())
# 3. 将日期列转为 datetime 类型
df['date'] = pd.to_datetime(df['date'])
# 4. 填补缺失的名字
df['name'] = df['name'].fillna('Unknown')
print(df)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
很好,我们现在进入 Pandas 的 第五阶段:数据分组与聚合(GroupBy),这是进行统计分析和数据总结时非常强大的工具。
# ✅ 第五阶段:数据分组与聚合(GroupBy)
这一阶段将讲解:
- 如何按列分组(groupby)
- 如何聚合(sum、mean、count 等)
- 多层分组与聚合
- 自定义聚合函数
# 🔹 5.1 基本分组与聚合
import pandas as pd
df = pd.DataFrame({
'department': ['HR', 'HR', 'IT', 'IT', 'Sales', 'Sales'],
'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva', 'Frank'],
'salary': [5000, 5200, 6000, 6200, 4000, 4200]
})
# 按部门求平均薪资
df.groupby('department')['salary'].mean()
2
3
4
5
6
7
8
9
10
输出:
department
HR 5100.0
IT 6100.0
Sales 4100.0
Name: salary, dtype: float64
2
3
4
5
# 🔹 5.2 多列聚合
df.groupby('department')[['salary']].agg(['mean', 'max', 'min'])
输出:
salary
mean max min
department
HR 5100 5200 5000
IT 6100 6200 6000
Sales 4100 4200 4000
2
3
4
5
6
# 🔹 5.3 多列分组
df = pd.DataFrame({
'department': ['HR', 'HR', 'IT', 'IT', 'Sales', 'Sales'],
'gender': ['F', 'M', 'M', 'M', 'F', 'M'],
'salary': [5000, 5200, 6000, 6200, 4000, 4200]
})
# 按部门和性别分组
df.groupby(['department', 'gender'])['salary'].mean()
2
3
4
5
6
7
8
输出:
department gender
HR F 5000.0
M 5200.0
IT M 6100.0
Sales F 4000.0
M 4200.0
Name: salary, dtype: float64
2
3
4
5
6
7
# 🔹 5.4 使用 agg()
自定义多个聚合操作
# 多列多个聚合函数
df.groupby('department').agg({
'salary': ['mean', 'std'],
'gender': 'count'
})
2
3
4
5
输出:
salary gender
mean std count
department
HR 5100.0 141.421356 2
IT 6100.0 141.421356 2
Sales 4100.0 141.421356 2
2
3
4
5
6
# 🔹 5.5 重置索引与排序
GroupBy 会默认以分组列作为索引,可以重置:
grouped = df.groupby('department')['salary'].mean().reset_index()
排序:
grouped.sort_values(by='salary', ascending=False)
# ✅ 小结表格
操作 | 示例 |
---|---|
单列分组 | df.groupby('col') |
聚合函数 | .mean() , .sum() , .count() , .max() |
多列聚合 | .agg({'col1': 'mean', 'col2': 'count'}) |
多重分组 | df.groupby(['col1', 'col2']) |
重置索引 | .reset_index() |
排序 | .sort_values(by='col') |
# 🧪 练习
df = pd.DataFrame({
'city': ['Beijing', 'Beijing', 'Shanghai', 'Shanghai', 'Beijing'],
'store': ['A', 'B', 'A', 'B', 'A'],
'sales': [100, 150, 200, 250, 120]
})
# 每个城市的平均销售额
print(df.groupby('city')['sales'].mean())
# 每个城市、每个店的总销售额
print(df.groupby(['city', 'store'])['sales'].sum().reset_index())
2
3
4
5
6
7
8
9
10
11
# ✅ 第六阶段:数据合并与连接
现在进入 第六阶段:数据合并与连接(Merge / Join / Concat),这是处理多张表时的核心技能,功能和 SQL 里的 JOIN
很相似。
下面将学到以下几种表格合并方式:
concat()
:上下/左右拼接merge()
:根据某列进行关联合并(类似 SQL 中的 JOIN)join()
:使用索引连接
# 🔹 6.1 使用 concat()
拼接数据
# 👉 按行拼接(纵向合并)
import pandas as pd
df1 = pd.DataFrame({
'name': ['Alice', 'Bob'],
'age': [25, 30]
})
df2 = pd.DataFrame({
'name': ['Charlie', 'David'],
'age': [35, 40]
})
result = pd.concat([df1, df2], ignore_index=True)
print(result)
2
3
4
5
6
7
8
9
10
11
12
13
14
输出:
name age
0 Alice 25
1 Bob 30
2 Charlie 35
3 David 40
2
3
4
5
# 👉 按列拼接(横向合并)
df3 = pd.DataFrame({
'city': ['Beijing', 'Shanghai']
})
result = pd.concat([df1, df3], axis=1)
print(result)
2
3
4
5
6
输出:
name age city
0 Alice 25 Beijing
1 Bob 30 Shanghai
2
3
# 🔹 6.2 使用 merge()
进行关联合并(推荐)
这是最常用的合并方式,和 SQL 的 JOIN 一样强大。
df_left = pd.DataFrame({
'employee': ['Alice', 'Bob', 'Charlie'],
'dept_id': [1, 2, 3]
})
df_right = pd.DataFrame({
'dept_id': [1, 2],
'dept_name': ['HR', 'IT']
})
# 默认是 inner join(只保留匹配的)
merged = pd.merge(df_left, df_right, on='dept_id')
print(merged)
2
3
4
5
6
7
8
9
10
11
12
13
输出:
employee dept_id dept_name
0 Alice 1 HR
1 Bob 2 IT
2
3
# 设置连接方式:how
参数
参数 | 含义 |
---|---|
'inner' | 默认,交集 |
'left' | 左连接 |
'right' | 右连接 |
'outer' | 并集,NaN 补全 |
pd.merge(df_left, df_right, on='dept_id', how='outer')
# 🔹 6.3 使用 join()
(按索引连接)
df1 = pd.DataFrame({'salary': [5000, 6000]}, index=['Alice', 'Bob'])
df2 = pd.DataFrame({'age': [25, 30]}, index=['Alice', 'Bob'])
joined = df1.join(df2)
print(joined)
2
3
4
5
输出:
salary age
Alice 5000 25
Bob 6000 30
2
3
# ✅ 小结对比表格
方法 | 用途 | 默认连接方式 | 支持 on 关键字? |
---|---|---|---|
concat() | 拼接多个 DataFrame | 无 | ❌ |
merge() | 类似 SQL join | inner | ✅ |
join() | 按索引连接 | left | ❌ |
# 🧪 练习
df_emp = pd.DataFrame({
'name': ['A', 'B', 'C'],
'dept_id': [1, 2, 3]
})
df_dept = pd.DataFrame({
'dept_id': [1, 2],
'dept_name': ['HR', 'Sales']
})
# 左连接(保留所有员工)
merged = pd.merge(df_emp, df_dept, on='dept_id', how='left')
print(merged)
2
3
4
5
6
7
8
9
10
11
12
13
# ✅ 第七阶段:时间序列处理(Datetime & Resampling)
将学会到:
- 将日期列转换为 datetime 类型
- 设置时间为索引
- 按日期筛选、分组
- 重新采样(如按月、按日汇总)
- 滚动窗口计算(移动平均)
# 🔹 7.1 将字符串转换为 datetime 类型
import pandas as pd
df = pd.DataFrame({
'date': ['2024-01-01', '2024-01-02', '2024-01-03'],
'value': [100, 120, 130]
})
df['date'] = pd.to_datetime(df['date'])
print(df.dtypes)
print(df)
2
3
4
5
6
7
8
9
10
输出:
date datetime64[ns]
value int64
dtype: object
date value
0 2024-01-01 100
1 2024-01-02 120
2 2024-01-03 130
2
3
4
5
6
7
# 🔹 7.2 设置时间列为索引
df = df.set_index('date')
print(df)
2
输出:
value
date
2024-01-01 100
2024-01-02 120
2024-01-03 130
2
3
4
5
这样就可以使用很多时间相关的操作了。
# 🔹 7.3 按时间筛选数据
# 取2024年1月之后的数据
df['2024-01-02':]
2
# 🔹 7.4 重采样(Resampling)
Resample 可以将数据按天、月、季度等频率进行汇总。
# 构造示例数据
df = pd.DataFrame({
'date': pd.date_range(start='2024-01-01', periods=10, freq='D'),
'sales': [100, 120, 110, 130, 150, 140, 160, 170, 180, 200]
})
df.set_index('date', inplace=True)
# 按周求和
weekly = df.resample('W').sum()
print(weekly)
2
3
4
5
6
7
8
9
10
常用频率:
代码 | 含义 |
---|---|
'D' | 每天 |
'W' | 每周 |
'M' | 每月 |
'Q' | 每季度 |
'A' | 每年 |
# 🔹 7.5 滚动窗口(Rolling)
用于计算移动平均等。
# 3天移动平均
df['rolling_mean'] = df['sales'].rolling(window=3).mean()
print(df)
2
3
# 🔹 7.6 提取年/月/日等时间字段
df['year'] = df.index.year
df['month'] = df.index.month
df['day'] = df.index.day
2
3
# 🧪 练习
import pandas as pd
df = pd.DataFrame({
'date': pd.date_range('2024-01-01', periods=12, freq='D'),
'temperature': [22, 23, 21, 24, 25, 26, 24, 23, 22, 21, 20, 19]
})
df.set_index('date', inplace=True)
# 1. 每周平均温度
print(df.resample('W').mean())
# 2. 3天滑动平均
df['avg_3d'] = df['temperature'].rolling(3).mean()
print(df)
2
3
4
5
6
7
8
9
10
11
12
13
14
# ✅ 小结表格
操作 | 方法 |
---|---|
转换为 datetime | pd.to_datetime() |
设置时间索引 | df.set_index('date') |
按时间筛选 | df['2024-01':'2024-03'] |
重采样 | df.resample('M').sum() |
滚动平均 | df.rolling(3).mean() |
# ✅ 第八阶段:Pandas 可视化(基于 Matplotlib)
Pandas 自带可视化功能,底层基于 Matplotlib。常见图表有:
- 折线图(line plot)
- 条形图(bar plot)
- 直方图(histogram)
- 箱线图(box plot)
- 散点图(scatter plot)
# 🔹 8.1 准备工作:导入绘图库
import pandas as pd
import matplotlib.pyplot as plt
# 使图像在 Jupyter/脚本中显示
plt.rcParams['font.family'] = 'Arial' # 避免中文乱码时可改为 'SimHei'
2
3
4
5
# 🔹 8.2 折线图(line plot)——默认图
适合:时间序列趋势、连续值变化
df = pd.DataFrame({
'day': ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
'sales': [100, 120, 90, 130, 150]
})
df.plot(x='day', y='sales', kind='line', marker='o')
plt.title('Daily Sales Trend')
plt.ylabel('Sales')
plt.grid(True)
plt.show()
2
3
4
5
6
7
8
9
# 🔹 8.3 条形图(bar plot)
适合:类别型数据的对比
df.plot(x='day', y='sales', kind='bar', color='skyblue')
plt.title('Sales by Day')
plt.ylabel('Sales')
plt.xticks(rotation=0)
plt.show()
2
3
4
5
# 🔹 8.4 直方图(histogram)
适合:数据分布(如成绩分布)
df = pd.DataFrame({'score': [60, 65, 70, 72, 75, 80, 82, 85, 90, 92, 95, 100]})
df.plot(kind='hist', bins=5, rwidth=0.9)
plt.title('Score Distribution')
plt.xlabel('Score')
plt.show()
2
3
4
5
# 🔹 8.5 箱线图(box plot)
适合:看中位数、异常值、四分位数
df = pd.DataFrame({
'Math': [80, 82, 90, 95, 100],
'English': [70, 75, 85, 90, 92]
})
df.plot(kind='box')
plt.title('Score Boxplot')
plt.show()
2
3
4
5
6
7
# 🔹 8.6 散点图(scatter plot)
适合:看变量之间是否相关
df = pd.DataFrame({
'hours_studied': [1, 2, 3, 4, 5, 6],
'score': [50, 60, 65, 70, 85, 90]
})
df.plot(kind='scatter', x='hours_studied', y='score')
plt.title('Study Time vs Score')
plt.xlabel('Hours Studied')
plt.ylabel('Score')
plt.grid(True)
plt.show()
2
3
4
5
6
7
8
9
10
11
# ✅ 小结表格
图表类型 | kind 类型 | 适用场景 |
---|---|---|
折线图 | 'line' | 趋势变化(如时间序列) |
条形图 | 'bar' | 类别比较(如每天销售) |
直方图 | 'hist' | 分布频率 |
箱线图 | 'box' | 看异常值、中位数等 |
散点图 | 'scatter' | 两个变量关系 |
# 🧪 练习
df = pd.DataFrame({
'day': ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
'sales': [100, 120, 90, 130, 150],
'visitors': [300, 400, 350, 500, 550]
})
# 1. 折线图:每天销售趋势
df.plot(x='day', y='sales', kind='line', marker='o')
plt.title('Daily Sales')
plt.show()
# 2. 散点图:访问人数 vs 销售额
df.plot(kind='scatter', x='visitors', y='sales')
plt.title('Visitors vs Sales')
plt.show()
2
3
4
5
6
7
8
9
10
11
12
13
14
15