2.1 ndarray 的基本概念 NumPy ndarray 的基本概念详解 2.1 ndarray 的基本概念 (N-dimensional array) 是 NumPy 中用于存储同类型数据的多维数组。它是一个表格形式的数据集合,其中所有元素都具有相同的数据类型。 的关键属性包括: (维度):数组的维度数量。例如,一个向量是一维数组,一个矩阵是二维数组。 (形状):一个元组,表示数组在每个维度上的大小。例如,一个 3x4 的矩阵的形状是 。 (大小):数组中元素的总数,等于 中各元素的乘积。 (数据类型):数组中元素的数据类型,例如 、 、 等。 (元素大小):数组中每个元素所占用的字节数。 (数据缓冲区):一个指向数组数据起始位置的内存地址。
ndarray (N-dimensional array) 是 NumPy 中用于存储同类型数据的多维数组。它是一个表格形式的数据集合,其中所有元素都具有相同的数据类型。ndarray 的关键属性包括:
ndim (维度):数组的维度数量。例如,一个向量是一维数组,一个矩阵是二维数组。
shape (形状):一个元组,表示数组在每个维度上的大小。例如,一个 3x4 的矩阵的形状是 (3, 4)。
size (大小):数组中元素的总数,等于 shape 中各元素的乘积。
dtype (数据类型):数组中元素的数据类型,例如 int64、float64、object 等。
itemsize (元素大小):数组中每个元素所占用的字节数。
data (数据缓冲区):一个指向数组数据起始位置的内存地址。通常,我们不需要直接访问这个属性,而是通过索引来访问数组元素。
可以使用多种方法创建 ndarray 对象。以下是一些常用的方法:
np.array():从 Python 列表、元组或其他序列创建数组。
import numpy as np # 从列表创建 list_data = [1, 2, 3, 4, 5] arr_from_list = np.array(list_data) print(f"从列表创建的数组: {arr_from_list}") print(f"数组的形状: {arr_from_list.shape}") print(f"数组的数据类型: {arr_from_list.dtype}") # 从元组创建 tuple_data = (6, 7, 8, 9, 10) arr_from_tuple = np.array(tuple_data) print(f"从元组创建的数组: {arr_from_tuple}") # 创建多维数组 matrix_data = [[1, 2, 3], [4, 5, 6]] arr_from_matrix = np.array(matrix_data) print(f"从矩阵创建的数组:\n{arr_from_matrix}") print(f"数组的形状: {arr_from_matrix.shape}") # (2, 3)
np.zeros():创建指定形状和数据类型的全零数组。
# 创建一个 2x3 的全零数组 zeros_array = np.zeros((2, 3)) print(f"全零数组:\n{zeros_array}") print(f"数组的数据类型: {zeros_array.dtype}")
np.ones():创建指定形状和数据类型的全一数组。
# 创建一个 3x2 的全一数组 ones_array = np.ones((3, 2), dtype=np.int32) #指定数据类型 print(f"全一数组:\n{ones_array}") print(f"数组的数据类型: {ones_array.dtype}")
np.empty():创建指定形状和数据类型但未初始化的数组。数组中的值是内存中的随机值。
# 创建一个 2x2 的未初始化数组 empty_array = np.empty((2, 2)) print(f"未初始化数组:\n{empty_array}")
np.arange():类似于 Python 的 range() 函数,但返回一个数组。
# 创建一个从 0 到 9 的数组 arange_array = np.arange(10) print(f"arange 数组: {arange_array}") # 创建一个从 2 到 10,步长为 2 的数组 arange_array_step = np.arange(2, 11, 2) print(f"arange 数组 (步长): {arange_array_step}")
np.linspace():创建指定范围内均匀间隔的数组。
# 创建一个从 0 到 1,包含 5 个元素的数组 linspace_array = np.linspace(0, 1, 5) print(f"linspace 数组: {linspace_array}")
np.eye():创建一个单位矩阵(对角线上为 1,其余为 0)。
# 创建一个 3x3 的单位矩阵 eye_matrix = np.eye(3) print(f"单位矩阵:\n{eye_matrix}")
ndarray 中的元素必须具有相同的数据类型。NumPy 支持多种数据类型,包括:
int8, int16, int32, int64: 有符号整数。
uint8, uint16, uint32, uint64: 无符号整数。
float16, float32, float64: 浮点数。
complex64, complex128: 复数。
bool: 布尔值 (True 或 False)。
object: Python 对象。
string_, unicode_: 字符串。
可以使用 dtype 属性查看数组的数据类型,并使用 astype() 方法转换数据类型。
import numpy as np # 创建一个整数数组 int_array = np.array([1, 2, 3, 4, 5], dtype=np.int32) print(f"整数数组: {int_array}") print(f"数组的数据类型: {int_array.dtype}") # 将整数数组转换为浮点数数组 float_array = int_array.astype(np.float64) print(f"浮点数数组: {float_array}") print(f"数组的数据类型: {float_array.dtype}") # 将浮点数数组转换为整数数组 (截断) int_array_from_float = float_array.astype(np.int32) print(f"整数数组 (从浮点数转换): {int_array_from_float}") print(f"数组的数据类型: {int_array_from_float.dtype}") # 将字符串数组转换为数值数组 string_array = np.array(['1.2', '2.3', '3.4']) numeric_array = string_array.astype(np.float64) print(f"数值数组 (从字符串转换): {numeric_array}") print(f"数组的数据类型: {numeric_array.dtype}")
除了 ndim、shape、size、dtype、itemsize 和 data 之外,ndarray 还有一些其他重要的属性:
T (转置):返回数组的转置。
flags (标志):提供有关数组内存布局的信息。
real (实部):返回复数数组的实部。
imag (虚部):返回复数数组的虚部。
import numpy as np # 创建一个 2x3 的数组 matrix = np.array([[1, 2, 3], [4, 5, 6]]) print(f"原始数组:\n{matrix}") # 转置数组 transposed_matrix = matrix.T print(f"转置数组:\n{transposed_matrix}") print(f"转置数组的形状: {transposed_matrix.shape}") # 创建一个复数数组 complex_array = np.array([1 + 2j, 3 + 4j]) print(f"复数数组: {complex_array}") # 获取实部和虚部 real_part = complex_array.real imag_part = complex_array.imag print(f"实部: {real_part}") print(f"虚部: {imag_part}")
可以使用索引和切片来访问和修改 ndarray 中的元素。NumPy 的索引和切片功能非常强大,可以灵活地选择数组的子集。
基本索引:使用整数索引访问单个元素。对于多维数组,需要为每个维度提供一个索引。
import numpy as np # 创建一个一维数组 arr = np.arange(10) print(f"一维数组: {arr}") # 访问单个元素 print(f"索引 0 的元素: {arr[0]}") print(f"索引 5 的元素: {arr[5]}") # 创建一个二维数组 matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(f"二维数组:\n{matrix}") # 访问单个元素 print(f"索引 (0, 0) 的元素: {matrix[0, 0]}") print(f"索引 (1, 2) 的元素: {matrix[1, 2]}")
切片:使用切片访问数组的子集。切片语法为 [start:stop:step]。
import numpy as np # 创建一个一维数组 arr = np.arange(10) print(f"一维数组: {arr}") # 切片 print(f"前 5 个元素: {arr[:5]}") print(f"索引 5 到末尾的元素: {arr[5:]}") print(f"索引 2 到 7 的元素: {arr[2:8]}") print(f"步长为 2 的元素: {arr[::2]}") print(f"倒序数组: {arr[::-1]}") # 创建一个二维数组 matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(f"二维数组:\n{matrix}") # 切片 print(f"第一行: {matrix[0, :]}") print(f"第一列: {matrix[:, 0]}") print(f"左上角的 2x2 子矩阵:\n{matrix[:2, :2]}")
布尔索引:使用布尔数组来选择数组的元素。
import numpy as np # 创建一个数组 arr = np.array([1, 2, 3, 4, 5, 6]) print(f"数组: {arr}") # 创建一个布尔数组 bool_arr = arr > 3 print(f"布尔数组: {bool_arr}") # 使用布尔索引选择元素 selected_elements = arr[bool_arr] print(f"选择的元素: {selected_elements}") # 使用布尔索引修改元素 arr[arr < 3] = 0 print(f"修改后的数组: {arr}")
花式索引:使用整数数组来选择数组的元素。
import numpy as np # 创建一个数组 arr = np.array([10, 20, 30, 40, 50, 60]) print(f"数组: {arr}") # 创建一个索引数组 index_arr = np.array([0, 2, 4]) print(f"索引数组: {index_arr}") # 使用花式索引选择元素 selected_elements = arr[index_arr] print(f"选择的元素: {selected_elements}") # 创建一个二维数组 matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(f"二维数组:\n{matrix}") # 使用花式索引选择元素 row_indices = np.array([0, 2]) col_indices = np.array([1, 2]) selected_elements = matrix[row_indices[:, np.newaxis], col_indices] print(f"选择的元素:\n{selected_elements}")
理解 NumPy 中视图 (view) 和副本 (copy) 的概念至关重要,尤其是在处理大型数组时。
视图:视图是指对原始数组的引用,它不创建新的数组对象。修改视图会影响原始数组,反之亦然。切片操作通常会创建视图。
副本:副本是指原始数组的完整复制,它创建了一个新的数组对象。修改副本不会影响原始数组,反之亦然。可以使用 copy() 方法创建副本。
import numpy as np # 创建一个数组 arr = np.arange(10) print(f"原始数组: {arr}") # 创建一个视图 view_arr = arr[3:7] print(f"视图: {view_arr}") # 修改视图 view_arr[0] = 100 print(f"修改后的视图: {view_arr}") print(f"原始数组 (已修改): {arr}") # 创建一个副本 copy_arr = arr.copy() print(f"副本: {copy_arr}") # 修改副本 copy_arr[0] = 200 print(f"修改后的副本: {copy_arr}") print(f"原始数组 (未修改): {arr}")
ndarray 是 NumPy 的核心数据结构,它提供了高效的多维数组操作。理解 ndarray 的基本概念,包括其属性、创建方法、数据类型、索引和切片以及视图与副本的区别,是使用 NumPy 进行科学计算的基础。掌握这些知识,可以更有效地利用 NumPy 的强大功能,解决各种数据处理和分析问题。