48·模块十:数据处理与分析进阶

科学计算:NumPy 数组与基础运算

numpyarraysscientific-computing

第48课:科学计算:NumPy 数组与基础运算

学习目标

  1. 理解 NumPy 的核心概念——ndarray数组对象,及其与 Python 列表的关键区别。
  2. 掌握创建一维、多维 NumPy 数组的多种方法。
  3. 熟悉 NumPy 数组的基本属性(ndim, shape, dtype, size)。
  4. 掌握 NumPy 的核心优势——向量化运算,实现高效的逐元素计算。
  5. 学习常用的数组操作函数,如切片、索引、变形和统计函数。

核心概念

1. 为什么需要 NumPy?

Python 列表非常灵活,但存储数据时每个元素都是一个独立的 Python 对象,这使得它在处理大量数值数据时效率低下。NumPy(Numerical Python)的核心是**ndarray(N-dimensional array)**对象,它是一个快速、灵活的同构数据容器。"同构"意味着数组中的所有元素必须是相同的数据类型(如整数、浮点数),这让 NumPy 能够以紧凑、连续的内存块存储数据,并利用底层 C 语言和 Fortran 编写的优化算法进行高速数学运算,速度远超纯 Python 循环。

2. ndarray 的关键属性

  • ndim: 数组的维度(轴)数量。
  • shape: 一个元组,表示每个维度上有多少个元素。例如,一个3行4列的矩阵,其shape(3, 4)
  • dtype: 数组中元素的数据类型(如 int64, float64)。
  • size: 数组中所有元素的总数。

代码示例

import numpy as np # 通常按惯例将numpy重命名为np

# 1. 创建数组的几种方法
# 从Python列表创建
arr_from_list = np.array([1, 2, 3, 4, 5])
print("从列表创建:\n", arr_from_list)

# 创建全0、全1、指定范围的数组
zeros_arr = np.zeros((2, 3)) # 2行3列的全0数组
ones_arr = np.ones_like(arr_from_list) # 创建一个与arr_from_list形状相同的全1数组
range_arr = np.arange(0, 10, 2) # 从0开始,到10结束(不包含),步长为2
print("全0数组:\n", zeros_arr)
print("全1数组:\n", ones_arr)
print("范围数组:\n", range_arr)

# 2. 查看数组属性
multi_dim_arr = np.array([[1, 2, 3], [4, 5, 6]])
print("维度数量 (ndim):", multi_dim_arr.ndim)
print("形状 (shape):", multi_dim_arr.shape)
print("数据类型 (dtype):", multi_dim_arr.dtype)
print("总元素数 (size):", multi_dim_arr.size)

# 3. 向量化运算(NumPy的灵魂)
a = np.array([1, 2, 3])
b = np.array([10, 20, 30])

# 逐元素运算,无需循环
print("加法:", a + b)       # [11 22 33]
print("乘法:", a * b)       # [10 40 90]
print("指数运算:", a ** 2)   # [1 4 9]
print("比较运算:", a > 1)   # [False  True  True]

# 4. 常用的数组操作
arr = np.arange(1, 10).reshape(3, 3) # 重塑为3x3矩阵
print("原始矩阵:\n", arr)

# 切片(类似于列表,但支持多维)
print("第二行:", arr[1, :])        # 输出:[4 5 6]
print("第二列:", arr[:, 1])        # 输出:[2 5 8]
print("子矩阵:\n", arr[:2, :2])   # 输出:[[1 2] [4 5]]

# 统计函数
print("总和:", arr.sum())
print("列方向均值:", arr.mean(axis=0)) # axis=0表示沿行(跨行)操作,得到每列的结果
print("最大值:", arr.max())

实践练习

练习1:基础数组创建与属性

创建一个包含从1到12的整数,并重塑为3行4列的二维数组。打印出该数组的形状(shape)、数据类型(dtype)和第2行所有元素。 预期输出:

形状: (3, 4)
数据类型: int64
第2行: [5 6 7 8]

练习2:向量化运算

给定两个数组 prices = np.array([25.5, 30.0, 15.75, 40.2])quantities = np.array([10, 5, 8, 3])

  1. 计算每个商品的总价(价格 * 数量)。
  2. 计算所有商品的总销售额(总价的总和)。 预期输出:
各商品总价: [255.  150.  126.  120.6]
总销售额: 651.6

练习3:综合练习

创建一个5x5的随机整数数组(元素范围0-9)。然后:

  1. 将数组中所有偶数替换为0。
  2. 计算替换后数组的对角线元素之和。 (提示:使用 np.random.randint,利用布尔索引进行条件替换,使用 np.diag 获取对角线) 预期输出示例(因随机数结果可能不同):
原始数组:
[[2 1 4 3 8]
 [5 0 7 6 2]
 [9 3 5 1 4]
 [8 7 2 0 9]
 [1 6 3 5 7]]
替换后数组:
[[0 1 0 3 0]
 [5 0 7 0 0]
 [9 3 5 1 0]
 [0 7 0 0 9]
 [1 0 3 5 7]]
对角线元素: [0 0 5 0 7]
对角线之和: 12

常见错误

  1. 数据类型混淆:尝试将不同数据类型的数组(如整数数组与字符串数组)进行数学运算会导致错误。NumPy 会尝试自动提升类型(如intfloat),但需注意结果可能不符合预期。
  2. 轴(axis)方向混淆axis=0通常表示"沿着行的方向"(垂直方向,跨行),作用于每一列;axis=1表示"沿着列的方向"(水平方向,跨列),作用于每一行。初学者极易搞反。
  3. 数组与标量的运算a + 5 是合法的,它会将标量5广播(Broadcast)到数组a的每个元素。但要注意数组间的运算,如 a + b,如果a和b的shape不匹配且无法广播,会抛出ValueError
  4. 视图(View)与复制(Copy)的混淆:NumPy的切片操作(如arr[0:2, :])返回的是原数组的一个视图,修改视图会直接影响原数组。如需独立副本,应使用 .copy() 方法。

小结

本课我们迈入了高性能科学计算的大门:

  • NumPy 的基石ndarray 数组,它是一个快速、高效、同构的多维数据容器。
  • 核心优势在于向量化运算,它避免了显式的Python循环,直接对整个数组进行操作,代码更简洁、速度飞快。
  • 掌握了数组的创建array, zeros, arange等)、属性查看shape, dtype)和基础操作(索引、切片、变形)。
  • 学习了常用的数学和统计函数sum, mean, max)以及它们对axis参数的使用。

NumPy 是 Pandas、Scikit-learn、TensorFlow 等众多数据科学和机器学习库的基础。熟练掌握其数组操作,是成为高效数据处理者的关键一步。下一课,我们将进入并发编程的世界。

练习编辑器

python
Loading...

继续学习

完成本课后,建议继续学习下一课「并发编程:多线程(threading)入门」 以巩固所学知识。