NumPy 基础操作
NumPy 基础操作
📝 概述
NumPy(Numerical Python)是Python中最重要的科学计算库,提供了高性能的多维数组对象和用于处理这些数组的工具。本文档介绍NumPy的基础概念、数组创建、基本操作和常用功能。
🎯 学习目标
- 理解NumPy数组(ndarray)的基本概念和属性
- 掌握各种数组创建方法
- 学会数组的基本运算和操作
- 了解数组的索引、切片和布尔索引
- 掌握数组的形状变换和轴操作
📋 前置知识
- Python基础语法
- 列表和元组的基本操作
- 基本的数学概念(矩阵、向量)
🔍 详细内容
数组的基本概念
ndarray的核心属性
import numpy as np
# 创建一个示例数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
# 查看数组的基本属性
print(f"数组形状: {arr.shape}") # (2, 3)
print(f"数组维度: {arr.ndim}") # 2
print(f"数据类型: {arr.dtype}") # int64
print(f"元素总数: {arr.size}") # 6
print(f"每个元素字节数: {arr.itemsize}") # 8
轴(axis)的概念
# 对于2维数组:axis=0表示行方向,axis=1表示列方向
arr_2d = np.array([[1, 2, 3], [4, 5, 6]])
print(f"沿axis=0求和: {np.sum(arr_2d, axis=0)}") # [5 7 9]
print(f"沿axis=1求和: {np.sum(arr_2d, axis=1)}") # [6 15]
# 对于3维数组:axis=0是最外层,然后依次向内
arr_3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(f"3维数组形状: {arr_3d.shape}") # (2, 2, 2)
数组创建方法
基本创建函数
| 函数 | 描述 | 示例 |
|---|---|---|
array |
从列表、元组等序列创建数组 | np.array([1, 2, 3]) |
asarray |
转换为数组,如果已是数组则不复制 | np.asarray([1, 2, 3]) |
arange |
类似range的数组版本 | np.arange(0, 10, 2) |
linspace |
在指定区间内生成等间距数组 | np.linspace(0, 1, 5) |
# 从Python列表创建数组
list_data = [1, 2, 3, 4, 5]
arr_from_list = np.array(list_data)
print(f"从列表创建: {arr_from_list}")
# 使用arange创建等差数组
arr_range = np.arange(0, 10, 2) # [0 2 4 6 8]
print(f"arange创建: {arr_range}")
# 使用linspace创建等间距数组
arr_linspace = np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1. ]
print(f"linspace创建: {arr_linspace}")
特殊值数组创建
# 全零数组
zeros_arr = np.zeros((3, 4)) # 3行4列的全零数组
print(f"全零数组:\n{zeros_arr}")
# 全一数组
ones_arr = np.ones((2, 3), dtype=np.int32) # 指定数据类型
print(f"全一数组:\n{ones_arr}")
# 单位矩阵
eye_arr = np.eye(3) # 3x3单位矩阵
print(f"单位矩阵:\n{eye_arr}")
# 指定值填充的数组
full_arr = np.full((2, 3), 7) # 用7填充的2x3数组
print(f"指定值数组:\n{full_arr}")
# 未初始化数组(值不确定)
empty_arr = np.empty((2, 2))
print(f"空数组:\n{empty_arr}")
随机数组创建
# 设置随机种子以获得可重复结果
np.random.seed(42)
# 标准正态分布随机数
randn_arr = np.random.randn(3, 3)
print(f"标准正态分布:\n{randn_arr}")
# 均匀分布随机数
rand_arr = np.random.rand(2, 4) # [0, 1)区间
print(f"均匀分布:\n{rand_arr}")
# 指定范围的随机整数
randint_arr = np.random.randint(1, 10, size=(3, 3))
print(f"随机整数:\n{randint_arr}")
数据类型和类型转换
NumPy数据类型
| 类型 | 类型代码 | 描述 |
|---|---|---|
int8, uint8 |
i1, u1 |
8位有符号/无符号整数 |
int16, uint16 |
i2, u2 |
16位有符号/无符号整数 |
int32, uint32 |
i4, u4 |
32位有符号/无符号整数 |
int64, uint64 |
i8, u8 |
64位有符号/无符号整数 |
float16 |
f2 |
半精度浮点数 |
float32 |
f4 |
单精度浮点数 |
float64 |
f8 |
双精度浮点数 |
complex64 |
c8 |
64位复数 |
bool |
? |
布尔类型 |
# 创建时指定数据类型
int_arr = np.array([1, 2, 3], dtype=np.int32)
float_arr = np.array([1.0, 2.0, 3.0], dtype=np.float32)
print(f"整数数组类型: {int_arr.dtype}")
print(f"浮点数组类型: {float_arr.dtype}")
# 类型转换
original = np.array([1.7, 2.3, 3.9])
int_converted = original.astype(np.int32)
print(f"原数组: {original}")
print(f"转换后: {int_converted}")
# 使用另一个数组的数据类型
template = np.array([1, 2, 3], dtype=np.float64)
converted = original.astype(template.dtype)
print(f"使用模板类型转换: {converted}")
数组的转置和轴变换
转置是一种特殊的数据重组形式,可以返回底层数据的视图而不需要复制任何内容。数组拥有transpose方法,也有特殊的T属性。

