索引
基本索引
NumPy索引类似于Python列表的索引,但它提供了更多的功能。对于一维数组,你可以使用整数索引访问特定位置的元素:
import numpy as np
arr = np.array([1, 2, 3, 4])
print(arr[2]) # 输出:3
对于多维数组,你可以使用逗号分隔的索引元组来访问元素:
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr[1, 2]) # 输出:6
切片索引
切片是Python和NumPy中一种常用的数据访问方式,允许你访问数组的一部分:
arr = np.array([0, 1, 2, 3, 4, 5])
# 获取索引1到4之前的元素
print(arr[1:4]) # 输出:[1 2 3]
# 获取从开始到索引3(不包含)的元素
print(arr[:3]) # 输出:[0 1 2]
# 获取索引2到末尾的元素
print(arr[2:]) # 输出:[2 3 4 5]
对于多维数组,你可以对每个维度分别进行切片:
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 获取第一行
print(arr[0, :]) # 输出:[1 2 3]
# 获取第一列
print(arr[:, 0]) # 输出:[1 4 7]
# 获取子数组(2x2,从arr[1:, 1:]开始)
print(arr[1:, 1:]) # 输出:
# [[5 6]
# [8 9]]
布尔索引
布尔索引允许你根据布尔数组的值来索引目标数组,这在条件筛选数据时非常有用:
arr = np.array([0, 1, 2, 3, 4, 5])
# 创建一个布尔数组
bool_arr = arr > 2
# 使用布尔数组进行索引
print(arr[bool_arr]) # 输出:[3 4 5]
# 直接使用布尔表达式
print(arr[arr > 2]) # 输出:[3 4 5]
花式索引
花式索引(Fancy indexing)允许你使用整数数组作为索引:
arr = np.array([0, 1, 2, 3, 4, 5])
# 使用整数数组索引
print(arr[[1, 3, 4]]) # 输出:[1 3 4]
对于多维数组,花式索引可以让你访问数组的任意位置,甚至以非常灵活的方式重排数组:
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 获取(0,1)、(1,2)和(2,0)位置的元素
print(arr[[0, 1, 2], [1, 2, 0]]) # 输出:[2 6 7]
注意事项
- NumPy索引是从0开始的。
- 切片是原数组的视图,修改切片会影响原数组。如果需要复制,可以使用 .copy()方法。
- 布尔索引和花式索引返回的数组不与原数组共享数据。
改变形状
numpy.reshape是NumPy库中的一个非常重要的函数,它允许你重新排列给定数组的维度,而不改变数组中的数据。这意味着你可以将任何形状的数组转换成你需要的任何其他形状,只要新形状的总元素数与原始数组相同。
reshape函数的基本语法如下:
numpy.reshape(a, newshape, order='C')
- a:要被重塑的数组。
- newshape:整数或整数元组,指定了新数组的形状。如果 newshape是整数,则结果将是一维数组。特别地, newshape可以为 -1,在这种情况下,值会自动计算以保持数组元素的总数不变。
- order:{'C', 'F', 'A'},可选。指定重塑操作和数组数据在内存中的读写顺序。'C'意味着C风格的顺序,'F'意味着Fortran风格的顺序,'A'意味着如果 a是Fortran连续的,在重塑过程中也应该保持Fortran连续。
示例1:基础重塑
将一维数组重塑为二维数组:
import numpy as np
arr = np.arange(6)
print("Original array:", arr)
# 重塑为2x3数组
reshaped_arr = arr.reshape((2, 3))
print("Reshaped array:\n", reshaped_arr)
示例2:自动计算维度
使用 -1自动计算维度,让NumPy自动确定正确的维度:
arr = np.arange(6)
# 只指定行数,列数自动计算
reshaped_arr = arr.reshape((2, -1))
print("Reshaped array with -1:\n", reshaped_arr)
示例3:从多维到一维
将多维数组重塑为一维数组:
arr = np.array([[1, 2, 3], [4, 5, 6]])
# 使用reshape
flat_arr = arr.reshape(-1)
print("Flattened array:", flat_arr)
# 使用ravel函数也可以实现相同的效果
flat_arr = np.ravel(arr)
print("Flattened array with ravel:", flat_arr)
# 返回一维数组的副本
flat_arr = np.flatten(arr)
print("Flattened array with flatten:", flat_arr)
注意事项
- reshape操作不会改变原始数组,而是返回一个新的重塑后的数组。如果你想就地修改原始数组,可以使用 resize方法。
- 使用 -1作为 newshape的一部分可以方便地自动计算维度,但需要确保总元素数不变。
- reshape和 ravel(或 flatten)可以相互转换,但要注意 ravel通常返回视图,而 flatten总是返回副本。
数组拼接
数组的拼接是将不同的数组按照一定的顺序组合成一个新的数组。根据数组的维度和拼接方向,NumPy提供了几种不同的函数来实现数组的拼接,主要包括 np.concatenate、 np.vstack(垂直栈)、 np.hstack(水平栈)和 np.dstack(深度栈)等。
np.concatenate
np.concatenate是最基础的数组拼接函数,它可以沿着指定的轴拼接一系列数组。
numpy.concatenate((a1, a2, ...), axis=0)
- a1,a2,...:要拼接的数组序列。
- axis:指定拼接的轴。默认为0,表示第一个轴。
import numpy as np
# 一维数组拼接
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
result = np.concatenate((arr1, arr2))
print(result) # 输出:[1 2 3 4 5 6]
# 二维数组沿着第一个轴(行)拼接
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6]])
result = np.concatenate((arr1, arr2), axis=0)
print(result)
# 输出:
# [[1 2]
# [3 4]
# [5 6]]
np.vstack 和 np.hstack
np.vstack(垂直栈)和 np.hstack(水平栈)提供了更简便的方法来进行垂直和水平方向的数组拼接。
# 垂直栈
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
result = np.vstack((arr1, arr2))
print(result)
# 输出:
# [[1 2 3]
# [4 5 6]]
# 水平栈
result = np.hstack((arr1, arr2))
print(result) # 输出:[1 2 3 4 5 6]
np.dstack
np.dstack将数组沿着第三个维度(深度方向)拼接。
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
result = np.dstack((arr1, arr2))
print(result)
# 输出:
# [[[1 4]
# [2 5]
# [3 6]]]
注意事项
- 拼接的数组在非拼接轴上的维度必须相同。
- np.vstack和 np.hstack在处理维度不同的数组时比 np.concatenate更加灵活,它们会自动处理维度以实现拼接。
- 使用 np.concatenate和相关函数时,要确保拼接的数组在指定的轴上是兼容的,否则会抛出异常。
数组分裂
将一个数组分割成多个较小数组的过程。NumPy提供了几个函数来执行不同形式的数组分裂,包括 np.split、 np.hsplit、 np.vsplit和 np.array_split等。这些函数允许你按照指定的索引或轴将数组分割成多个子数组。
1.np.split
np.split是最基础的数组分裂函数,它沿指定轴分割数组。
基本用法
numpy.split(ary, indices_or_sections, axis=0)
- ary:要分裂的输入数组。
- indices_or_sections:如果是整数,表示要分割成的均等分的数量;如果是整数数组,则表示在哪些索引位置进行分割。
- axis:指定分割的轴,默认为0。
示例
import numpy as np
arr = np.arange(9)
# 将数组分割成3个等长的子数组
print(np.split(arr, 3))
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 沿水平轴分割数组
print(np.split(arr2d, [1], axis=0))
# 沿垂直轴分割数组
print(np.split(arr2d, [2], axis=1))
2.np.hsplit和np.vsplit
np.hsplit和 np.vsplit是 np.split的特例,分别用于沿水平轴和垂直轴分割数组。
示例
# 水平分割
print(np.hsplit(arr2d, 3))
# 垂直分割
print(np.vsplit(arr2d, 3))
3.np.array_split
np.array_split与 np.split类似,但它允许分割成不等长的子数组。
示例
# 分割成不等长的子数组
print(np.array_split(arr, 4))
注意事项
- 使用 np.split时,如果指定的是分割成的均等分的数量,则数组的大小必须能被该数量整除,否则会报错。如果需要分割成不等长的子数组,应使用 np.array_split。
- 在使用索引数组进行分割时,提供的索引是分割点的位置。例如, np.split(arr,[2,5])会在索引2和5的位置分割数组,生成三个子数组。
- np.hsplit和 np.vsplit是为特定的分割方向提供便利的函数,分别对应于 axis=1和 axis=0的 np.split操作。
运算
1. 算术运算
NumPy允许你对数组执行各种算术运算,这些运算可以是数组与数组之间的,也可以是数组与标量之间的。
- 加法( + 或 np.add):数组元素相加。
- 减法( - 或 np.subtract):从第一个数组中减去第二个数组的元素。
- 乘法( * 或 np.multiply):数组元素相乘。
- 除法( / 或 np.divide):第一个数组元素除以第二个数组的元素。
- 平方根( np.sqrt):数组每个元素的平方根。
- 幂运算( ** 或 np.power):第一个数组元素的第二个数组元素次幂。
import numpy as np
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])
# 算术运算示例
print(a + b) # 加法
print(a - b) # 减法
print(a * b) # 乘法
print(a / b) # 除法
print(np.sqrt(a)) # 平方根
2. 比较运算
支持所有常见的比较运算符,比如 <(小于)、 >(大于)、 <=(小于等于)、 >=(大于等于)、\==(等于)和 !=(不等于)。这些运算符被应用于数组时,会逐元素地进行比较,返回一个同形状的布尔数组。
import numpy as np
x = np.array([1, 2, 3, 4, 5])
# 比较操作
print(x < 3) # 小于3
# 输出:[ True True False False False]
使用布尔数组作为掩码
得到比较运算的结果后,你可以将这个布尔数组用作掩码,以选择满足条件的元素。这通过简单地索引布尔数组来实现。
print(x[x < 3])
# 输出:[1 2]
组合条件
你还可以使用逻辑运算符,如 &(和)、 |(或)、 ^(异或)和 ~(非),来组合多个条件。注意,这些逻辑运算符要求使用括号来明确运算的顺序。
print(x[(x > 2) & (x < 5)])
# 输出:[3 4]
使用 np.where
np.where 是一个非常实用的函数,它返回满足条件的元素的索引。此外,它还可以作为三元运算符 cond?x:y 的向量化版本。
result = np.where(x < 3, x, -1) # 小于3的保留,其他替换为-1
print(result)
# 输出:[ 1 2 -1 -1 -1]
修改数组
你可以使用布尔掩码来修改数组中满足特定条件的元素。
x[x < 3] = 0
print(x)
# 输出:[0 0 3 4 5]
计数满足条件的元素
np.count_nonzero 和布尔数组的 sum 方法都可以用来计数数组中 True 的数量,即满足条件的元素数量。
print(np.count_nonzero(x < 3))
# 输出:2
# 或者
print(np.sum(x < 3))
# 输出:2
布尔运算的其他函数
- np.any():检查数组中是否至少有一个 True,用于测试是否至少有一个元素满足条件。
- np.all():检查数组中所有元素是否都是 True,用于测试是否所有元素满足条件。
print(np.any(x > 4)) # 至少有一个元素大于4吗?
# 输出:True
print(np.all(x < 6)) # 所有元素都小于6吗?
# 输出:True
3. 逻辑运算
NumPy提供了逻辑操作函数,如逻辑与( np.logical_and)、逻辑或( np.logical_or)、逻辑非( np.logical_not)等。
print(np.logical_and(a > 2, b < 8))
print(np.logical_or(a < 2, b > 7))
4. 统计运算
NumPy提供了一系列的统计函数来分析数组中的数据,包括最大值( np.max)、最小值( np.min)、平均值( np.mean)、中位数( np.median)、标准差( np.std)等。
print(np.max(a)) # 最大值
print(np.mean(a)) # 平均值
print(np.std(b)) # 标准差
5.三角函数
常用的NumPy三角函数
- np.sin(x): 正弦函数
- np.cos(x): 余弦函数
- np.tan(x): 正切函数
- np.arcsin(x): 反正弦函数
- np.arccos(x): 反余弦函数
- np.arctan(x): 反正切函数
- np.arctan2(y,x): 两个参数的反正切函数,返回给定的Y/X的反正切值
- np.radians(deg): 角度转换为弧度
- np.degrees(rad): 弧度转换为角度
- np.hypot(x,y): 计算直角三角形的斜边长度
使用示例
下面通过一些简单的示例,来说明如何使用这些三角函数。
正弦函数示例
import numpy as np
# 创建一个角度数组
degrees = np.array([0, 30, 45, 60, 90])
# 将角度转换为弧度
radians = np.radians(degrees)
# 计算这些角度的正弦值
sin_values = np.sin(radians)
print("Sin values:", sin_values)
反三角函数示例
# 已知正弦值,计算角度
sin_values = np.array([0, 1/2, np.sqrt(2)/2, np.sqrt(3)/2, 1])
# 使用 arcsin 计算角度的弧度值
angles_radians = np.arcsin(sin_values)
# 将弧度转换为角度
angles_degrees = np.degrees(angles_radians)
print("Angles:", angles_degrees)
6.对数
NumPy 提供了一系列的对数函数,使得对数组中的每个元素进行对数运算变得非常简单和高效。这些对数函数包括计算自然对数、底数为10的对数、底数为2的对数等。对数运算在数据分析、科学计算、工程等领域中非常常见,特别是在处理指数增长或衰减的数据时。
NumPy 中的主要对数函数
- np.log(x): 计算数组中各元素的自然对数(底数是e)。
- np.log10(x): 计算数组中各元素的以10为底的对数。
- np.log2(x): 计算数组中各元素的以2为底的对数。
- np.log1p(x): 计算 1+x的自然对数,对于小值 x,提高计算精度。
- np.expm1(x): 计算 exp(x)-1,与 np.log1p相对应,用于提高小值 x的计算精度。
使用示例
下面是一些使用NumPy进行对数运算的示例。
自然对数
import numpy as np
# 创建一个正数数组
x = np.array([1, e, e**2, e**3])
# 计算数组元素的自然对数
log_x = np.log(x)
print("Natural log:", log_x)
底数为10的对数
# 创建一个正数数组
x = np.array([1, 10, 100, 1000])
# 计算数组元素的以10为底的对数
log10_x = np.log10(x)
print("Log base 10:", log10_x)
底数为2的对数
# 创建一个正数数组
x = np.array([1, 2, 4, 8])
# 计算数组元素的以2为底的对数
log2_x = np.log2(x)
print("Log base 2:", log2_x)
提高小数计算精度的对数函数
对于非常接近0的正数,直接使用 np.log或其它对数函数可能会因为数值精度问题导致计算结果不准确。NumPy 提供了 np.log1p,它可以用来计算 1+x的自然对数,从而提高小数值计算的准确性。
# 对于非常小的数值
x = np.array([1e-99])
# 直接计算log(1+x)
log1p_x = np.log1p(x)
print("log(1+x) for small x:", log1p_x)
7.矩阵运算
创建矩阵:
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
矩阵加法和减法
两个形状相同的矩阵可以进行加法和减法运算,对应元素相加或相减:
# 矩阵加法
C = A + B
print("Matrix addition:\n", C)
# 矩阵减法
D = A - B
print("Matrix subtraction:\n", D)
矩阵乘法
矩阵乘法可以使用 np.dot() 函数或者 @ 操作符:
# 方法1:使用 np.dot() 函数
E = np.dot(A, B)
print("Matrix multiplication using np.dot():\n", E)
# 方法2:使用 @ 操作符
F = A @ B
print("Matrix multiplication using @:\n", F)
元素级乘法
如果你想进行元素级的乘法(即Hadamard积),可以直接使用 * 操作符:
G = A * B
print("Element-wise multiplication:\n", G)
矩阵的转置
矩阵的转置可以通过 .T 属性得到:
H = A.T
print("Transpose of matrix A:\n", H)
矩阵的逆
矩阵的逆可以通过 np.linalg.inv() 函数计算:
I = np.linalg.inv(A)
print("Inverse of matrix A:\n", I)
行列式计算
矩阵的行列式可以通过 np.linalg.det() 函数计算:
det_A = np.linalg.det(A)
print("Determinant of matrix A:", det_A)
特征值和特征向量
矩阵的特征值和特征向量可以通过 np.linalg.eig() 函数得到:
eigenvalues, eigenvectors = np.linalg.eig(A)
print("Eigenvalues of A:", eigenvalues)
print("Eigenvectors of A:\n", eigenvectors)
8.广播运算
NumPy 的广播(Broadcasting)功能是一种强大的机制,允许 NumPy 在执行算术运算时自动处理不同形状的数组。广播会按照一定的规则自动扩展数组的形状,使得它们的维度匹配,然后执行逐元素的运算。这使得在不实际复制数据的情况下,对不同形状的数组执行运算成为可能,从而可以高效地使用内存。
广播遵循一组简单的规则来应用:
- 维度对齐:如果两个数组的维数不相同,形状中较短的数组会在其前面被补1,直到两者的维数相同。
- 形状匹配:在每个维度上,如果两个数组的大小相等,或者其中一个数组在该维度上的大小为1,则认为这两个数组在该维度上是兼容的。
- 数组扩展:当两个数组的形状在某个维度上兼容时,如果其中一个数组在该维度上的大小为1,那么它会被扩展为与另一个数组在该维度上的大小相同。
- 运算执行:当以上条件都满足时,广播机制就会被应用,两个数组的运算就可以按元素逐个进行。
这里通过一些例子来更直观地理解广播的概念。
示例 1:标量和数组的广播
import numpy as np
a = np.array([1, 2, 3])
b = 2
# 2 被广播到数组的每个元素
print(a * b) # 输出:[2 4 6]
示例 2:一维数组和二维数组的广播
a = np.array([1, 2, 3])
b = np.array([[1, 2, 3], [4, 5, 6]])
# 'a' 在行方向上被广播,以匹配'b'的形状
print(a + b)
输出:
[[2 4 6]
[5 7 9]]
示例 3:两个二维数组的广播
a = np.array([[1], [2], [3]]) # 形状为 (3, 1)
b = np.array([1, 2, 3]) # 形状为 (3,)
# 'a' 在列方向上被广播,'b' 在行方向上被广播
print(a + b)
输出:
[[2 3 4]
[3 4 5]
[4 5 6]]
9.求和、求积
求和:np.sum
np.sum 函数用于计算数组中所有元素的总和。你可以对整个数组进行求和,也可以指定轴(axis)进行求和。
示例:整个数组的求和
import numpy as np
arr = np.array([[1, 2], [3, 4]])
total_sum = np.sum(arr)
print("Total sum:", total_sum) # 输出:10
示例:指定轴的求和
# 沿着第一个轴求和(列求和)
column_sum = np.sum(arr, axis=0)
print("Sum of each column:", column_sum) # 输出:[4 6]
# 沿着第二个轴求和(行求和)
row_sum = np.sum(arr, axis=1)
print("Sum of each row:", row_sum) # 输出:[3 7]
求积:np.prod
np.prod 函数用于计算数组中所有元素的乘积。同样,你可以对整个数组进行求积,或指定轴进行求积。
示例:整个数组的求积
product = np.prod(arr)
print("Total product:", product) # 输出:24
示例:指定轴的求积
# 沿着第一个轴求积(列求积)
column_product = np.prod(arr, axis=0)
print("Product of each column:", column_product) # 输出:[3 8]
# 沿着第二个轴求积(行求积)
row_product = np.prod(arr, axis=1)
print("Product of each row:", row_product) # 输出:[2 12]
累计求和和累计求积
NumPy 还提供了计算累计求和和累计求积的函数: np.cumsum 和 np.cumprod,它们分别计算给定轴上的元素的累计和与累计积。
累计求和
cumulative_sum = np.cumsum(arr)
print("Cumulative sum:", cumulative_sum) # 输出:[1 3 6 10]
累计求积
cumulative_product = np.cumprod(arr)
print("Cumulative product:", cumulative_product) # 输出:[1 2 6 24]
10.中位数,均值,方差,标准差
中位数(Median)
中位数是将数据集按顺序排列后位于中间的值。如果数据集的数量是偶数,中位数则是中间两个数的平均值。它是一种衡量数据中心位置的指标,对异常值不敏感。
- 计算方法: pythonimportnumpyasnp data=np.array([数值序列])median=np.median(data)
均值(Mean)
均值是所有数据加总后除以数据的数量。它是描述数据集平均水平的一个指标,但对异常值敏感。
- 计算方法: python mean=np.mean(data)
方差(Variance)
方差衡量的是数据点与数据平均值之间的差异程度。方差越大,表示数据分布越分散。
- 计算方法: python variance=np.var(data)
标准差(Standard Deviation)
标准差是方差的平方根,也用于衡量数据的分散程度。与方差相比,标准差与原始数据在同一量纲,更容易理解。
- 计算方法: python std_deviation=np.std(data)
示例
假设我们有一组数据 [1,2,3,4,5],我们来计算它们的中位数、均值、方差、和标准差。
import numpy as np
data = np.array([1, 2, 3, 4, 5])
median = np.median(data)
mean = np.mean(data)
variance = np.var(data)
std_deviation = np.std(data)
print("Median:", median)
print("Mean:", mean)
print("Variance:", variance)
print("Standard Deviation:", std_deviation)
排序
提供了多种排序算法来处理数组,包括一维和多维数组的排序。这些排序函数非常高效,适用于大数据集。主要的排序函数包括 np.sort 和 np.argsort,以及就地排序的 ndarray.sort 方法。此外,NumPy 还提供了用于查找元素的函数,如 np.partition。
np.sort
np.sort 函数返回数组的排序副本。它不会修改原数组。
import numpy as np
arr = np.array([3, 1, 5, 2])
sorted_arr = np.sort(arr)
print(sorted_arr) # 输出:[1 2 3 5]
对于多维数组,你可以指定 axis 参数来决定按哪个轴进行排序。
arr2d = np.array([[5, 2], [3, 4]])
sorted_arr2d = np.sort(arr2d, axis=0) # 沿着第一个轴(列)排序
print(sorted_arr2d)
np.argsort
np.argsort 函数返回的是数组排序后的索引。
arr = np.array([3, 1, 5, 2])
sorted_index = np.argsort(arr)
print(sorted_index) # 输出:[1 3 0 2]
使用这些索引可以对其他数组进行同样顺序的排序,这在数据分析中非常有用。
就地排序:ndarray.sort
使用 ndarray.sort 方法可以直接在原数组上进行排序,这称为就地排序。
arr = np.array([3, 1, 5, 2])
arr.sort()
print(arr) # 输出:[1 2 3 5]
部分排序:np.partition
np.partition 函数返回一个新数组,其中第 k个元素是这样一个值,它是数组排序后该位置上的元素,而前 k个元素都小于等于第 k个元素,后面的元素都大于等于第 k个元素。
arr = np.array([3, 4, 2, 1])
partitioned_arr = np.partition(arr, 2)
print(partitioned_arr) # 输出可能是 [2 1 3 4]
高级排序算法
NumPy 的排序函数支持多种排序算法,包括 quicksort(快速排序,默认)、 mergesort(归并排序)、 heapsort(堆排序)等。你可以通过 kind 参数选择算法:
sorted_arr = np.sort(arr, kind='mergesort')