Python第三方库学习笔记-NumPy

基于NumPy文档的个人总结

  博主通过NumPy中文文档进行NumPy库的学习,并整理笔记,记录如下!

一、创建多维数组

  多维数组是NumPy库中定义的一个容器对象,以下创建方式均返回一个多维数组容器ndarray

1、空数组创建

  *numpy.empty(shape, dtype=float, order=’C’, , device=None, like=None)

  shape:形状参数,必需,接受一个整数或整数元组(列表,可行、简单),其中第i个元素的值代表生成数组第i维的长度

1
2
3
4
5
# !!!本文中代码均默认自动导入numpy库,import numpy
numpy.empty(2) # 生成一个1×2的一维数组,元素自动初始化为随机垃圾值(后同)
numpy.empty((2, 3)) # 生成一个2×3的二维数组,
numpy.empty((2, 3, 4)) # 生成
numpy.empty([2, 3, 4]) # 使用列表可返回相同结果

  dtype:生成数组中元素的数据类型,可选,默认为float,也就是numpy.float64

  order:以何种方式生成数组,可选,默认为’C’,共’C’、’F’两种选项;’C’ => 行优先,即最右侧索引位最快;’F’ => 列优先,即最左侧索引位最快

1
2
3
4
5
6
# 如果是'C'方式创建的数组,z位索引变化的速度最快
array1 = numpy.empty((3, 3, 3), 'C')
array1[x][y][z]
# 如果是'F'方式创建的数组,x位索引变化的速度最快
array2 = numpy.empty((3, 3, 3), 'F')
array1[x][y][z]

  *:位置参数的终止符号,在此之前对“? = 输入参数”的判定只需根据输入参数摆放顺序,在此之后再输入参数必需按”关键字 = 输入参数”(关键字参数)的格式输入而无需再注意顺序

1
2
3
4
numpy.empty((2, 3), 'F')               # 可行但不推荐
numpy.empty((2, 3), float, 'F') # 推荐这一种
numpy.empty((2, 3), device=none) # 正确传入参数
numpy.empty((2, 3), float, 'F', none) # 错误,none参数前必需带上关键字

  device:指定用于创建数组的设备(如GPU),可选,如果未指定,则使用默认的 NumPy 设备

  like:模仿生成数组,可选,接受指定数组、数组子类或具有shape和dtype属性的对象,生成数组的shape和dtype属性将与之相同

  :上述属性如无特殊情况在本文后续不再赘述,均以上述说明为准

  另一种方法:**numpy.empty_like(a, dtype=None, order=’K’, subok=True, shape=None, *, device=None)**,作用类同上文函数中的like属性,不推荐,详查文档

2、仅对角线为1的二维零数组(矩阵)创建

  *numpy.eye(N, M=None, k=0, dtype=<class ‘float’>, order=’C’, , device=None, like=None)

  N:生成数组的行数,必需,接受一个整数值

  M:生成数组的列数,可选,默认为none <=> 列数与行数相同,接受一个整数值

  k:对角线的偏移量,可选,默认为0,即主对角线,接受一个整数值,k为几,主对角线向右上方移动几,如果某元素aii超过数组界限,不会报错,会直接设原位置的aii为0,如下图所示:

3、单位二维数组(单位矩阵)创建

  **numpy.identity(n, dtype=None, *, like=None)**,n接受一个整数值,生成一个n×n,数据类型为float的单位矩阵(仅对角线为1的零方阵)

4、全1数组创建

  *numpy.ones(shape, dtype=None, order=’C’, , device=None, like=None)

  *numpy.ones_like(a, dtype=None, order=’K’, subok=True, shape=None, , device=None)

  用法、参数含义同空数组生成函数一致,所生成的数组中所有元素的值均为1

5、全0数组创建

  *numpy.zeros(shape, dtype=None, order=’C’, , device=None, like=None)

  *numpy.zeros_like(a, dtype=None, order=’K’, subok=True, shape=None, , device=None)

  用法、参数含义同空数组生成函数一致,所生成的数组中所有元素的值均为0

6、指定数据数组创建

  *numpy.full(shape, fill_value, dtype=None, order=’C’, , device=None, like=None)

  *numpy.full_like(a, fill_value, dtype=None, order=’K’, subok=True, shape=None, , device=None)

  fill_value:填充数据,接受一个符合dtype类型的数值,也可以接受一个同数组尺寸匹配的列表

