杰瑞科技汇

NumPy入门,如何快速掌握基础操作?

NumPy 入门教程

目录

  1. 为什么需要 NumPy?
  2. 安装 NumPy
  3. 核心概念:NumPy 数组
  4. 创建数组
  5. 数组的基本属性
  6. 索引与切片
  7. 数组运算
  8. 聚合函数
  9. 矩阵运算
  10. 实际应用示例:图像处理入门
  11. 总结与进阶学习

为什么需要 NumPy?

想象一下,你有一个包含一百万个数字的列表,你需要对列表中的每一个数字都乘以 2,用 Python 的原生列表怎么做?

# 原生 Python 列表
my_list = list(range(1, 1000001))
result = [x * 2 for x in my_list] # 使用列表推导式

这段代码虽然能运行,但速度相对较慢,因为它是在 Python 层面一个一个元素地进行操作。

NumPy (Numerical Python) 的出现就是为了解决这个问题。

  • 高性能:NumPy 的核心是一个名为 ndarray (N-dimensional Array) 的对象,它使用 C 语言实现,数据在内存中是连续存储的,并且可以使用 CPU 的 SIMD 指令进行并行计算,这使得它的运算速度比 Python 原生列表快几个数量级。
  • 丰富的函数库:NumPy 提供了大量用于数学、统计、线性代数等的函数,无需编写复杂的循环。
  • 科学计算基石:NumPy 是几乎所有数据科学生态库(如 Pandas, Scikit-learn, Matplotlib, TensorFlow, PyTorch)的基石,不理解 NumPy,就很难深入这些领域。

安装 NumPy

如果你已经安装了 Anaconda,NumPy 通常已经包含在内,如果没有,你可以使用 pip 轻松安装:

pip install numpy

安装完成后,在你的 Python 脚本或 Jupyter Notebook 中导入它:

import numpy as np
# 按照惯例,我们通常使用别名 'np' 来指代 NumPy

核心概念:NumPy 数组

NumPy 的核心是 ndarray 对象,我们称之为数组,它和 Python 列表有本质区别:

特性 Python 列表 NumPy 数组
数据类型 可以包含不同类型的数据 (e.g., [1, 'a', 3.14]) 必须包含相同类型的数据 (e.g., 全是整数或全是浮点数)
性能 较慢,逐元素操作 极快,底层优化
功能 通用数据结构 专为数值计算设计,丰富的数学函数
内存 较大,每个元素都是一个完整的 Python 对象 较小,数据是连续的块

创建数组

创建 NumPy 数组最常用的方法是 np.array()

从列表创建

# 创建一维数组 (向量)
a = np.array([1, 2, 3, 4, 5])
print(a)
# 输出: [1 2 3 4 5]
# 创建二维数组 (矩阵)
b = np.array([[1, 2, 3], [4, 5, 6]])
print(b)
# 输出:
# [[1 2 3]
#  [4 5 6]]

使用内置函数创建

NumPy 提供了许多方便的函数来创建特定类型的数组。

# 创建一个全为 0 的 3x4 数组
zeros_array = np.zeros((3, 4))
print(zeros_array)
# 输出:
# [[0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]]
# 创建一个全为 1 的 2x2 数组
ones_array = np.ones((2, 2))
print(ones_array)
# 输出:
# [[1. 1.]
#  [1. 1.]]
# 创建一个单位矩阵 (方阵,对角线为1,其余为0)
identity_matrix = np.eye(3)
print(identity_matrix)
# 输出:
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]
# 创建一个用指定数字填充的数组
full_array = np.full((2, 2), 99)
print(full_array)
# 输出:
# [[99 99]
#  [99 99]]
# 创建一个范围数组 (类似 range)
range_array = np.arange(10) # 0 到 9
print(range_array)
# 输出: [0 1 2 3 4 5 6 7 8 9]
# 创建一个均匀分布的数组
linspace_array = np.linspace(0, 1, 5) # 从0到1,生成5个均匀分布的数
print(linspace_array)
# 输出: [0.   0.25 0.5  0.75 1.  ]
# 创建一个随机数组
random_array = np.random.rand(3, 2) # 生成一个 3x2 的 [0, 1) 之间的随机数数组
print(random_array)
# 输出 (每次运行结果不同):
# [[0.123 0.456]
#  [0.789 0.012]
#  [0.345 0.678]]

数组的基本属性

了解数组的几个关键属性非常重要。

arr = np.array([[1, 2, 3], [4, 5, 6]])
# .shape: 数组的维度 (行数, 列数)
print(f"Shape: {arr.shape}") # 输出: Shape: (2, 3)
# .ndim: 数组的维度 (轴的数量)
print(f"Number of dimensions: {arr.ndim}") # 输出: Number of dimensions: 2
# .size: 数组中元素的总数
print(f"Size: {arr.size}") # 输出: Size: 6
# .dtype: 数组中元素的数据类型
print(f"Data type: {arr.dtype}") # 输出: Data type: int64 (在64位系统上)
# 创建指定数据类型的数组
float_arr = np.array([1, 2, 3], dtype=np.float32)
print(f"Data type: {float_arr.dtype}") # 输出: Data type: float32

索引与切片

NumPy 的索引和切片与 Python 列表非常相似,但功能更强大,尤其是在多维数组上。

一维数组

a = np.array([0, 10, 20, 30, 40, 50])
# 索引
print(a[2])   # 输出: 20
# 切片
print(a[1:4])   # 输出: [10 20 30]
print(a[:3])    # 输出: [0 10 20]
print(a[2:])    # 输出: [20 30 40 50]
print(a[::2])   # 输出: [0 20 40] (步长为2)

