杰瑞科技汇

python numpy教程

NumPy 完整教程:从入门到精通

目录

  1. 什么是 NumPy?
  2. 为什么使用 NumPy?
  3. 安装与环境准备
  4. 核心概念:ndarray (N维数组对象)
  5. 创建 NumPy 数组
  6. 数组的基本属性
  7. 索引与切片
  8. 数组运算
    • 算术运算
    • 广播机制
    • 聚合函数
    • 其他常用数学函数
  9. 形状操作
    • reshape()
    • ravel()flatten()
    • stack()hstack(), vstack()
    • split()
  10. 矩阵运算
  11. 文件操作
  12. 随机数生成
  13. 实战案例
    • 案例1:替换数组中的特定值
    • 案例2:图像处理入门
  14. 总结与学习资源

什么是 NumPy?

NumPy 是 Numerical Python 的缩写,是 Python 语言中用于科学计算的核心库,它提供了一个强大的 N维数组对象 ndarray,以及各种操作这些数组的函数,这些函数比 Python 原生的列表操作要快几个数量级。

python numpy教程-图1
(图片来源网络,侵删)

NumPy 就是为 Python 提供了类似 MATLAB 或 R 语言那样的高效数值计算能力。

为什么使用 NumPy?

与 Python 原生的 list 相比,NumPy 有以下巨大优势:

  • 性能卓越:NumPy 数组在内存中是连续存储的,并且内部由 C 语言实现,这使得其计算速度非常快,而 Python 列表存储的是对象的指针,存在大量的类型检查和间接调用,速度较慢。
  • 内存占用小:NumPy 数组中的元素类型是固定的(如 int32, float64),因此比 Python 列表(每个元素都可以是不同类型)占用更少的内存。
  • 丰富的函数库:NumPy 提供了大量用于线性代数、傅里叶变换、随机数生成等领域的数学函数。
  • 广播机制:这是 NumPy 一个非常强大的特性,允许不同形状的数组之间进行算术运算。

安装与环境准备

你需要安装 NumPy,最简单的方式是使用 pip

pip install numpy

为了验证安装是否成功,可以在 Python 解释器或 Jupyter Notebook 中运行以下代码:

python numpy教程-图2
(图片来源网络,侵删)
import numpy as np
# 如果没有报错,说明安装成功
print(np.__version__)

核心概念:ndarray (N维数组对象)

ndarray 是 NumPy 的核心,它是一个所有元素类型相同、固定大小的多维数组。

与 Python list 的关键区别:

  • 类型统一ndarray 中的所有元素必须是相同的数据类型,这使得 NumPy 能够进行高效的内存分配和计算。
  • 性能:如上所述,其底层实现是基于 C 的,速度极快。

创建 NumPy 数组

1 从 Python 列表创建

import numpy as np
# 创建一维数组
arr1d = np.array([1, 2, 3, 4, 5])
print("一维数组:\n", arr1d)
# 创建二维数组
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
print("\n二维数组:\n", arr2d)
# 创建三维数组
arr3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print("\n三维数组:\n", arr3d)

2 使用内置函数创建

NumPy 提供了多种函数来创建特定类型的数组,这在初始化数据时非常有用。

# 创建全为 0 的数组
zeros_arr = np.zeros((3, 4)) # 形状为 (3, 4) 的二维数组
print("全0数组:\n", zeros_arr)
# 创建全为 1 的数组
ones_arr = np.ones((2, 3), dtype=int) # 可以指定数据类型
print("\n全1数组:\n", ones_arr)
# 创建单位矩阵
identity_matrix = np.eye(3)
print("\n单位矩阵:\n", identity_matrix)
# 创建指定范围的数组,类似 Python 的 range
range_arr = np.arange(10) # 从 0 到 9
print("\narange数组:\n", range_arr)
# 创建等差数列
linspace_arr = np.linspace(0, 1, 5) # 在 0 到 1 之间生成 5 个点
print("\nlinspace数组:\n", linspace_arr)
# 创建随机数组
random_arr = np.random.rand(2, 3) # 生成一个 2x3 的 [0, 1) 之间的随机浮点数数组
print("\n随机数组:\n", random_arr)

数组的基本属性

了解这些属性对于理解和使用 NumPy 至关重要。

python numpy教程-图3
(图片来源网络,侵删)
arr = np.array([[1, 2, 3], [4, 5, 6]])
# ndim: 数组的维度(轴数)
print("维度:", arr.ndim) # 输出 2
# shape: 数组的形状,一个元组,表示每个维度的大小
print("形状:", arr.shape) # 输出 (2, 3)
# size: 数组中元素的总数
print("元素总数:", arr.size) # 输出 6
# dtype: 数组元素的数据类型
print("数据类型:", arr.dtype) # 输出 int64 (取决于你的系统)
# itemsize: 每个元素占用的字节数
print("每个元素字节数:", arr.itemsize) # 输出 8 (int64 占用 8 字节)

