MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python使用NumPy处理多维数组

2021-07-031.2k 阅读

1. NumPy 基础:多维数组概述

1.1 什么是多维数组

在 Python 中,NumPy 库引入了 ndarray(N 维数组)对象,它是一个高效存储和处理多维数据的结构。多维数组本质上是一个由相同数据类型元素组成的网格,可以是一维、二维甚至更高维度。例如,一维数组类似于列表,只不过它要求所有元素类型一致;二维数组就像常见的表格形式,有行和列;更高维度数组则在此基础上进一步拓展维度概念。

1.2 多维数组的优势

与 Python 内置的列表相比,NumPy 的多维数组在性能和功能上有显著优势。性能方面,NumPy 数组是在 C 语言层面实现的,其存储和操作数据更加高效,尤其是对于大规模数据的计算。例如,进行简单的数组元素加法运算,NumPy 数组的速度比普通列表快很多倍。功能上,NumPy 提供了丰富的函数和方法来对多维数组进行各种操作,如数学运算、统计分析、索引和切片等,这些操作可以直接应用到整个数组,无需像列表那样使用循环逐个处理元素。

2. 创建 NumPy 多维数组

2.1 使用 numpy.array() 创建

最常见的创建 NumPy 多维数组的方式是使用 numpy.array() 函数。该函数接受一个序列(如列表或元组)作为参数,并将其转换为 NumPy 数组。例如:

import numpy as np

# 创建一维数组
arr1d = np.array([1, 2, 3, 4])
print(arr1d)

# 创建二维数组
arr2d = np.array([[1, 2], [3, 4]])
print(arr2d)

在上述代码中,通过传递不同维度的列表,我们分别创建了一维和二维的 NumPy 数组。numpy.array() 函数会自动推断数组的数据类型,当然也可以通过 dtype 参数显式指定,例如:

arr = np.array([1, 2, 3], dtype='float64')
print(arr.dtype)

这里我们将数组的数据类型指定为 float64

2.2 使用专门的创建函数

除了 numpy.array(),NumPy 还提供了一些专门用于创建特定类型数组的函数。

  • numpy.zeros():创建一个全零的数组。可以指定数组的形状,例如:
zeros_1d = np.zeros(5)
print(zeros_1d)

zeros_2d = np.zeros((3, 4))
print(zeros_2d)

这里分别创建了长度为 5 的一维全零数组和形状为 3 行 4 列的二维全零数组。

  • numpy.ones():与 numpy.zeros() 类似,不过创建的是全一的数组。
ones_1d = np.ones(4)
print(ones_1d)

ones_2d = np.ones((2, 3))
print(ones_2d)
  • numpy.arange():类似于 Python 内置的 range() 函数,但返回的是 NumPy 数组。它可以接受起始值、结束值(不包含)和步长作为参数。
arr_range = np.arange(1, 10, 2)
print(arr_range)

此代码创建了从 1 开始,到 10 结束(不包含 10),步长为 2 的一维数组。

3. 多维数组的数据类型

3.1 常见数据类型

NumPy 支持多种数据类型,常见的有:

  • 整数类型:如 int8(8 位有符号整数)、int16(16 位有符号整数)、int32(32 位有符号整数)、int64(64 位有符号整数)。还有无符号整数类型,如 uint8uint16 等。
  • 浮点类型float16float32float64 等,其中 float64 是默认的浮点类型。
  • 布尔类型bool,用于存储布尔值 TrueFalse

不同的数据类型在内存占用和精度上有所不同。例如,float16 占用的内存比 float64 少,但精度也相对较低。

3.2 数据类型转换

可以使用 astype() 方法对 NumPy 数组的数据类型进行转换。例如:

arr = np.array([1, 2, 3])
float_arr = arr.astype('float64')
print(float_arr.dtype)