# 创建示例数组
arr = np.arange(12).reshape(3, 4)
print(f"原数组:\n{arr}")
# 转置操作
transposed = arr.T # 或者 arr.transpose()
print(f"转置后:\n{transposed}")
# 示例:转置操作
a = np.arange(15).reshape(5, 3)
print(a.T)
# 返回结果:
# [[ 0 3 6 9 12]
# [ 1 4 7 10 13]
# [ 2 5 8 11 14]]
# 高维数组的轴变换
arr_3d = np.arange(24).reshape(2, 3, 4)
print(f"3D数组形状: {arr_3d.shape}")
# 指定轴的顺序进行转置
transposed_3d = arr_3d.transpose(1, 0, 2) # 交换轴0和轴1
print(f"轴变换后形状: {transposed_3d.shape}")
# 交换任意两个轴
swapped = arr_3d.swapaxes(0, 2) # 交换轴0和轴2
print(f"轴交换后形状: {swapped.shape}")
数组的基本运算
算术运算
# 创建示例数组
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
# 基本算术运算(元素级别)
print(f"加法:\n{a + b}")
print(f"减法:\n{a - b}")
print(f"乘法:\n{a * b}")
print(f"除法:\n{a / b}")
print(f"幂运算:\n{a ** 2}")
# 与标量的运算
print(f"数组乘以标量:\n{a * 3}")
print(f"数组加标量:\n{a + 10}")
比较运算和布尔操作
# 比较运算
arr = np.array([1, 2, 3, 4, 5])
print(f"大于3: {arr > 3}") # [False False False True True]
print(f"等于3: {arr == 3}") # [False False True False False]
# 布尔索引
filtered = arr[arr > 3] # 选择大于3的元素
print(f"筛选结果: {filtered}") # [4 5]
# 复合条件
complex_filter = (arr > 2) & (arr < 5) # 注意使用&而不是and
print(f"复合条件: {arr[complex_filter]}") # [3 4]
# 布尔数组的统计
print(f"满足条件的元素个数: {(arr > 3).sum()}")
print(f"是否有元素大于10: {(arr > 10).any()}")
print(f"是否所有元素都大于0: {(arr > 0).all()}")
数组索引和切片
基本索引
# 一维数组索引
arr_1d = np.arange(10)
print(f"第3个元素: {arr_1d[2]}")
print(f"最后一个元素: {arr_1d[-1]}")
print(f"切片[2:7]: {arr_1d[2:7]}")
# 二维数组索引
arr_2d = np.arange(12).reshape(3, 4)
print(f"第2行第3列: {arr_2d[1, 2]}")
print(f"第2行所有列: {arr_2d[1, :]}")
print(f"所有行第3列: {arr_2d[:, 2]}")
print(f"子矩阵: \n{arr_2d[1:3, 1:3]}")
花式索引
# 使用整数数组进行索引
arr = np.arange(20)
indices = [1, 3, 5, 7]
print(f"花式索引结果: {arr[indices]}")
# 二维数组的花式索引
arr_2d = np.arange(12).reshape(3, 4)
row_indices = [0, 2]
col_indices = [1, 3]
print(f"选择特定位置: {arr_2d[row_indices, col_indices]}")
# 组合使用
print(f"选择多行: \n{arr_2d[[0, 2]]}")
print(f"选择多行多列: \n{arr_2d[[0, 2]][:, [1, 3]]}")
数组形状操作
reshape和resize
# reshape:返回新视图,不改变原数组
arr = np.arange(12)
reshaped = arr.reshape(3, 4)
print(f"重塑为3x4:\n{reshaped}")
# 自动计算维度
auto_reshaped = arr.reshape(3, -1) # -1表示自动计算
print(f"自动计算维度:\n{auto_reshaped}")
# resize:直接修改原数组
arr_copy = arr.copy()
arr_copy.resize(2, 6)
print(f"resize后:\n{arr_copy}")
数组展平
arr_2d = np.arange(12).reshape(3, 4)
# flatten:返回副本
flattened = arr_2d.flatten()
print(f"flatten结果: {flattened}")
# ravel:返回视图(如果可能)
raveled = arr_2d.ravel()
print(f"ravel结果: {raveled}")
# 验证是否为视图
raveled[0] = 999
print(f"修改ravel后原数组:\n{arr_2d}") # 原数组也会改变
💡 实际应用
基础用法示例
# 计算数组的基本统计信息
data = np.random.randn(1000)
print(f"均值: {np.mean(data):.4f}")
print(f"标准差: {np.std(data):.4f}")
print(f"最大值: {np.max(data):.4f}")
print(f"最小值: {np.min(data):.4f}")
矩阵运算示例
# 矩阵乘法
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
# 元素级乘法
element_wise = A * B
print(f"元素级乘法:\n{element_wise}")
# 矩阵乘法
matrix_mult = np.dot(A, B) # 或者 A @ B
print(f"矩阵乘法:\n{matrix_mult}")
数据处理示例
# 处理缺失值
data_with_nan = np.array([1.0, 2.0, np.nan, 4.0, 5.0])
# 检测NaN
nan_mask = np.isnan(data_with_nan)
print(f"NaN位置: {nan_mask}")
# 移除NaN
clean_data = data_with_nan[~nan_mask]
print(f"清理后数据: {clean_data}")
# 用0替换NaN
data_filled = np.where(np.isnan(data_with_nan), 0, data_with_nan)
print(f"填充后数据: {data_filled}")
⚠️ 注意事项
- 数组切片返回视图:修改切片会影响原数组
- 数据类型转换:可能导致精度损失或溢出
- 广播规则:不同形状数组运算时要注意广播规则
- 内存使用:大数组操作时注意内存消耗
- 布尔运算符:使用
&、|、~而不是and、or、not
🔗 相关内容
📚 扩展阅读
🏷️ 标签
numpy 数组 数值计算 科学计算 线性代数 数据类型 索引 切片 形状操作
最后更新: 2024-01-15
作者: Python技术文档工程师
版本: 1.0.0
讨论与反馈
欢迎在下方留言讨论,分享你的学习心得或提出问题。评论基于GitHub Issues,需要GitHub账号。