numpy索引和选择数据
基础索引
NumPy的索引从0开始,和Python的原生列表(list)类似。对于一个一维数组,索引的使用也非常直观:
arr = np.arange(10)
# 创建一个0-9的数组print(arr[5])
# 输出: 5print(arr[-1])
# 输出: 9
多维数组索引
多维数组的索引稍微复杂一些,但遵循同样的基本逻辑。对于二维数组,可以使用逗号分隔的索引元组来选择数据:
arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
# 选取第一行的第二个元素print(arr[0, 1])
# 输出: 2
# 选取第三行的所有元素print(arr[2])
# 输出: [7 8 9]# 或者print(arr[2, :]) # 输出: [7 8 9]
切片
切片在NumPy中是通过在[]中使用:符号来实现的。它可以在多维数组中使用:
# 一维数组切片
arr = np.arange(10)
print(arr[1:5]) # 输出: [1 2 3 4]# 二维数组切片
arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
# 选取第二列的所有数据
print(arr[:, 1])
# 输出: [2 5 8]
# 选取第一和第二行的第二和第三列
print(arr[0:2, 1:3])
# 输出: [[2 3]# [5 6]]
布尔索引
布尔索引允许我们选择数组中符合特定条件的元素。这在数据分析中特别有用:
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
# 创建一个布尔数组
mask = arr > 5
# 使用布尔数组选择数据
print(arr[mask])
# 输出: [6 7 8 9]
布尔索引也可以直接在条件语句中使用,不必显式创建布尔数组:
print(arr[arr > 5])
# 输出: [6 7 8 9]
花式索引
花式索引(Fancy indexing)是通过整数数组进行索引。可以一次性选取数组中的多个元素:
arr = np.array([10, 20, 30, 40, 50])
# 使用整数列表来指定所需的索引
print(arr[[1, 3, 4]])
# 输出: [20 40 50]
在多维数组中使用花式索引会更复杂一些:
arr = np.arange(16).reshape((4,4))
# 选取(0, 0),(1, 1),(2, 2)位置的元素
print(arr[[0, 1, 2], [0, 1, 2]])
# 输出: [ 0 5 10]
Numpy合并_分割_复制
数据合并
在NumPy中,可以使用多种方式来合并数组:
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
# 沿着第一个轴合并
c = np.concatenate((a, b), axis=0)
print(c)
# 输出:# [[1 2]# [3 4]# [5 6]]
- np.vstack(垂直堆叠) 和 np.hstack(水平堆叠):
np.vstack 和 np.hstack 提供了垂直和水平的数组堆叠方式。
# 垂直堆叠
d = np.vstack((a, b))
print(d)
# 输出:# [[1 2]# [3 4]# [5 6]]# 水平堆叠
e = np.hstack((a, a))
print(e)
# 输出:# [[1 2 1 2]# [3 4 3 4]]
- np.column_stack 和 np.row_stack:
这两个函数分别用于堆叠一维数组作为列或行。
a1 = np.array([1, 2, 3])
a2 = np.array([4, 5, 6])
# 作为列堆叠
f = np.column_stack((a1, a2))
print(f)
# 输出:# [[1 4]# [2 5]# [3 6]]# 作为行堆叠
g = np.row_stack((a1, a2))
print(g)
# 输出:# [[1 2 3]# [4 5 6]]
数据分割
与合并相对应,NumPy也提供了多种数据分割的方法:
- np.split:
np.split 可以沿指定轴分割数组。
a = np.arange(9)
# 分割成3个相等的子数组
b1, b2, b3 = np.split(a, 3)
print(b1, b2, b3)
# 输出:# [0 1 2] [3 4 5] [6 7 8]
- np.vsplit 和 np.hsplit:
这两个函数分别按垂直和水平轴分割数组。
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 垂直分割
c1, c2 = np.vsplit(a, 2)
print(c1)
print(c2)
# 输出:# [[1 2 3]# [4 5 6]]# [[7 8 9]]# 水平分割
d1, d2, d3 = np.hsplit(a, 3)
print(d1)
print(d2)
print(d3)
# 输出:# [[1]# [4]# [7]]# [[2]# [5]# [8]]# [[3]# [6]# [9]]
数组的复制
在NumPy中,数组的赋值并不会创建数据的副本。为了确保获得数组的一个副本,应该使用np.copy:
- np.copy 或 copy 方法:
a = np.array([1, 2, 3])
b = np.copy(a)
# 或者
b = a.copy()
# 修改 b 不会影响 a
b[0] = 10print(a) # 输出:[1 2 3]print(b) # 输出:[10 2 3]
Numpy多维与轴
NumPy 中的轴(Axes)是理解多维数组操作的关键概念。一个轴是数组的一个维度,在 NumPy 中,每个轴都有一个关联的整数索引,从 0 开始。对于二维数组,0 轴通常是“行”(垂直方向),1 轴是“列”(水平方向)。在更高维度的数组中,每个新轴都会添加一个新的维度。
在 NumPy 中进行操作时,经常需要指定沿着哪个轴执行操作。例如,如果你对一个二维数组执行求和操作,可以对整个数组求和,也可以沿着行或列分别求和。
让我们通过代码演示来深入理解轴的概念:
import numpy as np
# 创建一个二维数组(矩阵)
matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 对整个数组求和
total_sum = np.sum(matrix)
# 对 0 轴(行方向)求和,即将每一列的元素相加
sum_along_axis0 = np.sum(matrix, axis=0)
# 对 1 轴(列方向)求和,即将每一行的元素相加
sum_along_axis1 = np.sum(matrix, axis=1)
print("Total Sum:", total_sum)
print("Sum along axis 0:", sum_along_axis0)
print("Sum along axis 1:", sum_along_axis1)
# Total Sum: 45Sum along axis 0: [12 15 18]Sum along axis 1: [ 6 15 24]
这里:
- total_sum 是所有元素的总和(1+2+3+4+5+6+7+8+9=45)。
- sum_along_axis0 沿着轴 0 求和,把每一列的元素加在一起,所以结果是一个包含三个元素的数组,分别为每一列的和([1+4+7, 2+5+8, 3+6+9])。
- sum_along_axis1 沿着轴 1 求和,把每一行的元素加在一起,因此结果是一个包含三个元素的数组,分别为每一行的和([1+2+3, 4+5+6, 7+8+9])。
在处理多维数组时,理解轴的概念非常重要,特别是在执行如 reshape、broadcasting、sum、mean、transpose 等操作时。轴的索引编号依赖于数组的维度,对于一个 n 维数组,轴的编号从 0 到 n-1。在三维数组中,轴编号如下: - 轴 0 - 通常是“深度”,在 z 方向。
- 轴 1 - 通常是“行”,在 y 方向。
- 轴 2 - 通常是“列”,在 x 方向。
现在,让我们用一个三维数组的例子来演示:
# 创建一个三维数组
arr_3d = np.array([[[1, 2], [3, 4]],
[[5, 6], [7, 8]]])
# 对整个数组求和
total_sum_3d = np.sum(arr_3d)
# 沿着不同轴求和
sum_along_axis0_3d = np.sum(arr_3d, axis=0)
sum_along_axis1_3d = np.sum(arr_3d, axis=1)
sum_along_axis2_3d = np.sum(arr_3d, axis=2)
print("Total Sum 3D:", total_sum_3d)
print("Sum along axis 0:", sum_along_axis0_3d)
print("Sum along axis 1:", sum_along_axis1_3d)
print("Sum along axis 2:", sum_along_axis2_3d)
输出将解释如何沿着三维数组的不同轴进行累加:
Total Sum 3D: 36
Sum along axis 0: [[ 6 8]
[10 12]]
Sum along axis 1: [[ 4 6]
[12 14]]
Sum along axis 2: [[ 3 7]
[11 15]]
在上面的三维数组例子中:
- sum_along_axis0_3d 计算了两个 2x2 矩阵在“深度”方向上的和。
- sum_along_axis1_3d 将每个“深度”层内的行相加。
- sum_along_axis2_3d 在每个“深度”层内将列相加。
数组元素的添加和删除
在NumPy中,添加和删除数组元素通常不如在Python原生的数据结构(如列表)中那么自由,因为NumPy的数组是固定大小的。当你添加或删除元素时,实际上是创建了一个新的数组。尽管如此,NumPy提供了一些函数来帮助添加和删除元素。
添加元素
以下是添加元素到NumPy数组的一些函数:
- np.append:
- np.append 用于将值添加到数组末尾。你可以沿指定轴添加元素,如果不指定轴,np.append会将数组展平。
arr = np.array([1, 2, 3])
# 添加单个元素
new_arr = np.append(arr, [4])
print(new_arr) # 输出: [1 2 3 4]# 添加多个元素
new_arr = np.append(arr, [4, 5, 6])
print(new_arr) # 输出: [1 2 3 4 5 6]
- np.insert:
- np.insert 用于沿指定轴在给定索引之前插入值。如果没有提供轴,则输入数组会被展开。
arr = np.array([1, 2, 3])
# 在索引1的位置插入值
new_arr = np.insert(arr, 1, [7, 8])
print(new_arr) # 输出: [1 7 8 2 3]
- np.concatenate:
- 如前所述,np.concatenate 可以用来沿指定轴连接数组序列,也可以间接用来添加元素。
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
# 沿着第一个轴连接
c = np.concatenate((a, b), axis=0)
print(c)
# 输出:# [[1 2]# [3 4]# [5 6]]
删除元素
以下是删除NumPy数组元素的一些函数:
- np.delete:
- np.delete 用于沿指定轴删除数组中的子数组。如果没有提供轴,那么输入数组将展平。
arr = np.array([1, 2, 3, 4, 5])
# 删除索引3处的元素
new_arr = np.delete(arr, 3)
print(new_arr) # 输出: [1 2 3 5]
numpy字符串函数
NumPy 提供了一系列的字符串函数,这些函数可以对数组中的字符串元素进行向量化操作。这意味着它们可以快速地处理 NumPy 数组中的每个元素,无需使用循环。这些函数大多数都位于 NumPy 的 char 模块中。
这里是一些常用的 NumPy 字符串函数及其说明:
- np.char.add:
- 将两个数组中的字符串元素逐个相加(串联)。
np.char.add(['hello'], [' world'])
# 输出: array(['hello world'], dtype='<U11')
- np.char.lower 和 np.char.upper:
- 分别将数组中的字符串元素转换为小写或大写。
np.char.lower(['HELLO', 'WORLD'])
# 输出: array(['hello', 'world'], dtype='<U5')
np.char.upper(['hello', 'world'])
# 输出: array(['HELLO', 'WORLD'], dtype='<U5')
- np.char.center:
- 将字符串居中,并在两侧用指定字符填充至指定宽度。
np.char.center(['hello'], width=10, fillchar='-')
# 输出: array(['--hello---'], dtype='<U10')
- np.char.split:
- 默认按空格分割字符串,也可以指定其他分隔符。
np.char.split(['hello world'])
# 输出: array([list(['hello', 'world'])], dtype=object)
- np.char.splitlines:
- 按换行符(\n)分割字符串。
np.char.splitlines(['hello\nworld'])
# 输出: array([list(['hello', 'world'])], dtype=object)
- np.char.strip:
- 移除字符串开始和结尾处的指定字符,默认移除空格。
np.char.strip([' hello ', ' world '], ' ')
# 输出: array(['hello', 'world'], dtype='<U7')
- np.char.join:
- 将指定的分隔符连接数组中的字符串元素。
np.char.join([':'], ['dmy'])
# 输出: array(['d:m:y'], dtype='<U5')
- np.char.replace:
- 在字符串中替换子字符串。
np.char.replace(['hello world'], 'world', 'numpy')
# 输出: array(['hello numpy'], dtype='<U11')
- np.char.encode 和 np.char.decode:
- 分别用于编码和解码字符数组,可以指定编码方式如’utf-8’。
a = np.char.encode(['hello'], 'utf-8')
print(a)
# 输出: array([b'hello'], dtype='|S5')
print(np.char.decode(a, 'utf-8'))
# 输出: array(['hello'], dtype='<U5')
numpy的数学函数
umPy(Numerical Python的缩写)是Python中用于科学计算的基础包之一,它提供了大量的数学函数来对数组进行操作。这些函数可以进行基本的数学运算,如加、减、乘、除,也包括更高级的数学运算,如指数、对数、统计等。
以下是一些在NumPy中常用的数学函数及其用途:
基本运算
- np.add(x, y): 对应元素相加。
- np.subtract(x, y): 对应元素相减。
- np.multiply(x, y): 对应元素相乘。
- np.divide(x, y): 对应元素相除。
- np.negative(x): 数组元素取负。
- np.power(x, y): 元素 x 的 y 次方。
- np.mod(x, y): 对应元素取模运算。
统计函数
- np.mean(arr): 数组的平均值。
- np.median(arr): 数组的中位数。
- np.std(arr): 标准差。
- np.var(arr): 方差。
三角函数
- np.sin(arr): 正弦函数。
- np.cos(arr): 余弦函数。
- np.tan(arr): 正切函数。
- np.arcsin(arr): 反正弦函数。
- np.arccos(arr): 反余弦函数。
- np.arctan(arr): 反正切函数。
指数和对数
- np.exp(arr): e 的 arr 次方。
- np.log(arr): 自然对数。
- np.log2(arr): 底为 2 的对数。
- np.log10(arr): 底为 10 的对数。
线性代数
- np.linalg.inv(a): 矩阵的逆。
- np.linalg.det(a): 矩阵的行列式。
- np.linalg.eig(a): 矩阵的特征值和特征向量。
累计函数
- np.cumsum(arr): 累加求和。
- np.cumprod(arr): 累乘求积。
矩阵操作
- np.transpose(a): 矩阵转置。
- np.dot(a, b): 矩阵点积。
使用例子
下面是一些使用NumPy进行数学运算的简单例子:
import numpy as np
# 创建数组
arr = np.array([1, 2, 3, 4])
# 基本运算print(np.add(arr, 1)) # 输出:[2 3 4 5]print(np.subtract(arr, 1)) # 输出:[0 1 2 3]print(np.multiply(arr, 2)) # 输出:[2 4 6 8]print(np.divide(arr, 2)) # 输出:[0.5 1. 1.5 2. ]# 统计函数print(np.mean(arr)) # 输出:2.5print(np.std(arr)) # 输出:1.118033988749895# 三角函数
angles = np.array([0, np.pi/2, np.pi])
print(np.sin(angles)) # 输出:[0.0000000e+00 1.0000000e+00 1.2246468e-16]# 指数和对数print(np.exp(arr)) # 输出:[ 2.71828183 7.3890561 20.08553692 54.59815003]print(np.log(arr)) # 输出:[0. 0.69314718 1.09861229 1.38629436]
NumPy的数学函数非常丰富,可以处理各种数组操作和数学计算的需要。掌握它们是进行科学和工程计算的关键。
数组平方
在 NumPy 中,可以使用多种方式对数组中的每个元素进行平方操作。最直观的方法是使用 np.square() 函数,或者简单地使用数组与自身的乘法操作。下面展示了两种方法:
方法 1: 使用 np.square()
import numpy as np
# 创建一个数组
arr = np.array([1, 2, 3, 4])
# 使用np.square()函数平方每个元素
squared_arr = np.square(arr)
print(squared_arr) # 输出: [ 1 4 9 16]
方法 2: 使用元素乘法
import numpy as np
# 创建一个数组
arr = np.array([1, 2, 3, 4])
# 通过元素乘法平方每个元素
squared_arr = arr * arr
print(squared_arr) # 输出: [ 1 4 9 16]
另外,如果你喜欢使用数学符号,也可以使用幂运算符 ** 来平方:
import numpy as np
# 创建一个数组
arr = np.array([1, 2, 3, 4])
# 使用幂运算符平方每个元素
squared_arr = arr ** 2print(squared_arr) # 输出: [ 1 4 9 16]
幂运算
在NumPy中,您可以使用**运算符或numpy.power函数来计算数组中每个元素的5次方。这里有一个例子:
import numpy as np
# 创建一个NumPy数组
arr = np.array([1, 2, 3, 4])
# 使用 ** 运算符计算每个元素的5次方
arr_5th_power = arr ** 5# 输出结果print(arr_5th_power)
或者使用numpy.power函数:
import numpy as np
# 创建一个NumPy数组
arr = np.array([1, 2, 3, 4])
# 使用 numpy.power 函数计算每个元素的5次方
arr_5th_power = np.power(arr, 5)
# 输出结果print(arr_5th_power)
>>> [ 1 32 243 1024]
Numpy的IO操作
NumPy 提供了多种读取和写入数组数据到文件的方法。主要的 IO 函数包括:
- np.save: 保存一个数组到一个二进制文件中,扩展名为.npy。
- np.load: 读取一个.npy二进制文件中的数组。
- np.savetxt: 将数组保存到一个文本文件中。
- np.loadtxt: 从一个文本文件中加载数组。
- np.genfromtxt: 类似于 np.loadtxt,但它面向结构化数组和缺失数据处理。
- np.savez: 将多个数组保存到一个以.npz为扩展名的文件中,这是一个压缩文件格式。
下面是使用这些 NumPy IO 函数的一些例子:
保存和加载 .npy 格式的文件
import numpy as np
# 创建数组
array_to_save = np.arange(10)
# 保存数组到.npy文件
np.save('saved_array.npy', array_to_save)
# 读取.npy文件
loaded_array = np.load('saved_array.npy')
print(loaded_array)
保存和加载文本文件
import numpy as np
# 创建数组
array_to_save = np.arange(10).reshape(2, 5)
# 保存数组到.txt文件
np.savetxt('saved_array.txt', array_to_save)
# 读取.txt文件
loaded_array_txt = np.loadtxt('saved_array.txt')
print(loaded_array_txt)
使用 np.savez 和 np.load 保存和加载多个数组
import numpy as np
# 创建数组
array1 = np.arange(10)
array2 = np.arange(10, 20)
# 保存多个数组到.npz文件
np.savez('saved_arrays.npz', array1=array1, array2=array2)
# 读取.npz文件
loaded_npz = np.load('saved_arrays.npz')
print(loaded_npz['array1'])
print(loaded_npz['array2'])
处理缺失数据和结构化数组
import numpy as np
# 假设我们有一个带有缺失数据的文件:missing_data.txt,内容可能如下:# 1,2,3# 4,,6# 7,8,9# 使用genfromtxt加载数据,缺失值将被填充为nan
data_with_missing = np.genfromtxt('missing_data.txt', delimiter=',')
print(data_with_missing)
在使用这些函数时,你需要注意:
- 保存为.npy或.npz文件时,数据会以二进制格式存储,这通常会比文本格式更加高效和节省空间。
- 读取文本文件时,np.loadtxt 和 np.genfromtxt 都需要你知道文件的格式,例如分隔符。
- np.savetxt 可以保存为一个文本文件,你可以指定分隔符,默认是空格。
- np.savez_compressed 与 np.savez 类似,但它会压缩保存的数组,因此更适用于保存大型数组或多个数组。
这些 IO 方法为 NumPy 数据的持久存储提供了快速方便的手段。在数据分析和科学计算中,这些方法非常有用,因为它们允许您保存中间结果,并且可以方便地与其他使用 Python 的同事分享数据。