这里将整数类型的数组转换为了 float64 类型。需要注意的是,在进行类型转换时,如果目标类型无法准确表示原数据,可能会发生数据截断或精度损失。例如,将浮点数转换为整数时,小数部分会被截断。

4. 多维数组的基本操作

4.1 索引

4.1.1 一维数组索引

对于一维 NumPy 数组,索引方式与 Python 列表类似,从 0 开始计数。例如:

arr = np.array([10, 20, 30, 40, 50])
print(arr[0])
print(arr[3])

通过索引可以获取数组中指定位置的元素。

4.1.2 二维数组索引

二维数组需要两个索引来指定元素位置,第一个索引表示行,第二个索引表示列。例如:

arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr_2d[1, 2])

这里 arr_2d[1, 2] 表示获取第 2 行(索引为 1)第 3 列(索引为 2)的元素。

4.1.3 高维数组索引

更高维度数组的索引方式类似,按照维度顺序依次指定每个维度的索引值。例如,对于三维数组 arr_3darr_3d[i, j, k] 表示获取第 i 个三维块中的第 j 行第 k 列的元素。

4.2 切片

4.2.1 一维数组切片

一维数组的切片与列表切片类似,可以使用 start:stop:step 的语法。例如:

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
sub_arr = arr[2:7:2]
print(sub_arr)

这里从索引 2 开始(包含),到索引 7 结束(不包含),步长为 2 进行切片。

4.2.2 二维数组切片

二维数组切片时,对每个维度都可以进行切片操作。例如:

arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
sub_arr_2d = arr_2d[1:3, 0:2]
print(sub_arr_2d)

这里对行进行从索引 1 到 3(不包含)的切片,对列进行从索引 0 到 2(不包含)的切片,得到一个 2 行 2 列的子数组。

4.2.3 高维数组切片

高维数组切片也是对每个维度进行相应的切片操作,通过合理组合不同维度的切片范围,可以获取到特定的子数组。

4.3 数学运算

NumPy 多维数组支持各种数学运算,这些运算会自动应用到数组的每个元素上。

  • 基本算术运算:可以进行加(+)、减(-)、乘(*)、除(/)等运算。例如:
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
add_result = arr1 + arr2
print(add_result)

这里将两个数组对应位置的元素相加。

  • 三角函数运算:如 np.sin()np.cos()np.tan() 等。这些函数会对数组中的每个元素进行相应的三角函数计算。
arr = np.array([0, np.pi/2, np.pi])
sin_result = np.sin(arr)
print(sin_result)
  • 指数和对数运算np.exp() 计算指数,np.log() 计算自然对数等。
arr = np.array([1, 2, 3])
exp_result = np.exp(arr)
log_result = np.log(arr)
print(exp_result)
print(log_result)

5. 多维数组的统计方法

5.1 求和

可以使用 sum() 方法对 NumPy 多维数组进行求和操作。对于一维数组,直接计算所有元素的和;对于多维数组,可以通过指定 axis 参数来沿着特定维度求和。例如:

arr_2d = np.array([[1, 2, 3], [4, 5, 6]])
total_sum = arr_2d.sum()
row_sum = arr_2d.sum(axis = 1)
col_sum = arr_2d.sum(axis = 0)
print(total_sum)
print(row_sum)
print(col_sum)

这里 total_sum 计算整个二维数组所有元素的和,row_sum 沿着列方向(axis = 1)计算每行的和,col_sum 沿着行方向(axis = 0)计算每列的和。

5.2 求均值

mean() 方法用于计算数组的均值。同样,对于多维数组可以通过 axis 参数指定计算方向。

arr = np.array([[1, 2, 3], [4, 5, 6]])
mean_all = arr.mean()
mean_row = arr.mean(axis = 1)
mean_col = arr.mean(axis = 0)
print(mean_all)
print(mean_row)
print(mean_col)

5.3 求最大值和最小值

max()min() 方法分别用于求数组的最大值和最小值。多维数组同样可通过 axis 参数沿特定维度查找。