索引与切片

NumPy 的索引和切片语法与 Python 列表非常相似,但功能更强大。

1 一维数组

a = np.array([0, 10, 20, 30, 40, 50])
# 获取单个元素
print(a[2]) # 输出 20
# 切片
print(a[1:5]) # 输出 [10 20 30 40]
print(a[::2]) # 输出 [ 0 20 40] (步长为2)

2 多维数组

对于多维数组,使用逗号 分隔不同维度的索引或切片。

b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 获取单个元素
print(b[0, 1]) # 输出 2 (第0行,第1列)
# 获取整行
print(b[1, :]) # 输出 [4 5 6] (等同于 b[1])
# 获取整列
print(b[:, 0]) # 输出 [1 4 7] (第0列的所有行)
# 切片获取子数组
print(b[0:2, 1:3])
# 输出:
# [[2 3]
#  [5 6]]

数组运算

这是 NumPy 最强大的部分。

1 算术运算

NumPy 会对数组中的每个元素执行操作(这被称为 向量化)。

a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
print(a + b) # [11 22 33 44]
print(a - b) # [-9 -18 -27 -36]
print(a * b) # [ 10  40  90 160]
print(a / b) # [0.1 0.1 0.1 0.1]
print(a ** 2) # [ 1  4  9 16]

2 广播机制

当两个形状不同的数组进行算术运算时,NumPy 会尝试通过“广播”使它们的形状兼容。

广播规则

  1. 比较两个数组的维度,从后向前(即从右向左)比较。
  2. 如果两个维度的大小相等,或者其中一个为1,则它们是兼容的。
  3. 如果不兼容,则会抛出 ValueError
  4. 广播后,形状为1的维度会被“拉伸”以匹配另一个数组的对应维度。
# 标量与数组
a = np.array([1, 2, 3])
print(a * 3) # [ 3  6  9] (标量3被广播到数组a的每个元素)
# 数组与一维数组
x = np.array([[1], [2], [3]]) # 形状 (3, 1)
y = np.array([4, 5, 6])       # 形状 (3,)
# 广播后,x 变成 (3, 3), y 变成 (3, 3)
# x:
# [[1 1 1]
#  [2 2 2]
#  [3 3 3]]
# y:
# [[4 5 6]
#  [4 5 6]
#  [4 5 6]]
print(x + y)
# 输出:
# [[5 6 7]
#  [6 7 8]
#  [7 8 9]]

3 聚合函数

这些函数对数组中的元素进行汇总计算。

arr = np.array([[1, 2, 3], [4, 5, 6]])
# 求和
print("总和:", np.sum(arr))       # 输出 21
print("列求和:", np.sum(arr, axis=0)) # 输出 [5 7 9] (对每一列求和)
print("行求和:", np.sum(arr, axis=1)) # 输出 [ 6 15] (对每一行求和)
# 最大值/最小值
print("最大值:", np.max(arr))     # 输出 6
print("列最大值:", np.max(arr, axis=0)) # 输出 [4 5 6]
# 平均值
print("平均值:", np.mean(arr))   # 输出 3.5
# 标准差
print("标准差:", np.std(arr))
# 中位数
print("中位数:", np.median(arr))

4 其他常用数学函数

arr = np.array([0, np.pi/2, np.pi])
# 三角函数
print(np.sin(arr)) # [0.0000000e+00 1.0000000e+00 1.2246468e-16]
# 指数和对数
print(np.exp(arr)) # [ 1.          4.81047738 23.14069263]
print(np.log(arr)) # 会产生警告,因为 log(0) 是 -inf

形状操作

1 reshape()

改变数组的形状,但元素总数不变。

a = np.arange(12)
print("原始数组:\n", a)
b = a.reshape(3, 4)
print("\nreshape后:\n", b)
# -1 表示自动计算维度
c = a.reshape(2, -1)
print("\n使用-1自动计算:\n", c)

2 ravel()flatten()

将多维数组展平为一维数组。

  • ravel():返回一个视图(view),如果可能的话,不占用新内存,修改视图会影响原数组。
  • flatten():返回一个副本(copy),一定会占用新内存,修改副本不会影响原数组。
a = np.array([[1, 2], [3, 4]])
# ravel
b = a.ravel()
b[0] = 99
print("修改 ravel 后的 a:\n", a) # a 会改变
# flatten
a = np.array([[1, 2], [3, 4]]) # 重新创建 a
c = a.flatten()
c[0] = 99
print("修改 flatten 后的 a:\n", a) # a 不会改变

3 stack()hstack(), vstack()

