NumPy 入门:ndarray、向量化计算与广播机制

从 ndarray、索引切片、形状变换到向量化与广播,建立 NumPy 作为数据分析底层数组库的核心认知。

一、NumPy 是做什么的

NumPy 是 Python 数据分析里的底层数组库,很多上层库都会用到它。可以先把三剑客理解成:NumPy 负责数值数组和数学计算,Pandas 负责表格数据处理,Matplotlib 负责可视化;相比原生 list,NumPy 的 ndarray 类型更统一、运算更适合批量计算也就是向量化,也更容易发挥性能优势。

二、核心对象:ndarray

NumPy 最核心的数据结构是 ndarray,也就是 N 维数组。

import numpy as np

arr = np.array([1, 2, 3, 4])

print(arr) #[1 2 3 4]
print(type(arr)) # <class 'numpy.ndarray'>
print(arr.dtype) #int64
print(arr.shape) #输出数组形状,这里是一维数组,所以结果是 (4,)

输出中几个最常见的信息:

  • dtype 表示元素类型,例如 int64float64
  • shape 表示数组形状,例如 (4,)(3, 2)
  • ndim 表示数组维度数量

二维数组也很常见:

matrix = np.array([
    [1, 2, 3],
    [4, 5, 6],
])

print(matrix.shape)  # (2, 3)
print(matrix.ndim)   # 2

三、创建数组的常见方式

import numpy as np

zeros = np.zeros((2, 3))      # 参数 (2, 3) 表示生成 2 行 3 列的全 0 数组
ones = np.ones((2, 3))        # 参数 (2, 3) 表示生成 2 行 3 列的全 1 数组
seq = np.arange(0, 10, 2)     # 参数依次表示起始值 0、结束值 10(不包含)、步长 2
line = np.linspace(0, 1, 5)   # 参数依次表示起点 0、终点 1、平均取 5 个点

print(zeros) 
"""
[[0. 0. 0.]
 [0. 0. 0.]]
"""
print(ones) 
'''
[[1. 1. 1.]
 [1. 1. 1.]]
'''
print(seq) #[0 2 4 6 8]
print(line) #[0.   0.25 0.5  0.75 1.  ]

这些函数在数据分析中非常常见:

  • np.zeros() 创建全 0 数组
  • np.ones() 创建全 1 数组
  • np.arange() 按步长生成序列
  • np.linspace() 按区间平均生成指定数量的点

四、索引、切片与形状变换

import numpy as np

arr = np.array([
    [10, 20, 30],
    [40, 50, 60],
    [70, 80, 90],
])

print(arr[0, 1])      # 20
print(arr[:, 0])      # 第一列
print(arr[1:3, 1:3])  # 子区域
"""
20
[10 40 70]
[[50 60]
 [80 90]]
"""

变换形状时常用:

import numpy as np

nums = np.arange(1, 13)   # 生成 1 到 12 的一维数组,13 不包含在内
grid = nums.reshape(3, 4) # 把这 12 个元素重新排成 3 行 4 列的二维数组

print(grid)
"""
[[1 2 3 4]
 [5 6 7 8]
 [9 10 11 12]]
"""
print(nums.shape)  # 打印结果: (12,) 表示原始数据是一维数组,共 12 个元素
print(grid.shape)  # 打印结果: (3, 4) 表示重塑后变成 3 行 4 列

需要注意的是,reshape() 只是换一种视角理解数据,前提是元素总数一致。

五、向量化:NumPy 的性能关键

很多初学者第一次接触 NumPy 时,会觉得“它和列表好像也差不多”,真正的差别在于向量化运算。 向量化的核心思想是:把“单个处理”变成“批量处理”。

import numpy as np

prices = np.array([10, 20, 30])
counts = np.array([2, 3, 4])

total = prices * counts
print(total)          # [20 60 120]
print(total.sum())    # 200

这类批量计算不需要自己写 for 循环,代码通常更短,也更容易利用底层优化。

