NumPy 中数组的核心概念与操作技巧

发布日期 :2026-09-07 07:55:54 UTC

作者 :xuzhiping

访问量: 10 次浏览

一、学习目标

1.分清 NumPy 数组 ndarray 与 Python 原生 list 列表的本质差异

2.熟练多种 NumPy 数组创建方式

3.掌握 NumPy 常用数据类型以及类型转换

4.完成数组基础运算、聚合统计操作

5.理解并使用广播机制

6.运用数学、统计函数处理实际数据

二、为什么学习 NumPy

1.速度优势:百万级数字求和,Python 列表约 50ms,NumPy 约 1ms,速度提升数十倍,数据量越大差距越明显。

2.功能优势:列表只适合简单存储遍历;ndarray 原生支持矩阵运算、统计分析、线性代数等高级数值操作。

3.生态地位:是数据分析库的底层通用基础。

比喻:Python 列表相当于普通收纳盒,类型混杂,检索计算慢;NumPy 数组相当于智能收纳柜,内存规整,自带批量计算能力。

三、认识 ndarray:NumPy 核心数据结构

1. ndarray 概念

ndarray 即 N‑dimensional Array,N 维数组,要求全部元素必须为同一种数据类型,是多维容器。

和 Python 列表关键区别:

  • Python list:允许存放不同类型元素;运算需要循环;内存分散;运行速度慢;只提供基础存储功能。
  • NumPy ndarray:元素类型统一;支持向量化运算;内存紧凑连续;运算速度快;矩阵、统计功能丰富。

2. ndarray 运行速度快的三点原因

1.内存连续存储:所有元素在内存地址上紧密排列,CPU 缓存读取效率高。

2.底层 C 语言实现:核心计算逻辑用 C 编写,避开 Python 解释器开销。

3.SIMD 指令集优化:利用 CPU 单指令多数据,实现并行计算。

3. ndarray 常用核心属性

import numpy as np
arr = np.array([[1, 2, 3],[4, 5, 6]])
print(f"维度数量 ndim:{arr.ndim}")
print(f"数组形状 shape:{arr.shape}") #(2,3)代表2行3列
print(f"元素总个数 size:{arr.size}")
print(f"元素数据类型 dtype:{arr.dtype}")
print(f"单个元素字节 itemsize:{arr.itemsize}")
print(f"整体占用字节 nbytes:{arr.nbytes}")
  • ndim:维度 / 轴的数量;
  • shape:元组格式,描述每一维长度,二维为 (行,列);
  • size:所有元素总数量;
  • dtype:数组内元素的数据类型;
  • itemsize:单个元素占用字节;
  • nbytes:整个数组占用内存总字节。

四、NumPy 数组的 4 种创建方式

方式 1:由 Python 列表、元组转换

#一维数组
arr1 = np.array([1,2,3,4,5])
#二维嵌套列表
arr2 = np.array([[1,2,3],[4,5,6]])
#元组转数组
arr3 = np.array((10,20,30))
#创建时指定数据类型
arr4 = np.array([1,2,3],dtype=np.float64)

方式 2:内置函数生成特殊数组

np.zeros((3,4))     #3行4列全0
np.ones((2,3))      #2行3列全1
np.full((2,2),7)    #全部填充数字7
np.eye(3)           #3阶单位矩阵,对角线为1
np.diag([1,2,3])    #对角矩阵

方式 3:生成数值序列

np.arange(10)               #0‑9,类似range
np.arange(2,10,2)           #起点、终点、步长
np.linspace(0,1,5)          #等间距,包含终点
np.logspace(0,2,5)          #等比数列
x = np.linspace(-np.pi,np.pi,100) #绘图x轴坐标

方式 4:生成随机数组

np.random.seed(42) #设置随机种子,保证结果复现
np.random.rand(3,3)        #[0,1)均匀分布
np.random.randn(3,3)      #标准正态分布,均值0,标准差1
np.random.randint(1,100,size=(3,4)) #指定范围整数
np.random.choice(['A','B','C','D'],size=10) #从集合抽样

随机数常用于模拟数据、A/B 测试、抽样、机器学习权重初始化。

五、NumPy 数据类型

