查看全课大纲(第 40 / 101 节)
- 1.数据分析基本概念
- 2.学习数据分析的一般路线
- 3.数据分析的流程
- 4.数据类型
- 5.环境部署(1)
- 6.环境部署(2)
- 7.课程介绍
- 8.TXT文件操作
- 9.JSON文件操作
- 10.CSV文件操作
- 11.Excel文件操作
- 12.数据库及SQL常用语法
- 13.数据库基本操作
- 14.数据库多表连接
- 15.实战:欧洲职业足球数据库分析
- 16.爬虫简介
- 17.URL管理模块
- 18.网页下载模块
- 19.网页解析模块(1)
- 20.网页解析模块(2)
- 21.Scrapy简介
- 22.Scrapy使用步骤(1)
- 23.Scrapy使用步骤(2)
- 24.Scrapy使用步骤(3)
- 25.Scrapy使用步骤(4)
- 26.实战:获取国内城市空气质量指数数据
- 27.NumPy和SciPy介绍
- 28.多维数组
- 29.多维数组操作
- 30.NumPy的常用方法
- 31.向量化介绍
- 32.向量化及通用函数
- 33.实战:2016美国大选分析
- 34.数据结构-Series
- 35.数据结构-DataFrame
- 36.数据结构-Index
- 37.Series的索引操作
- 38.DataFrame的索引操作
- 39.索引操作总结
- 40.运算与对齐
- 41.函数应用操作(1) -- map
- 42.函数应用操作 (2) -- apply applymap
- 43.文件读写操作
- 44.排序操作
- 45.数据清洗--处理缺失数据
- 46.数据清洗--处理重复数据
- 47.数据清洗--替换数据
- 48.常用统计方法(1) -- describe quantile
- 49.常用统计方法(2) -- sum mean median count
- 50.常用统计方法(3) -- max min idxmax idxmin
- 51.常用统计方法(4) -- mad var std cumsum
- 52.实战:全球食品数据分析
- 53.层级索引
- 54.分组与聚合介绍
- 55.分组操作(1) -- GroupBy对象及常用聚合操作
- 56.分组操作(2) -- 自定义分组及聚合操作
- 57.透视表介绍
- 58.透视表操作
- 59.数据规整(1) -- 数据合并concat
- 60.数据规整(2) -- 数据连接merge
- 61.数据重构(3) -- 数据重构stack unstack
- 62.实战:互联网电影资料库分析
- 63.探索性数据分析EDA介绍
- 64.EDA的目的
- 65.EDA常用工具
- 66.Matplotlib绘图基本介绍
- 67.Matplotlib画布
- 68.散点图和柱状图的绘制
- 69.直方图的绘制
- 70.矩阵绘图
- 71.子图的使用
- 72.Matplotlib颜色、标记、线型
- 73.Matplotlib坐标刻度、标签、图例、标题
- 74.Seaborn介绍
- 75.数据集分布可视化(1) -- 单变量分布、双变量分布
- 76.数据集分布可视化(2) -- 变量关系可视化
- 77.类别数据可视化 -- 类别散布图、类别内数据分布、类别内统计图
- 78.交互式数据可视化工具Bokeh介绍
- 79.Bokeh绘制散点图、柱状图、盒子图、弦图
- 80.Bokeh绘制常用图形元素
- 81.3D绘图 -- mplot3d
- 82.3D曲线可视化
- 83.3D散点图可视化
- 84.3D柱状图可视化
- 85.Pandas绘图
- 86.实战:Lending Club借贷数据探索性分析及可视化
- 87.机器学习介绍及应用场景
- 88.机器学习建模介绍 (1) -- 分类
- 89.机器学习建模介绍 (2) -- 回归
- 90.机器学习建模介绍 (3) -- 聚类
- 91.机器学习分类
- 92.机器学习工具scikit-learn
- 93.使用scikit-learn的流程
- 94.数据集准备及划分
- 95.模型选择
- 96.数据预处理及特征工程
- 97.过拟合与欠拟合
- 98.模型调参介绍
- 99.模型调参方法
- 100.模型测试及评价
- 101.实战:通过移动设备行为数据预测性别和年龄
运算与对齐
约 11 分钟
小象实战讲义 · Python数据分析实战
在数据分析中,我们经常需要对不同来源、不同结构的数据进行合并与计算。Pandas 的强大之处在于,它能够智能地处理这些操作,而“对齐”正是其核心机制。本节我们将深入探讨 Pandas 中 Series 和 DataFrame 进行算术运算时,索引是如何决定计算结果的,以及如何处理未对齐的数据。
💡 核心导读
- 索引是运算的“导航图”:Pandas 的运算不是基于数据的位置,而是基于索引标签的匹配。
- Series 间的对齐:发生在索引上,相同索引的值进行计算,未对齐的位置补
NaN。 - DataFrame 间的对齐:同时发生在行索引和列索引两个维度上。
- Series 与 DataFrame 的混合运算:规则特殊,Series 的索引会被视为列,与 DataFrame 的列进行匹配计算。
理解索引对齐机制
Pandas 的设计哲学是“带标签的数据计算”。这意味着,当对两个 Pandas 对象进行运算时,Pandas 不会简单地将第一个对象的第一行与第二个对象的第一行相加,而是会去寻找两个对象中索引标签相同的位置,并对这些位置上的值进行计算。
如果某个索引标签只存在于一个对象中,而在另一个对象中找不到对应的标签,那么该位置在计算结果中将被填充为 NaN(Not a Number,表示缺失值)。这种自动对齐的特性,使得我们可以安全地对不同形状、不同来源的数据进行运算,而无需手动对齐。
Series 间的运算与对齐
我们通过一个具体的例子来理解 Series 间的对齐。假设有两个 Series:
import pandas as pd
import numpy as np
# 创建 Series 1: 索引 0-9,值 10-19
ser1 = pd.Series(range(10, 20), index=range(10))
print("Series 1:")
print(ser1)
print()
# 创建 Series 2: 索引 0-4,值 20-24
ser2 = pd.Series(range(20, 25), index=range(5))
print("Series 2:")
print(ser2)
print()
# Series 间的加法运算
result = ser1 + ser2
print("ser1 + ser2 的结果:")
print(result)Series 1:
0 10
1 11
2 12
3 13
4 14
5 15
6 16
7 17
8 18
9 19
dtype: int64
Series 2:
0 20
1 21
2 22
3 23
4 24
dtype: int64
ser1 + ser2 的结果:
0 30.0
1 32.0
2 34.0
3 36.0
4 38.0
5 NaN
6 NaN
7 NaN
8 NaN
9 NaN
dtype: float64运算过程解析:
- 对齐:Pandas 首先找到两个 Series 共有的索引标签:
0, 1, 2, 3, 4。 - 计算:对共有索引位置的值进行相加:
10+20=30,11+21=32, …,14+24=38。 - 处理未对齐项:
ser1中索引5到9在ser2中找不到对应项。因此,结果中索引5到9的位置被填充为NaN。 - 数据类型:由于引入了
NaN(在 Pandas 中属于浮点类型),整个结果 Series 的数据类型从int64自动提升为float64。
这个例子清晰地展示了 “索引对齐优先于位置顺序” 的原则。
DataFrame 间的运算与对齐
DataFrame 是二维表格,其对齐发生在两个维度:行索引(index)和列索引(columns)。只有行和列标签都匹配的位置,才会进行计算。
import pandas as pd
import numpy as np
# 创建 DataFrame 1: 2行2列,值全为1
df1 = pd.DataFrame(np.ones((2, 2)), columns=['a', 'b'], index=[0, 1])
print("DataFrame 1:")
print(df1)
print()
# 创建 DataFrame 2: 3行3列,值全为1
df2 = pd.DataFrame(np.ones((3, 3)), columns=['a', 'b', 'c'], index=[0, 1, 2])
print("DataFrame 2:")
print(df2)
print()
# DataFrame 间的加法运算
df_result = df1 + df2
print("df1 + df2 的结果:")
print(df_result)DataFrame 1:
a b
0 1.0 1.0
1 1.0 1.0
DataFrame 2:
a b c
0 1.0 1.0 1.0
1 1.0 1.0 1.0
2 1.0 1.0 1.0
df1 + df2 的结果:
a b c
0 2.0 2.0 NaN
1 2.0 2.0 NaN
2 NaN NaN NaN运算过程解析:
- 行列对齐:Pandas 寻找两个 DataFrame 行和列标签的交集。
- 行交集:
[0, 1] - 列交集:
[‘a‘, ‘b‘]
- 行交集:
- 计算:仅对行标签和列标签都匹配的单元格进行计算,即
(0,a),(0,b),(1,a),(1,b)这四个位置。每个位置都是1.0 + 1.0 = 2.0。 - 处理未对齐项:
- 对于行
2和列c,因为它们在df1中不存在,所以对应行/列的所有位置都是NaN。 - 结果 DataFrame 的形状由两个输入对象的行、列标签的并集决定。
- 对于行
Series 与 DataFrame 的混合运算
这是最容易令人困惑的部分。核心规则是:当 Series 与 DataFrame 进行运算时,Series 的索引(index)会被匹配到 DataFrame 的列(columns)上。然后,Series 的值会沿着 DataFrame 的行方向进行广播(即每一行都会与这个 Series 进行运算)。
情况一:Series 的索引与 DataFrame 的列完全不匹配
import pandas as pd
import numpy as np
# 创建 DataFrame 1
df1 = pd.DataFrame(np.ones((2, 2)), columns=['a', 'b'], index=[0, 1])
# 创建 Series 2 (索引为数字0-4)
ser2 = pd.Series(range(20, 25), index=range(5))
print("DataFrame 1 (列为字母‘a‘,‘b‘):")
print(df1)
print()
print("Series 2 (索引为数字0-4):")
print(ser2)
print()
mixed_result_1 = ser2 + df1
print("ser2 + df1 的结果:")
print(mixed_result_1)DataFrame 1 (列为字母‘a‘,‘b‘):
a b
0 1.0 1.0
1 1.0 1.0
Series 2 (索引为数字0-4):
0 20
1 21
2 22
3 23
4 24
dtype: int64
ser2 + df1 的结果:
a b 0 1 2 3 4
0 NaN NaN NaN NaN NaN NaN NaN
1 NaN NaN NaN NaN NaN NaN NaN结果分析: 运算时,ser2 的索引 [0,1,2,3,4] 被当作列标签去匹配 df1 的列 [‘a‘, ‘b‘]。由于没有一列能匹配上,所以所有交叉位置都产生 NaN。同时,结果 DataFrame 的列是两者列标签的并集 [0,1,2,3,4,‘a‘,‘b‘],行与 df1 相同 [0,1]。
情况二:Series 的索引与 DataFrame 的列部分匹配
import pandas as pd
import numpy as np
# 创建 DataFrame 1
df1 = pd.DataFrame(np.ones((2, 2)), columns=['a', 'b'], index=[0, 1])
# 创建 Series 3 (索引为字母‘a‘,‘b‘,‘c‘)
ser3 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
print("DataFrame 1:")
print(df1)
print()
print("Series 3 (索引为字母‘a‘,‘b‘,‘c‘):")
print(ser3)
print()
mixed_result_2 = ser3 + df1
print("ser3 + df1 的结果:")
print(mixed_result_2)DataFrame 1:
a b
0 1.0 1.0
1 1.0 1.0
Series 3 (索引为字母‘a‘,‘b‘,‘c‘):
a 1
b 2
c 3
dtype: int64
ser3 + df1 的结果:
a b c
0 2.0 3.0 NaN
1 2.0 3.0 NaN结果分析:
- 列对齐:
ser3的索引[‘a‘, ‘b‘, ‘c‘]与df1的列进行匹配。‘a‘和‘b‘匹配成功。 - 广播与计算:对于匹配成功的列,
ser3中该列对应的值会与df1中该列的每一行进行计算。- 列
a:df1中所有行的值都是1.0,加上ser3[‘a‘]=1,结果该列所有行变为2.0。 - 列
b:1.0 + 2 = 3.0。
- 列
- 处理未匹配项:
ser3中的‘c‘在df1中没有对应列,因此结果中新增一列c,其值全部为NaN。
本章小结
Pandas 的运算与对齐机制是其数据处理能力的基石。它让我们能够以声明式的方式操作数据,而无需陷入繁琐的循环和条件判断中。
- 对齐是核心:所有运算都基于索引标签的匹配,而非数据的位置。
NaN是安全符:未对齐的数据用NaN填充,避免了计算错误,也明确标识了数据缺失的情况。- 维度决定规则:
- Series vs Series:在索引维度对齐。
- DataFrame vs DataFrame:在行和列两个维度对齐。
- Series vs DataFrame:Series 的索引对齐 DataFrame 的列,然后沿行广播。
📋 行动清单
- 尝试创建两个索引部分重叠的 Series,手动预测它们相加的结果,再用代码验证。
- 构造一个 Series 和一个 DataFrame,确保 Series 的索引与 DataFrame 的列部分一致,观察广播计算的效果。
- 在遇到包含
NaN的计算结果时,思考这些NaN产生的原因是由于行索引、列索引,还是两者都不匹配导致的。
📝 动手练一练
- 概念辨析:如果两个 DataFrame 具有完全相同的行索引,但列索引完全不同,它们相加的结果会是什么形状?结果中会有非
NaN的值吗?
👉 点击查看参考答案
结果 DataFrame 的形状将是:行数为共同的行索引数量,列数为两个 DataFrame 列索引的并集的数量。因为没有任何一列是相同的,所以所有单元格都无法对齐计算,结果中将全部是 NaN 值。
- 动手实验:参考视频中的思考题,将
ser2的索引从[0,1,2,3,4]改为[0,2,4,6,8],然后计算ser1 + ser2。请先手动推理结果,再用以下代码验证你的想法。
import pandas as pd
# 创建 Series 1
ser1 = pd.Series(range(10, 20), index=range(10))
# 创建修改索引后的 Series 2
ser2_modified = pd.Series(range(20, 25), index=[0, 2, 4, 6, 8])
print("修改后的 Series 2:")
print(ser2_modified)
print()
print("ser1 + 修改后的ser2 的结果:")
print(ser1 + ser2_modified)👉 点击查看参考答案
修改后的 Series 2:
0 20
2 21
4 22
6 23
8 24
dtype: int64
ser1 + 修改后的ser2 的结果:
0 30.0
1 NaN
2 33.0
3 NaN
4 36.0
5 NaN
6 39.0
7 NaN
8 42.0
9 NaN
dtype: float64推理与验证:两个 Series 共有的索引是 0, 2, 4, 6, 8。因此,只有这些位置的值能进行计算:10+20=30, 12+21=33, 14+22=36, 16+23=39, 18+24=42。其他索引位置由于无法对齐,结果均为 NaN。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载本节课件:运算与对齐PDF · 193KB
- 下载全套课件打包(第1-5章)ZIP · 12.8MB
- 下载全套课件打包(第6-8章)ZIP · 15MB
- 下载实战数据集:AppleStore 应用商城分析ZIP · 329KB
- 下载实战数据集:女性服装电商分析ZIP · 2.8MB
- 下载Python 数据分析环境搭建指南PDF · 2MB
- 下载Scrapy 安装教程PDF · 12.7MB
- 下载附加实战项目:AppleStore 应用商城数据分析ZIP · 0.3MB · ipynb + CSV 数据
- 下载附加实战项目:银行电话营销数据分析ZIP · 0.4MB · ipynb + CSV 数据
- 下载附加实战项目:女性服装电商评论数据分析ZIP · 2.7MB · ipynb + CSV 数据
- 下载附加实战项目:美国化学学会杂志数据分析ZIP · 34.2MB · ipynb + SQLite 数据库