arr_2d = np.array([[1, 2, 3], [4, 5, 6]])
max_all = arr_2d.max()
max_row = arr_2d.max(axis = 1)
max_col = arr_2d.max(axis = 0)
print(max_all)
print(max_row)
print(max_col)

最小值操作类似,使用 min() 方法。

6. 多维数组的形状操作

6.1 改变数组形状

可以使用 reshape() 方法改变 NumPy 多维数组的形状。例如,将一个一维数组转换为二维数组:

arr = np.arange(1, 7)
reshaped_arr = arr.reshape((2, 3))
print(reshaped_arr)

这里将长度为 6 的一维数组转换为了 2 行 3 列的二维数组。需要注意的是,reshape() 方法要求新形状的元素总数与原数组相同。

6.2 数组的转置

对于二维数组,转置操作是将行和列进行交换,可以使用 transpose() 方法或 T 属性。例如:

arr_2d = np.array([[1, 2, 3], [4, 5, 6]])
transposed_arr = arr_2d.transpose()
print(transposed_arr)

# 或者使用 T 属性
transposed_arr_2 = arr_2d.T
print(transposed_arr_2)

这两种方式都实现了二维数组的转置。

6.3 拼接数组

6.3.1 水平拼接

使用 np.hstack() 函数可以水平拼接两个或多个数组。例如:

arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
hstack_result = np.hstack((arr1, arr2))
print(hstack_result)

这里将两个二维数组水平拼接在一起,要求拼接的数组在垂直方向(行数)上维度一致。

6.3.2 垂直拼接

np.vstack() 函数用于垂直拼接数组。例如:

arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
vstack_result = np.vstack((arr1, arr2))
print(vstack_result)

垂直拼接要求数组在水平方向(列数)上维度一致。

7. 广播机制

7.1 广播的概念

广播是 NumPy 中一个强大的特性,它允许在形状不同的数组之间进行算术运算。当进行运算时,如果两个数组的形状不完全相同,NumPy 会尝试通过广播机制调整数组形状,使运算能够顺利进行。广播机制的基本原则是从右到左比较两个数组的形状,如果维度不匹配,且其中一个数组的维度为 1,则将该维度扩展为另一个数组对应维度的大小。

7.2 广播示例

例如,一个形状为 (3, 1) 的数组与一个形状为 (1, 4) 的数组相加:

arr1 = np.array([[1], [2], [3]])
arr2 = np.array([[4, 5, 6, 7]])
result = arr1 + arr2
print(result)

这里 arr1 会在列方向上进行广播扩展,arr2 会在行方向上进行广播扩展,最终两个数组都扩展为形状 (3, 4) 后进行加法运算。

8. 存储和读取多维数组

8.1 使用 numpy.save()numpy.load()

NumPy 提供了 numpy.save() 函数用于将数组保存到文件中,文件扩展名为 .npy。例如:

arr = np.array([[1, 2, 3], [4, 5, 6]])
np.save('my_array.npy', arr)

要读取保存的数组,可以使用 numpy.load() 函数:

loaded_arr = np.load('my_array.npy')
print(loaded_arr)

8.2 使用文本文件存储

也可以将 NumPy 数组保存为文本文件,使用 numpy.savetxt() 函数。例如:

arr = np.array([[1, 2, 3], [4, 5, 6]])
np.savetxt('my_array.txt', arr, fmt='%d', delimiter=' ')

这里 fmt='%d' 表示以整数格式保存,delimiter=' ' 表示使用空格作为分隔符。读取文本文件可以使用 numpy.loadtxt() 函数:

loaded_arr = np.loadtxt('my_array.txt', dtype='int')
print(loaded_arr)

通过以上内容,我们全面地了解了如何使用 NumPy 处理多维数组,从基础概念到各种操作和应用场景,NumPy 为 Python 在数据处理和科学计算领域提供了强大的支持。