第48课:科学计算:NumPy 数组与基础运算
学习目标
- 理解 NumPy 的核心概念——
ndarray数组对象,及其与 Python 列表的关键区别。 - 掌握创建一维、多维 NumPy 数组的多种方法。
- 熟悉 NumPy 数组的基本属性(
ndim,shape,dtype,size)。 - 掌握 NumPy 的核心优势——向量化运算,实现高效的逐元素计算。
- 学习常用的数组操作函数,如切片、索引、变形和统计函数。
核心概念
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])。
- 计算每个商品的总价(价格 * 数量)。
- 计算所有商品的总销售额(总价的总和)。 预期输出:
各商品总价: [255. 150. 126. 120.6]
总销售额: 651.6
练习3:综合练习
创建一个5x5的随机整数数组(元素范围0-9)。然后:
- 将数组中所有偶数替换为0。
- 计算替换后数组的对角线元素之和。
(提示:使用
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
常见错误
- 数据类型混淆:尝试将不同数据类型的数组(如整数数组与字符串数组)进行数学运算会导致错误。NumPy 会尝试自动提升类型(如
int转float),但需注意结果可能不符合预期。 - 轴(
axis)方向混淆:axis=0通常表示"沿着行的方向"(垂直方向,跨行),作用于每一列;axis=1表示"沿着列的方向"(水平方向,跨列),作用于每一行。初学者极易搞反。 - 数组与标量的运算:
a + 5是合法的,它会将标量5广播(Broadcast)到数组a的每个元素。但要注意数组间的运算,如a + b,如果a和b的shape不匹配且无法广播,会抛出ValueError。 - 视图(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...