1
2
numpy.full((3, 3), 2)              # 生成一个3×3型数组,每个元素均被初始化为2
numpy.full((3, 3), [1, 2, 3]) # 生成一个3×3型数组,每行元素均被分别初始化为1、2、3

7、其他对象转换数组

  *numpy.array(a, dtype=None, , copy=True, order=’K’, subok=False, ndmin=0, like=None)

  copy:是否复制其中值,可选,接受一bool值,默认为真

  subok:是否返回为ndarray子类,可选,接受一bool值,默认为真

1
2
3
4
5
class MyArray(numpy.ndarray):
~~~ # 假设我们实现了一个ndarray的子类
test_array = MyArray(~~~) # 创建一个实例
Array1 = numpy.array(test_array, copy=True) # Array1类型为MyArray
Array2 = numpy.array(test_array, copy=False) # Array2类型为ndarray

  函数接受一个具有数组接口的对象,返回与其对应的ndarray数组;如果对象已经为一个ndarray数组,则返回其副本(作用基本将numpy.copy函数覆盖,故对numpy.copy不再赘述,可自行查阅)

8、提取numpy.tofile函数存入的数据来创建数组

  *numpy.fromfile(file, dtype=float, count=-1, sep=’’, offset=0, , like=None)

  file:读取文件,必需,接受一个文件路径或者一个文件读取对象

  count:读取项数,可选,默认为-1,即读取文件中所有项,接受一个非负整数

  sep:分隔字符,可选,以分隔符分割数据,用于从文本文件读取数据,接受一个字符

  offset:偏移量,可选,即从何处开始读取文件,默认为0,即从头读取,接受一个正整数

1
2
3
array1 = np.fromfile('data.txt', dtype=np.float32, sep=' ')  # 以空格为间隔符,读取data.txt中所有数据,生成数组
array2 = np.fromfile('data.txt', count=10, sep='!') # 以!为间隔符,读取data.txt中10个数据,生成数组
array2 = np.fromfile('data.txt', count=10, offset=16) # 从第17个字节读取data.txt中10个数据,生成数组

  该函数主要用于读取二进制文件,对于文本文件的读取有专门的函数numpy.loadtxt,较为复杂,可自行查阅

9、调用函数创建数组

  *numpy.fromfunction(function, shape, , dtype=<class ‘float’>, like=None, ******kwargs)

  function:调用函数,必需,接受一个函数,函数的参数数量与数组维度相匹配

  shape:数组尺寸,数组的维度不能超过函数的参数数量,数组中每个元素的索引值将作为参数传入函数并调用,并将返回后的结果作为初始化值储存

  **kwargs:函数允许当数组维度小于参数数量时,捕捉外界变量作为参数,较为复杂,不做使用

1
2
3
4
5
6
7
8
9
def my_function(x, y):
return x + y
result = np.fromfunction(my_function, (3, 3), dtype=int)
'''
返回数组
[[0 1 2]
[1 2 3]
[2 3 4]]
'''

二、操作多维数组

  ndarray容器的属性与方法多样,这里只记录已学习使用的部分

1、ndarray数组的数组属性

  ndarray.flags:一个包含了关于 NumPy 数组内存布局信息的对象,其内存放多个bool属性值

1
2
3
4
5
6
7
8
9
10
11
# 创建NumPy数组
arr = numpy.array([1, 2, 3, 4, 5])
# 访问ndarray.flags属性
flags = arr.flags
# 打印各个标志(列举部分)
print("C_CONTIGUOUS:", flags.C_CONTIGUOUS) # 为True则表示数组以行单位存储方式
print("F_CONTIGUOUS:", flags.F_CONTIGUOUS) # 为True则表示数组以列单位存储方式
print("OWNDATA:", flags.OWNDATA) # 为True则表示数组拥有独立内存,修改该数组不会影响其他数组
print("WRITEABLE:", flags.WRITEABLE) # 为True则表示数组中数据可以被修改,为False则数组只读
print("ALIGNED:", flags.ALIGNED) # 为True则表示数组针对硬件进行了适当的对齐
print("WRITEBACKIFCOPY:", flags.WRITEBACKIFCOPY) # 为True则表示数组是另一数组的副本

  ndarray.shape:一个存储数组维度数据的元组,也可以通过赋值修改数组的尺寸