拼接数组。

  • np.stack():沿着一个新轴增加维度来堆叠数组。
  • np.hstack():水平(按列)堆叠数组。
  • np.vstack():垂直(按行)堆叠数组。
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# hstack
print("hstack:\n", np.hstack((a, b))) # [1 2 3 4 5 6]
# vstack
print("vstack:\n", np.vstack((a, b)))
# [[1 2 3]
#  [4 5 6]]
# stack
print("stack:\n", np.stack((a, b), axis=0))
# [[1 2 3]
#  [4 5 6]]

4 split()

将数组分割成多个子数组。

a = np.arange(9).reshape(3, 3)
print("原始数组:\n", a)
# 水平分割
split_h = np.hsplit(a, 3)
print("\n水平分割为3部分:\n", split_h)
# 垂直分割
split_v = np.vsplit(a, 3)
print("\n垂直分割为3部分:\n", split_v)

矩阵运算

虽然 NumPy 是数组库,但它也提供了专门的矩阵对象 np.matrix不推荐新项目使用,推荐直接使用 ndarray 并使用 运算符进行矩阵乘法)。

对于 ndarray

  • 逐元素乘法
  • 矩阵乘法
  • np.dot() 也可以用于矩阵乘法。
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
# 逐元素乘法
print("逐元素乘法:\n", a * b)
# 矩阵乘法
print("矩阵乘法 (@):\n", a @ b)
print("矩阵乘法 (np.dot):\n", np.dot(a, b))

文件操作

NumPy 可以轻松地将数组保存到文件并从文件中读取。

  • np.save() / np.load():保存和加载 .npy 文件(二进制,高效)。
  • np.savetxt() / np.loadtxt():保存和加载文本文件(如 .txt, .csv),方便人类阅读。
arr = np.arange(10)
# 保存为二进制文件
np.save('my_array.npy', arr)
# 从二进制文件加载
loaded_arr = np.load('my_array.npy')
print("从 .npy 加载:", loaded_arr)
# 保存为文本文件
np.savetxt('my_array.txt', arr, delimiter=',')
# 从文本文件加载
loaded_txt_arr = np.loadtxt('my_array.txt', delimiter=',')
print("从 .txt 加载:", loaded_txt_arr)

随机数生成

np.random 模块功能强大,是机器学习和数据科学的基础。

# 设置随机种子,保证结果可复现
np.random.seed(42)
# 生成标准正态分布随机数
randn_arr = np.random.randn(2, 3)
print("标准正态分布:\n", randn_arr)
# 生成指定范围的随机整数
randint_arr = np.random.randint(0, 10, size=(3, 3))
print("\n随机整数:\n", randint_arr)
# 打乱数组顺序
data = np.arange(10)
np.random.shuffle(data)
print("\n打乱后的数组:\n", data)

实战案例

1 案例1:替换数组中的特定值

假设我们有一个数组,想将其中所有大于 5 的数替换为 1,小于等于 5 的数替换为 0。

Pythonic (但低效) 的方式:

arr = np.random.randint(0, 10, size=(5,))
result = [1 if x > 5 else 0 for x in arr]

NumPy (高效) 的方式: 利用布尔索引和向量化操作。

arr = np.random.randint(0, 10, size=(5,))
print("原始数组:", arr)
# 创建一个与 arr 形状相同的全0数组
result = np.zeros_like(arr)
# 找出大于5的元素的索引,并将这些位置的值设为1
result[arr > 5] = 1
print("处理后的数组:", result)

2 案例2:图像处理入门

一张灰度图可以看作一个二维数组,彩色图是一个三维数组(高 x 宽 x 通道)。

这里我们用 NumPy 创建一个简单的渐变图。

import matplotlib.pyplot as plt
# 创建一个 100x100 的二维数组
# 每一行的值从0到1线性增加
# np.linspace(0, 1, 100) 创建 [0, ..., 1]
# np.tile 将其复制100次,形成100行
gradient = np.tile(np.linspace(0, 1, 100), (100, 1))
# 使用 matplotlib 显示图像
plt.imshow(gradient, cmap='gray')'A Simple Gradient Image')
plt.axis('off') # 关闭坐标轴
plt.show()

总结与学习资源

NumPy 是数据科学和机器学习领域的基石,掌握它的核心概念——ndarray、广播、向量化运算和索引——是通往更高级库(如 Pandas, Scikit-learn, TensorFlow, PyTorch)的必经之路,多动手练习,尝试用 NumPy 重写一些用 Python 原生列表实现的计算任务,你会深刻体会到它的威力。

学习资源

  • 官方文档NumPy User Guide (最权威,但可能对初学者稍显枯燥)
  • Scipy Lecture NotesScipy Lecture Notes (非常经典的免费教程,内容详实)
  • Real PythonNumPy Tutorial (讲解清晰,示例丰富)
  • YouTube:搜索 "NumPy Tutorial",有很多优秀的视频教程,如 Corey Schafer 的系列视频。
  • 练习:在 LeetCodeKaggle 上寻找需要数值计算的问题来练习。
分享:
扫描分享到社交APP
上一篇
下一篇