Python包---numpy1
1.基础
1.1 概念
NumPy 的全称是“ Numeric Python”,它是 Python 的第三方扩展包,主要用来计算、处理一维或多维数组
在数组算术计算方面, NumPy 提供了大量的数学函数
NumPy 的底层主要用 C语言编写,因此它能够高速地执行数值计算
NumPy 还提供了多种数据结构,这些数据结构能够非常契合的应用在数组和矩阵的运算上
1.2 优点
NumPy 可以很便捷高效地处理大量数据,使用 NumPy 做数据处理的优点如下:
NumPy 是 Python 科学计算基础库
NumPy 可以对数组进行高效的数学运算
NumPy 的 ndarray 对象可以用来构建多维数组
NumPy 能够执行傅立叶变换与重塑多维数组形状
NumPy 提供了线性代数,以及随机数生成的内置函数
1.3 与python列表区别
NumPy 数组是同质数据类型(homogeneous),即数组中的所有元素必须是相同的数据类型。数据类型在创建数组时指定,并且数组中的所有元素都必须是该类型。
Python 列表是异质数据类型(heterogeneous),即列表中的元素可以是不同的数据类型。列表可以包含整数、浮点数、字符串、对象等各种类型的数据。
NumPy 数组提供了丰富的数学函数和操作,如矩阵运算、线性代数、傅里叶变换等。
Python 列表提供了基本的列表操作,如添加、删除、切片、排序等。
2.ndarray
在NumPy中,ndarray
(N维数组对象)是其核心数据结构,用于存储和操作同类型元素的大型多维数组。ndarray
提供了高性能的多维数组处理能力,是科学计算和数据分析领域不可或缺的工具。
2.1ndarray的特点
固定大小:
ndarray
的大小在创建时是固定的,即数组的维度(形状)和元素类型(数据类型)是确定的,之后不能改变(除非通过特殊操作如reshape
或resize
)。同类型元素:
ndarray
中的所有元素必须是相同的数据类型,这使得数组在内存中的存储更加高效。连续存储:
ndarray
中的元素在内存中是连续存储的,这有助于提高数组操作的性能。多维支持:
ndarray
可以是一维的(向量)、二维的(矩阵)或更高维度的数组。广播机制:NumPy支持广播机制,允许在不同形状的数组之间进行算术运算。
2.2ndarray的创建
你可以使用多种方式创建ndarray
:
- 使用
numpy.array()
从Python列表或元组创建数组。- 使用NumPy提供的特殊函数创建具有特定形状和类型的数组,如
numpy.zeros()
、numpy.ones()
、numpy.empty()
、numpy.arange()
、numpy.linspace()
等。- 使用
numpy.random
模块中的函数生成随机数数组。
2.3ndarray的属性
shape
:数组的维度,即数组在每个轴上的大小。dtype
:数组元素的数据类型。size
:数组中元素的总数。ndim
:数组的维度数(轴的数量)。data
:指向实际数据缓冲区的内存地址(通常不直接访问)。
2.4ndarray的操作
ndarray
支持丰富的数组操作,包括:
- 元素级运算:如加法、减法、乘法、除法等。
- 聚合操作:如求和、最大值、最小值、平均值等。
- 形状操作:如
reshape
、resize
、transpose
等。- 切片和索引:允许访问数组的子集。
- 线性代数运算:如矩阵乘法、转置、求解线性方程组等。
- 统计函数:如计算标准差、方差、中位数等。
示例
import numpy as np # 创建一个一维数组 arr1 = np.array([1, 2, 3, 4, 5]) # 创建一个二维数组 arr2 = np.array([[1, 2, 3], [4, 5, 6]]) # 获取数组的形状 print(arr2.shape) # 输出: (2, 3) # 获取数组的数据类型 print(arr2.dtype) # 输出: int64(或根据系统配置的不同而有所不同) # 元素级运算 arr3 = arr1 + 10 # 每个元素加10 # 聚合操作 sum_arr = np.sum(arr1) # 计算数组元素的和 # 形状操作 arr4 = arr2.reshape((3, 2)) # 将二维数组重塑为3行2列 # 切片和索引 slice_arr = arr2[0, :2] # 取第一行的前两个元素 # 线性代数运算 A = np.array([[1, 2], [3, 4]]) B = np.dot(A, A) # 矩阵A与自身的点积
3.数据类型
NumPy是Python中用于科学计算的一个重要库,提供了高效的多维数组对象(ndarray)以及对这些数组对象进行操作的大量函数。在NumPy中,数据类型(Data Types)是指用于表示数组元素的类型,是NumPy数组的重要组成部分,它们定义了数组的存储方式和运算规则。NumPy支持多种数据类型,以下是NumPy中常见的数据类型:
3.1基本数据类型
1.1整数类型(Integer Types)
- 有符号整数:包括int8、int16、int32、int64等,分别表示8位、16位、32位、64位的有符号整数。
- 无符号整数:包括uint8、uint16、uint32、uint64等,分别表示8位、16位、32位、64位的无符号整数。
1.2浮点数类型(Floating-Point Types)
- 包括float16、float32、float64、float128等,分别表示半精度、单精度、双精度、扩展精度的浮点数。
1.3复数类型(Complex Types)
- 包括complex64、complex128、complex256等,分别由两个32位、64位、128位浮点数表示的复数。
1.4布尔类型(Boolean Types)
- 用于表示逻辑值,值为True或False。在NumPy中,布尔类型占用1个字节。
1.5字符串类型(String Types)
- 用于表示字符串,可以是固定长度的字符串(如'S10'表示长度为10的字符串)或Unicode字符串(如'U10'表示长度为10的Unicode字符串)。
1.6日期和时间类型(Datetime Types)
- 用于表示日期和时间,即datetime64类型。
1.7对象类型(Object Types)
- 可以存储任何Python对象,即object类型。
3.2数据类型的特点
- 高效性:NumPy的数据类型是经过优化的,可以提高计算的效率。
- 灵活性:NumPy的数据类型可以满足不同数据的需求,包括整数、浮点数、复数等。
- 数组操作:NumPy的数据类型可以与数组对象一起使用,进行各种数组操作。
3.3数据类型的指定和查看
- 指定数据类型:在创建NumPy数组时,可以通过指定数据类型来定义数组中元素的类型。这可以通过dtype参数来实现。
- 查看数据类型:可以通过dtype属性来查看NumPy数组使用的数据类型。
4.数组属性
NumPy数组是科学计算中不可或缺的数据结构,它具有多种属性,这些属性为我们提供了关于数组本身的重要信息。以下是NumPy数组的一些常用属性:
- ndim:返回数组的维度数量,即数组的轴数(秩)。一维数组的ndim为1,二维数组的ndim为2,以此类推。
- shape:返回一个元组,表示数组在每个维度上的大小。例如,一个二维数组的大小可能表示为(m, n),其中m是行数,n是列数。
- size:返回数组中元素的总数。对于二维数组,这个值等于行数乘以列数。
- dtype:返回数组元素的数据类型。NumPy支持多种数据类型,包括整数(如int8、int16、int32等)、浮点数(如float32、float64等)、复数、布尔值等。在创建数组时,可以通过dtype参数指定数组的数据类型。
- itemsize:以字节的形式返回数组中每个元素的大小。这个属性取决于数组元素的数据类型。例如,一个元素类型为float64的数组,其itemsize属性值为8(因为float64占用64位,即8字节)。
- flags:提供了关于数组内存布局的信息。例如,C_CONTIGUOUS表示数组在C语言风格的内存中是连续的,F_CONTIGUOUS表示数组在Fortran语言风格的内存中是连续的。这些信息对于理解数组的内存布局和性能优化很有帮助。
这些属性为我们提供了强大的工具来检查和理解NumPy数组。掌握这些属性对于有效地使用NumPy进行科学计算至关重要。可以通过以下示例代码来查看这些属性的使
import numpy as np # 创建一个二维数组 a = np.array([[1, 2, 3], [4, 5, 6]]) # 查看数组属性 print("ndim:", a.ndim) # 输出数组的维度数量 print("shape:", a.shape) # 输出数组的形状 print("size:", a.size) # 输出数组中元素的总数 print("dtype:", a.dtype) # 输出数组元素的数据类型 print("itemsize:", a.itemsize) # 输出数组中每个元素的大小(字节) print("flags:", a.flags) # 输出数组的内存信息 # 对于复数数组 b = np.array([1+2j, 3+4j]) print("Real part:", b.real) # 输出数组的实部 print("Imaginary part:", b.imag) # 输出数组的虚部
5.创建数组的其他方法
在NumPy中,除了使用numpy.array
函数从现有数据(如列表、元组等)创建数组外,还有其他多种方法可以创建数组。以下是一些常用的方法:
numpy.zeros
:创建一个指定形状和类型的新数组,数组中的元素全部初始化为0。import numpy as np arr = np.zeros((2, 3)) # 创建一个2x3的二维数组,元素全为0
numpy.ones
:创建一个指定形状和类型的新数组,数组中的元素全部初始化为1。arr = np.ones((3, 4), dtype=float) # 创建一个3x4的二维数组,元素全为1.0
numpy.empty
:创建一个指定形状的新数组,但不初始化数组中的元素(即数组中的元素值是未定义的,可能是任何值)。arr = np.empty((2, 2)) # 创建一个2x2的二维数组,元素值未定义
numpy.arange
:返回一个指定间隔的一维数组。类似于Python内置的range
函数,但返回的是NumPy数组。arr = np.arange(10) # 创建一个包含0到9的一维数组 arr = np.arange(1, 10, 2) # 创建一个包含1, 3, 5, 7, 9的一维数组,步长为2
numpy.linspace
:在指定的间隔内返回均匀间隔的数字。arr = np.linspace(0, 1, 5) # 在0到1之间生成5个均匀间隔的数字
6.切片
在NumPy中,切片(slicing)是一种强大的工具,它允许你访问数组的子集或子数组。通过切片,你可以指定要提取的数组部分,包括起始索引、结束索引以及步长(即元素之间的间隔)。切片操作适用于所有维度的数组,无论是一维、二维还是更高维度的数组。
6.1一维数组切片
对于一个一维数组,切片的基本语法是:
array[start:stop:step]
start
是切片的起始索引(包含),默认为0。stop
是切片的结束索引(不包含)。step
是步长,默认为1。import numpy as np arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) # 获取从索引2到索引6(不包含6)的元素,步长为1 slice_arr = arr[2:6] print(slice_arr) # 输出: [2 3 4 5] # 获取所有元素,步长为2 stride_arr = arr[::2] print(stride_arr) # 输出: [0 2 4 6 8] # 获取从索引5到数组末尾的元素 end_arr = arr[5:] print(end_arr) # 输出: [5 6 7 8 9]
6.2二维数组切片
对于二维数组(矩阵),你可以分别指定行和列的切片。语法如下:
array[row_start:row_stop:row_step, col_start:col_stop:col_step]
arr_2d = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]) # 获取第1行到第3行(不包含第3行),第0列到第2列(不包含第2列)的元素 slice_2d = arr_2d[1:3, 0:2] print(slice_2d) # 输出: # [[3 4] # [6 7]] # 获取所有行,第1列到第3列(不包含第3列)的元素 cols_slice = arr_2d[:, 1:3] print(cols_slice) # 输出: # [[ 1 2] # [ 4 5] # [ 7 8] # [10 11]] # 获取所有列,第1行到第3行(不包含第3行)的元素 rows_slice = arr_2d[1:3, :] print(rows_slice) # 输出: # [[3 4 5] # [6 7 8]]
7.高级索引
7.1整数数组索引
整数数组索引的基本思想是,你提供一个数组,其中每个元素都是目标数组中的索引。NumPy会根据提供的索引数组来选择目标数组中的对应元素。
- 一维数组中的整数数组索引
import numpy as np # 创建一个一维数组 arr = np.array([10, 20, 30, 40, 50]) # 创建一个索引数组 indices = np.array([0, 2, 4]) # 使用整数数组索引来选择元素 selected_elements = arr[indices] print(selected_elements) # 输出: [10 30 50]
- 多维数组中的整数数组索引
import numpy as npdef two():array_one = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])print('原数组:\n',array_one)array_one = array_one[[0,0,-1,-1], [0,-1,0,-1]]print('这个数组的四个角元素是:')print(array_one)#这个数组的四个角元素是:#[ 0 2 9 11]
7.2 布尔索引
布尔索引(Boolean indexing)是一种根据条件来选择数组元素的方法。它允许你使用一个布尔数组(即元素为True或False的数组)来指定哪些元素应该被选中。布尔索引在处理数据时非常有用,特别是当你需要根据某些条件过滤数组时。
- 一维数组中的布尔索引
import numpy as np # 创建一个一维数组 arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]) # 创建一个布尔数组,表示arr中哪些元素大于5 condition = arr > 5 # 使用布尔索引来选择元素 selected_elements = arr[condition] print(selected_elements) # 输出: [6 7 8 9]
在这个例子中,
condition
是一个布尔数组,其元素与arr
中的元素相对应。当arr
中的元素大于5时,condition
中的对应元素为True;否则为False。然后,我们使用布尔索引arr[condition]
来选择arr
中所有满足条件(即大于5)的元素。
- 多维数组中的布尔索引
# 创建一个二维数组 arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 创建一个布尔数组,表示arr_2d中哪些元素大于5 condition_2d = arr_2d > 5 # 使用布尔索引来选择元素 selected_elements_2d = arr_2d[condition_2d] print(selected_elements_2d) # 输出: [6 7 8 9]
在这个例子中,
condition_2d
是一个与arr_2d
形状相同的布尔数组。我们使用arr_2d[condition_2d]
来选择所有满足条件(即大于5)的元素。注意,结果是一个一维数组,因为它包含了所有满足条件的元素,而不考虑它们在原始二维数组中的位置。
注意:numpy的逻辑运算符:
&:与运算,组合多个条件。
|:或运算,组合多个条件。
~:非运算,取反条件。
8.广播
NumPy广播(Broadcasting)是NumPy库中的一种强大机制,它允许numpy在执行数组运算时对不同形状的数组进行隐式扩展。这种机制使得数组操作更加高效和灵活,特别是在处理形状不一致的数组时。
8.1基本原理
广播机制基于以下规则:
- 如果两个数组的维度数不同,则较小维度的数组形状会在前面补1。
- 如果两个数组在某个维度上的大小不同,则其中一个数组在该维度上的大小必须是1。这样,大小为1的维度可以被扩展(广播)以匹配另一个数组在该维度上的大小。
- 如果两个数组在所有维度上的大小都兼容(相等或其中一个为1),则它们可以进行广播。
示例1:简单广播
import numpy as np a = np.array([1, 2, 3]) b = np.array([10, 20, 30]) # 形状分别为 (3,) 和 (3,) print(a + b) # 输出: [11 22 33]
示例2:形状不同,但兼容import numpy as np# 创建一个二维数组 arr2d = np.array([[1, 2, 3], [4, 5, 6]])# 创建一个一维数组 arr1d = np.array([10, 20, 30])# 相加 result = arr2d + arr1dprint(result) # 输出: # [[11 22 33] # [14 25 36]]
示例3:更高维度的广播
a = np.array([[1], [2], [3]]) # 形状为 (3, 1) b = np.array([10, 20, 30]) # 形状为 (3,) # 广播后,a的形状变为 (3, 3),b的形状变为 (1, 3) 然后扩展为 (3, 3) print(a + b) # 输出: # [[11 12 13] # [21 22 23] # [31 32 33]]
注意事项
- 如果两个数组在任何维度上的大小都不兼容,并且其中没有一个维度的大小为1,则无法进行广播。
- 广播后的数组不会实际创建新的内存空间来存储扩展后的数组,而是在进行运算时动态地处理这些维度。这使得广播操作非常高效。