04 【保姆级教程】NumPy数组变换与统计函数(零基础吃透+实战对比)
本文系统讲解了NumPy数组变换与统计函数的核心用法,针对零基础学习者常见困惑点提供保姆级教程。主要内容包括:1)数组变换操作(扁平化、合并、转置),重点区分ravel()与flatten()的视图/副本特性;2)统计函数(求和、均值、标准差等)的轴向参数使用;3)条件统计方法。所有代码均附带学生成绩分析场景的实战案例,包含修改前后对比和易错点标注,帮助读者彻底掌握NumPy数据处理基础。通过本文
·
【保姆级教程】NumPy数组变换与统计函数(零基础吃透+实战对比)
引言
在NumPy教学过程中发现,很多零基础学生容易陷入核心困惑:对数组扁平化、合并的规则理解不清晰,统计函数的axis参数使用频繁出错,经常分不清按行/按列统计的逻辑,这些问题直接导致学生在后续数据分析、机器学习实战中,面对数组结构调整、数据特征分析等场景无从下手。
为此,本文从学生的认知规律出发,以「学生成绩」为实战场景,系统讲解数组变换(扁平化、合并、转置)和统计函数(均值、极值、标准差等)的核心用法,所有代码均附带「修改前后对比」和「新手易错点标注」,帮助零基础学生彻底吃透NumPy核心操作。
核心定位
本章节聚焦NumPy中数组变换(扁平化、合并、转置)和统计函数(均值、极值、标准差、最值索引)两大核心能力,数组变换是适配不同数据处理场景的基础操作,统计函数则是数据描述性分析的核心工具,是零基础入门NumPy数据处理、支撑后续数据分析/机器学习实战的必备内容。
一、核心知识点讲解(零基础友好版)
1. 数组变换:结构调整
(1)基础结构调整
| 操作类型 | 核心函数/方法 | 功能说明 | 新手关键点 |
|---|---|---|---|
| 扁平化 | ravel() / flatten() |
多维数组转1维数组 | ravel()返回视图(修改会影响原数组),flatten()返回副本(独立数据) |
| 横向合并 | np.hstack((arr1, arr2)) |
数组左右拼接(列数增加) | 合并的数组行数必须相同 |
| 纵向合并 | np.vstack((arr1, arr2)) |
数组上下拼接(行数增加) | 合并的数组列数必须相同 |
| 转置 | .T / transpose() |
行列互换 | 2维数组转置:(m,n)→(n,m);新手优先用.T |
2. 统计函数:数据特征分析
支持「全局统计」和「轴向统计」(按行/列),核心函数如下:
| 统计类型 | 核心函数 | 功能说明 | 轴向参数 |
|---|---|---|---|
| 求和 | np.sum(arr) |
计算元素总和 | axis=0按列,axis=1按行 |
| 均值 | np.mean(arr) |
计算平均值 | 同上 |
| 标准差 | np.std(arr) |
衡量数据离散程度 | 同上 |
| 最大值 | np.max(arr) |
找出最大元素 | 同上 |
| 最值索引 | np.argmax/argmin(arr) |
返回最值位置 | 同上 |
3. 条件统计扩展
np.where(条件, 满足值, 不满足值):按条件替换数组元素,结合统计函数实现条件化分析。
二、代码实操(全注释+修改前后对比版)
代码片段1:数组扁平化与转置
import numpy as np
# ===================== 1. 初始化2维测试数组 =====================
# 创建3×3的2维数组,模拟3个学生×3门科目的成绩表
arr_2d = np.array([[1,2,3], [4,5,6], [7,8,9]])
print("【原始状态】2维数组(3学生×3科目)")
print(f"数组值:\n{arr_2d}")
print(f"维度数(ndim):{arr_2d.ndim} → 2维")
print(f"形状(shape):{arr_2d.shape} → (3,3)")
print("-" * 60)
# ===================== 2. 扁平化操作 - ravel()(返回视图) =====================
# 操作:将2维数组转为1维,返回视图(与原数组共享内存)
# 场景:将成绩表转为1维,用于全校成绩排名(修改会影响原数据)
arr_ravel = arr_2d.ravel()
print("【修改后】ravel()扁平化(视图)")
print(f"1维数组值:{arr_ravel}")
print(f"形状(shape):{arr_ravel.shape} → (9,)")
# 验证视图特性:修改扁平化后的数组,原数组同步变化
arr_ravel[0] = 99 # 修改第1个元素为99(对应原数组[0,0]位置)
print("【修改验证】修改ravel结果后,原数组变化:")
print(f"原数组值:\n{arr_2d}") # 原数组[0,0]变为99
print(f"【对比】修改前原数组[0,0]:1 → 修改后:{arr_2d[0,0]}")
print("-" * 60)
# ===================== 3. 扁平化操作 - flatten()(返回副本) =====================
# 操作:将2维数组转为1维,返回副本(与原数组独立)
# 场景:生成独立的1维成绩单,修改不影响原数据
arr_flatten = arr_2d.flatten()
print("【修改后】flatten()扁平化(副本)")
print(f"1维数组值:{arr_flatten}")
print(f"形状(shape):{arr_flatten.shape} → (9,)")
# 验证副本特性:修改扁平化后的数组,原数组无变化
arr_flatten[1] = 88 # 修改第2个元素为88(对应原数组[0,1]位置)
print("【修改验证】修改flatten结果后,原数组无变化:")
print(f"原数组值:\n{arr_2d}") # 原数组[0,1]仍为2
print(f"【对比】修改前原数组[0,1]:2 → 修改后:{arr_2d[0,1]}(无变化)")
print("-" * 60)
# ===================== 4. 数组转置 - .T(行列互换) =====================
# 操作:将2维数组转置,行列互换,(3,3) → (3,3)
# 场景:将"学生×科目"的成绩表转为"科目×学生",方便按科目统计
arr_trans = arr_2d.T
print("【修改后】数组转置(.T)")
print(f"转置后数组值:\n{arr_trans}")
print(f"原形状:{arr_2d.shape} → 转置后形状:{arr_trans.shape}")
# 补充:非方阵转置示例(3行2列 → 2行3列)
# 模拟3个学生×2门科目的成绩表
arr_32 = np.array([[1,2], [3,4], [5,6]])
arr_32_trans = arr_32.T
print("\n【补充示例】非方阵转置(3行2列 → 2行3列)")
print(f"原数组值:\n{arr_32}")
print(f"转置后数组值:\n{arr_32_trans}")
print(f"【对比】原形状:{arr_32.shape} → 转置后形状:{arr_32_trans.shape}")
代码片段2:数组合并操作
import numpy as np
# ===================== 1. 初始化合并用基础数组 =====================
# 创建两个3行2列的数组,模拟两个班级的"3学生×2科目"成绩表
arr_a = np.array([[10,20], [30,40], [50,60]]) # 班级A成绩
arr_b = np.array([[70,80], [90,100], [110,120]]) # 班级B成绩
print("【原始状态】待合并的两个数组")
print(f"数组A(班级A):\n{arr_a} → 形状:{arr_a.shape}")
print(f"数组B(班级B):\n{arr_b} → 形状:{arr_b.shape}")
print("-" * 60)
# ===================== 2. 横向合并(hstack)- 行数相同,列数累加 =====================
# 操作:左右拼接数组,(3,2) + (3,2) → (3,4)
# 场景:给班级成绩表新增2门科目,合并为完整成绩表
arr_h = np.hstack((arr_a, arr_b))
print("【修改后】横向合并(hstack)")
print(f"合并后数组值:\n{arr_h}")
print(f"【对比】原数组形状:{arr_a.shape} + {arr_b.shape} → 合并后形状:{arr_h.shape}")
print("说明:行数保持3不变,列数从2+2=4")
print("-" * 60)
# ===================== 3. 纵向合并(vstack)- 列数相同,行数累加 =====================
# 操作:上下拼接数组,(3,2) + (3,2) → (6,2)
# 场景:合并两个班级的成绩表,生成年级成绩表
arr_v = np.vstack((arr_a, arr_b))
print("【修改后】纵向合并(vstack)")
print(f"合并后数组值:\n{arr_v}")
print(f"【对比】原数组形状:{arr_a.shape} + {arr_b.shape} → 合并后形状:{arr_v.shape}")
print("说明:列数保持2不变,行数从3+3=6")
print("-" * 60)
# ===================== 4. 通用合并(concatenate)- 指定轴控制方向 =====================
# axis=0:等同于vstack(纵向合并)
arr_concat0 = np.concatenate((arr_a, arr_b), axis=0)
print("【修改后】concatenate(axis=0)(纵向合并)")
print(f"形状:{arr_concat0.shape} → 与vstack结果一致:{arr_v.shape}")
# axis=1:等同于hstack(横向合并)
arr_concat1 = np.concatenate((arr_a, arr_b), axis=1)
print("【修改后】concatenate(axis=1)(横向合并)")
print(f"形状:{arr_concat1.shape} → 与hstack结果一致:{arr_h.shape}")
print("【对比总结】")
print(f"axis=0 → 纵向合并 → 行数增加:{arr_concat0.shape}")
print(f"axis=1 → 横向合并 → 列数增加:{arr_concat1.shape}")
代码片段3:统计函数与条件统计
import numpy as np
# ===================== 1. 初始化统计测试数组 =====================
# 固定随机种子,确保结果可复现
np.random.seed(123)
# 创建4行3列随机整数数组(0-20),模拟4个学生×3门科目的成绩
arr_stat = np.random.randint(0, 21, (4, 3))
print("【原始状态】统计测试数组(4学生×3科目)")
print(f"数组值:\n{arr_stat}")
print(f"形状:{arr_stat.shape} → (4,3)")
print("-" * 60)
# ===================== 2. 全局统计 - 整个数组的特征 =====================
print("【全局统计】计算整个数组的特征")
# 总和:所有学生所有科目的总分
sum_total = np.sum(arr_stat)
# 均值:所有成绩的平均分(保留2位小数)
mean_total = round(np.mean(arr_stat), 2)
# 标准差:成绩离散程度(值越大,分数差距越大)
std_total = round(np.std(arr_stat), 2)
# 最大值:所有成绩中的最高分
max_total = np.max(arr_stat)
# 最小值索引:全局最小值的位置(扁平化后的索引)
min_idx_total = np.argmin(arr_stat)
min_value_total = arr_stat.flatten()[min_idx_total]
print(f"总和:{sum_total} → 所有成绩相加的结果")
print(f"均值:{mean_total} → 所有成绩的平均分")
print(f"标准差:{std_total} → 成绩离散程度(越大差距越大)")
print(f"最大值:{max_total} → 所有成绩中的最高分")
print(f"最小值索引:{min_idx_total} → 对应值:{min_value_total}(全局第{min_idx_total+1}个元素)")
print("-" * 60)
# ===================== 3. 轴向统计 - 按行/列计算 =====================
print("【轴向统计】按行/列计算特征")
# axis=0 → 按列统计(每一列的特征,对应每门科目的特征)
sum_col = np.sum(arr_stat, axis=0) # 每科总分
max_col = np.max(arr_stat, axis=0) # 每科最高分
# axis=1 → 按行统计(每一行的特征,对应每个学生的特征)
mean_row = np.round(np.mean(arr_stat, axis=1), 2) # 每个学生的平均分
min_idx_row = np.argmin(arr_stat, axis=1) # 每个学生最低分科目的索引
print("【按列统计(axis=0)→ 每门科目】")
print(f"每科总分:{sum_col} → 第1科:{sum_col[0]}, 第2科:{sum_col[1]}, 第3科:{sum_col[2]}")
print(f"每科最高分:{max_col} → 第1科:{max_col[0]}, 第2科:{max_col[1]}, 第3科:{max_col[2]}")
print("\n【按行统计(axis=1)→ 每个学生】")
for i in range(4):
print(f"学生{i+1} → 平均分:{mean_row[i]}, 最低分科目索引:{min_idx_row[i]}(0=第1科,1=第2科,2=第3科)")
print("-" * 60)
# ===================== 4. 条件统计 - np.where替换元素 =====================
# 操作规则:>15→15(满分限制),<5→5(及格保底),其余保持不变
# 场景:成绩修正(高分封顶,低分保底)
arr_where = np.where(arr_stat > 15, 15, np.where(arr_stat < 5, 5, arr_stat))
print("【条件替换】成绩修正(>15→15,<5→5)")
print(f"原始数组:\n{arr_stat}")
print(f"修正后数组:\n{arr_where}")
# 对比修正前后的均值
mean_where = round(np.mean(arr_where), 2)
print(f"【对比】修正前均值:{mean_total} → 修正后均值:{mean_where}")
print("说明:修正后均值降低,因为高分被限制,低分被保底")
三、核心总结
- 扁平化差异:
ravel()返回视图(修改影响原数组,节省内存),flatten()返回副本(修改不影响原数组,更安全),学生可根据是否需要保留原数据选择对应方法; - 数组合并规则:横向合并(hstack)需行数一致,列数累加;纵向合并(vstack)需列数一致,行数累加;
concatenate通过axis统一控制合并方向(0=纵向、1=横向),是合并操作的通用方法; - 统计函数关键:
axis=0按列运算(科目维度)、axis=1按行运算(学生维度),这是新手最易混淆的点,建议结合实际场景(如按科目统计总分)记忆; - 条件统计价值:
np.where可实现条件化数据替换,结合统计函数能完成复杂的数据分析,如成绩修正、异常值处理等实战场景。
四、实操说明
- 环境准备:提前安装NumPy(终端执行
pip install numpy),建议使用Jupyter Notebook分步运行每个代码片段,便于观察输出; - 结构验证:每完成一次数组变换,打印
shape(形状),直观理解数组结构变化逻辑; - 随机数复现:代码中使用
np.random.seed(123)固定随机种子,若需测试不同随机数组,可注释该行; - 易错点规避:合并数组前务必检查形状是否匹配(如横向合并确认行数相同),避免维度不兼容报错;统计函数使用时,先明确是按行还是按列分析,再指定
axis参数。
五、课后练习
练习1:数组扁平化与转置(基础巩固)
- 题目:创建2维数组
arr = np.array([[8,15,7], [12,9,20]]),完成以下操作:- 分别用
ravel()和flatten()扁平化数组,修改扁平化后数组的第3个元素为0,对比原数组是否变化; - 将原数组转置,计算转置后数组按行的最大值;
- 将转置后的数组再次扁平化,统计大于10的元素个数。
- 分别用
练习2:数组合并与统计(进阶)
- 题目:生成两个3行2列的随机整数数组(10-50),完成以下操作:
- 横向合并两个数组,转置后计算每列的标准差(保留2位小数);
- 找出标准差最大的列的索引,计算该列的最大值;
- 将合并后的数组扁平化,统计其中大于30的元素个数。
练习3:条件统计综合(实战)
- 题目:生成5行5列的随机浮点数数组(0-1),完成以下操作:
- 使用
np.where将数组中>0.7的元素替换为0.7,<0.3的替换为0.3; - 计算替换后数组的全局方差(保留3位小数)、按行的最大值;
- 统计替换后数组中值为0.7的元素总数,以及值为0.3的元素总数。
- 使用
练习答案提示
- 练习1:
ravel()修改后原数组会变化,flatten()修改后原数组不变;转置后按行最大值用np.max(..., axis=1);统计大于10的元素数用np.sum(flatten_arr>10); - 练习2:标准差用
np.std(..., axis=0),最大值索引用np.argmax(); - 练习3:方差用
np.var(),统计指定值元素数用np.sum(arr_where==0.7)和np.sum(arr_where==0.3)。
更多推荐



所有评论(0)