常见向量化操作包括:

  • 数组与数组的四则运算
  • 数组与标量的四则运算
  • 聚合统计,例如 sum()mean()max()

什么是“标量”(Scalar)?
在数学和编程中,标量指的是“单个的数值”。
它只有一个维度,没有长度、宽度或形状。比如:1、3.14、-5、0.5。
与之相对的是“向量”或“数组”,它们是一组数据的集合(比如 [1, 2, 3])。

四则运算就是我们在小学数学里学的最基本的四种计算:加、减、乘、除。

六、布尔索引:按条件筛选数据

除了按位置切片,NumPy 还非常常用于“按条件取数据”。

import numpy as np

scores = np.array([58, 72, 91, 84, 66])

mask = scores >= 80
print(mask)          # [False False  True  True False]
print(scores[mask])  # [91 84]
print(scores[scores >= 80])  #[91 84] # 也可以直接把条件写进索引里

这里的核心直觉是:

  • 条件表达式会先得到一个由 True / False 组成的布尔数组
  • 再用这个布尔数组去筛选原数组中满足条件的元素

多个条件组合时,也很常见:

import numpy as np

scores = np.array([58, 72, 91, 84, 66])

result = scores[(scores >= 60) & (scores < 90)]
print(result)  # [72 84 66]

要特别注意:

  • NumPy 中组合条件通常用 &|
  • 每个条件两边最好都加上括号

七、广播:不同形状也能参与运算

广播是 NumPy 中非常高频、也最容易让初学者困惑的机制。

import numpy as np

scores = np.array([
    [80, 85, 90],
    [70, 88, 95],
])

bonus = np.array([5, 3, 2])

final_scores = scores + bonus
print(final_scores)
"""
[[85 88 92]
 [75 91 97]]
"""

这里 scores 的形状是 (2, 3)bonus 的形状是 (3,)。NumPy 会自动把 bonus 理解为“每一行都加同一组列补偿值”,这就是广播。

可以先记住一个实用直觉:

  • 维度相同,按位置运算
  • 维度不同但某一侧是 1,可能触发广播
  • 维度既对不上,也无法扩展时,就会报错

八、NumPy 在数据分析中的典型用途

在真实项目里,NumPy 很少单独作为“业务层主角”,但它经常出现在这些场景:

  • 存储大批量数值数据
  • 做矩阵和向量计算
  • 进行统计预处理
  • 为机器学习模型准备特征矩阵
  • 作为 Pandas 底层数组能力的支撑

九、一个简单示例:计算各科平均分

import numpy as np

scores = np.array([        # 3 行 3 列的二维数组,可以理解为 3 位学生的 3 门成绩
    [88, 76, 90],          # 第 1 位学生的成绩
    [92, 81, 85],          # 第 2 位学生的成绩
    [79, 95, 87],          # 第 3 位学生的成绩
])

subject_mean = scores.mean(axis=0)  # 按列求平均,得到每一门学科的平均分
student_mean = scores.mean(axis=1)  # 按行求平均,得到每一位学生的平均分

print("各科平均分:", subject_mean)
print("每位学生平均分:", student_mean)

这里:

  • axis=0 表示按列聚合
  • axis=1 表示按行聚合

这是 NumPy、Pandas 中都非常常见的思维方式。

十、学习 NumPy 时最容易踩的坑

  • 把 NumPy 当成“支持更多语法的列表”,忽略了它的数组思维
  • 不清楚 shapendimaxis 的含义
  • 写条件筛选时把 &| 和 Python 原生的 andor 混在一起
  • 广播规则只靠背,没结合实际例子理解
  • 明明已经是数组运算,还继续写很多 Python 循环

小结

NumPy 解决的是“高效处理数值数组”这个基础问题。它不是数据分析里最贴近业务语义的库,却是很多分析任务最底层的算力基础。

理解了 ndarray、布尔索引、向量化和广播,你再去学习 Pandas 和机器学习相关库时,会轻松很多。