Numpy介绍
NumPy(Numerical Python的简称)是Python编程语言的一个库,主要用于科学计算和数据处理。它提供了支持高性能多维数组和矩阵运算的功能,以及大量的数学函数库。以下是对NumPy的一些关键特性的介绍:
核心功能
-
多维数组对象(ndarray):
- NumPy的核心是其强大的多维数组对象
ndarray
。这个对象比Python内置的列表(list)更高效,尤其是在处理大量数据时。 - 支持多种数据类型,包括整数、浮点数、布尔值、复数等。
- NumPy的核心是其强大的多维数组对象
-
广播机制:
- 允许不同形状的数组在运算时进行对齐,从而避免了显式地复制数据,提升了效率。
-
向量化运算:
- 许多NumPy的操作都是对整个数组进行的,而不是对数组中的每个元素进行循环操作,这种方式称为向量化运算。向量化运算能够极大地提高计算效率。
-
丰富的数学函数库:
- 提供了大量的数学函数,如线性代数、傅里叶变换、随机数生成等。
-
高级索引和切片:
- 支持布尔索引、花式索引等高级索引操作,使得数据操作更加灵活和方便。
安装
可以通过以下命令安装NumPy:
pip install numpy
查看Pytorch版本,查看Pytorch是否支持GPU运算
import torch
print(torch.__version__) # 输出: 1.14.0a0+44dac51
print(torch.cuda.is_available()) # 输出: True
- 输出解释:Pytorch版本为
1.14.0a0+44dac51
,支持GPU运算。
检查NumPy版本
import numpy as np
print(np.__version__) # 输出: 1.22.2
- 输出解释:NumPy版本为
1.22.2
。
NumPy 的维度
在 NumPy 中,数组是一个多维的、同质的数据容器。数组的维度(dimension)是指数组的轴(axis)数目。
维度的基本概念
- 轴(Axis):NumPy 数组的每一个维度称为一个轴。轴的编号从 0 开始。例如,对于一个二维数组,轴 0 是行方向,轴 1 是列方向。
示例与解释
一维数组
import numpy as np
arr_1d = np.array([1, 2, 3, 4, 5])
print("一维数组:", arr_1d)
print("形状:", arr_1d.shape)
print("维度:", arr_1d.ndim)
print("元素个数:", arr_1d.size)
输出:
一维数组: [1 2 3 4 5]
形状: (5,)
维度: 1
元素个数: 5
- 解释:
arr_1d
是一个一维数组,形状为(5,)
,表示它有 5 个元素。维度数ndim
为 1。
二维数组
import numpy as np
arr_2d = np.array([[1, 2, 3], [4, 5, 6]])
print("二维数组:\n", arr_2d)
print("形状:", arr_2d.shape)
print("维度:", arr_2d.ndim)
print("元素个数:", arr_2d.size)
输出:
二维数组:
[[1 2 3]
[4 5 6]]
形状: (2, 3)
维度: 2
元素个数: 6
- 解释:
arr_2d
是一个二维数组,形状为(2, 3)
,表示它有 2 行 3 列。维度数ndim
为 2。
三维数组
import numpy as np
arr_3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print("三维数组:\n", arr_3d)
print("形状:", arr_3d.shape)
print("维度:", arr_3d.ndim)
print("元素个数:", arr_3d.size)
输出:
三维数组:
[[[ 1 2 3]
[ 4 5 6]]
[[ 7 8 9]
[10 11 12]]]
形状: (2, 2, 3)
维度: 3
元素个数: 12
- 解释:
arr_3d
是一个三维数组,形状为(2, 2, 3)
,表示它有 2 个 2x3 的二维数组。维度数ndim
为 3。
NumPy的多维数组对象(ndarray
)创建
NumPy的多维数组对象(ndarray
)是其核心数据结构,支持高效的数组操作。创建ndarray
的方法多种多样,以下是一些常用的方法:
1. 从Python列表或元组创建
import numpy as np
# 从列表创建一维数组
array_1d = np.array([1, 2, 3, 4])
print(array_1d) # 输出: [1 2 3 4]
# 从嵌套列表创建二维数组
array_2d = np.array([[1, 2, 3], [4, 5, 6]])
print(array_2d) # 输出: [[1 2 3]
# [4 5 6]]
# 从元组创建数组
array_from_tuple = np.array((1, 2, 3))
print(array_from_tuple) # 输出: [1 2 3]
c = np.array([91, 72, 63, 74, 5], ndmin = 2)
print(c) # 输出: [[91 72 63 74 5]]
d = np.array([15, 26, 38], dtype = complex)
print(d) # 输出: [15.+0.j 26.+0.j 38.+0.j]
2. 使用内置的函数创建
2.1. 创建全零数组
# 创建一个3x3的全零数组
zeros_array = np.zeros((3, 3))
print(zeros_array)
# 输出:
# [[0. 0. 0.]
# [0. 0. 0.]
# [0. 0. 0.]]
2.2. 创建全一数组
# 创建一个2x4的全一数组
ones_array = np.ones((2, 4))
print(ones_array)
# 输出:
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]]
2.3. 创建单位矩阵(对角线为1,其余为0)
# 创建一个3x3的单位矩阵
identity_matrix = np.eye(3)
print(identity_matrix)
# 输出:
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
2.4. 创建未初始化的数组
# 创建一个2x3的未初始化数组(数组中的值是内存中的随机值)
empty_array = np.empty((2, 3))
print(empty_array)
# 输出:
# [[0.000e+000 0.000e+000 0.000e+000]
# [0.000e+000 0.000e+000 0.000e+000]]
3. 使用数值范围创建
3.1. 使用arange
函数
# 创建一个包含0到9的数组
range_array = np.arange(10)
print(range_array) # 输出: [0 1 2 3 4 5 6 7 8 9]
# 创建一个包含0到10,步长为2的数组
step_array = np.arange(0, 10, 2)
print(step_array) # 输出: [0 2 4 6 8]
3.2. 使用linspace
函数
# 创建一个包含0到1之间的5个均匀分布的数值的数组
linspace_array = np.linspace(0, 1, 5)
print(linspace_array) # 输出: [0. 0.25 0.5 0.75 1. ]
4. 使用随机数创建
4.1. 使用random.rand
函数
# 创建一个2x3的数组,包含0到1之间的随机浮点数
random_array = np.random.rand(2, 3)
print(random_array)
# 输出:
# [[0.5488135 0.71518937 0.60276338]
# [0.54488318 0.4236548 0.64589411]]
4.2. 使用random.randint
函数
# 创建一个2x3的数组,包含1到10之间的随机整数
random_int_array = np.random.randint(1, 10, (2, 3))
print(random_int_array)
# 输出:
# [[3 7 9]
# [2 4 1]]
5. 创建特定形状的数组
5.1. 使用reshape
函数
# 创建一个包含0到11的数组,并将其重塑为3x4的数组
reshaped_array = np.arange(12).reshape(3, 4)
print(reshaped_array)
# 输出:
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
通过这些方法,您可以根据需要创建各种形状和类型的ndarray
,以便高效地进行数据处理和科学计算。
NumPy的ndarray
的运算操作
好的,以下是去掉了广播机制部分的NumPy ndarray
运算的介绍:
NumPy的ndarray
对象支持丰富的运算操作,包括基本的算术运算、逻辑运算、统计运算、线性代数运算等。这些运算大多是向量化的,即在整个数组上进行操作,而不是在数组的每个元素上逐个操作,从而提高了计算效率。以下是对NumPy ndarray
运算的一些介绍和示例:
1. 基本算术运算
NumPy支持对数组进行基本的算术运算,包括加、减、乘、除、幂运算等。
import numpy as np
a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
# 加法
print(a + b) # 输出: [11 22 33 44]
# 减法
print(a - b) # 输出: [ -9 -18 -27 -36]
# 乘法
print(a * b) # 输出: [ 10 40 90 160]
# 除法
print(a / b) # 输出: [0.1 0.1 0.1 0.1]
# 幂运算
print(a ** 2) # 输出: [ 1 4 9 16]
2. 统计运算
NumPy提供了丰富的统计运算函数,例如求和、均值、标准差、最小值、最大值等。
a = np.array([1, 2, 3, 4, 5])
# 求和
print(a.sum()) # 输出: 15
# 均值
print(a.mean()) # 输出: 3.0
# 标准差
print(a.std()) # 输出: 1.4142135623730951
# 最小值
print(a.min()) # 输出: 1
# 最大值
print(a.max()) # 输出: 5
3. 逻辑运算
NumPy支持对数组进行逻辑运算,例如与、或、非等操作。
a = np.array([True, False, True])
b = np.array([False, False, True])
# 与运算
print(np.logical_and(a, b)) # 输出: [False False True]
# 或运算
print(np.logical_or(a, b)) # 输出: [ True False True]
# 非运算
print(np.logical_not(a)) # 输出: [False True False]
4. 比较运算
NumPy支持对数组进行比较运算,返回布尔数组。
a = np.array([1, 2, 3, 4])
b = np.array([4, 3, 2, 1])
# 大于
print(a > b) # 输出: [False False True True]
# 小于
print(a < b) # 输出: [ True True False False]
# 等于
print(a == b) # 输出: [False False False False]
5. 线性代数运算
NumPy提供了线性代数运算的函数,例如矩阵乘法、矩阵转置、逆矩阵、特征值等。
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
# 矩阵乘法
print(np.dot(A, B))
# 输出:
# [[19 22]
# [43 50]]
# 矩阵转置
print(A.T)
# 输出:
# [[1 3]
# [2 4]]
# 逆矩阵
print(np.linalg.inv(A))
# 输出:
# [[-2. 1. ]
# [ 1.5 -0.5]]
# 特征值
eigvals, eigvecs = np.linalg.eig(A)
print(eigvals) # 输出: [-0.37228132 5.37228132]
print(eigvecs)
# 输出:
# [[-0.82456484 -0.41597356]
# [ 0.56576746 -0.90937671]]
6. 聚合运算
NumPy提供了多种聚合运算函数,例如sum
、mean
、std
、min
、max
等,可以在指定轴上进行聚合运算。
a = np.array([[1, 2, 3], [4, 5, 6]])
# 沿轴0(列)求和
print(a.sum(axis=0)) # 输出: [5 7 9]
# 沿轴1(行)求和
print(a.sum(axis=1)) # 输出: [ 6 15]
7. 特殊运算示例
7.1 reciprocal函数
reciprocal
函数用于计算数组中每个元素的倒数。
import numpy as np
s = np.array([888, 1000, 20, 0.1])
print('原数组是:')
print(s) # 输出: [8.88e+02 1.00e+03 2.00e+01 1.00e-01]
print('*'*20)
print('调用reciprocal函数:')
print(np.reciprocal(s)) # 输出: [1.12612613e-03 1.00000000e-03 5.00000000e-02 1.00000000e+01]
7.2 power函数
power
函数用于计算数组中每个元素的幂。
import numpy as np
s = np.array([2, 4, 8])
print('原数组是;')
print(s) # 输出: [2 4 8]
print('*'*20)
print('调用power函数:')
print(np.power(s, 2)) # 输出: [ 4 16 64]
print('*'*20)
print('power之后数组:')
w = np.array([1, 2, 3])
print(w) # 输出: [1 2 3]
print('*'*20)
print('再次调用power函数:')
print(np.power(s, w)) # 输出: [ 2 16 512]
7.3 mod函数
mod
和remainder
函数用于计算数组中每个元素的取模。
import numpy as np
s = np.array([3, 6, 9])
w = np.array([2, 4, 8])
print('第一个数组:')
print(s) # 输出: [3 6 9]
print('*'*20)
print('第二个数组:')
print(w) # 输出: [2 4 8]
print('*'*20)
print('调用mod()函数:')
print(np.mod(s, w)) # 输出: [1 2 1]
print('*'*20)
print('调用remainder()函数:')
print(np.remainder(s, w)) # 输出: [1 2 1]
7.4 三角函数
NumPy提供了多种三角函数,如sin
、cos
、tan
等。
import numpy as np
a = np.array([0, 30, 45, 60, 90])
print('不同角度的正弦值:')
print(np.sin(a * np.pi / 180)) # 输出: [0. 0.5 0.70710678 0.8660254 1. ]
print('*'*20)
print('数组中角度的余弦值:')
print(np.cos(a * np.pi / 180)) # 输出: [1.00000000e+00 8.66025404e-01 7.07106781e-01 5.00000000e-01 6.12323400e-17]
print('*'*20)
print('数组中角度的正切值:')
print(np.tan(a * np.pi / 180)) # 输出: [0.00000000e+00 5.77350269e-01 1.00000000e+00 1.73205081e+00 1.63312394e+16]
7.5 反三角函数
NumPy还提供了反三角函数,如arcsin
、arccos
、arctan
等。
import numpy as np
a = np.array([0, 30, 45, 60, 90])
print('含有正弦值的数组:')
sin = np.sin(a * np.pi / 180)
print(sin) # 输出: [0. 0.5 0.70710678 0.8660254 1. ]
print('*'*20)
print('计算角度的反正弦,返回值以弧度为单位:')
inv = np.arcsin(sin)
print(inv) # 输出: [0. 0.52359878 0.78539816 1.04719755 1.57079633]
print('*'*20)
print('通过转化为角度制来检查结果:')
print(np.degrees(inv)) # 输出: [ 0. 30. 45. 60. 90.]
print('*'*20)
print('arccos 和 arctan 函数行为类似:')
cos = np.cos(a * np.pi / 180)
print(cos) # 输出: [1.00000000e+00 8.66025404e-01 7.07106781e-01 5.00000000e-01 6.12323400e-17]
print('*'*20)
print('反余弦:')
inv = np.arccos(cos)
print(inv) # 输出: [0. 0.52359878 0.78539816 1.04719755 1.57079633]
print('*'*20)
print('角度制单位:')
print(np.degrees(inv)) # 输出: [ 0. 30. 45. 60. 90.]
print('*'*20)
print('tan 函数:')
tan = np.tan(a * np.pi / 180)
print(tan) # 输出: [0.00000000e+00 5.77350269e-01 1.00000000e+00 1.73205081e+00 1.63312394e+16]
print('*'*20)
print('反正切:')
inv = np.arctan(tan)
print(inv) # 输出: [0. 0.52359878 0.78539816 1.04719755 1.57079633]
print('*'*20)
print('角度制单位:')
print(np.degrees(inv)) # 输出: [ 0. 30. 45. 60. 90.]
7.6 around函数
around
函数用于对数组中的元素进行四舍五入。
import numpy as np
a = np.array([100.0, 100.5, 123, 0.876, 76.998])
print('原数组:')
print(a) # 输出: [100. 100.5 123. 0.876 76.998]
print('*'*20)
print('舍入后:')
print(np.around(a)) # 输出: [100. 100. 123. 1. 77.]
print(np.around(a, decimals=1)) # 输出: [100. 100.5 123. 0.9 77. ]
print(np.around(a, decimals=-1)) # 输出: [100. 100. 120. 0. 80.]
7.7 floor函数
floor
函数用于向下取整。
import numpy as np
s = np.array([-9999.7, 100333.5, -23340.2, 0.987, 10.88888])
print('提供的数组:')
print(s) # 输出: [-9.999700e+03 1.003335e+05 -2.334020e+04 9.870000e-01 1.088888e+01]
print('*'*20)
print('修改后的数组:')
print(np.floor(s)) # 输出: [-1.00000e+04 1.00333e+05 -2.33410e+04 0.00000e+00 1.00000e+01]
7.8 ceil函数
ceil
函数用于向上取整。
import numpy as np
s = np.array([-100.3, 18.98, -0.49999, 0.563, 10])
print('提供的数组:')
print(s) # 输出: [-100.3 18.98 -0.49999 0.563 10. ]
print('*'*20)
print('修改后的数组:')
print(np.ceil(s)) # 输出: [-100. 19. -0. 1. 10.]
通过这些运算,NumPy提供了强大的数据处理和计算能力,使得科学计算和数据分析变得更加高效和便捷。
NumPy的广播机制介绍
NumPy的广播机制是一种强大的功能,允许不同形状的数组在一起进行算术运算。广播机制能够在不显式复制数据的情况下,对形状不匹配的数组进行对齐,从而提高计算效率。
广播机制的基本规则
广播机制的核心规则如下:
- 数组维度对齐:如果两个数组的维度不同,较小维度的数组会在左侧进行扩展,以匹配较大维度的数组。
- 形状对齐:从后往前比较两个数组的形状。如果两个维度的大小相同,或者其中一个维度的大小为1,则认为它们是兼容的,可以进行广播。
- 维度扩展:如果一个数组的某个维度大小为1,则在计算时会沿着该维度进行复制,以匹配另一个数组的大小。
广播机制的应用示例
示例1:标量与数组的广播
import numpy as np
arr = np.array([1, 2, 3, 4])
scalar = 10
# 标量和数组相加
result = arr + scalar
print(result) # 输出: [11 12 13 14]
解释:标量 10
被广播为与数组 arr
相同的形状 [10, 10, 10, 10]
,然后进行逐元素相加。
示例2:一维数组与二维数组的广播
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([[4], [5], [6]])
# 一维数组和二维数组相加
result = arr1 + arr2
print(result)
输出:
[[ 5 6 7]
[ 6 7 8]
[ 7 8 9]]
解释:一维数组 arr1
的形状是 (3,)
,二维数组 arr2
的形状是 (3, 1)
。通过广播机制,arr1
被扩展为 (3, 3)
,arr2
被扩展为 (3, 3)
,然后进行逐元素相加。
示例3:二维数组与三维数组的广播
import numpy as np
arr1 = np.array([[1, 2, 3], [4, 5, 6]])
arr2 = np.array([[[1]], [[2]], [[3]]])
# 二维数组和三维数组相加
result = arr1 + arr2
print(result)
输出:
[[[ 2 3 4]
[ 5 6 7]]
[[ 3 4 5]
[ 6 7 8]]
[[ 4 5 6]
[ 7 8 9]]]
解释:二维数组 arr1
的形状是 (2, 3)
,三维数组 arr2
的形状是 (3, 1, 1)
。通过广播机制,arr1
被扩展为 (1, 2, 3)
,然后复制三次成为 (3, 2, 3)
;arr2
被扩展为 (3, 2, 3)
,然后进行逐元素相加。
广播机制的具体步骤
-
对齐形状:
- 比较两个数组的形状,从后往前对齐。
- 如果某个维度不匹配且其中一个维度为1,则可以进行广播。
- 如果某个维度不匹配且都不为1,则无法进行广播。
-
扩展维度:
- 对于维度为1的数组,沿该维度进行复制,直到匹配另一个数组的大小。
广播机制的优势
- 内存效率:广播机制可以避免显式地复制数据,从而节省内存。
- 计算效率:广播机制可以在底层进行优化,提高计算速度。
- 代码简洁:广播机制使得代码更加简洁和易读,减少了显式数据对齐和复制的代码量。
NumPy的广播机制是一种强大的功能,允许不同形状的数组在一起进行算术运算。通过广播机制,可以在不显式复制数据的情况下,对形状不匹配的数组进行对齐,从而提高计算效率。广播机制在数据处理和科学计算中具有广泛的应用,使得NumPy在处理多维数组时更加灵活和高效。
NumPy 数组的形状操作
NumPy 提供了丰富的数组形状操作功能,可以方便地对数组的形状进行调整和变换。这些操作在数据处理和科学计算中非常有用,能够帮助我们更灵活地处理多维数据。
常见的形状操作
reshape
:改变数组的形状。resize
:改变数组的形状并修改其大小。ravel
:将多维数组展平为一维数组。flatten
:返回一个一维数组的副本。transpose
:转置数组。swapaxes
:交换数组的两个轴。expand_dims
:扩展数组的形状。squeeze
:从数组的形状中移除单维度。
详细解释和示例
1. reshape
:改变数组的形状
import numpy as np
arr = np.arange(12)
print("原数组:\n", arr)
reshaped_arr = arr.reshape(3, 4)
print("改变形状后的数组:\n", reshaped_arr)
输出:
原数组:
[ 0 1 2 3 4 5 6 7 8 9 10 11]
改变形状后的数组:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
- 解释:
reshape
可以将一维数组转换为二维数组,或者将多维数组转换为不同形状的数组,但总元素数必须保持不变。
2. resize
:改变数组的形状并修改其大小
import numpy as np
arr = np.arange(12)
print("原数组:\n", arr)
arr.resize(3, 4)
print("改变形状并修改大小后的数组:\n", arr)
输出:
原数组:
[ 0 1 2 3 4 5 6 7 8 9 10 11]
改变形状并修改大小后的数组:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
- 解释:
resize
改变数组的形状并修改其大小,如果新大小比原大小大,则用零填充。
3. ravel
:将多维数组展平为一维数组
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print("原数组:\n", arr)
flattened_arr = arr.ravel()
print("展平后的数组:\n", flattened_arr)
输出:
原数组:
[[1 2 3]
[4 5 6]
[7 8 9]]
展平后的数组:
[1 2 3 4 5 6 7 8 9]
- 解释:
ravel
将多维数组展平为一维数组,但返回的是原数组的视图。
4. flatten
:返回一个一维数组的副本
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print("原数组:\n", arr)
flattened_arr = arr.flatten()
print("展平后的数组副本:\n", flattened_arr)
输出:
原数组:
[[1 2 3]
[4 5 6]
[7 8 9]]
展平后的数组副本:
[1 2 3 4 5 6 7 8 9]
- 解释:
flatten
返回一个一维数组的副本,与ravel
不同,flatten
创建的是数组的副本。
5. transpose
:转置数组
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
print("原数组:\n", arr)
transposed_arr = arr.transpose()
print("转置后的数组:\n", transposed_arr)
输出:
原数组:
[[1 2 3]
[4 5 6]]
转置后的数组:
[[1 4]
[2 5]
[3 6]]
- 解释:
transpose
将数组的行和列互换,返回转置后的数组。
6. swapaxes
:交换数组的两个轴
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
print("原数组:\n", arr)
swapped_arr = arr.swapaxes(0, 1)
print("交换轴后的数组:\n", swapped_arr)
输出:
原数组:
[[1 2 3]
[4 5 6]]
交换轴后的数组:
[[1 4]
[2 5]
[3 6]]
- 解释:
swapaxes
交换数组的两个轴,例如从 (0, 1) 变为 (1, 0)。
7. expand_dims
:扩展数组的形状
import numpy as np
arr = np.array([1, 2, 3])
print("原数组:\n", arr)
expanded_arr = np.expand_dims(arr, axis=0)
print("扩展形状后的数组:\n", expanded_arr)
输出:
原数组:
[1 2 3]
扩展形状后的数组:
[[1 2 3]]
- 解释:
expand_dims
在指定轴上扩展数组的形状,例如在0轴上扩展。
8. squeeze
:从数组的形状中移除单维度
import numpy as np
arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print("原数组:\n", arr)
squeezed_arr = np.squeeze(arr, axis=0)
print("移除单维度后的数组:\n", squeezed_arr)
输出:
原数组:
[[[1 2]
[3 4]]
[[5 6]
[7 8]]]
移除单维度后的数组:
[[1 2]
[3 4]
[5 6]
[7 8]]
- 解释:
squeeze
从数组的形状中移除单维度,例如从 (1, 4, 2) 变为 (4, 2)。
总结
通过上述形状操作,NumPy 数组可以灵活地进行调整和变换,以适应不同的数据处理需求。这些操作在机器学习、数据分析、科学计算等领域中都有广泛的应用。
NumPy数组的切片操作
NumPy数组的切片操作允许用户获取数组的子集。切片操作的语法与Python内置的列表切片类似,但NumPy数组可以是多维的,因此切片操作也可以应用于多维数组。
基础切片操作
一维数组切片
切片的基本语法是 start:stop:step
,其中:
start
是切片的起始索引(包含)。stop
是切片的结束索引(不包含)。step
是切片的步长。
import numpy as np
a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 获取从索引2到索引5的元素 (不包含索引5)
print(a[2:5]) # 输出: [2 3 4]
# 获取从索引0到索引8的元素,步长为2
print(a[0:8:2]) # 输出: [0 2 4 6]
# 获取从索引1到末尾的元素
print(a[1:]) # 输出: [1 2 3 4 5 6 7 8 9]
# 获取从开始到索引5的元素
print(a[:5]) # 输出: [0 1 2 3 4]
# 获取整个数组的元素
print(a[:]) # 输出: [0 1 2 3 4 5 6 7 8 9]
二维数组切片
对于二维数组,切片操作可以分别应用于每个维度。语法是 array[row_start:row_stop:row_step, col_start:col_stop:col_step]
。
b = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
# 获取第1行到第3行,第1列到第3列的子数组
print(b[1:3, 1:3])
# 输出:
# [[ 5 6]
# [ 9 10]]
# 获取第2行的所有元素
print(b[2, :]) # 输出: [ 8 9 10 11]
# 获取所有行的第2列
print(b[:, 2]) # 输出: [ 2 6 10 14]
三维数组切片
对于三维数组,切片操作可以分别应用于每个维度。语法是 array[dim1_start:dim1_stop:dim1_step, dim2_start:dim2_stop:dim2_step, dim3_start:dim3_stop:dim3_step]
。
c = np.array([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]],
[[18, 19, 20],
[21, 22, 23],
[24, 25, 26]]])
# 获取第0维度的第1个子数组
print(c[1])
# 输出:
# [[ 9 10 11]
# [12 13 14]
# [15 16 17]]
# 获取第0维度的第1个子数组的第1行
print(c[1, 1])
# 输出: [12 13 14]
# 获取第0维度的第1个子数组的第1行的第1个元素
print(c[1, 1, 1]) # 输出: 13
# 获取第0维度的第0个和第1个子数组,第1维度的第1行和第2行,第2维度的第0个和第2个元素
print(c[0:2, 1:3, 0:3:2])
# 输出:
# [[[ 3 5]
# [ 6 8]]
#
# [[12 14]
# [15 17]]]
高级切片操作
布尔索引
布尔索引允许你基于条件筛选数组中的元素。
d = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
# 获取所有大于5的元素
print(d[d > 5]) # 输出: [6 7 8 9]
花式索引
花式索引允许你使用整数数组进行索引。
e = np.array([10, 20, 30, 40, 50])
# 使用整数数组进行索引
print(e[[0, 2, 4]]) # 输出: [10 30 50]
混合索引
你可以混合使用基本切片、布尔索引和花式索引。
f = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
# 获取第1行和第3行的第0列和第2列的元素
print(f[[1, 3], [0, 2]]) # 输出: [ 4 14]
# 获取第0行到第2行的所有元素,步长为2
print(f[0:3:2, :]) # 输出: [[ 0 1 2 3]
# [ 8 9 10 11]]
三维数组切片的具体示例
g = np.array([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]],
[[18, 19, 20],
[21, 22, 23],
[24, 25, 26]]])
# 获取第1维度的第1个子数组的第1行的所有元素
print(g[1, 1, :]) # 输出: [12 13 14]
# 获取第0维度的第0个和第1个子数组,第1维度的第1行和第2行,第2维度的所有元素
print(g[0:2, 1:3, :])
# 输出:
# [[[ 3 4 5]
# [ 6 7 8]]
#
# [[12 13 14]
# [15 16 17]]]
# 获取第0维度的所有子数组,第1维度的第0行和第2行,第2维度的第1个元素
print(g[:, [0, 2], 1])
# 输出:
# [[ 1 7]
# [10 16]
# [19 25]]
通过这些示例,你可以看到NumPy数组的切片操作非常强大且灵活,能够满足多种数据处理需求。特别是对于三维数组,切片操作可以让你方便地获取多维数据的子集。
Numpy中的轴及沿轴操作
在 NumPy 中,很多操作(如求和、均值等)都可以沿指定的轴进行。为了更好地理解这些操作,我们需要深入了解轴的概念及其在多维数组中的应用。
基本概念
- 轴(Axis):NumPy 数组的每一个维度称为一个轴。轴的编号从 0 开始。
- 沿轴操作:沿指定轴进行操作时,NumPy 会在该轴方向上进行计算,而保留其他轴的结构。
示例与解释
示例:二维数组的轴操作
import numpy as np
arr_2d = np.array([[1, 2, 3], [4, 5, 6]])
print("原数组:\n", arr_2d)
- 二维数组:
arr_2d
是一个 2x3 的数组,具有两个轴:- 轴 0(行方向):包含
[1, 2, 3]
和[4, 5, 6]
两行。 - 轴 1(列方向):包含
[1, 4]
、[2, 5]
和[3, 6]
三列。
- 轴 0(行方向):包含
沿轴 0 求和
sum_axis0 = np.sum(arr_2d, axis=0)
print("沿轴0求和:", sum_axis0)
- 计算过程:
- 沿轴 0 进行求和时,NumPy 会在行方向上对每一列的元素进行相加。
- 计算过程:
- 第一列:
1 + 4 = 5
- 第二列:
2 + 5 = 7
- 第三列:
3 + 6 = 9
- 第一列:
- 结果:
[5, 7, 9]
输出:
沿轴0求和: [5 7 9]
沿轴 1 求和
sum_axis1 = np.sum(arr_2d, axis=1)
print("沿轴1求和:", sum_axis1)
- 计算过程:
- 沿轴 1 进行求和时,NumPy 会在列方向上对每一行的元素进行相加。
- 计算过程:
- 第一行:
1 + 2 + 3 = 6
- 第二行:
4 + 5 + 6 = 15
- 第一行:
- 结果:
[6, 15]
输出:
沿轴1求和: [ 6 15]
示例:三维数组的轴操作
arr_3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print("原三维数组:\n", arr_3d)
- 三维数组:
arr_3d
是一个 2x2x3 的数组,具有三个轴:- 轴 0(页方向):包含两个 2x3 的二维数组。
- 轴 1(行方向):每页包含两行。
- 轴 2(列方向):每行包含三列。
沿轴 0 求均值
mean_axis0 = np.mean(arr_3d, axis=0)
print("沿轴0求均值:\n", mean_axis0)
- 计算过程:
- 沿轴 0 进行求均值时,NumPy 会在页方向上对每个位置的元素进行求均值。
- 计算过程:
- 第一页和第二页的第一个位置:
(1 + 7) / 2 = 4
- 第一页和第二页的第二个位置:
(2 + 8) / 2 = 5
- 第一页和第二页的第三个位置:
(3 + 9) / 2 = 6
- 以此类推…
- 第一页和第二页的第一个位置:
- 结果:
[[ 4. 5. 6.] [ 7. 8. 9.]]
输出:
沿轴0求均值:
[[ 4. 5. 6.]
[ 7. 8. 9.]]
沿轴 1 求均值
mean_axis1 = np.mean(arr_3d, axis=1)
print("沿轴1求均值:\n", mean_axis1)
- 计算过程:
- 沿轴 1 进行求均值时,NumPy 会在行方向上对每一页的每一列进行求均值。
- 计算过程:
- 第一页的第一列和第二列:
(1 + 4) / 2 = 2.5
- 第一页的第二列和第三列:
(2 + 5) / 2 = 3.5
- 第一页的第三列和第四列:
(3 + 6) / 2 = 4.5
- 以此类推…
- 第一页的第一列和第二列:
- 结果:
[[ 2.5 3.5 4.5] [ 8.5 9.5 10.5]]
输出:
沿轴1求均值:
[[ 2.5 3.5 4.5]
[ 8.5 9.5 10.5]]
沿轴 2 求均值
mean_axis2 = np.mean(arr_3d, axis=2)
print("沿轴2求均值:\n", mean_axis2)
- 计算过程:
- 沿轴 2 进行求均值时,NumPy 会在列方向上对每一行的元素进行求均值。
- 计算过程:
- 第一页的第一行:
(1 + 2 + 3) / 3 = 2
- 第一页的第二行:
(4 + 5 + 6) / 3 = 5
- 第二页的第一行:
(7 + 8 + 9) / 3 = 8
- 第二页的第二行:
(10 + 11 + 12) / 3 = 11
- 第一页的第一行:
- 结果:
[[ 2. 5.] [ 8. 11.]]
输出:
沿轴2求均值:
[[ 2. 5.]
[ 8. 11.]]
通过上述示例,我们可以看到沿指定轴进行操作的计算过程。无论是求和、均值还是其他操作,NumPy 都允许我们指定轴进行计算,从而灵活地处理多维数组的数据。这种灵活性使得 NumPy 在数据处理和科学计算中非常强大和高效。
NumPy数据类型(dtype)
NumPy支持多种数据类型(dtype),这些数据类型允许用户在数组中存储不同类型的数据。选择合适的数据类型可以优化内存使用和计算效率。以下是NumPy中常用的数据类型及其应用场合:
常用数据类型
-
整数类型(Integer Types)
int8
: 8位有符号整数,范围从 -128 到 127。int16
: 16位有符号整数,范围从 -32768 到 32767。int32
: 32位有符号整数,范围从 -2147483648 到 2147483647。int64
: 64位有符号整数,范围从 -9223372036854775808 到 9223372036854775807。
应用场合: 当需要存储整数数据时,根据数据范围选择合适的整数类型。例如,
int8
适用于存储范围较小的整数数据,可以节省内存。 -
无符号整数类型(Unsigned Integer Types)
uint8
: 8位无符号整数,范围从 0 到 255。uint16
: 16位无符号整数,范围从 0 到 65535。uint32
: 32位无符号整数,范围从 0 到 4294967295。uint64
: 64位无符号整数,范围从 0 到 18446744073709551615。
应用场合: 当数据不包含负数且需要更大的范围时使用无符号整数。例如,图像处理中的像素值通常使用
uint8
类型。 -
浮点数类型(Floating Point Types)
float16
: 16位半精度浮点数。float32
: 32位单精度浮点数。float64
: 64位双精度浮点数(NumPy默认浮点数类型)。
应用场合: 当需要存储实数数据时使用浮点数类型。
float32
适用于内存有限但精度要求不高的场合,而float64
适用于需要较高精度的计算。 -
复数类型(Complex Types)
complex64
: 32位实数和32位虚数组成的复数。complex128
: 64位实数和64位虚数组成的复数(NumPy默认复数类型)。
应用场合: 当需要处理包含复数的数学计算时使用复数类型。例如,信号处理和量子计算中常用复数表示。
-
布尔类型(Boolean Type)
bool
: 布尔类型,存储True
或False
。
应用场合: 用于条件判断和逻辑操作。例如,布尔数组可以用于掩码操作和条件筛选。
-
字符串类型(String Types)
string_
: 固定长度字符串类型。unicode_
: 固定长度的Unicode字符串类型。
应用场合: 当需要存储文本数据时使用字符串类型。
string_
适用于ASCII字符,而unicode_
适用于多语言文本。 -
日期时间类型(Datetime Types)
datetime64
: 日期时间类型,表示日期和时间。timedelta64
: 时间差类型,表示两个日期时间之间的时间差。
应用场合: 当需要处理时间序列数据时使用日期时间类型。例如,金融数据分析和时间序列预测中常用。
数据类型示例
import numpy as np
# 创建不同数据类型的数组
int_array = np.array([1, 2, 3], dtype=np.int32)
float_array = np.array([1.0, 2.0, 3.0], dtype=np.float64)
complex_array = np.array([1+2j, 3+4j], dtype=np.complex128)
bool_array = np.array([True, False, True], dtype=np.bool_)
str_array = np.array(['a', 'b', 'c'], dtype=np.string_)
unicode_array = np.array(['a', 'b', 'c'], dtype=np.unicode_)
datetime_array = np.array(['2023-01-01', '2023-01-02'], dtype=np.datetime64)
timedelta_array = np.array([1, 2, 3], dtype=np.timedelta64)
# 打印数组和数据类型
print(int_array, int_array.dtype) # 输出: [1 2 3] int32
print(float_array, float_array.dtype) # 输出: [1. 2. 3.] float64
print(complex_array, complex_array.dtype) # 输出: [1.+2.j 3.+4.j] complex128
print(bool_array, bool_array.dtype) # 输出: [ True False True] bool
print(str_array, str_array.dtype) # 输出: [b'a' b'b' b'c'] |S1
print(unicode_array, unicode_array.dtype) # 输出: ['a' 'b' 'c'] <U1
print(datetime_array, datetime_array.dtype) # 输出: ['2023-01-01' '2023-01-02'] datetime64[D]
print(timedelta_array, timedelta_array.dtype) # 输出: [1 2 3] timedelta64[D]
通过合理选择数据类型,可以优化内存使用和计算效率,从而提升程序性能。不同应用场合需要选择合适的数据类型,以满足特定需求。