1
2
3
4
5
6
7
8
arr = numpy.zeros((2, 3, 4))           # 生成一个2×3×4尺寸数组
print(arr.shape) # 返回:(2, 3, 4)
arr.shape = (3, 8) # 可以通过赋值修改属性值,前提是新形状的数组元素个数要与之前一致
print(arr) '''
返回:[[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]]
'''

  ndarray.ndim:数组维数

1
2
arr = numpy.zeros((2, 3, 4))         # 生成三维数组
print(arr.ndim) # 返回为3

  ndarray.size:数组中元素数

1
2
arr = numpy.zeros((2, 3, 4))         # 生成2×3×4零数组
print(arr.size) # 返回为24

  ndarray.itemsize:单个元素所占内存字节数

1
2
arr = numpy.zeros((2, 3, 4))         # 未对数组数据类型修改,默认为numpy.float64
print(arr.itemsize) # 返回为8

  ndarray.nbytes:整个数组所占内存字节数

1
2
arr = numpy.zeros((2, 3, 4))         # 未对数组数据类型修改,默认为numpy.float64
print(arr.nbytes) # 返回为8×24=192

  ndarray.base:指向数组的基对象,如果为其本身则返回None,当该属性不为None时,修改数组可能会对其基对象产生影响

1
2
3
4
5
6
arr = numpy.zeros((2, 3, 4))
print(arr.base) # 数组基对象即其本身,返回None
arr_0 = arr[0] # arr_0借助arr的内存切片生成
print(arr_0.base) # 返回:<memory at 0x...>,即为数组arr的内存地址
arr_0[0][0] = 1 # 修改arr_0第一行第一列元素为1
print(arr[0][0][0]) # 此时arr_0[0][0]对应的原数组中arr[0][0][0]也会变成1,输出:1

  ndarray.T:转置数组,即返回一个颠倒维度的数组

1
2
arr = numpy.zeros((2, 3, 4, 5))
print(arr.T) # 返回的应为一个5×4×3×2数组

  ndarray.real:复数数组的实部

  ndarray.imag:复数数组的虚部

1
2
3
arr = numpy.array([1 + 0j, 0 + 1j])
print(arr.real) # 返回:[1, 0]
print(arr.imag) # 返回:[0, 1]

2、数组的各种方法

  太多了太多了,这里只展示使用过的 T_T T_T T_T

  ndarray.sum(axis=None, dtype=None, out=None, keepdims=False, initial=0, where=True)

  axis:沿某一轴求和,可选,默认为None,表示为求数组中所有元素和,接受一个整数或整数元组

  out:指定一个数组来放置结果,可选,默认无,如果提供,它必须具有与默认输出相同的形状和类型

  keepdims:是否保持原有维数,可选,默认否,不推荐使用(据说很不好用,不过我也没用过)

  initial:累加初始值,可选,默认为零,即求和结果为<元素总和+初始值>,接受一个整数

  where:根据指定bool数组确定求和元素,可选,默认无,只有当where数组中对应位置为True时,输入数组中的元素才会被包含在总和计算中,接受一个尺寸相同的bool数组

1
2
3
4
5
6
7
8
9
10
11
12
13
arr = numpy.ones((2, 3, 4))                     # 生成一个2×3×4的全1数组
sum_all = numpy.sum(arr) # 返回:24
sum_axis0 = arr.sum(axis=0) # 顺第1轴计算结果
print(sum_axis0) # 返回一个3×4的数组,其中第(i, j)位为原数组中第(:, i ,j)的和
sum_axis1 = arr.sum(axis=1) # 顺第2轴计算结果
print(sum_axis1) # 返回一个2×4的数组
sum_axis2 = arr.sum(axis=[0, 1]) # axis接受第几轴的数字,该维维数输出时即变成1
print(sum_axis2) # 返回一个四个数(1×1×4)的数组
out_arr = numpy.zeros((2, 4), dtype=arr.dtype) # 生成一个类型、尺寸均符合输出结果要求的数组
arr.sum(out=out_arr) # 结果储存于out_array中
print(out_arr) # 返回一个2×4的数组
arr_initial = 1
sum_initial = numpy.sum(initial=arr_initial) # 返回:24 + 1 = 25