常用类型

  • 整数:int8、int16、int32、int64;无符号 uint8(0‑255,图像像素常用)
  • 浮点数:float16、float32、float64(系统默认浮点)
  • 布尔:bool_
  • 字符串:U 类型,U5 代表最多 5 个字符

类型转换 astype ()

arr = np.array([1,2,3,4,5])
arr_float = arr.astype(np.float64)
arr_bool = arr.astype(bool)
arr_str = arr.astype(str)

#浮点转整数会直接截断,不是四舍五入
arr_big = np.array([1.7,2.9,3.1])
arr_int = arr_big.astype(np.int32) #输出[1,2,3]

六、数组基本运算

1. 算术运算:向量化逐元素运算,不需要 for 循环

a = np.array([10,20,30,40])
b = np.array([1,2,3,4])
print(a+b)
print(a-b)
print(a*b)
print(a/b)
print(a//b) #整除
print(a%b)  #取余
print(a**2) #幂运算

#数组和标量直接运算
print(a+5)
print(a*2)

2. 比较运算:返回布尔数组

a = np.array([10,20,30,40,50])
print(a>25)
print(a==30)
print(a!=20)
#多条件使用& |,注意加括号
print((a>=20)&(a<=40))

3. 聚合统计运算

scores = np.array([85,92,78,96,88,73,95,81])
scores.sum()    #总和
scores.mean()   #平均值
scores.std()    #标准差
scores.var()    #方差
scores.max()    #最大值
scores.min()    #最小值
scores.argmax() #最大值索引
scores.argmin() #最小值索引
np.median(scores) #中位数
scores.cumsum() #累计求和

4. 多维数组 axis 轴参数

axis=N: 沿着第 N 个维度做压缩;axis=0 按列运算(压缩行);axis=1 按行运算(压缩列);不写 axis,对全部元素计算。

matrix = np.array([[1,2,3],[4,5,6],[7,8,9]])
matrix.sum(axis=0) #按列求和
matrix.sum(axis=1) #按行求和
matrix.sum()       #全部元素求和

七、索引与切片

一维数组索引切片

arr = np.array([10,20,30,40,50,60])
arr[0]      #正向索引,从0开始
arr[-1]     #负向索引,倒数第一个
arr[:3]     #切片 start:stop:step
arr[2:]
arr[::2]
arr[::-1]   #数组反转

二维数组索引切片

matrix = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
matrix[1,2]         #第2行第3列
matrix[0]           #取一行
matrix[:2]          #前两行
matrix[:,1]         #取第2列
matrix[:,1:3]       #第2‑3列
matrix[1:3,1:3]     #同时切片行列

重点陷阱:切片默认返回视图(view),和原数组共享内存,修改切片内容会改变原数组;需要独立副本调用.copy()

sub = matrix[:2,:2].copy() #生成独立副本,修改不影响原数组

八、广播机制 Broadcasting

广播允许不同形状数组直接运算,自动扩展维度,不需要手动循环。

广播三条规则

1.如果两个数组维度数量不一致,维度少的数组在前面自动补维度 1;

2.对应维度长度,如果相等,或者其中一个等于 1,就可以广播扩展;

3.对应维度长度都不等于 1,且数值不一样,广播失败,抛出异常。

示例

#数组+标量
arr = np.array([1,2,3])
arr + 10

#二维数组 + 一维数组
matrix = np.array([[1,2,3],[4,5,6]])
row_add = np.array([10,20,30])
matrix + row_add

#列向量+行向量
col = np.array([[1],[2],[3]]) #shape(3,1)
row = np.array([10,20,30])    #shape(3,)
col + row

广播失败示例

a = np.array([[1,2,3],[4,5,6]]) #shape(2,3)
b = np.array([1,2])             #shape(2,)
# a + b 会报错,末尾维度3和2,都不为1,不能广播

九、常用数学函数

x = np.array([0, np.pi/6, np.pi/4, np.pi/3, np.pi/2])
np.sin(x)
np.cos(x)
np.tan(x)
np.exp(x)
np.log(x+1)
np.log10(x+1)

numbers = np.array([1.2,2.5,3.7,4.49,5.5])
np.round(numbers) #四舍五入
np.ceil(numbers)  #向上取整
np.floor(numbers) #向下取整
np.trunc(numbers) #直接截断小数

neg = np.array([-3,-2,-1,0,1,2,3])
np.abs(neg)
np.sign(neg) #符号函数

十、综合实战案例

实战 1:学生成绩分析系统

模拟 30 名学生,5 门课程成绩,完成各科统计、个人总分平均分、找出单科最高分、成绩等级统计。

import numpy as np
np.random.seed(42)
n_students = 30
n_subjects = 5
subjects = ['语文','数学','英语','物理','化学']
scores = np.random.normal(70,15,(n_students,n_subjects))
scores = np.clip(scores,0,100)
scores = np.round(scores,1)

#各科统计
for i,subject in enumerate(subjects):
    col = scores[:,i]
    print(f"{subject}:平均={col.mean():.1f},最高={col.max():.1f},最低={col.min():.1f},标准差={col.std():.1f}")

total_scores = scores.sum(axis=1)
avg_scores = scores.mean(axis=1)
print(f"班级总平均分:{avg_scores.mean():.1f}")
print(f"最高总分:{total_scores.max():.1f}")
print(f"最低总分:{total_scores.min():.1f}")

#单科最高分学生
for i,subject in enumerate(subjects):
    best = scores[:,i].argmax()
    print(f"{subject}最高分:学生{best+1}号,{scores[best,i]}分")

实战 2:矩阵运算实现图像灰度处理

模拟 4×4 的 RGB 图像,按公式Gray = 0.299*R + 0.587*G +0.114*B转为灰度,再做二值化。

import numpy as np
np.random.seed(42)
image = np.random.randint(0,256,(4,4,3),dtype=np.uint8)
weights = np.array([0.299,0.587,0.114])
gray = np.dot(image,weights)
gray = np.round(gray).astype(np.uint8)
binary = (gray>128).astype(np.uint8)*255 #阈值128二值化
print("灰度图\n",gray)
print("二值图\n",binary)

十一、实战练习题

练习 1:数组创建基础

1.创建 0‑9 一维数组;

2.创建 3 行 4 列全 1 数组;

3.创建 4 阶单位矩阵;

4.创建 1‑100 之间全部 3 的倍数组成的数组。

arr1 = np.arange(10)
arr2 = np.ones((3,4))
arr3 = np.eye(4)
arr4 = np.arange(3,101,3)

练习 2:统计分析

营业额数据[1200,1500,1800,1350,2100,2800,2500],求日均营业额、标准差、高于日均的日期、预估 30 天总收入。

revenue = np.array([1200,1500,1800,1350,2100,2800,2500])
daily_avg = revenue.mean()
std = revenue.std()
above_avg = revenue>daily_avg
days = np.array(['周一','周二','周三','周四','周五','周六','周日'])
monthly = daily_avg*30

练习 3:广播机制应用

5 名学生,3 门课程成绩矩阵,1. 每个学生成绩减去本人平均分;2. 每门课数据除以该科最高分,归一化到 0‑1。

scores = np.array([[85,90,78],[92,88,95],[76,82,88],[95,91,89],[70,75,80]])
row_mean = scores.mean(axis=1,keepdims=True)
centered = scores - row_mean
col_max = scores.max(axis=0)
normalized = scores / col_max

练习 4:向量化思维训练

不写 for 循环,计算 1‑1000 所有偶数的平方和

numbers = np.arange(1,1001)
even = numbers[numbers%2==0]
res = (even**2).sum()
#简写 np.sum(np.arange(2,1001,2)**2)

十二、全文总结

1.ndarray 是 NumPy 的核心,重点掌握 ndim、shape、size、dtype;

2.数组有多种创建途径,按需选择;

3.dtype 控制数据类型,astype 完成转换,注意浮点转整数直接截断;

4.向量化运算替代 for 循环,批量逐元素计算;

5.axis 轴参数:axis=0 按列,axis=1 按行,多维统计必备;

6.切片返回视图会共享内存,修改原数组,需要副本调用.copy()

7.广播是 NumPy 高级特性,记住三条广播规则;

8.NumPy 编程思想:尽量少写循环,优先使用数组操作。