多维数组

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

b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 获取单个元素
print(b[0, 1])   # 第0行,第1列 -> 输出: 2
# 获取一行
print(b[1, :])   # 第1行,所有列 -> 输出: [4 5 6]
print(b[1])      # 简写,同样获取第1行 -> 输出: [4 5 6]
# 获取一列
print(b[:, 0])   # 所有行,第0列 -> 输出: [1 4 7]
# 获取一个子矩阵
print(b[0:2, 1:3])
# 输出:
# [[2 3]
#  [5 6]]

数组运算

这是 NumPy 最强大的地方,你可以对整个数组进行数学运算,而无需编写循环,这被称为向量化

a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
# 加法
print(a + b)
# 输出: [11 22 33 44]
# 减法
print(b - a)
# 输出: [ 9 18 27 36]
# 乘法 (对应元素相乘,不是矩阵乘法)
print(a * b)
# 输出: [ 10  40  90 160]
# 除法
print(b / a)
# 输出: [10.  10.  10.  10.]
# 与标量的运算
print(a * 2)
# 输出: [ 2  4  6  8]
print(a ** 2) # 平方
# 输出: [ 1  4  9 16]
print(np.sqrt(a)) # 开方
# 输出: [1.         1.41421356 1.73205081 2.        ]

聚合函数

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

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.min(arr, axis=0)) # 输出: [1 2 3] (每列的最小值)
# 平均值
print(np.mean(arr))       # 输出: 3.5
# 标准差
print(np.std(arr))        # 输出: 1.707825127659933

矩阵运算

虽然 NumPy 主要使用 ndarray,但它也提供了专门的 matrix 类型,但更常见的做法是直接使用 ndarray 进行矩阵运算。

A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
# 矩阵乘法 (点积)
# 方法1: 使用 @ 运算符 (推荐)
C_dot = A @ B
print("@ 运算符结果:\n", C_dot)
# 方法2: 使用 np.dot() 函数
C_func = np.dot(A, B)
print("\nnp.dot() 结果:\n", C_func)
# 两种方法输出相同:
# [[19 22]
#  [43 50]]
# 转置矩阵
A_transposed = A.T
print("\nA的转置:\n", A_transposed)
# 输出:
# [[1 3]
#  [2 4]]

实际应用示例:图像处理入门

一张灰度图可以看作一个二维数组,每个像素的值代表亮度,一张彩色图可以看作一个三维数组(高 x 宽 x 颜色通道)。

我们使用 scikit-image 库来读取图片(如果没安装,请 pip install scikit-image)。

from skimage import io
import numpy as np
# 读取一张示例图片
# 如果没有网络,可以自己找一张 local.jpg 放在脚本同目录下
try:
    image = io.imread('https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/200px-Google_%22G%22_Logo.svg.png')
    print(f"图片形状: {image.shape}") # 输出 (高度, 宽度, 通道数)
except:
    print("无法从网络加载图片,请准备本地图片。")
    # 创建一个示例彩色数组
    image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
# 将图片转换为灰度图 (一种简单的方法是取颜色通道的平均值)
# image 的形状是 (height, width, 3)
# 沿着最后一个轴 (axis=2) 求平均
gray_image = np.mean(image, axis=2).astype(np.uint8)
print(f"灰度图形状: {gray_image.shape}")
# 增加图片亮度 (向量化运算的威力)
brighter_image = gray_image + 50
# 注意:像素值不能超过255,NumPy 会自动处理 (称为溢出,但结果可能不对)
# 更安全的做法是使用 np.clip
brighter_image_safe = np.clip(gray_image + 50, 0, 255)
# 显示图片 (需要安装 matplotlib: pip install matplotlib)
try:
    import matplotlib.pyplot as plt
    plt.figure(figsize=(10, 5))
    plt.subplot(1, 3, 1)
    plt.title("Original")
    plt.imshow(image)
    plt.subplot(1, 3, 2)
    plt.title("Gray")
    plt.imshow(gray_image, cmap='gray')
    plt.subplot(1, 3, 3)
    plt.title("Brighter (Safe)")
    plt.imshow(brighter_image_safe, cmap='gray')
    plt.show()
except ImportError:
    print("matplotlib 未安装,无法显示图片。")

这个例子展示了如何将一张图片表示为数组,并利用 NumPy 的强大功能进行快速处理,而无需编写任何像素级别的循环。


总结与进阶学习

  • NumPy 是 Python 科学计算的基石,提供了高性能的多维数组对象 ndarray
  • 核心优势向量化运算,避免了 Python 层面的循环,速度极快。
  • 关键特性:统一的数据类型、丰富的数学函数、强大的索引和切片能力。
  • 必须掌握的属性.shape, .dtype, .ndim, .size
  • 必须掌握的函数np.array(), np.zeros(), np.ones(), np.arange(), np.linspace(), np.sum(), np.mean(), np.max(), (矩阵乘法)。

进阶学习

当你掌握了这些基础知识后,可以继续学习:

  • 广播:NumPy 如何处理不同形状数组之间的运算。
  • 排序、搜索和计数np.sort(), np.argsort(), np.where() 等。
  • 文件 I/O:使用 np.save()np.load() 保存和加载数组。
  • 更多线性代数函数:在 numpy.linalg 子模块中,如 np.linalg.inv() (求逆), np.linalg.eig() (求特征值)。
  • 结合 Pandas:学习 NumPy 如何与 Pandas 的 DataFrame 对象协同工作。

希望这份教程能帮助你顺利入门 NumPy!多动手实践,尝试创建数组、进行运算,你会发现它非常直观和强大。

分享:
扫描分享到社交APP
上一篇
下一篇