[python] Numpy库用法(持续更新)
目录
一、np.random用法
二.一些数据处理函数
三.数学计算
四.数组运算
先介绍一下吧
NumPy,全称 Numerical Python,是一款开源的 Python 数学库,深受数据科学家、工程师和学术界的喜爱,因其在高性能数值计算中的卓越能力而备受推崇。这个库是 Python 科学计算的基石,提供了一个强大的数组对象,广泛应用于数据整理、模拟操作、统计建模、机器学习等多个领域。
核心功能围绕一个称为 ndarray 的多维数组对象展开,这不仅是一种强大的数据结构,也是通过矩阵运算来表达复杂算法的理想工具。NumPy 数组的高效性主要来源于其背后的优化 C 和 Fortran 代码,这使得处理大规模数据比原生 Python 快得多,同时提供了广泛的数学函数库来支持这些数组操作,从基本的数学计算如加、减、乘、除到更高级的线性代数运算、统计分析和随机数生成。
此外,NumPy 的设计哲学在于简洁和高效。它支持广播和矢量化操作,这意味着用户可以减少显式循环和迭代,从而写出更简洁、更快速且更易于阅读的代码。这种处理多维数据的能力让 NumPy 成为科学计算中不可或缺的工具,尤其是在处理图像、声音、视频等复杂数据类型时,其效率和简便性表现尤为突出。
简言之,NumPy 不仅仅是科学计算的工具库,它也是一种使 Python 编程语言变得更强大、更适用于数据密集型应用的方式,是连接 Python 与数据科学世界的金桥。
先导入一下
import numpy as np
一、np.random用法
-
生成随机整数:np.random.randint(low, high, size)
- low: 最小值
- high: 最大值
- size: 生成的数组大小(可以是多维,下面同理)
-
生成随机浮点数:np.random.uniform(low, high, size)
- low: 最小值
- high: 最大值
- size: 生成的数组大小
在NumPy中,
np.random.uniform
这个函数的名称中的"uniform"指的是均匀分布(Uniform Distribution)。这种分布中,所有数值在一定范围内出现的概率是均等的,也就是说,这个范围内的任何一个数被选中的机会都是一样的。这和其他一些分布不同,比如正态分布,其中某些数值出现的机率比其他数值高。具体来说,当你使用
np.random.uniform(low, high, size)
时:low
和high
参数定义了数值的范围,其中low
是下限(包含),high
是上限(不包含)。size
参数决定了生成多少个这样的随机数。举个例子,如果你调用
np.random.uniform(1, 5, 3)
,NumPy将会生成一个数组,包含3个在1(包含)到5(不包含)之间均匀分布的随机浮点数。因此,这个函数被命名为"uniform",正是因为它生成的是遵循均匀分布规律的随机数。
-
生成服从正态分布的随机数:np.random.normal(loc, scale, size)
- loc: 均值
- scale: 标准差
- size: 生成的数组大小
-
生成一个随机排列:np.random.permutation(x)
- x: 输入的数组或整数
-
生成一个随机样本:np.random.sample(size)
- size: 生成的数组大小
-
生成一个随机种子:np.random.seed(seed)
- seed: 种子值
-
生成一个符合指定概率分布的随机数:np.random.choice(a, size, replace, p)
- a: 输入的数组
- size: 生成的数组大小
- replace: 是否可以重复抽样
- p: 每个元素被抽样的概率
-
生成一个随机数组成的矩阵:np.random.rand(d0, d1, …, dn)
- d0, d1, …, dn: 矩阵的维度
-
生成一个随机整数矩阵:np.random.randint(low, high, size)
- low: 最小值
- high: 最大值
- size: 生成的矩阵大 小
import numpy as np
# 生成一个随机整数
random_int = np.random.randint(1, 10, 5)
print(random_int)
# 生成一个随机浮点数
random_float = np.random.uniform(1.0, 5.0, 5)
print(random_float)
# 生成一个服从正态分布的随机数
random_normal = np.random.normal(0, 1, 5)
print(random_normal)
# 生成一个随机排列
random_permutation = np.random.permutation([1, 2, 3, 4, 5])
print(random_permutation)
# 生成一个随机样本
random_sample = np.random.sample(5)
print(random_sample)
# 生成一个随机种子
np.random.seed(0)
random_seed = np.random.rand(3)
print(random_seed)
# 生成一个符合指定概率分布的随机数
random_choice = np.random.choice([1, 2, 3, 4, 5], 3, replace=False, p=[0.1, 0.2, 0.3, 0.2, 0.2])
print(random_choice)
# 生成一个随机矩阵
random_matrix = np.random.rand(2, 3)
print(random_matrix)
# 生成一个随机整数矩阵
random_int_matrix = np.random.randint(1, 10, (2, 3))
print(random_int_matrix)
# 生成一个服从均匀分布的随机数
random_uniform = np.random.rand(2, 3)
print(random_uniform)
输出结果
[9 6 4 8 5]
[1.87678294 4.17125097 4.34816045 4.56395443 1.99147984]
[-0.27015379 -1.82642694 0.96417976 1.38643896 0.23534789]
[5 1 3 2 4]
[0.73823778 0.70459439 0.67601929 0.45422436 0.67000757]
[0.5488135 0.71518937 0.60276338]
[3 4 2]
[[0.891773 0.96366276 0.38344152]
[0.79172504 0.52889492 0.56804456]]
[[6 9 5]
[4 1 4]]
[[0.95715516 0.14035078 0.87008726]
[0.47360805 0.80091075 0.52047748]]
np.random.randn
是 NumPy 库中用于生成符合标准正态分布(均值为 0,标准差为 1)的随机数的函数。
该函数的语法为:
np.random.randn(d0, d1, ..., dn)
其中 d0, d1, ..., dn
是表示数组形状的整数参数,用于指定要生成的随机数组的形状。如果没有传入参数,则返回单个标准正态分布的随机数。
import numpy as np
# 生成一个形状为 (2, 3) 的数组,其中的元素符合标准正态分布
random_array = np.random.randn(2, 3)
print(random_array)
np.random.randn
和 np.random.normal
都是用于生成服从正态分布(高斯分布)的随机数的函数,但它们有一些不同之处。
-
参数传递方式:
np.random.randn
函数的参数是用于指定数组形状的整数,而不是指定均值和标准差。np.random.normal
函数的参数包括均值、标准差和数组形状。-
使用方式:
np.random.randn
生成的是均值为 0,标准差为 1 的标准正态分布随机数,不需要指定均值和标准差。np.random.normal
可以根据指定的均值和标准差生成符合指定参数的正态分布随机数。
在实际使用中,如果只需要生成标准正态分布的随机数,可以使用 np.random.randn
更加简洁。而如果需要生成具有特定均值和标准差的正态分布随机数,则应该使用 np.random.normal
,因为它允许用户指定这些参数。
总的来说,这两个函数在生成服从正态分布的随机数时都有其独特的用途,具体使用取决于需要生成的随机数的性质。
二.一些数据处理函数
np.load
.npy
文件中的NumPy数组。这是一种高效存储和读取NumPy数组数据的方式,特别适用于持久化大型数组。np.astype
astype
方法允许你复制数组并将其元素转换为一个指定的类型。这在数据处理中非常常见,比如将整数数组转换为浮点数数组,或者将浮点数数组转换为整数数组。类型转换是数据预处理的一个重要步骤。np.shape 和 .shape
np.shape
是一个函数,而.shape
是数组对象的一个属性。了解数组的形状对于进行数组操作(如重塑或切片)是非常重要的。np.reshape
reshape
方法允许在不更改数组数据的前提下,给数组一个新的形状。这在将数据准备为特定格式进行机器学习模型训练时尤其有用。np.std
np.mean
mean
函数计算沿指定轴的平均值。平均值是最常用的统计量之一,用于描述数据集中趋势的中心位置。np.max
np.arange
arange
函数返回一个有等差数列构成的数组。这个函数非常适用于生成序列数据,例如生成连续的时间点序列。它是Python内置range
函数的NumPy版本,但可以生成浮点序列并具有更多的灵活性。val_X.reshape(val_X.shape[0], -1)
的操作并不是将数组重塑为一维数组,而是重塑为二维数组,其中第一维度保持不变,第二维度自动计算以包含剩余的所有元素。
具体来说:
val_X.shape[0]
:这是val_X
数组的第一个维度的大小,即行数。-1
:这个参数告诉NumPy自动计算第二个维度的大小,以便保持所有数据元素的总数不变。例如,如果val_X
原来的形状是(100, 2, 3)
,这表示有100个2×3的矩阵。执行val_X.reshape(val_X.shape[0], -1)
后,形状将变为(100, 6)
,这意味着每个原始的2×3矩阵现在被展平成一个包含6个元素的一维数组,但在更大框架下,它们作为100行的二维数组存在。
因此,reshape
操作并没有创建一个真正的一维数组,而是创建了一个二维数组,其第一维保持为原数组的行数,第二维展平了原有的每个子矩阵。
假设我们有一个数组test_Y
,它表示某种测试数据的标签,如下所示:
test_Y = np.array([1, 2, 1, 3, 2, 1, 3])
我们想要找出所有标签等于1
的数据的索引。在这个例子中,y
的值设为1
。
-
首先,
np.arange(num_data)
生成一个从0开始的等差数列。假设num_data
等于test_Y
的长度,即7,那么生成的数组就是[0, 1, 2, 3, 4, 5, 6]
。 -
接下来,
test_Y == 1
生成一个布尔数组,表示test_Y
中每个位置的值是否等于1
。对于我们的test_Y
,结果是:[True, False, True, False, False, True, False]
这意味着在位置0、2和5的值等于
1
。 -
最后,通过使用上一步生成的布尔数组作为索引,我们从步骤1生成的等差数列中选择索引。因此,
np.arange(num_data)[test_Y == 1]
的结果将是:[0, 2, 5]
这个结果告诉我们,在
test_Y
数组中,值等于1
的元素位于原数组的第0、第2和第5个位置。
总结一下,这行代码的作用是找出test_Y
中所有等于y
值的元素的索引,并以数组的形式返回这些索引。这种技巧在处理分类问题时特别有用,例如,当你需要根据分类结果选择或操作数据的子集时。
在 NumPy 库中,np.mean
和 np.std
是用来计算数组的平均值和标准差的函数。
-
np.mean
函数: - 用于计算数组中元素的算术平均值。
- 语法:
np.mean(a, axis=None, dtype=None, out=None, keepdims=<no value>)
- 参数:
a
: 输入数组。axis
: 可选参数,指定沿哪个轴计算平均值。默认为None
,计算所有元素的平均值。如果指定轴,可以是整数或整数的元组。dtype
: 可选参数,指定计算时使用的数据类型。out
: 可选参数,指定一个数组用于存放结果。keepdims
: 布尔值,表示是否保留原数组的维度。
import numpy as np
a = np.array([[1, 2], [3, 4]])
mean_all = np.mean(a) # 计算所有元素的平均值
mean_axis0 = np.mean(a, axis=0) # 计算每列的平均值
2.np.std
函数:
np.std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=<no value>)
a
: 输入数组。axis
: 可选参数,指定沿哪个轴计算标准差。dtype
: 可选参数,指定计算时使用的数据类型。out
: 可选参数,指定一个数组用于存放结果。ddof
: "Delta Degrees of Freedom"。默认为0。在计算方差或标准差时,分母使用 n - ddof
,其中 n
是元素数目。keepdims
: 布尔值,表示是否保留原数组的维度。import numpy as np
a = np.array([[1, 2], [3, 4]])
std_all = np.std(a) # 计算所有元素的标准差
std_axis0 = np.std(a, axis=0) # 计算每列的标准差
三.数学计算
numpy
库中的 clip
函数用于将数组中的元素限制在指定的范围内。该函数可以接受三个参数:要进行处理的数组、限制的最小值和最大值。如果数组中的元素小于最小值,则将其替换为最小值;如果元素大于最大值,则将其替换为最大值;如果元素在最小值和最大值之间,则不做任何操作。
以下是 clip
函数的详细介绍:
import numpy as np arr = np.array([1, 2, 3, 4, 5])
arr_clip = np.clip(arr, 2, 4)
print(arr_clip) # 输出:[2 2 3 4 4]
在这个例子中,我们使用 clip
函数将数组 arr
中小于 2 的元素替换为 2,大于 4 的元素替换为 4,其余元素保持不变。
cache[-1]
表示从列表 cache
中获取倒数第一个元素。在 Python 中,使用负数索引可以从列表的末尾开始获取元素。例如,cache[-1]
表示获取列表 cache
中的最后一个元素,cache[-2]
表示获取倒数第二个元素,依此类推。
以下是一个示例,演示如何使用负数索引获取列表的元素:
cache = [10, 20, 30, 40, 50]
print(cache[-1]) # 输出:50
print(cache[-2]) # 输出:40
在这个例子中,cache[-1]
返回的是列表 cache
中的最后一个元素,即 50。
NumPy 是一个功能强大的 Python 库,主要用于进行大规模数值计算。它提供了大量的数学函数来处理数组运算。下面我会介绍一些常用的数学函数,以及附上一些例子帮助你理解它们的用法。
-
指数和对数函数:
np.exp(x)
: 计算e^x
的值,其中e
是自然对数的底。np.log(x)
: 计算自然对数,即以e
为底的对数。np.log10(x)
: 计算以 10 为底的对数。np.log2(x)
: 计算以 2 为底的对数。np.expm1(x)
: 计算exp(x) - 1
的值,对于很小的x
值这种计算方式更精确。np.log1p(x)
: 计算log(1 + x)
的值,同样适用于计算很小的x
值。-
三角函数:
np.sin(x)
: 计算正弦。np.cos(x)
: 计算余弦。np.tan(x)
: 计算正切。np.arcsin(x)
: 计算反正弦。np.arccos(x)
: 计算反余弦。np.arctan(x)
: 计算反正切。-
双曲函数:
np.sinh(x)
: 计算双曲正弦。np.cosh(x)
: 计算双曲余弦。np.tanh(x)
: 计算双曲正切。-
平方根和绝对值函数:
np.sqrt(x)
: 计算平方根。np.abs(x)
: 计算绝对值。-
舍入函数:
np.ceil(x)
: 向上取整。np.floor(x)
: 向下取整。np.round(x)
: 四舍五入。
示例
import numpy as np
# 创建一个数组
x = np.array([1, 2, 3, 4, 5])
# 使用 exp 和 log 函数
print("e^x:", np.exp(x))
print("log(x):", np.log(x))
# 使用三角函数
angles = np.array([0, np.pi/2, np.pi, 3*np.pi/2])
print("sin(angles):", np.sin(angles))
print("cos(angles):", np.cos(angles))
# 使用平方根和绝对值函数
values = np.array([-9, 4, -16, 25])
print("sqrt(abs(values)):", np.sqrt(np.abs(values)))
代码输出
A @ B:
[[ 4 4]
[10 8]]
np.dot(A, B):
[[ 4 4]
[10 8]]
行列式 np.linalg.det(A): -2.0000000000000004
矩阵逆 np.linalg.inv(A):
[[-2. 1. ]
[ 1.5 -0.5]]
特征值: [-0.37228132 5.37228132]
特征向量:
[[-0.82456484 -0.41597356]
[ 0.56576746 -0.90937671]]
奇异值: [5.4649857 0.36596619]
左奇异向量 U:
[[-0.40455358 -0.9145143 ]
[-0.9145143 0.40455358]]
右奇异向量 V:
[[-0.57604844 -0.81741556]
[ 0.81741556 -0.57604844]]
解线性方程组: [-2. 1.5]
四.数组运算
-
数组属性:
ndarray.T
: 返回数组的转置。如果是一维数组,它就是原数组。ndarray.shape
: 数组的形状(每个维度的大小)。ndarray.size
: 数组中元素的总数。ndarray.dtype
: 数组元素的数据类型。ndarray.ndim
: 数组的维数。-
数组形状和大小调整:
np.reshape(a, newshape)
: 不改变数据的前提下,改变数组的形状。np.resize(a, new_shape)
: 改变数组大小,如果新大小大于原大小,则会重复数组中的元素填充。np.ravel(a)
: 返回一个连续的扁平数组。np.flatten()
: 与np.ravel
类似,但返回的是拷贝,对返回数组的修改不会影响原数组。np.transpose(a)
: 计算数组的转置,相当于.T
属性。-
添加/删除元素:
np.append(a, values)
: 将值附加到数组的末尾。np.insert(a, index, values)
: 在给定索引前插入值。np.delete(a, obj)
: 返回一个新数组,并删除指定的子数组。-
数组拼接和分割:
np.concatenate((a1, a2, ...), axis=0)
: 沿指定轴连接数组序列。np.vstack((a1, a2, ...))
: 垂直堆叠数组序列。np.hstack((a1, a2, ...))
: 水平堆叠数组序列。np.split(a, indices_or_sections)
: 将数组分割为多个子数组。
import numpy as np
# 创建一个数组
a = np.array([[1, 2], [3, 4], [5, 6]])
# 使用 .T 获得数组的转置
print("转置:\n", a.T)
# 改变数组形状
print("改变形状:\n", np.reshape(a, (2, 3)))
# 扁平化数组
print("扁平化:\n", a.ravel())
# 水平和垂直堆叠
b = np.array([[7, 8]])
print("垂直堆叠:\n", np.vstack((a, b)))
print("水平堆叠:\n", np.hstack((a, [[7], [8], [9]])))
# 数组分割
c = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
print("数组分割:", np.split(c, 3))
代码输出
转置:
[[1 3 5]
[2 4 6]]
改变形状:
[[1 2 3]
[4 5 6]]
扁平化:
[1 2 3 4 5 6]
垂直堆叠:
[[1 2]
[3 4]
[5 6]
[7 8]]
水平堆叠:
[[1 2 7]
[3 4 8]
[5 6 9]]
数组分割: [array([1, 2, 3]), array([4, 5, 6]), array([7, 8, 9])]
np.zeros
和 np.ones
是 NumPy 库中用于创建特定形状的全零数组和全一数组的函数。
np.zeros(shape, dtype=float, order='C')
:shape
: 定义数组的形状,可以是一个整数,表示一维数组的长度,或者是一个元组,表示多维数组的形状。dtype
: 可选参数,表示数组的数据类型,默认为 float。order
: 可选参数,表示数组在内存中的存储顺序,C 表示 C 风格的存储(行主序),F 表示 Fortran 风格的存储(列主序)。
import numpy as np
# 创建一个形状为 (3, 4) 的全零数组
zeros_array = np.zeros((3, 4))
print(zeros_array)
np.ones(shape, dtype=None, order='C')
:shape
: 定义数组的形状,与np.zeros
相同。dtype
: 可选参数,表示数组的数据类型,默认为 float。order
: 可选参数,表示数组在内存中的存储顺序,与np.zeros
相同。
import numpy as np
# 创建一个形状为 (2, 3, 4) 的全一数组
ones_array = np.ones((2, 3, 4))
print(ones_array)
这两个函数在数据处理和模型初始化过程中经常被使用,例如在神经网络中初始化权重和偏置,或者在进行数组运算时创建临时数组。它们提供了一种简单而高效的方式来创建特定形状的全零或全一数组。
在 NumPy 库中,np.sum
是用于计算数组元素总和的函数,非常有用于统计和数据分析中。该函数可以对整个数组或指定轴的元素进行求和。
np.sum(a, axis=None, dtype=None, out=None, keepdims=False)
参数
None
,表示求整个数组的元素总和。可以是整数或整数的元组,指定多个轴。True
,输出的数组维度与输入相同,否则维度可能会被压缩。import numpy as np
# 创建一个数组
a = np.array([[1, 2], [3, 4]])
# 计算所有元素的总和
total_sum = np.sum(a)
print("Total Sum:", total_sum)
# 沿着第一个轴(每列)求和
column_sum = np.sum(a, axis=0)
print("Column Sum:", column_sum)
# 沿着第二个轴(每行)求和
row_sum = np.sum(a, axis=1)
print("Row Sum:", row_sum)
Total Sum: 10
Column Sum: [4 6]
Row Sum: [3 7]
应用
np.sum
可以用在多种数据处理场景中,例如计算数组元素的总和、沿着某个方向的累加结果等。它的灵活性使其成为数据分析和科学计算中不可或缺的工具。
此函数与其他类似函数(如 np.mean
, np.std
等)一起,构成了 NumPy 提供的强大数据操作功能的基础。
np.putmask
是 NumPy 库中的一个函数,用于根据指定的掩码条件修改数组元素。这个函数直接在原数组上进行操作,改变原数组的内容。
语法
np.putmask(a, mask, values)
参数
a
同形状,指定哪些位置需要被替换。values
是单一值,那么所有被掩码标记的位置都将被替换为这个值。如果 values
是数组,则必须广播到 a
的形状。import numpy as np
# 创建一个原始数组
a = np.array([1, 2, 3, 4, 5])
# 定义一个掩码,指定要修改的位置
mask = np.array([False, True, False, True, False])
# 使用单一值替换被掩码标记的位置
np.putmask(a, mask, -1)
print(a) # 输出: [1 -1 3 -1 5]
# 使用数组替换被掩码标记的位置
a = np.array([1, 2, 3, 4, 5])
values = np.array([10, 20, 30, 40, 50])
np.putmask(a, mask, values)
print(a) # 输出: [1 20 3 40 5]
应用
np.putmask
函数在数据预处理、条件替换等场景中非常有用。例如,可以用它快速修正数据集中的异常值或应用条件逻辑替换。这种“就地”修改方式使得内存使用更高效,特别是在处理大型数组时。
通过这种方式,np.putmask
提供了一种强大且灵活的方法来按条件更新数组元素,使其在科学计算和数据分析中应用广泛。
np.zeros_like
是 NumPy 库中的一个函数,用于创建一个与给定数组形状和数据类型相同,但所有元素都为0的新数组。
np.zeros_like(a, dtype=None, order='K', subok=True, shape=None)
参数
import numpy as np
# 创建一个示例数组
a = np.array([[1, 2, 3], [4, 5, 6]], dtype=float)
# 创建一个与a形状和数据类型都相同,但所有元素为0的数组
b = np.zeros_like(a)
print(b)
# 输出:
# [[0. 0. 0.]
# [0. 0. 0.]]
应用
np.zeros_like
函数在数组初始化和数据处理中非常有用,特别是当需要一个与其他数组具有相同形状和数据类型的零填充数组时。这使得其在科学计算、数据预处理、测试和其他多种场景中都非常实用
np.put_along_axis
是 NumPy 库中的一个函数,用于沿指定轴在数组中放置值。这个函数允许你根据索引数组将值替换到目标数组的指定位置上,非常适合进行高效的数组元素更新。
语法
np.put_along_axis(arr, indices, values, axis)
参数
arr
指定位置的值。这个值的形状应该广播到 arr
的形状。示例
假设你有一个数组 arr
和一个目标索引数组 indices
,你想在这些索引位置放入新的值 values
。
import numpy as np
# 创建一个初始数组
arr = np.array([[10, 20, 30], [40, 50, 60], [70, 80, 90]])
# 创建索引数组
indices = np.array([2, 0, 1])
# 创建要插入的值数组
values = np.array([777, 888, 999])
# 沿着轴1(列轴)替换值
np.put_along_axis(arr, indices[:, None], values[:, None], axis=1)
print(arr)
# 输出:
# [[ 10 20 777]
# [888 50 60]
# [ 70 999 80]]
在这个例子中,indices
数组定义了每行中应该被替换的元素的索引位置,而 values
提供了新的值。np.put_along_axis
根据这些索引更新 arr
中的相应位置。
应用
np.put_along_axis
特别适用于需要基于索引进行高效元素更新的情况,如在数据预处理、特征工程或在实现某些数学算法中,比如自定义排序或替换操作。这个功能使得在复杂的数组操作中可以更灵活地控制数据。
在 NumPy 中,使用 None
作为下标(也可以使用 np.newaxis
)用来增加数组的维度。在表达式 indices[:, None]
中,indices
是一个一维数组,而 None
是用来在指定位置增加一个新的轴(维度)。
indices[:, None]
实质上是将 indices
这个一维数组转换成一个二维数组,其中新的维度(轴)被添加到原有维度的末尾。如果 indices
的形状原本是 (n,)
,使用 [:, None]
之后,形状变为 (n, 1)
。这种操作常用于需要将一维数组扩展成二维数组以便进行某些特定的数组操作,如广播(broadcasting)或者与其他二维数组进行操作时,确保维度匹配。在 np.put_along_axis
的例子中,这样做可以确保 indices
和 values
数组在传入函数时能够适配目标数组 arr
的形状,允许沿指定的轴正确地替换值。
当然,我来用一个简化的例子来帮助你理解 None
在下标中的作用。
假设我们有一个一维数组 indices
,内容如下:
indices = np.array([0, 2, 1])
这个数组的形状是 (3,)
,意味着它是一个有3个元素的一维数组。如果我们想要将其用在一些需要二维数组的操作中,比如在多维数组中选择或替换元素,我们就需要将其转换成二维数组。
通过使用 [:, None]
,我们实际上是在这个数组的末尾添加了一个新的轴,这样做会改变数组的形状:
new_indices = indices[:, None]
print(new_indices)
这段代码的输出将是:
[[0]
[2]
[1]]
现在 new_indices
的形状是 (3, 1)
,变成了一个列向量。这种转换特别有用,因为它允许 new_indices
与其他可能是多维的数组进行兼容操作,特别是在进行广播或者适配到其他具体的函数需求时。
例如,在 np.put_along_axis
函数中使用时,假设我们有以下的 arr
和 values
:
arr = np.array([[10, 20, 30],
[40, 50, 60],
[70, 80, 90]])
values = np.array([777, 888, 999])
我们希望在每一行中根据 indices
的指示替换对应的值,那么 indices
需要是二维的以匹配到 arr
的二维结构。这时,通过使用 indices[:, None]
和 values[:, None]
来确保它们在沿着指定轴(这里是列轴)操作时形状正确:
np.put_along_axis(arr, indices[:, None], values[:, None], axis=1)
print(arr)
这会更新 arr
中指定的列,结果如下:
[[ 10 20 777]
[888 50 60]
[ 70 999 80]]
在这个例子中,indices[:, None]
创建了一个形状为 (3, 1)
的数组,它告诉函数在每一行中哪个位置应该被替换。这样,新的值 777
, 888
, 999
被放入了正确的位置。
np.expand_dims
和使用 None
(或 np.newaxis
)在索引中都是用来增加数组的维度,但它们在语法和可读性方面略有不同。
np.expand_dims
np.expand_dims
是一个明确的函数调用,用于在指定的轴位置增加一个新的轴。它通过函数参数明确指定在哪个轴上添加维度,使得代码的意图更加明显,从而提高了代码的可读性。
语法:
np.expand_dims(a, axis)
例如,如果你有一个一维数组 indices
并希望在第一维前添加一个新轴,你可以这样做:
indices = np.array([0, 2, 1])
new_indices = np.expand_dims(indices, axis=0)
print(new_indices)
# 输出: [[0 2 1]]
如果你想在第二维后添加一个新轴(变成列向量),则可以:
new_indices = np.expand_dims(indices, axis=1)
print(new_indices)
# 输出:
# [[0]
# [2]
# [1]]
使用 None
或 np.newaxis
使用 None
或 np.newaxis
来增加维度通常是通过索引操作完成的。这种方法较为简洁,但可能不如 np.expand_dims
明显,特别是对于初学者来说。
例如,以下两种方法都可以将 indices
转换为列向量:
indices = np.array([0, 2, 1])
# 使用 None
new_indices = indices[:, None]
print(new_indices)
# 使用 np.newaxis
new_indices = indices[:, np.newaxis]
print(new_indices)
两种方法的输出都是:
[[0]
[2]
[1]]
总结
np.expand_dims
可能更好,因为它通过参数明确指定了增加维度的轴。None
或 np.newaxis
在索引中可能更方便。在实际应用中,你可以根据具体的场景和个人偏好选择使用哪一种。
当在 np.expand_dims
函数中使用 axis
参数值为 -1
时,这表示在数组的最后一个轴后面添加一个新的维度。在 Python 和 NumPy 中,负索引用于从数组的末尾开始反向定位,其中 -1
表示最后一个位置。
例如,如果你有一个一维数组:
arr = np.array([1, 2, 3])
使用 axis=-1
来添加一个新的维度会将数组变成一个二维数组,其中每个原始元素变为一个单独的行:
new_arr = np.expand_dims(arr, axis=-1)
print(new_arr)
输出将是:
[[1]
[2]
[3]]
这里,新的维度是在原数组的每个元素后面添加的,所以原来的每个元素 1, 2, 3
现在分别变成了 [1], [2], [3]
这样的行向量。这种操作常用于需要将一维数组转换为列向量的场合,便于与其他多维数组进行操作,比如在矩阵乘法或广播中使用。
numpy.take_along_axis
是 NumPy 库中的一个函数,它用于从数组中按照指定的索引提取元素。这个函数非常有用,特别是在你需要从数组的特定轴上根据另一个数组的索引来选择数据时。
函数签名
numpy.take_along_axis(arr, indices, axis)
参数
arr
中选择元素的索引。这个数组的形状必须广播到 arr
的形状。返回值
indices
相同,这个数组包含了从 arr
按照 indices
指定的方式沿着 axis
轴提取出的元素。使用场景和例子
numpy.take_along_axis
非常适合处理那些需要根据索引数组从目标数组中提取数据的复杂情况,特别是当索引的维度与目标数组不完全对齐时。以下是一些示例来展示如何使用这个函数:
示例 1: 基本使用
假设有一个数组 arr
和一个索引数组 indices
,我们想沿着某个轴提取元素:
import numpy as np
arr = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
indices = np.array([[2, 1, 0],
[0, 2, 1]])
# Take elements along axis 0
result = np.take_along_axis(arr, indices, axis=0)
print(result) # 输出: [[7 5 3]
# [1 9 6]]
在这个例子中,indices
数组的每个位置指定了 arr
中相应位置应该选取的元素的索引。
示例 2: 高级索引
你也可以使用更复杂的索引数组来提取数据,例如:
arr = np.random.rand(3, 4, 5) # 创建一个3x4x5的随机数组
indices = np.array([[[1, 2, 3, 2, 1],
[0, 1, 2, 3, 0],
[4, 3, 2, 1, 0]],
[[1, 0, 3, 1, 2],
[2, 3, 4, 0, 1],
[3, 2, 1, 0, 4]],
[[0, 4, 3, 2, 1],
[3, 2, 1, 0, 4],
[2, 1, 0, 3, 2]]])
# Take elements along axis 2
result = np.take_along_axis(arr, indices, axis=2)
print(result)
arr
是一个三维数组。indices
是一个同样形状为 (3, 3, 5) 的索引数组。axis=2
,表示索引操作是在每个 3×4 的子数组的每一行进行。输出 result
将会是一个形状也为 (3, 3, 5) 的数组,其中包含从 arr
按照 indices
的指定,从第三维(axis=2
)提取的元素。这种方式允许我们从每个子数组中按照复杂的模式选择元素,非常适合进行高级数组操作和数据抽取任务。
cumsum
作者:StudyingPanda