目录
(11)使用 np.stack, np.concatenate, np.vstack, np.hstack:
一、NumPy概述:
NumPy(Numerical Python的缩写)是一个开源的Python科学计算库。它提供了一个强大的N维数组对象ndarray
和用于操作这些数组的工具和函数。NumPy是许多其他科学计算和数据分析库(如SciPy、Pandas、Matplotlib、Scikit-learn等)的基础。
(1)NumPy的主要特点包括:
-
多维数组对象(ndarray):
- NumPy的核心是一个强大的N维数组对象,它比Python原生的列表更加高效,因为它提供了连续内存块的快速操作。
-
广泛的数学函数库:
- 提供了大量的数学函数,用于在数组上进行各种计算,包括统计、代数、傅里叶变换、随机数生成等。
-
高效的操作:
- NumPy的数组操作是高度优化的,可以利用底层的C语言和Fortran代码来提高性能。
-
广播功能:
- 允许不同形状的数组在算术运算中协同工作,无需显式地匹配维度。
-
索引和切片:
- 提供了强大的索引和切片功能,可以方便地访问和修改数组的子集。
-
输入和输出:
- 可以轻松地将数组保存到磁盘(使用
np.save
、np.savez
等)和从磁盘加载(使用np.load
),也可以与其他格式(如CSV、TXT、JSON等)进行转换。
- 可以轻松地将数组保存到磁盘(使用
-
线性代数、傅里叶变换和随机数生成:
- 提供了线性代数运算、傅里叶变换和随机数生成的功能,这些都是科学计算中常见的需求。
(2)NumPy的安装:
- 通常,NumPy可以通过Python的包管理器pip来安装:
pip install numpy
(3)NumPy的使用示例:
import numpy as np
# 创建一个NumPy数组
arr = np.array([1, 2, 3, 4, 5])
# 数组的加法
arr2 = np.array([5, 4, 3, 2, 1])
result = arr + arr2
# 打印结果
print(result)
# 创建一个2x3的二维数组
matrix = np.array([[1, 2, 3], [4, 5, 6]])
# 打印矩阵
print(matrix)
# 矩阵转置
print(matrix.T)
运行结果:
二、ndarray对象:
ndarray
是 NumPy 中的核心数据结构,它是一个多维数组对象,用于有效地存储和操作大规模数据集。ndarray
在内部由同类型数据的连续块组成,这使得它在执行数组操作时非常高效。
(1)ndarray
的主要特点包括:
-
同质性:
ndarray
中的所有元素必须是相同类型的。这意味着数组中的数据类型是一致的,例如,一个数组可以包含整数、浮点数或布尔值,但不能同时包含多种类型。
-
固定形状:
- 一旦创建,
ndarray
的形状(即维度大小)是固定的。如果需要改变形状,通常会创建一个新的数组。
- 一旦创建,
-
快速操作:
ndarray
支持快速的数组操作,包括元素级运算、切片、索引、广播等。
-
广播:
- 广播是一种强大的机制,它允许 NumPy 用不同形状的数组进行算术运算,而不需要显式地匹配维度。
-
切片:
- 可以通过切片来访问
ndarray
的子集,切片操作返回原始数组的视图,而不是副本。
- 可以通过切片来访问
-
索引:
- 可以通过索引来访问、修改或赋值
ndarray
中的单个元素或元素组。
- 可以通过索引来访问、修改或赋值
-
内存效率:
ndarray
在内存中紧凑地存储数据,这使得它在处理大型数据集时非常高效。
(2)创建 ndarray
的方法:
-
直接从列表创建:
import numpy as np array = np.array([1, 2, 3, 4, 5])
-
使用
np.zeros
创建全零数组:zeros_array = np.zeros((3, 4)) # 创建一个3x4的全零数组
-
使用
np.ones
创建全一数组:ones_array = np.ones((2, 2)) # 创建一个2x2的全一数组
-
使用
np.arange
创建范围数组:range_array = np.arange(10) # 创建一个包含0到9的数组
-
使用
np.empty
创建未初始化的数组:empty_array = np.empty((3, 3)) # 创建一个3x3的未初始化数组
(3)ndarray
的属性:
.shape
:返回数组的形状,即每个维度的大小。.size
:返回数组中元素的总数。.dtype
:返回数组中元素的数据类型。.ndim
:返回数组的维度数。
(4)ndarray
的操作示例:
np.array
是 NumPy 库中用于创建数组的函数。
- 函数原型:
numpy.array(object, dtype=None, copy=True, order='C', subok=False, ndmin=0)
-
参数
-
object : array_like
- 输入数据,可以是列表、元组、另一个数组或任何可迭代的对象。
np.array
将这些数据转换成 ndarray。
- 输入数据,可以是列表、元组、另一个数组或任何可迭代的对象。
-
dtype : data-type, optional
- 数据类型。默认为 None,这意味着数组的数据类型将由输入数据自动决定。如果指定,数组将被转换为这个数据类型。
-
copy : bool, optional
- 是否复制输入数据。默认为 True,意味着即使输入数据已经是一个 ndarray,也会创建数据的副本。如果设置为 False,而输入数据已经是一个 ndarray,并且不需要改变数据类型或不要求复制,那么将不会复制数据。
-
order : {'C', 'F', 'A', 'K'}, optional
- 创建数组的内存布局。'C' 表示按行主序(C风格的数组),'F' 表示按列主序(Fortran风格的数组),'A' 表示任意顺序(实际是 'C' 或 'F' 中的第一个),'K' 表示保持输入数据的顺序。
-
subok : bool, optional
- 默认为 False,意味着返回的数组将不是 numpy 子类。如果设置为 True,则允许创建 numpy 子类的实例。
-
ndmin : int, optional
- 要创建的数组的最小维度。默认为 0,这意味着输入数据可以是标量。如果输入数据是标量,将创建一个零维数组。
-
返回值:
- 返回一个新的 ndarray 对象。
-
示例:
import numpy as np
# 从列表创建数组
arr = np.array([1, 2, 3, 4, 5])
# 从元组创建数组
arr_tuple = np.array((1, 2, 3))
# 从另一个数组创建数组
arr_from_arr = np.array(arr)
# 指定数据类型
arr_dtype = np.array([1, 2, 3], dtype=np.float64)
# 指定数组的最小维度
arr_ndmin = np.array(1, ndmin=2) # 结果是一个 1x1 的数组
np.array
是创建 NumPy 数组的基础函数,它非常灵活,可以接受多种类型的输入,并允许在创建时定制数组的多个方面。
三、NumPy数据类型:
NumPy 是 Python 中用于科学计算的核心库,它提供了高性能的多维数组对象和一系列用于操作这些数组的工具。NumPy 的数据类型(dtype)非常重要,因为它们决定了数组中元素的存储方式和操作方式。
(1)常用的 NumPy 数据类型:
-
整数类型:
np.int8
: 8位整数(-128到127)np.int16
: 16位整数(-32768到32767)np.int32
: 32位整数(-2^31到2^31-1)np.int64
: 64位整数(-2^63到2^63-1)np.uint8
: 8位无符号整数(0到255)np.uint16
: 16位无符号整数(0到65535)np.uint32
: 32位无符号整数(0到2^32-1)np.uint64
: 64位无符号整数(0到2^64-1)
-
浮点数类型:
np.float16
: 16位半精度浮点数np.float32
: 32位单精度浮点数np.float64
: 64位双精度浮点数np.float128
: 128位扩展精度浮点数(某些系统上可能不可用)
-
复数类型:
np.complex64
: 复数,由两个32位浮点数表示实部和虚部np.complex128
: 复数,由两个64位浮点数表示实部和虚部np.complex256
: 复数,由两个128位浮点数表示实部和虚部(某些系统上可能不可用)
-
布尔类型:
np.bool_
: 布尔类型(True或False)
-
对象类型:
np.object
: 用于存储任意Python对象
-
字符串类型:
np.string_
: 字符串类型np.unicode_
: 用于存储Unicode字符串
-
无符号整数类型:
np.ubyte
,np.ushort
,np.uintc
,np.ulonglong
: 这些类型的大小和范围取决于平台。
-
时间类型:
np.datetime64
: 用于存储日期和时间np.timedelta64
: 用于存储两个日期或时间之间的差值
-
结构化数据类型:
- 可以定义为一系列具有不同数据类型的字段。
(2)代码示例:
import cv2
import numpy as np
# C:\\Users\\86173\\Desktop\\TI\\image\\faves.png
# 整数类型
int8_array = np.array([1, 2, 3], dtype=np.int8)
int16_array = np.array([1, 2, 3], dtype=np.int16)
int32_array = np.array([1, 2, 3], dtype=np.int32)
int64_array = np.array([1, 2, 3], dtype=np.int64)
uint8_array = np.array([1, 2, 3], dtype=np.uint8)
uint16_array = np.array([1, 2, 3], dtype=np.uint16)
uint32_array = np.array([1, 2, 3], dtype=np.uint32)
uint64_array = np.array([1, 2, 3], dtype=np.uint64)
# 浮点数类型
float16_array = np.array([1.0, 2.0, 3.0], dtype=np.float16)
float32_array = np.array([1.0, 2.0, 3.0], dtype=np.float32)
float64_array = np.array([1.0, 2.0, 3.0], dtype=np.float64)
#float128_array = np.array([1.0, 2.0, 3.0], dtype=np.float128) # 某些系统上可能不可用
# 复数类型
complex64_array = np.array([1+2j, 3+4j], dtype=np.complex64)
complex128_array = np.array([1+2j, 3+4j], dtype=np.complex128)
#complex256_array = np.array([1+2j, 3+4j], dtype=np.complex256) # 某些系统上可能不可用
# 布尔类型
bool_array = np.array([True, False, True])
# 对象类型
object_array = np.array([1, 'a', 3.14], dtype=object)
# 字符串类型
string_array = np.array(['hello', 'world'], dtype='S5') # 固定长度字符串
unicode_array = np.array(['你好', '世界'], dtype='U5') # 固定长度Unicode字符串
# 无符号整数类型
ubyte_array = np.array([1, 2, 3], dtype=np.ubyte)
ushort_array = np.array([1, 2, 3], dtype=np.ushort)
uintc_array = np.array([1, 2, 3], dtype=np.uintc)
ulonglong_array = np.array([1, 2, 3], dtype=np.ulonglong)
# 时间类型
datetime_array = np.array(['2021-01-01', '2021-01-02'], dtype='datetime64[D]')
timedelta_array = np.array([1, 2], dtype='timedelta64[D]')
# 结构化数据类型
dtype = [('field1', 'int32'), ('field2', 'float64')]
structured_array = np.array([(1, 2.0), (3, 4.0)], dtype=dtype)
# 打印数组和它们的数据类型
print("int8_array:", int8_array, "dtype:", int8_array.dtype)
print("float32_array:", float32_array, "dtype:", float32_array.dtype)
print("complex128_array:", complex128_array, "dtype:", complex128_array.dtype)
print("bool_array:", bool_array, "dtype:", bool_array.dtype)
print("object_array:", object_array, "dtype:", object_array.dtype)
print("string_array:", string_array, "dtype:", string_array.dtype)
print("unicode_array:", unicode_array, "dtype:", unicode_array.dtype)
print("datetime_array:", datetime_array, "dtype:", datetime_array.dtype)
print("structured_array:", structured_array, "dtype:", structured_array.dtype)
(3) np.dtype
类:
NumPy 还允许用户定义自己的数据类型,这可以通过继承 np.dtype
类或使用 np.dtype
的构造函数来实现。例如,你可以定义一个包含多个字段的数据类型,每个字段都有自己的数据类型。
- 定义和使用结构化数据类型的例子:
import numpy as np
# 定义一个结构化数据类型
dt = np.dtype([('name', 'S10'), ('height', 'f4'), ('age', 'i4')])
# 创建一个结构化数组
a = np.array([('Alice', 1.65, 25), ('Bob', 1.8, 30)], dtype=dt)
# 访问结构化数组的字段
print(a['name']) # 输出名字
print(a['height']) # 输出身高
print(a['age']) # 输出年龄
(4)内建类型的字符:
-
整数类型:
'i1'
: 8位有符号整数'i2'
: 16位有符号整数'i4'
: 32位有符号整数'i8'
: 64位有符号整数'u1'
: 8位无符号整数'u2'
: 16位无符号整数'u4'
: 32位无符号整数'u8'
: 64位无符号整数
-
浮点数类型:
'f2'
: 16位半精度浮点数(不常用)'f4'
: 32位单精度浮点数'f8'
: 64位双精度浮点数'f16'
: 128位扩展精度浮点数(某些系统上可能不可用)
-
复数类型:
'c8'
: 两个32位单精度浮点数的复数'c16'
: 两个64位双精度浮点数的复数'c32'
: 两个128位扩展精度浮点数的复数(某些系统上可能不可用)
-
布尔类型:
'b1'
: 布尔类型(True 或 False)
-
对象类型:
'O'
: 任意 Python 对象
-
字符串类型:
'S'
: 固定长度的字节字符串'U'
: 固定长度的 Unicode 字符串
-
日期和时间类型:
'datetime64'
: 64位日期和时间'timedelta64'
: 64位时间差
-
无符号整数类型:
'uint8'
: 8位无符号整数'uint16'
: 16位无符号整数'uint32'
: 32位无符号整数'uint64'
: 64位无符号整数
-
其他类型:
'bytes'
: 可变长度的字节字符串'str'
: 可变长度的 Unicode 字符串
四、数组属性:
在 NumPy 中,数组对象具有多个属性,这些属性提供了关于数组的有用信息。
(1)属性介绍:
-
ndarray.ndim:秩,
表示数组的维度数(轴的数量)。 -
ndarray.shape:
一个表示数组各维度大小的元组。 -
ndarray.size:
数组中元素的总数。 -
ndarray.dtype:
数组元素的数据类型。 -
ndarray.itemsize:
数组中每个元素的字节大小。 -
ndarray.data
::包含数组数据的缓冲区。 -
ndarray.strides:
一个元组,表示为了跳到下一个元素需要在每个维度上移动的字节数。 -
ndarray.nbytes:
数组所占用的总字节数。 -
ndarray.flags:
一个包含多个布尔标志的对象,例如C_CONTIGUOUS
(数组在 C 语言风格上是连续的)、F_CONTIGUOUS
(数组在 Fortran 风格上是连续的)、OWNDATA
(数组拥有自己的数据)等。 -
ndarray.real:
如果数组包含复数,则返回实部;否则,返回数组本身。 -
ndarray.imag:
如果数组包含复数,则返回虚部;否则,返回一个全为零的数组。 -
ndarray.flat:
返回一个迭代器,使得数组可以像一维数组一样迭代。 -
ndarray.T:
返回数组的转置。 -
ndarray.ctypes:
一个包含用于与 C 语言接口的数据类型的对象。 -
ndarray.base:
如果数组是由另一个数组派生(切片或索引)而来,则返回原始数组;否则,返回None
。
(2)示例访问属性:
import numpy as np
# 创建一个二维数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
# 访问数组属性
print("ndim:", arr.ndim) # 数组的维度数
print("shape:", arr.shape) # 数组的形状
print("size:", arr.size) # 数组中元素的总数
print("dtype:", arr.dtype) # 数组元素的数据类型
print("itemsize:", arr.itemsize) # 每个元素的字节大小
print("strides:", arr.strides) # 每个维度的步长
print("nbytes:", arr.nbytes) # 数组占用的总字节数
print("C_CONTIGUOUS:", arr.flags['C_CONTIGUOUS']) # 是否是C风格连续
print("F_CONTIGUOUS:", arr.flags['F_CONTIGUOUS']) # 是否是Fortran风格连续
print("OWNDATA:", arr.flags['OWNDATA']) # 是否拥有自己的数据
(3)ndarray对象的内存信息:
在 NumPy 中,ndarray
对象的内存信息可以通过其 flags
属性来获取,这个属性是一个包含多个布尔值的字典,描述了数组在内存中的存储特性。
-
C_CONTIGUOUS
(或CONTIGUOUS
):- 如果为
True
,则表示数组在内存中是按 C 语言风格的连续存储的,即最后一个维度的元素是最先存储的。
- 如果为
-
F_CONTIGUOUS
:- 如果为
True
,则表示数组在内存中是按 Fortran 语言风格的连续存储的,即第一个维度的元素是最先存储的。
- 如果为
-
OWNDATA
:- 如果为
True
,则表示数组拥有自己的数据副本,即修改数组的数据不会影响原始数据。
- 如果为
-
WRITEABLE
:- 如果为
True
,则表示数组是可写的。
- 如果为
-
ALIGNED
:- 如果为
True
,则表示数组的数据在内存中是对齐的,这有助于提高性能。
- 如果为
-
WRITEBACKIFCOPY
:- 如果为
True
,则表示数组是一个拷贝,其数据最终需要写回到原始数组。
- 如果为
(4)代码示例:
import numpy as np
# 创建一个数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
# 打印内存相关的属性
print("Array data type:", arr.dtype)
print("Array itemsize:", arr.itemsize)
print("Array size:", arr.size)
print("Array nbytes:", arr.nbytes)
print("Array is C contiguous:", arr.flags['C_CONTIGUOUS'])
print("Array is F contiguous:", arr.flags['F_CONTIGUOUS'])
print("Array owns its data:", arr.flags['OWNDATA'])
print("Array is writeable:", arr.flags['WRITEABLE'])
print("Array is aligned:", arr.flags['ALIGNED'])
五、新建数组:
在 NumPy 中,可以使用多种方法来创建新的数组。
(1)使用 np.array
:
- 将列表或其他序列转换为 NumPy 数组。
import numpy as np
# 从列表创建数组
arr = np.array([1, 2, 3, 4, 5])
(2)使用 np.zeros
:
- 创建一个由 0 组成的数组。
# 创建一个形状为 (3, 4) 的数组,所有元素都是 0
zeros_arr = np.zeros((3, 4))
(3)使用 np.ones
:
- 创建一个由 1 组成的数组。
# 创建一个形状为 (2, 2) 的数组,所有元素都是 1
ones_arr = np.ones((2, 2))
(4)使用 np.full
:
- 创建一个由指定填充值组成的数组。
# 创建一个形状为 (3, 3) 的数组,所有元素都是 7
full_arr = np.full((3, 3), 7)
(5)使用 np.arange
:
- 创建一个具有等间隔序列的一维数组。
# 创建一个从 0 到 9 的数组,步长为 1
arange_arr = np.arange(10)
(6)使用 np.linspace
:
- 创建一个在指定范围内具有等间隔的一维数组。
# 创建一个从 0 到 1 的 5 个元素的数组
linspace_arr = np.linspace(0, 1, 5)
(7)使用 np.eye
:
- 创建一个二维的单位矩阵(对角线上的元素为 1,其余为 0)。
# 创建一个 3x3 的单位矩阵
eye_arr = np.eye(3)
(8)使用 np.diag
:
- 创建一个以提供的一维数组为对角线元素的二维数组。
# 创建一个对角线上元素为 1 的 3x3 对角矩阵
diag_arr = np.diag([1, 2, 3])
(9)使用 np.random
模块:
- 创建一个由随机数组成的数组。
# 创建一个形状为 (2, 3) 的随机数组
random_arr = np.random.rand(2, 3)
(10)使用 np.empty
:
- 创建一个未初始化的数组(其值是内存中当前的垃圾值)。
# 创建一个形状为 (2, 2) 的未初始化数组
empty_arr = np.empty((2, 2))
-
(11)使用
np.stack
,np.concatenate
,np.vstack
,np.hstack
:- 将多个数组堆叠或连接成一个新数组。
# 创建两个数组
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# 垂直堆叠
vstack_arr = np.vstack((a, b))
# 水平堆叠
hstack_arr = np.hstack((a, b))
六、从已有的数组创建数组:
(1)np.asarray:
np.asarray
是 NumPy 中的一个函数,它将输入的对象转换为 NumPy 数组。如果输入对象已经是一个 NumPy 数组,那么 np.asarray
会返回该数组的一个引用(除非 dtype
参数指定了不同的数据类型)。这个函数对于确保你拥有一个 NumPy 数组非常有用,尤其是在不确定输入数据类型的情况下。
a.函数原型:
numpy.asarray(a, dtype=None, order=None, device=None)
b.参数:
-
a : array_like
- 输入的数据,可以是列表、元组、另一个 NumPy 数组,或者是任何其他形式的序列。
-
dtype : data-type, optional
- 目标数组的数据类型。如果指定,数组的元素将被转换为该数据类型。
-
order : {'C', 'F'}, optional
- 创建数组的内存布局。
'C'
表示 C 风格的行主序(默认),'F'
表示 Fortran 风格的列主序。
- 创建数组的内存布局。
-
device : {'cpu', 'cuda'}, optional
- 指定数组应该在哪个设备上分配。默认为
'cpu'
。
- 指定数组应该在哪个设备上分配。默认为
c.返回:
- 一个 NumPy 数组。
d.用法示例:
import numpy as np
# 从列表创建 NumPy 数组
list_data = [1, 2, 3]
array = np.asarray(list_data)
print(array) # 输出: [1 2 3]
# 转换数据类型
array = np.asarray(list_data, dtype=float)
print(array) # 输出: [1. 2. 3.]
# 保持原数组的顺序
array = np.asarray([[1, 2, 3], [4, 5, 6]], order='F')
print(array) # 输出: [[1 2 3] [4 5 6]]
# 从另一个 NumPy 数组创建数组
existing_array = np.array([1, 2, 3])
new_array = np.asarray(existing_array)
print(new_array is existing_array) # 输出: True,表明 new_array 是 existing_array 的引用
(2)np.frombuffer
:
np.frombuffer
是 NumPy 中的一个函数,它用于从缓冲区(如字节字符串或内存区域)创建一个一维数组。这个函数对于直接从内存中的数据创建数组非常有用,尤其是在处理二进制数据或与低级程序接口时。
a.函数原型:
numpy.frombuffer(buffer, dtype=float, count=-1, offset=0)
b.参数:
-
buffer : buffer_like
- 一个缓冲区对象,如 bytes 或 bytearray。
-
dtype : data-type, optional
- 数组元素的数据类型。如果不指定,将自动推断数据类型。
-
count : int, optional
- 要读取的元素数量。如果为 -1(默认),则读取整个缓冲区。
-
offset : int, optional
- 缓冲区开始读取前的字节偏移量。
c.返回:
- 一个一维 NumPy 数组。
d.用法示例:
import numpy as np
# 创建一个字节字符串
buffer = b'\x01\x02\x03\x04\x05\x06\x07\x08'
# 从缓冲区创建数组
array = np.frombuffer(buffer, dtype=np.uint8)
print(array) # 输出: [ 1 2 3 4 5 6 7 8]
# 指定 count 参数
array = np.frombuffer(buffer, dtype=np.uint8, count=4)
print(array) # 输出: [1 2 3 4]
# 指定 offset 参数
array = np.frombuffer(buffer, dtype=np.uint8, count=4, offset=2)
print(array) # 输出: [3 4 5 6]
- 创建了一个包含 8 个字节的字节字符串。然后,使用
np.frombuffer
从这个缓冲区创建了一个一维数组。使用count
和offset
参数来控制从缓冲区中读取的数据。 np.frombuffer
特别适用于处理二进制文件或网络数据流,因为它允许直接将原始字节数据转换为 NumPy 数组,从而进行进一步的数值处理。
(3)np.fromiter
:
np.fromiter
是 NumPy 中的一个函数,它用于从一个迭代器创建一个数组。这个函数对于从任何可迭代对象(如生成器、迭代器或其他序列)创建数组非常有用,特别是当需要将大量数据有效地转换为 NumPy 数组时。
a.函数原型:
numpy.fromiter(iterable, dtype, count=-1)
b.参数:
-
iterable : iterable
- 一个迭代器或可迭代对象,其元素将被用来创建数组。
-
dtype : data-type
- 数组元素的数据类型。
-
count : int, optional
- 要读取的元素数量。如果为 -1(默认),则读取迭代器中的所有元素。
c.返回:
- 一个一维 NumPy 数组。
d.用法示例:
import numpy as np
# 创建一个迭代器
iterable = (i * i for i in range(5))
# 从迭代器创建数组
array = np.fromiter(iterable, dtype=int)
print(array) # 输出: [ 0 1 4 9 16]
# 使用 count 参数
array = np.fromiter(iterable, dtype=int, count=3)
print(array) # 输出: [ 0 1 4]
- 创建了一个生成器表达式,它生成一个数字的平方。然后,使用
np.fromiter
从这个迭代器创建了一个一维数组。使用count
参数来控制从迭代器中读取的数据数量。 np.fromiter
是一个非常灵活的函数,它可以处理任何类型的迭代器,包括那些在迭代过程中动态生成数据的迭代器。这使得它成为处理流式数据或大型数据集时的一个强大工具。
七、从数值范围创建数组:
在 NumPy 中,从数值范围创建数组通常涉及到生成一系列连续的数值
(1)np.arange
:
- 创建一个等差数列的一维数组。
- 参数:
start
: 起始值(包含)。stop
: 终止值(不包含)。step
: 步长(默认为 1)。dtype
: 返回数组的数据类型(可选)。目录
(11)使用 np.stack, np.concatenate, np.vstack, np.hstack:
- 用法:
import numpy as np array = np.arange(0, 10, 2) # 从 0 到 9,步长为 2 print(array) # 输出: [0 2 4 6 8]
(2)np.linspace
:
- 创建一个在指定范围内均匀分布的一维数组。
- 参数:
start
: 范围的起始值。stop
: 范围的终止值。num
: 要生成的等间隔样本数量。endpoint
: 布尔值,确定是否包括终止值(默认为 True)。dtype
: 数组的数据类型(可选)。
- 用法:
array = np.linspace(0, 1, 5) # 从 0 到 1 生成 5 个数字 print(array) # 输出: [0. 0.25 0.5 0.75 1. ]
(3)np.logspace
:
- 创建一个对数等比数列的一维数组。
- 参数:
start
: 对数尺度的起始值的指数。stop
: 对数尺度的终止值的指数。num
: 要生成的等间隔样本数量。endpoint
: 布尔值,确定是否包括终止值(默认为 True)。base
: 对数的底数(默认为 10)。dtype
: 数组的数据类型(可选)。
- 用法:
array = np.logspace(1, 2, 5) # 从 10^1 到 10^2 生成 5 个数字 print(array) # 输出: [ 10. 17.78 31.62 56.23 100. ]
(4)np.fromfunction
:
- 从一个函数生成数组,该函数定义了数组中的元素值。
- 参数:
function
: 一个返回数组元素值的函数。shape
: 生成数组的形状。dtype
: 数组的数据类型(可选)。
- 用法:
def func(x, y): return x + y array = np.fromfunction(func, (3, 3), dtype=int) print(array) # 输出: [[0 1 2] [1 2 3] [2 3 4]]
(5)np.tile
:
- 重复数组中的元素以创建更大的数组。
- 参数:
a
: 要重复的数组。reps
: 重复次数,可以是一个整数或形状为元组的数组。
- 用法:
array = np.array([1, 2, 3]) repeated_array = np.tile(array, (2, 3)) # 重复 2 行 3 列 print(repeated_array) # 输出: # [[1 2 3 1 2 3] # [1 2 3 1 2 3]]
(6)np.repeat
:
- 重复数组中的每个元素多次。
- 参数:
a
: 要重复的数组。repeats
: 每个元素重复的次数,可以是一个整数或数组。
- 用法:
array = np.array([1, 2, 3]) repeated_elements = np.repeat(array, 2) # 每个元素重复 2 次 print(repeated_elements) # 输出: [1 1 2 2 3 3]
八、切片和索引:
在 NumPy 中,切片和索引是访问和操作数组元素的基本方法。
(1)索引:
索引用于访问数组中的单个元素。在 NumPy 中,多维数组的索引是按行优先顺序进行的。
import numpy as np
# 创建一个二维数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
# 访问第二行第一列的元素
element = arr[1, 0] # 输出 4
(2)切片:
切片用于访问数组的一部分,即子数组。切片操作返回原数组的视图,而不是副本。
# 创建一个一维数组
arr = np.arange(10)
# 访问从第三个元素到第六个元素(不包括索引 6)
slice = arr[2:6] # 输出 [3 4 5]
(4)切片语法:
- 一维数组的切片:
arr[start:stop:step]
- 多维数组的切片:
arr[x_start:x_stop:x_step, y_start:y_stop:y_step]
(5)省略和默认值:
- 省略
start
:默认从序列的开始位置取。 - 省略
stop
:默认取到序列的结束位置。 - 省略
step
:默认步长为 1。
# 访问从开始到索引 5 的所有元素
slice = arr[:5] # 输出 [0 1 2 3 4]
# 访问从索引 5 到结束的所有元素
slice = arr[5:] # 输出 [5 6 7 8 9]
# 访问整个数组
slice = arr[:] # 输出 [0 1 2 3 4 5 6 7 8 9]
(6)负索引:
- 负索引用于从数组的末尾开始计数。
# 访问最后一个元素
element = arr[-1] # 输出 9
# 访问最后三个元素
slice = arr[-3:] # 输出 [7 8 9]
(7)花式索引:
- 花式索引允许通过提供一个索引数组来访问多个元素。
# 创建一个索引数组
indexes = np.array([0, 2, 4])
# 使用花式索引
fancy_slice = arr[indexes] # 输出 [0 2 4 6 8]
(8)布尔索引:
- 布尔索引允许基于条件表达式来索引数组。
# 选择所有大于 5 的元素
bool_index = arr[arr > 5] # 输出 [6 7 8 9]
(9)切片与复制:
- 使用切片时,返回的是原数组的视图,而不是副本。如果你需要修改切片内容而不影响原数组,可以使用
.copy()
方法创建副本。
# 创建一个副本
slice_copy = arr[2:6].copy()
(10)多维数组切片:
- 在多维数组中,你可以通过为每个维度提供切片索引来获取子数组。
# 创建一个二维数组
arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 获取第二行
row = arr_2d[1, :] # 输出 [4 5 6]
# 获取第一列
column = arr_2d[:, 0] # 输出 [1 4 7]
# 获取中间的子数组
sub_array = arr_2d[1:3, 1:3] # 输出 [[5 6] [8 9]]
九、迭代数组:
在 NumPy 中,迭代数组通常指的是遍历数组中的元素或子数组。NumPy 提供了几种方法来迭代数组,包括使用 Python 的标准循环结构或 NumPy 的特定函数。以下是一些常用的迭代方法:
(1) 使用 Python 的 for 循环:
最直接的方法是使用 Python 的内置 for
循环直接迭代 NumPy 数组的元素。
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
for element in arr:
print(element)
- 这种方法简单直观,适用于一维数组。对于多维数组,你可以通过嵌套循环来迭代。
(2)使用 np.nditer:
np.nditer
是一个更高级的迭代器,它支持多维数组和更复杂的迭代需求,如 C 或 Fortran 样式的迭代。
arr = np.array([[1, 2], [3, 4]])
for element in np.nditer(arr):
print(element)
np.nditer
可以配置多个选项,例如避免复制、多数组迭代等。
(3)使用 np.flat
或 np.ravel:
- 这两个方法返回数组的一维迭代器,允许以一维的方式迭代多维数组。
arr = np.array([[1, 2], [3, 4]])
# 使用 np.flat
for element in np.flatiter(arr):
print(element)
# 使用 np.ravel 返回的数组迭代
for element in np.ravel(arr):
print(element)
(4) 使用 np.ndenumerate:
- 如果需要在迭代时同时获取索引,
np.ndenumerate
是一个非常有用的工具。它返回数组的索引和值。
arr = np.array([[1, 2], [3, 4]])
for index, element in np.ndenumerate(arr):
print(f"Index: {index}, Value: {element}")
(5)使用条件迭代:
有时你可能需要根据条件迭代数组中的元素。这可以通过结合条件语句和迭代方法来实现。
arr = np.array([1, 2, 3, 4, 5])
for element in arr:
if element % 2 == 0:
print(f"Even number: {element}")
(6)使用生成器表达式:
虽然这不是直接迭代数组的方法,但生成器表达式可以用来创建一个迭代器,这在处理大型数组时可以节省内存。
arr = np.array([1, 2, 3, 4, 5])
# 创建一个生成器表达式
gen = (x * 2 for x in arr)
# 迭代生成器
for element in gen:
print(element)
(7)np.nditer详细介绍:
np.nditer
是 NumPy 提供的一个强大的多维数组迭代器对象,它提供了多种灵活的方法来访问一个或多个数组的所有元素。
a.函数原型:
numpy.nditer(op, flags=None, op_flags=None,
op_dtypes=None, order='K', casting='safe',
op_axes=None, itershape=None, buffersize=0)
b.参数:
-
op : 对象序列
- 要迭代的对象序列,通常是 NumPy 数组。
-
flags : {'buffered', 'delay_bufalloc', 'external_loop', 'f_index', 'multi_index', 'c_index', 'refs_ok', 'zerosize_ok', 'copy_if_overlap', 'no_broadcast', 'no_subtype', 'remove_axis', 'writemasked', 'readwrite'}, optional
- 控制迭代器行为的标志列表。
-
op_flags : 列表或对象序列,可选
- 每个操作数的额外行为标志列表。
-
op_dtypes : 数据类型或数据类型序列,可选
- 操作数期望的数据类型。
-
order : {'C', 'F', 'A', 'K'}, optional
- 内存布局顺序:'C' 表示行主序(行优先),'F' 表示列主序(列优先),'A' 表示任意顺序(实际顺序),'K' 表示保持数组的原始顺序。
-
casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
- 类型转换规则。
-
op_axes : 列表或轴序列,可选
- 每个操作数的轴到迭代器轴的映射。
-
itershape : 元组,可选
- 迭代器的期望输出形状。
-
buffersize : 整数,可选
- 当使用 'buffered' 标志时,控制缓冲区的大小。
c.返回:
- 返回一个
nditer
对象,可以通过它迭代数组。
d.基本用法:
np.nditer
可以迭代单个或多个数组,提供对数组元素的访问。例如:
a = np.arange(6).reshape(2, 3)
for x in np.nditer(a):
print(x, end=' ')
e.控制迭代顺序:
- 可以通过
order
参数控制迭代的顺序,如 'C'(行序优先,默认)或 'F'(列序优先):
for x in np.nditer(a, order='F'):
print(x, end=' ')
f.修改数组中的元素:
- 使用
op_flags
参数可以修改数组中的元素,例如使用 'readwrite' 标志:
for x in np.nditer(a, op_flags=['readwrite']):
x[...] = x * 2
g.外部循环:
- 使用
flags
参数中的 'external_loop' 可以实现逐行或逐列的迭代:
for x in np.nditer(a, flags=['external_loop'], order='F'):
print(x, end=' ')
h.广播迭代
np.nditer
支持广播机制,可以同时迭代多个可广播的数组:
b = np.array([1, 2, 3, 4])
for x, y in np.nditer([a, b]):
print("%d:%d" % (x, y), end=", ")
(8)注意事项:
nditer
可以作为上下文管理器使用,确保在迭代完成后正确处理数据。- 如果使用 'writeonly' 或 'readwrite' 标志,操作数可能是原始数据的视图,需要特别注意数据的回写。
- 迭代 NumPy 数组时,尽量避免修改迭代的数组,因为这可能会导致不可预测的结果。
- 对于大型数组,考虑迭代效率和内存使用。
十、数组操作:
在 NumPy 中,数组的形状、维度和元素可以进行多种操作。
(1) 修改数组形状:
np.reshape
:
- 函数原型:
numpy.reshape(a, newshape, order='C')
- 参数:
a
: 输入数组。newshape
: 元组,新的数组形状。order
: {'C', 'F', 'A'},数组的内存顺序。
- 作用: 返回一个具有新形状的数组,不改变数据。
import numpy as np
a = np.arange(6)
b = np.reshape(a, (2, 3))
print(b)
# 输出:
# [[0 1 2]
# [3 4 5]]
numpy.ndarray.flat:
numpy.ndarray.flat
是 NumPy 中的一个属性,它返回一个迭代器,使得数组可以像一维数组一样迭代。这个迭代器允许访问数组中的每个元素,就好像它们在一维数组中一样。- 函数原型:
numpy.ndarray.flat
- 参数:无参数。
-
作用:返回一个迭代器,用于迭代多维数组中的所有元素,就好像它们在一维数组中一样。
-
代码示例:
import numpy as np
# 创建一个二维数组
a = np.array([[1, 2, 3], [4, 5, 6]])
# 使用 flat 迭代器
for element in a.flat:
print(element, end=' ')
# 输出: 1 2 3 4 5 6
a.flat
返回的迭代器允许你对数组 a
进行迭代,而不需要关心它的维度。这在处理任意维度的数组时非常有用,因为你可以使用相同的迭代代码。
注意事项:
a.flat
返回的迭代器不支持索引操作,它只能用于迭代。- 如果你需要修改数组中的元素,可以使用
a.flat
迭代器,但更常见的做法是使用索引或者切片。
numpy.ndarray.flatten:
numpy.ndarray.flatten
是一个方法,它返回一个折叠成一维的数组副本。这个方法对于将多维数组转换为一维数组非常有用,尤其是在你需要对数组元素进行顺序处理时。-
函数原型:
numpy.ndarray.flatten([order])
-
参数:
- order : {'C', 'F', 'A', 'K'}, optional
- 'C' 表示返回的是类似 C 语言的行主序数组(默认)。
- 'F' 表示返回的是类似 Fortran 语言的列主序数组。
- 'A' 表示返回的是数组的任意顺序,与原数组的顺序相同。
- 'K' 表示返回的是原数组的顺序。
-
作用:返回一个折叠成一维的数组副本。
-
代码示例:
import numpy as np
# 创建一个二维数组
a = np.array([[1, 2, 3], [4, 5, 6]])
# 使用 flatten 方法
flattened_array = a.flatten()
print(flattened_array)
# 输出: [1 2 3 4 5 6]
注意事项:
flatten()
返回的是原数组的一个副本,对返回的数组进行修改不会影响原数组。- 如果需要一个不复制数据的迭代器,可以使用
.flat
属性,它返回一个迭代器,可以在不创建副本的情况下迭代数组中的每个元素。
numpy.ravel:
numpy.ravel
函数是 NumPy 中用于将多维数组扁平化为一维数组的函数。与flatten()
方法不同,ravel()
默认返回的是原数组的视图(view),而不是副本(copy)。如果可能,它不会复制数据,这意味着对返回数组的修改将影响原始数组。如果需要确保返回一个副本,可以设置copy=True
。- 函数原型:
numpy.ravel(a, order='C')
- 参数:
-
a : array_like
- 输入的多维数组。
-
order : {'C', 'F', 'A'}, optional
- 'C' 表示按行主序(默认)。
- 'F' 表示按列主序。
- 'A' 表示保持数组原来的顺序(只有当输入是数组时才有意义)。
- 作用:返回一个一维数组,该数组是原始多维数组的扁平化版本。
-
代码示例:
import numpy as np
# 创建一个二维数组
a = np.array([[1, 2, 3], [4, 5, 6]])
# 使用 ravel 函数
flattened_array = np.ravel(a)
print(flattened_array)
# 输出: [1 2 3 4 5 6]
# 如果需要确保返回一个副本,可以设置 copy=True
flattened_array_copy = np.ravel(a, copy=True)
注意事项:
- 当
order='C'
时,数组将按行主序扁平化,这意味着第一维度的元素会先被迭代。 - 当
order='F'
时,数组将按列主序扁平化,这意味着最后一维度的元素会先被迭代。 - 如果原始数组已经是一维的,
ravel()
将返回原始数组本身(除非指定copy=True
)。 ravel()
通常比flatten()
更有效率,因为它避免了不必要的数组复制。
(2)翻转数组:
np.flip
:
- 函数原型:
numpy.flip(a, axis=None)
- 参数:
a
: 输入数组。axis
: 整数或整数数组,指定要翻转的轴。
- 作用: 反转数组中的元素顺序。
a = np.arange(6)
b = np.flip(a)
print(b)
# 输出: [5 4 3 2 1 0]
numpy.transpose
:
numpy.transpose
函数是 NumPy 中用于交换数组轴的函数。这个函数可以重新排列多维数组的维度,使得可以轻松地从一个维度顺序转换到另一个维度顺序。-
函数原型:
numpy.transpose(a, axes=None)
-
参数:
-
a : array_like
- 输入的多维数组。
-
axes : tuple of ints, optional
- 一个包含轴索引的元组,用于指定新的轴顺序。如果不提供,轴将被逆序排列。
-
作用:返回一个新的数组,其轴顺序被重新排列。
-
代码示例:
import numpy as np
# 创建一个二维数组
a = np.array([[1, 2, 3], [4, 5, 6]])
# 使用 transpose 函数
transposed_array = np.transpose(a)
print(transposed_array)
# 输出:
# [[1 4]
# [2 5]
# [3 6]]
# 指定新的轴顺序
transposed_array_custom = np.transpose(a, axes=(1, 0))
print(transposed_array_custom)
# 输出:
# [[1 2 3]
# [4 5 6]]
注意事项:
transpose
函数返回的是原数组的一个视图(view),除非指定了新的轴顺序,这种情况下它将返回一个副本。- 如果你只需要简单地反转数组的轴,可以使用
a.T
,这是transpose
的简写形式。 transpose
函数不会改变原始数组的数据,它只是重新排列了轴。
numpy.rollaxis:
numpy.rollaxis
函数是 NumPy 中用于将数组中的轴滚动到指定位置的函数。这个函数可以用来改变数组的维度顺序,但不改变数组中元素的顺序。-
函数原型:
numpy.rollaxis(a, axis, start=0)
-
参数:
-
a : ndarray
- 输入的多维数组。
-
axis : int
- 要滚动的轴的索引。
-
start : int, optional
- 滚动的起始位置。默认为 0,表示将轴滚动到最前面。
-
作用:将数组中的指定轴滚动到新的位置。
- 代码示例:
import numpy as np
# 创建一个三维数组
a = np.array([[[ 0, 1], [ 2, 3]],
[[ 4, 5], [ 6, 7]]])
# 将第一个轴滚动到最前面
rolled_array = np.rollaxis(a, 0, start=0)
print(rolled_array)
# 输出:
# [[[0 1]
# [2 3]]
#
# [[4 5]
# [6 7]]]
# 将第二个轴滚动到最后面
rolled_array = np.rollaxis(a, 1, start=2)
print(rolled_array)
# 输出:
# [[[0 2]
# [1 3]]
#
# [[4 6]
# [5 7]]]
注意事项:
rollaxis
函数返回的是原数组的一个视图(view),除非滚动操作涉及到数组的物理布局改变,这种情况下它将返回一个副本。rollaxis
函数不会改变原始数组的数据,它只是改变了轴的顺序。- 如果
start
参数大于数组的维度数,轴将被滚动到数组的末尾。
numpy.swapaxes
:
numpy.swapaxes
函数是 NumPy 中用于交换数组的两个轴的函数。这个函数可以方便地改变数组的维度顺序。-
函数原型:
numpy.swapaxes(a, axis1, axis2)
-
参数:
-
a : ndarray
- 输入的多维数组。
-
axis1 : int
- 第一个轴的索引。
-
axis2 : int
- 第二个轴的索引。
-
作用:返回一个新的数组,其中
axis1
和axis2
被交换。 -
代码示例:
import numpy as np
# 创建一个二维数组
a = np.array([[1, 2, 3], [4, 5, 6]])
# 交换数组的轴
swapped_array = np.swapaxes(a, 0, 1)
print(swapped_array)
# 输出:
# [[1 4]
# [2 5]
# [3 6]]
# 对于三维数组,交换前两个轴
a = np.array([[[ 0, 1], [ 2, 3]],
[[ 4, 5], [ 6, 7]]])
swapped_array = np.swapaxes(a, 0, 1)
print(swapped_array)
# 输出:
# [[[0 4]
# [2 6]]
#
# [[1 5]
# [3 7]]]
注意事项:
swapaxes
函数返回的是原数组的一个视图(view),如果轴交换不涉及数据的物理重新排列,就不会创建数据的副本。- 交换轴的索引是从 0 开始的,例如,在二维数组中,0 代表行(第一个轴),1 代表列(第二个轴)。
- 这个函数不会改变原始数组的数据,它只是返回一个新的视图,其中轴的顺序被交换。
(3)修改数组维度:
np.expand_dims
:
- 函数原型:
numpy.expand_dims(a, axis)
- 参数:
a
: 输入数组。axis
: 要插入的新轴的索引。
- 作用: 在指定轴位置插入一个新的轴。
a = np.arange(3)
b = np.expand_dims(a, axis=1)
print(b)
# 输出:
# [[0]
# [1]
# [2]]
(4)分割数组:
np.split
:
- 函数原型:
numpy.split(ary, indices_or_sections, axis=0)
- 参数:
ary
: 输入数组。indices_or_sections
: 分割的索引或部分。axis
: 分割的轴。
- 作用: 将数组分割成多个子数组。
a = np.arange(6)
b = np.split(a, 3)
print(b)
# 输出: [array([0, 1]), array([2, 3]), array([4, 5])]
(5) 数组元素的添加和修改:
np.append
:
- 函数原型:
numpy.append(a, values, axis=None)
- 参数:
a
: 输入数组。values
: 要添加的值。axis
: 要添加值的轴。
- 作用: 沿指定轴添加元素。
a = np.array([1, 2, 3])
b = np.append(a, [4, 5])
print(b)
# 输出: [1 2 3 4 5]
np.insert
:
- 函数原型:
numpy.insert(ary, obj, values, axis=None)
- 参数:
ary
: 输入数组。obj
: 插入位置的索引。values
: 要插入的值。axis
: 要插入值的轴。
- 作用: 在指定位置插入元素。
a = np.array([1, 2, 3])
b = np.insert(a, 1, 5)
print(b)
# 输出: [1 5 2 3]
十一、数组创建图像:
import cv2
import numpy as np
# 创建一个 100x100 的全黑图像
black_image = np.zeros((300, 300), dtype=np.uint8)
# 创建一个 100x100 的全白图像
white_image = np.ones((300, 300), dtype=np.uint8) * 255
# 显示图像
cv2.imshow('Black Image', black_image)
cv2.imshow('White Image', white_image)
cv2.waitKey(0)
cv2.destroyAllWindows()