1. 认识 Pandas #
- 本章介绍 Pandas 的定位,并带你跑通第一个表格数据处理示例。
- 学完你会知道 Pandas 解决什么问题,以及它和 Excel、NumPy 的关系。
1.1 Pandas 是什么? #
- Pandas 是 Python 最流行的表格型数据分析库,名字来自 Panel Data(面板数据)。
- 核心数据结构是 Series(一维,像一列)和 DataFrame(二维,像 Excel 表)。
- 底层基于 NumPy,读写 CSV/Excel/JSON,做清洗、筛选、统计、分组都很快。
- 数据科学、运营分析、报表自动化项目几乎都会用到。
1.2 为什么需要 Pandas? #
- Python 原生列表不适合表达「行 + 列 + 列名」的表格结构。
- Pandas 一行代码完成:读文件、筛数据、按组统计、导出结果。
- 和 Excel 比:适合大批量、可重复、可编程;和 SQL 比:适合探索分析和脚本化任务。
- 学会 Pandas 是学 pandas 生态(Matplotlib、scikit-learn)的基础。
1.3 第一个 Pandas 示例 #
- 习惯写法:
import pandas as pd。
- 用字典创建 DataFrame,再算一列的平均值。
import pandas as pd
df = pd.DataFrame({
'姓名': ['小明', '小红', '小刚'],
'数学': [85, 92, 78],
'英语': [90, 88, 95]
})
print(df)
print("数学平均分:", df['数学'].mean())
2. 前置知识 #
- 本章补充学习 Pandas 前需要知道的概念。
- 建议先学过 NumPy 基础。
2.1 表格数据是什么? #
- 行(row):一条记录,如一个学生的信息。
- 列(column):一个字段,如「姓名」「成绩」。
- 索引(index):行的标签,默认 0、1、2…,也可自定义。
- DataFrame 就是「带列名和行索引的二维表」。
2.2 NumPy 与缺失值 NaN #
- Pandas 底层用 NumPy 存数值,很多运算返回 NumPy 数组。
- 缺失值用 NaN(Not a Number)表示,来自
numpy.nan。
NaN 参与运算结果仍是 NaN,清洗数据时要专门处理。
import numpy as np
import pandas as pd
print("NaN:", np.nan)
s = pd.Series([1, 2, np.nan, 4])
print(s.isna())
3. 安装与环境 #
- 本章完成 Pandas 安装与验证。
- 读 Excel 需额外安装
openpyxl。
3.1 安装 Pandas #
- Pandas 不是标准库,需 pip 安装。
- 依赖 NumPy,安装时会自动带上。
pip install pandas
pip install openpyxl
python -c "import pandas as pd; print(pd.__version__)"
3.2 导入方式 #
- 社区约定:
import pandas as pd。
- 数值计算常配合
import numpy as np。
import pandas as pd
import numpy as np
print("Pandas 版本:", pd.__version__)
4. Series 入门 #
- Series 是带标签的一维数组,可看作 DataFrame 的「一列」。
- 掌握 Series 有助于理解列运算和索引。
4.1 创建 Series #
pd.Series(数据, index=标签) 创建。
- 不写
index 时,默认 0、1、2…
import pandas as pd
scores = pd.Series([88, 92, 85, 96])
print(scores)
named = pd.Series([88, 92, 85], index=['张三', '李四', '王五'])
print(named)
4.2 索引与常用统计 #
- 用标签或位置取元素:
s['张三']、s.iloc[0]。
- 列运算常用:
mean、sum、max、describe。
import pandas as pd
sales = pd.Series([1200, 1500, 1800, 2100], index=['Q1', 'Q2', 'Q3', 'Q4'])
print("Q2:", sales['Q2'])
print("总和:", sales.sum())
print("均值:", sales.mean())
print(sales.describe())
- 25%:第一四分位数(Q1),又称 下四分位数。表示有 25% 的数据小于或等于这个值,75% 的数据大于它。
- 50%:第二四分位数(Q2),也就是 中位数(Median)。表示有 50% 的数据小于或等于它,另外 50% 大于它。它比均值更能抵抗极端值的影响。
- 75%:第三四分位数(Q3),又称 上四分位数。表示有 75% 的数据小于或等于这个值,25% 的数据大于它。
5. DataFrame 入门 #
- DataFrame 是 Pandas 的核心,整张表都是 DataFrame。
- 每一列是一个 Series,列名就是字段名。
5.1 创建 DataFrame #
- 最常用:字典,键为列名,值为列表。
- 也可用列表的列表、字典列表等方式。
import pandas as pd
df = pd.DataFrame({
'产品': ['手机', '电脑', '平板'],
'销量': [120, 85, 150],
'单价': [2999, 5999, 2499]
})
print(df)
5.2 查看数据概况 #
head() 看前几行,tail() 看后几行。
info() 看列类型和缺失情况,describe() 看数值列统计。
shape 返回 (行数, 列数)。
import pandas as pd
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [20, 21, 19, 22],
'成绩': [85.5, 92.0, 78.5, 88.0]
})
print("head:\n", df.head(2))
print("shape:", df.shape)
print("info:")
df.info()
print("describe:\n", df.describe())
5.3 选取列与单列运算 #
df['列名'] 取一列,得到 Series。
df[['列A','列B']] 取多列,仍是 DataFrame。
- 可对列直接做运算,如
df['销量'] * df['单价']。
import pandas as pd
df = pd.DataFrame({
'产品': ['手机', '电脑', '平板'],
'销量': [120, 85, 150],
'单价': [2999, 5999, 2499]
})
print("销量列:\n", df['销量'])
df['销售额'] = df['销量'] * df['单价']
print(df)
6. 选取行:loc 与 iloc #
- loc:按标签索引,
df.loc[行, 列]。
- iloc:按整数位置索引,从 0 开始,
df.iloc[行, 列]。
- 记住:loc 用名字,iloc 用数字。
6.1 loc 按标签选取 #
df.loc[0] 取第 0 行(标签为 0 时)。
df.loc[0, '姓名'] 取单个单元格。
- 切片
df.loc[1:2, '姓名':'成绩'] 含结束标签。
import pandas as pd
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五'],
'年龄': [20, 21, 19],
'成绩': [85.5, 92.0, 78.5]
})
print("第 2 行:\n", df.loc[1])
print("单元格:", df.loc[0, '姓名'])
print("子表:\n", df.loc[0:1, ['姓名', '成绩']])
loc 是 基于标签的索引(label-based indexing)。它按照 DataFrame 的行索引(index)和列索引(columns)的标签值来选取数据。
- 在你的 DataFrame 中,由于创建时没有指定
index 参数,Pandas 会默认使用从 0 开始的整数作为行标签:[0, 1, 2]。
- 因此,
df.loc[1] 中的 1 被解释为 行标签为 1 的那一行(即“李四”所在的行),而不是第 2 行的“位置”。
6.2 iloc 按位置选取 #
iloc 只用整数位置,切片不含结束位置(和 NumPy 一样)。
df.iloc[:, 0] 取第 1 列;df.iloc[1:3, :] 取第 2~3 行。
import pandas as pd
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [20, 21, 19, 22],
'成绩': [85.5, 92.0, 78.5, 88.0]
})
print("iloc 第 2 行:\n", df.iloc[1])
print("行切片:\n", df.iloc[1:3])
print("列切片:\n", df.iloc[:, 1:3])
6.3 布尔条件筛选 #
df[df['成绩'] > 85] 筛选满足条件的行。
- 多条件:
(df['A'] > 1) & (df['B'] < 10),用 &、|,条件加括号。
import pandas as pd
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六'],
'成绩': [85.5, 92.0, 78.5, 88.0],
'城市': ['北京', '上海', '广州', '深圳']
})
high = df[df['成绩'] > 85]
print(high)
filtered = df[(df['成绩'] >= 85) & (df['城市'] != '上海')]
print(filtered)
7. 增删改 #
- 日常分析常要新增计算列、改个别值、删无用列。
- 多数操作返回新对象;加
inplace=True 可原地修改。
7.1 新增与修改列 #
df['新列'] = ... 直接赋值即可新增列。
- 修改:
df.loc[条件, '列'] = 值。
import pandas as pd
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五'],
'成绩': [85, 92, 78]
})
df['等级'] = ['良好', '优秀', '及格']
df.loc[df['成绩'] < 80, '等级'] = '待提升'
print(df)
7.2 删除行与列 #
drop(columns=['列名']) 删列;drop(index=[0,1]) 删行。
- 默认
inplace=False,返回新 DataFrame。
import pandas as pd
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五'],
'年龄': [20, 21, 19],
'备注': ['', '班长', '']
})
df2 = df.drop(columns=['备注'])
df3 = df2.drop(index=[0])
print(df3)
8. 读写 CSV #
- CSV 是项目中最常见的数据交换格式。
read_csv 读入,to_csv 写出;中文建议 encoding='utf-8-sig'。
8.1 写入与读取 CSV #
- 写出时
index=False 不把行索引写入文件。
- 读取后得到 DataFrame,可直接分析。
import pandas as pd
df = pd.DataFrame({
'城市': ['北京', '上海', '广州'],
'人口': [2154, 2487, 1868],
'GDP': [36102, 38701, 25019]
})
df.to_csv('城市数据.csv', index=False, encoding='utf-8-sig')
loaded = pd.read_csv('城市数据.csv', encoding='utf-8-sig')
print(loaded)
8.2 常用 read_csv 参数 #
usecols:只读指定列,大文件省内存。
na_values:把特定字符串当成缺失值。
nrows:只读前 N 行,快速预览大文件。
import pandas as pd
df = pd.read_csv(
'城市数据.csv',
encoding='utf-8-sig',
usecols=['城市', '人口'],
na_values=['--']
)
print(df)
print("列名:", df.columns.tolist())
9. Excel 与 JSON #
- Excel 适合和同事交换报表;JSON 适合 API 和配置文件。
- 二者用法与 CSV 类似,掌握一种即可类推。
9.1 读写 Excel #
- 读:
pd.read_excel('文件.xlsx', sheet_name='表名')。
- 写:
df.to_excel('文件.xlsx', index=False)。
- 需安装:
pip install openpyxl。
import pandas as pd
df = pd.DataFrame({
'产品': ['手机', '电脑'],
'销量': [120, 85]
})
df.to_excel('销量.xlsx', index=False, sheet_name='Q1')
loaded = pd.read_excel('销量.xlsx', sheet_name='Q1')
print(loaded)
9.2 读写 JSON #
- API 返回的 JSON 数组常用
orient='records'。
- 写出时用
orient='records' + force_ascii=False 保留中文。
- 从字符串读取时,新版 Pandas 会把多行文本当成文件路径,需用
StringIO 包装。
import pandas as pd
from io import StringIO
json_str = '''
[
{"姓名": "张三", "年龄": 20, "城市": "北京"},
{"姓名": "李四", "年龄": 21, "城市": "上海"}
]
'''
df = pd.read_json(StringIO(json_str), orient='records')
print(df)
df.to_json('用户.json', orient='records', force_ascii=False, indent=2)
10. 数据清洗 #
- 真实数据常有缺失、重复、格式混乱。
- 清洗是分析前最关键的一步。
10.1 缺失值处理 #
isna() / isnull() 检测缺失;sum() 统计每列缺失个数。
dropna() 删除含缺失的行/列;fillna(值) 填充。
import pandas as pd
import numpy as np
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六'],
'数学': [85, np.nan, 92, 78],
'英语': [90, 88, np.nan, 95]
})
print("缺失统计:\n", df.isna().sum())
df['数学'] = df['数学'].fillna(df['数学'].mean())
df['英语'] = df['英语'].fillna(df['英语'].mean())
print(df)
10.2 重复值处理 #
duplicated() 标记重复行;drop_duplicates() 去重。
- 可指定
subset=['列名'] 按某几列判断重复。
import pandas as pd
df = pd.DataFrame({
'订单号': ['A001', 'A002', 'A001', 'A003'],
'客户': ['张三', '李四', '张三', '王五'],
'金额': [100, 200, 100, 150]
})
df_unique = df.drop_duplicates()
print(df_unique)
10.3 类型与日期转换 #
astype() 转换列类型。
pd.to_datetime() 把字符串列转为日期类型。
- 日期字符串格式不统一(如
- 和 / 混用)时,加 format='mixed' 逐条识别。
import pandas as pd
df = pd.DataFrame({
'日期': ['2024-01-15', '2024/02/20', '2024-03-10'],
'销售额': ['1200', '1500', '1800']
})
df['销售额'] = df['销售额'].astype(int)
df['日期'] = pd.to_datetime(df['日期'], format='mixed')
print(df.dtypes)
print(df)
11. 排序与分组聚合 #
- 排序:找 Top N、按时间排列。
- 分组:按部门、品类等汇总统计,项目极高频。
11.1 排序 sort_values #
sort_values(by='列名', ascending=False) 降序排列。
- 多列排序:
by=['列1','列2']。
import pandas as pd
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六'],
'数学': [85, 92, 78, 96],
'英语': [90, 87, 95, 82]
})
sorted_df = df.sort_values(by='数学', ascending=False)
print(sorted_df)
11.2 分组 groupby #
df.groupby('列名')['数值列'].mean() 按组求均值。
- 常用聚合:
sum、mean、count、max、min。
- 多列聚合:
.agg({'销售额':'sum', '订单数':'count'})。
import pandas as pd
df = pd.DataFrame({
'地区': ['华东', '华南', '华东', '华南', '华北'],
'产品': ['A', 'B', 'A', 'B', 'A'],
'销售额': [1000, 1500, 1200, 1800, 900]
})
by_region = df.groupby('地区')['销售额'].sum()
print("各地区销售额:\n", by_region)
by_two = df.groupby(['地区', '产品'])['销售额'].sum()
print("\n地区-产品销售额:\n", by_two)
12. 合并表格 #
- 多张表合并是报表、宽表建设的常见需求。
concat 纵向/横向拼接;merge 按关键字段关联(类似 SQL JOIN)。
12.1 concat 拼接 #
pd.concat([df1, df2], ignore_index=True) 纵向堆叠。
axis=1 横向拼列(列数要对齐或接受 NaN)。
import pandas as pd
df1 = pd.DataFrame({'姓名': ['张三', '李四'], '年龄': [20, 21]})
df2 = pd.DataFrame({'姓名': ['王五', '赵六'], '年龄': [19, 22]})
merged = pd.concat([df1, df2], ignore_index=True)
print(merged)
12.2 merge 关联 #
pd.merge(左表, 右表, on='关键列', how='inner')。
how:inner 交集、left 保留左表、outer 并集。
import pandas as pd
orders = pd.DataFrame({
'订单号': ['O1', 'O2', 'O3'],
'客户ID': ['C1', 'C2', 'C1'],
'金额': [100, 200, 150]
})
customers = pd.DataFrame({
'客户ID': ['C1', 'C2', 'C4'],
'客户名': ['张三', '李四', '王五']
})
result = pd.merge(orders, customers, on='客户ID', how='inner')
print(result)