Numpy(Numerical Python)是python的一个语言拓展程序库,它提供了一个强大的多维数组对象(ndarray
),以及用于操作数组的函数和工具。NumPy是许多其他科学计算库和数据分析库的基础,如SciPy(Scientfic Python)、Pandas和Matplotlib(绘图库)。
SciPy:开源的python算法库和数学工具包,包含的模块有最优化、线性代数、积分、插值、快速傅里叶变换、信号处理和图像处理等
Pandas:另一个数据处理和分析工具,核心数据结构是两种类型的对象:Series 和 DataFrame
Matplotlib:Numpy的可视化操作界面,利用通用的图形用户界面工具包(如Tkinter)向应用程序嵌入式绘图提供API
Numpy官方手册:
NumPy user guide — NumPy v1.26 Manual
1. 数据类型
Numpy支持的数据类型可以和C语言的数据类型对应上,和python内置的六大数据类型相比,Numpy提供的数据类型相应的要细分很多,以下是常用的数据类型:
名称 | 概述 |
---|---|
bool_ | 布尔型数据类型(True或False) |
int_ | 默认的整数类型(C语言中的long,int32或int64) |
intc | c的int类型,int32或int64 |
intp | 索引的整数类型 |
int8 | 整数 -128 to 127 |
int16 | 整数 -32768 to 32767 |
int32 | 整数 -2147483648 to 2147483647 |
int64 | 整数 -9223372036854775808 to 9223372026854775807 |
uint8 | 无符号整数 0 to 255 |
uint16 | 无符号整数 0 to 65535 |
uint32 | 无符号整数 0 to 4294967295 |
uint64 | 无符号整数 0 to 18446744073709551615 |
float_ | float64类型 |
complex_ | complex128类型,128位复数 |
bytes_ | 字节序列数据类型,可以包含任意字节值,通常用于处理原始的二进制数据 |
str_ | 字符串数据类型,存储 Unicode 字符串数据 |
在numpy中,数据类型是通过 dtype
对象来表示的。dtype
对象描述了数据在内存中的存储方式,包括数据的类型(整数、浮点数等)和字节大小等信息。每个数据类型都对应一个唯一的字符码(Character Code),用于标识该数据类型。
dtype
对象本身是一个类,它有多个属性和方法来描述和操作数据类型。例如,int32
数据类型的 dtype
对象可以通过 np.int32
或 np.dtype('int32')
来创建。它的字符码是 'i'
,用于表示整数类型。
2. 创建数组
Numpy最大的特征(或者说是核心)是其提供的N维数组对象ndarray
(N-dimensional array,多维数组),其有以下特征:
- 多维数组:ndarray是一个多维数组对象
- 数据类型:ndarray中的元素具有相同的数据类型,通常是数值类型,如整数(int)、浮点数(float)或复数(complex)
- 形状:ndarray对象的形状用于描述数组的维度。例如,一维数组的形状是一个整数,表示数组的长度;二维数组的形状是一个元组(rows, columns),表示数组的行数和列数
- 大小:ndarray对象的大小等于数组形状中各个维度的乘积,可以通过ndarray对象的
size
属性获取- 内存布局:ndarray对象在内存中以连续的方式存储数据。这种连续存储的方式使得对数组的访问和操作更加高效
- 索引和切片:可以使用索引和切片操作访问ndarray对象中的元素。一维数组的索引类似于Python的列表索引(0下标开始),而多维数组可以用整数数组索引等来访问特定的元素或切片
- 广播(Broadcasting):
ndarray
支持广播操作,可以在不同形状的数组之间进行运算,NumPy 会自动进行形状的调整,使得运算能够进行
ndarray
就类似于python中的list
,只不过ndarray
只能存储同一个类型的数据。
我们可以直接用ndarray构造器来创建数组:
1 | import numpy as np |
也可以用其他方式创建数组:
1 | # .zero创建指定大小数组,元素以0填充 |
3. 数组属性
Numpy的数组有以下几个常用的属性:
属性 | 说明 |
---|---|
ndarray.ndim | 数组的维度数量(也称为秩, rank),比如一维就是1,二维就是2 |
ndarray.shape | 数组的维度。这是一个整数元组,指示数组每个维度的大小,比如二维数组n行m列 |
ndarray.size | 数组元素的总数,比如上面二维数组就是n*m |
ndarray.dtype | 数组对象的元素类型 |
ndarray.itemsize | 数组中每个元素大小(字节为单位),如float64类型的元素数组的 itemsize 为 8 (=64/8) |
ndarray.data | 包含数组元素缓冲区 |
1 | a = np.array([[1, 2], [2, 3], [3, 4]]) |
4. 索引、切片和迭代
对于一维数据,python用的索引和切片方法,Numpy中均可以使用:
1 | a = np.arange(10) |
对于多维数组,Numpy中还有一种索引方式方式称为**”整数数组索引”(integer array indexing)或“花式索引”**(fancy indexing),使用整数数组作为索引来选择数组中的元素:
1 | a = np.array([[1, 2, 3], [5, 8, 9], [10, 12, 15]]) |
两个整数数组 [0, 1, 2]
和 [0, 1, 0]
作为索引,分别表示要选择的行和列的索引。这种索引方式会返回一个由对应位置上的元素组成的新数组。
具体来说,在这个例子中,我们选择了数组 a
的以下元素:
- 行索引为 0,列索引为 0 的元素:
a[0, 0]
,值为 1 - 行索引为 1,列索引为 1 的元素:
a[1, 1]
,值为 8 - 行索引为 2,列索引为 0 的元素:
a[2, 0]
,值为 10
这些选中的元素被组合成一个新的一维数组 b
,即 [1, 8, 10]
。
还可以使用逗号分隔的索引元组来访问特定元素,每个索引元组对应一个维度的切片范围:
1 | a = np.array([[1, 2, 3], [5, 8, 9], [10, 12, 15]]) |
a[:, 1]
表示对二维数组 a
的所有行进行切片,并选择索引值为1的列的元素。
在Numpy中进行数组的迭代只会发生在数组的第一个维度上,我们用以下方式生成一个数组:
1 | # np.fromfunction(function, shape, **kwargs),根据指定的形状,在每个位置 (i, j) 上调用函数 f(i, j),并将返回的值作为数组的元素填充 |
5. 广播机制
广播(broadcasting)机制描述的是Numpy在算术操作过程中,如何处理不同形状(shape)的数组。简单来说,当两个数组的维度和长度相同时(形状相同),两个数组的运算将会发生在两个数组对应的位置;当两个数组大小不一致,较小的数组会在较大的数组中被“广播”:
1 | # 较小数组被扩展成相同的形状 |
广播机制遵循以下规则:
- 如果两个数组的维度数不同,那么维度较低的数组会在前面补1,直到维度数匹配。
- 如果两个数组的维度在任何一个维度上都不匹配,且在该维度上一个数组的形状为1,那么可以将其扩展为与另一个数组相同的形状。
- 如果两个数组的维度在任何一个维度上都不匹配,且在该维度上两个数组的形状都不为1,那么会引发一个错误,表示无法进行广播。
数组 a
的形状是 (4, 3)
,数组 b
的形状是 (3)
,它们的维度不匹配。但是根据广播机制的规则,可以将数组 b
扩展为 (1, 3)
的形状,使得它与数组 a
的形状匹配。在进行元素级的运算时,广播机制会自动将数组 b
在第一个维度上进行复制,使得它的形状与数组 a
相同,然后进行对应位置的运算。
如果 b
的形状是 (2, 3)
或者是 (4)
都无法进行扩张。
6. 数组基础操作
修改数组形状
1 | # resize、reshape修改数组形状,两者区别如下 |
注意下这里的副本和视图的概念:
flatten
返回数组的副本,也就是一个数组的完整拷贝(深拷贝),它和原始数据存在不同的物理内存,副本的修改不会影响原数据。ravel
返回数组的视图,也就是数据的别称或者说是引用(浅拷贝),它和原始数据物理内存在同一个位置,修改视图会影响原数据。切片修改数据会影响原始数组。
翻转数组
1 | # transpose、T将数组维度进行翻转 |
修改维度
1 | # np.expand_dims(arr,axis)在指定位置插入新的维度 |
数组拼接
1 | # np.concatenate((a1,a2),axis)多个数组在指定的维度上进行拼接,默认是0维 |
数组拆分
1 | # 为了方便演示再创建一个随机数生成器对象,种子值(1)进行初始化 |
数组增删
1 | # np.append(arr,values,axis=None)增加数组元素 |
7. 常用函数
函数 | 描述 |
---|---|
数学函数 | |
np.around() | 函数返回指定数字的四舍五入值 |
np.floor() | 返回小于或者等于指定表达式的最大整数,也就是向下取整 |
np.ceil() | 返回大于或者等于指定表达式的最小整数,也就是向上取整 |
np.abs() | 计算数组元素的绝对值 |
np.sqrt() | 计算数组元素的平方根 |
np.sum() | 计算数组元素的和 |
np.mean() | 计算数组元素的平均值 |
np.max() / np.min() | 找出数组的最大/最小值 |
字符串函数 | |
np.char.add() | 两个数组逐个字符串拼接 |
np.char.center() | 居中字符串 |
np.char.capitalize() | 将字符串第一个字母转为大写 |
np.char.title() | 字符串每个单词的第一个字母转大写 |
np.char.lower() / np.char.upper() | 数组元素转小写/大写 |
np.char.strip() | 移除开头和结尾的特殊字符 |
np.char.join() | 指定分隔符连接数组元素 |
np.char.replace() | 替换字符串 |
np.char.split() | 指定分隔符对字符串分割,返回数组列表 |
8. Matplotlib
在Numpy的官方文档的Numpy实际应用案例中,几乎所有的可视化数据案例都是用Matplotlib
库做的。Matplotlib
是python的绘图库。
Matplotlib就和R类似,能做的图非常多,要用的时候还是直接查官方文档比较方便:
Using Matplotlib — Matplotlib 3.8.0 documentation
对于一副Matplotlib绘制的图,我们需要知道以下的一些图表属性:
用Matplotlib库简单绘制一个图(推荐用Jupyter Notebook):
1 | import numpy as np |
NumPy Applications — NumPy Tutorials
从上面的Numpy应用案例中看一个绘制分形图像的例子:
1 | import numpy as np |