python之numpy库--科学计算基础库必学(二)

python之numpy库--科学计算基础库必学(一)中,已经介绍了numpy相关基础知识,现在接着讲解,到本文章结束,基本可以认为numpy相关的基础知识已经学习完成,后续可基于实际项目需求,进一步熟练和深入。

一、数组相关操作

1.1 修改数组形状相关

函数或属性 说明 示例

np.reshape(arr,(m,n))

arr.reshape(m,n)

将指定数组修改为指定形状

arr=np.arange(1,10)

np.reshape(arr,(3,3)) #或arr.reshape(3,3)

arr.flat 指定数组的元素迭代器

for i in arr.flat:

    print(i)

arr.flatten(order='C')

返回一个指定数组被展开为一维数组的数组

order用来指定展开指定数组的方向,C代表按行从上到下展开,F代表按列从左到右展开

修改展开后的数组,不会影响原数组

arr=np.arange(1,10)

arr.flatten() #返回 array([1, 2, 3, 4, 5, 6, 7, 8, 9])

np.ravel(arr,order='C')

返回一个指定数组被展开为一维数组的数组

order用来指定展开指定数组的方向,C代表按行从上到下展开,F代表按列从左到右展开

修改展开后的数组,会影响原数组

arr=np.arange(1,10)

b=np.ravel(a)

b[2]=10 #修改b的元素,同时a对应元素也会发生变化

1.2 翻转数组

函数或属性 说明 示例
np.transpose(arr)

对换指定数组的维数,比如将(m,n)的数组转变成(n,m)

即求数组的转置

arr=np.arange(1,10).reshape(3,3)

np.transpose(arr)

arr.T 求某数组的转置,作用域transpose一样

arr=np.arange(1,10).reshape(3,3)

arr.T

 

1.3 修改数组维数

函数或属性 说明 示例
np.broadcast_to(array, shape)

将指定数组,按照广播机制,构造成新的形状

如果指定的数组不满足广播机制,则抛出错误

a=np.arange(1,5)
np.broadcast_to(a,(3,4))

np.expand_dims(arr, axis) 在指定数组的指定位置插入新的轴来扩展数组形状

a=np.arange(1,13).reshape(3,4)

b=np.expand_dims(a,0)

b.shape #此时为 (1,3,4)

np.squeeze(arr) 去除指定数组内维度长度为1的维数,相当于精简数组

a=np.arange(1,9).reshape(1,4,2)

np.squeeze(a).shape #输出结果为 (4,2)

 

1.4 连接数组

函数或属性 说明 示例
np.concatenate((a1, a2, ...), axis)

沿着指定轴,将形状相同的两个或多个数组连接在一起

默认是沿着0轴连接,即行连接

输出的数组,形状和输入数组的形状相同

a=np.arange(1,9).reshape(2,4)
b=np.arange(10,18).reshape(2,4)

c=np.concatenate((a,b))

c.shape#输出为(4,4)

np.stack(arrs, axis)

沿着新的轴,将形状相同的两个或多个数组连接在一起

默认是沿着0轴链接,即沿着行方向纵向堆叠

输出的数组,形状和输入数组的形状不同,会多一个维数

a=np.arange(1,13).reshape(3,4)
b=np.arange(20,32).reshape(3,4)

c=np.stack((a,b),2)

c.shape #输出为(3, 4, 2)

np.hstack(arrs)

沿着水平方向,将形状相同的两个或多个数组连接在一起

输出的数组,形状和输入的数组形状相同

a=np.arange(1,13).reshape(3,4)
b=np.arange(20,32).reshape(3,4)

c=np.hstack((a,b))

c.shape #输出为(3,8)

np.vstack(arrs)

沿着垂直方向,将形状相同的两个或多个数组连接在一起

输出的数组,形状和输入的数组形状相同

a=np.arange(1,13).reshape(3,4)
b=np.arange(20,32).reshape(3,4)

c=np.vstack((a,b))

c.shape #输出为(6,4)

1.5 分割数组

函数或属性 说明 示例
np.split(ary, indices_or_sections, axis)

将指定数组,沿着指定的轴,进行切割

如果indices_or_sections传入的是整数,则是沿着指定轴切割成指定份数

如果indices_or_sections传入的是列表,则是沿着指定轴,并按照列表开始和结束(前闭后开)切割数组,相当于列表指定了切割的位置

切割后,输出的数组形状会和输入的数组形状不同

a=np.arange(1,13).reshape(3,4)

np.split(a,3) #输出结果如下:

[array([[1, 2, 3, 4]]), array([[5, 6, 7, 8]]), array([[ 9, 10, 11, 12]])]

np.hsplit(arr, count)

将指定数组,在水平方向进行切割,并切割成相同形状的指定份数

切割后,输出的数组的形状和输入的数组形状相同

a=np.arange(1,13).reshape(3,4)
b=np.hsplit(a,2)
b[0].shape #输出为(3, 2)
np.vsplit(arr, count)

将指定数组,在垂直方向进行切割,并切割成相同形状的指定份数

切割后,输出的数组的形状和输入的数组形状相同

a=np.arange(1,13).reshape(3,4)
b=np.hsplit(a,3)
b[0].shape #输出为(1,4)

1.6 数组元素的添加与删除

函数或属性 说明 示例
np.resize(arr, shape)

将指定数组改变为新的形状

如果新数组大小大于原始大小,则包含原始数组中的元素的副本。

而reshape则需要严格要求输入的数组与输出的数组元素整体个数完全相同

a=np.arange(1,9)
np.resize(a,(3,4)) #结果如下:

array([[1, 2, 3, 4],
       [5, 6, 7, 8],
       [1, 2, 3, 4]])

np.append(arr, values, axis=None)

会在指定数组的末尾追加指定的值,函数不会改变输入数组的形状

要求添加的值,在追加的轴方向,形状需与数组相同

如果轴不指定,则会将原数组展开成一维,然后再追加

如果指定,则会在指定轴方向追加

a=np.arange(1,9).reshape(2,4)
np.append(a,[[1,2,3,4]],axis=0) #输出结果为

array([[1, 2, 3, 4],
       [5, 6, 7, 8],
       [1, 2, 3, 4]])

np.delete(arr, obj, axis)

从指定数组中,沿着指定轴,删除指定子数组,然后返回新数组

如果axis未指定,则数组会先被展开,再删除

如果指定,则会沿着指定轴,删除,obj可以是整数或列表

a=np.arange(1,9).reshape(2,4)
np.delete(a,0,axis=0) #输出结果为

array([[5, 6, 7, 8]])

np.unique(arr, return_index, return_inverse, return_counts) 删除指定数组内的重复元素并返回新一维数组,如果输入数组不是一维的,则会先被展开再去重  

二、数组运算

2.1 位运算

位运算一般使用比较少,基本是在追求极高运算效率的时候执行,因为数值运算,对计算机来说,本质就是位运算,所以直接进行位运算,效率会更高,下面简单介绍数组的位运算,数值的位运算同理

2.1.1 位与

#bitwise_and,位与运算,是二元运算,即将两个相同形状的数组,对应的位置上的数值,分别进行位与运算,最后得出相同形状的数组
a=np.array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
b=np.array([20, 21, 22, 23, 24, 25, 26, 27, 28, 29])

#下面函数即求两个数组的位与运算
np.bitwise_and(a,b)#结果如下
array([ 0,  1,  4,  5,  8,  9, 16, 17, 16, 17])

2.1.2 位或

#bitwise_or,位或运算,是二元运算,即将两个相同形状的数组,对应的位置上的数值,分别进行位或运算,最后得出相同形状的数组
a=np.array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
b=np.array([20, 21, 22, 23, 24, 25, 26, 27, 28, 29])

#下面函数即求两个数组的位与运算
np.bitwise_or(a,b)#结果如下
array([30, 31, 30, 31, 30, 31, 26, 27, 30, 31])

2.1.3 按位取反

#invert,按位取反运算,是一元运算,即将指定数组内每个数值,转为二进制表达方式,并逐位取反,0变成1,1变成0
a=np.array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])

#下面函数即求两个数组的位与运算
np.invert(a)#结果如下
array([-11, -12, -13, -14, -15, -16, -17, -18, -19, -20])

2.1.4 左移

#left_shift,左移位运算,是一元运算,即将指定数组内每个数值,转为二进制表达方式,并逐位向左移动,并在最后一位补充0,比如010,变为100
#一般左移被当做2**n的替代运算
a=np.array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])

#下面函数即左移两位
np.left_shift(a,2)#结果如下,可见数组内每个数值均变为原数值的4倍,因向左移动了两位
array([40, 44, 48, 52, 56, 60, 64, 68, 72, 76])

2.1.5 右移

#right_shift,右移位运算,是一元运算,即将指定数组内每个数值,转为二进制表达方式,并逐位向右移动,并在最左一位补充0,比如010,变为001
#一般右移被当做1/2**n的替代运算,不过一般表示不了小数
a=np.array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])

#下面函数即左移两位
np.right_shift(a,1)#结果如下,可见数组内每个数值均变为原数值的1/2倍,因向右移动了两位
array([5, 5, 6, 6, 7, 7, 8, 8, 9, 9])

2.2 通用函数运算

2.2.1 算数运算函数

函数 说明 示意
np.add(array1,array2) 二元运算,将两个形状相同或满足广播条件的数组,按位逐元素相加

array1=np.arange(10,19).reshape(3,3),array2=np.arange(20,29).reshape(3,3)

np.add(array1,array2)

np.subtract(array1,array2) 二元运算,将两个形状相同或满足广播条件的数组,按位主元素相减

array1=np.arange(10,19).reshape(3,3),array2=np.arange(20,29).reshape(3,3)

np.subtract(array1,array2)

np.multiply(array1,array2) 二元运算,将两个形状相同或满足广播条件的数组,按位主元素相乘

array1=np.arange(10,19).reshape(3,3),array2=np.arange(20,29).reshape(3,3)

np.multiply(array1,array2)

np.divide(array1,array2) 二元运算,将两个形状相同或满足广播条件的数组,按位主元素相除

array1=np.arange(10,19).reshape(3,3),array2=np.arange(20,29).reshape(3,3)

np.divide(array1,array2)

np.reciprocal(array1) 一元运算,对指定数组内的元素,逐个求倒数

array1=np.arange(10,19).reshape(3,3)

np.reciprocal(array1)

np.power(array1,power)

np.power(array1,array2)

二元运算,对指定数组内的元素,逐个求指定power次方

或对array1,按照广播机制,逐个求其对应位置array2的次方

array1=np.arange(10,19).reshape(3,3)

np.power(array1,3)#逐元素求其3次方

np.mod(array1,array2) 二元运算,对array1数组内元素,用array2对应元素求余数

array1=np.arange(10,19).reshape(3,3),array2=np.arange(20,29).reshape(3,3)

np.mod(array1,array2)

2.2.2 数学函数运算

函数 说明 示意
np.sin(array)、np.cos(array)、np.tan(array) 一元运算函数,对指定数组内的元素,逐个求其三角函数对应的值

np.sin(array*np.pi/180)

np.cos(array*np.pi/180)

np.around(array, decimals =  decimal) 一元运算函数,对指定数组内的元素,逐个求其四舍五入值,并保留指定小数点 np.around(array, decimals =  2) #四舍五入并保留2位小数点
np.floor(array) 一元运算函数,对指定数组内的元素,逐个向下取整  
np.ceil(array) 一元运算函数,对指定数组内的元素,逐个向上取整  

2.2.3 统计函数运算

函数 说明 示意
np.amin(array1,axis) 

对指定数组,按照指定轴方向,求每行或每列最小值

如果不指定轴,则求整个数组的最小值

array1=np.arange(10,19).reshape(3,3)

np.amin(array1,1) #求每行最小值

np.amax(array1,axis) 

对指定数组,按照指定轴方向,求每行或每列最大值

如果不指定轴,则求整个数组的最大值

array1=np.arange(10,19).reshape(3,3)

np.amax(array1,1) #求每行最大值

np.ptp(array1,axis)

对指定数组,按照指定轴方向,求每行或每列最大值和最小值的差

如不指定轴,则求整个数组的最大值和最小值的差

array1=np.arange(10,19).reshape(3,3)

np.ptp(array1,1) #求每行最大值与最小值的差

np.percentile(array, percent, axis)

对指定数组,按照指定轴方向,求每行或每列指定百分位数值

如不指定轴,则求整个数组的指定百分位数值

array1=np.arange(10,19).reshape(3,3)

np.percentile(array1,50,1) #求每行50%位的数值

np.median(array, axis =  0)

对指定数组,按照指定轴方向,求每行或每列的中位数(中值)

如不指定轴,则求整个数组的中位数(中值)

array1=np.arange(10,19).reshape(3,3)

np.median(array1,1) #求每行的中位数

np.mean(array, axis =  0)

对指定数组,按照指定轴方向,求每行或每列的算数平均值

如不指定轴,则求整个数组的算数平均值

array1=np.arange(10,19).reshape(3,3)

np.mean(array1,1) #求每行的算数平均值

np.average(array1, axis =  1, weights = array2)

对指定数组,根据在另一个数组中给出的各自的权重计算数组中元素的加权平均值

可指定计算加权平均值的轴方向,如果不指定,则会最终得到整个数组的加权平均值

array1=np.arange(10,19).reshape(3,3)
array2=np.arange(20,29).reshape(3,3)

np.average(array1, weights = array2)

np.std(array1,axis=1)

对指定数组,按照指定轴方向,求每行或每列的标准差

如果不指定轴,则求整个数组的标准差

array1=np.arange(10,19).reshape(3,3)

np.std(array1,axis=1) #求每行的标准差

np.var(array,axis=1)

对指定数组,按照指定轴方向,求每行或每列的方差

如果不指定轴,则求整个数组的方差

array1=np.arange(10,19).reshape(3,3)

np.var(array1,axis=1)  #求每行的方差

2.3 矢量运算

2.3.1 广播机制

广播机制是矢量运算独有的运算机制,一般矢量运算,基本都是对几个数组的相应元素进行运算,但如果两两运算的数组形状不同时,按照原形状,无法进行相应元素运算,此时,便会触发广播机制。

广播机制的本质是,使两个形状不同的数组能进行矢量运算,并且一般计算结果也是我们所希望的。

广播机制的核心原则为:如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符,或其中的一方的长度为1,则认为它们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行,最后得出的数组的形状是输入数组形状的各个维度上的最大值。

即:

  1. 如果两个数组的后缘维度的轴长相等,则进行广播,并在缺失的维度上进行广播。比如arr1的shape为(2,3,4),arr2的shape为(3,4),因为两个数组后缘维数均为(3,4),故广播会在arr2的缺失维度上进行,不断加1,以与arr1在维度1上靠齐,最后两两在相应元素上进行运算
  2. 如果其中一个数组长度为1,则也可以进行广播,并在长度为1的维度上进行广播。比如arr1的shape为(2,3,4),arr2的shape为(2,3,1),则会在arr2的数组长度为1的轴上发生广播。
import numpy as np
#1、当其中一个数组在某维度上有缺失时,即其中一个数组的维数小于另外一个数组
a=np.zeros((3,4),dtype=int)
array([[0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])
b=np.arange(1,5)
array([1, 2, 3, 4])
a+b
array([[1, 2, 3, 4],
       [1, 2, 3, 4],
       [1, 2, 3, 4]])

#2、当其中一个数组在某维度上的长度为1时,即两个数组的维数相同,而后缘维度轴长不同,但是其中一个数组在某维数上的长度为1
a=np.zeros((4,4),dtype=int)
array([[0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])
b=np.arange(1,5).reshape(4,1)
array([[1],
       [2],
       [3],
       [4]])
a+b
array([[1, 1, 1, 1],
       [2, 2, 2, 2],
       [3, 3, 3, 3],
       [4, 4, 4, 4]])

2.3.2 矢量与矢量间运算

矢量与矢量间运算,如果形状相同,则可直接对应位置元素两两进行算术运算即可,如果形状不相同但满足广播机制的条件,则会按照广播机制进行运算,如果也不满足广播机制条件,则无法进行运算

2.3.3 矢量与标量间运算

矢量与标量间的运算,即矢量内每个元素与该标量分别进行算数运算,其实也可以认为是一种特殊的满足广播机制的运算。

三、线性代数相关

函数 说明 示例
np.dot(a, b, out=None) 

求两个数组的点积(即对应元素之间相乘)

如果是一维数组,则求的是两个一维数组的点积

如果是多维数组,则求的是两个多维数组的矩阵积

a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,7]])
np.dot(a,b) #结果如下

array([[37, 40],
       [85, 92]])

np.vdot(a,b)

求两个向量的点积

如果是多维数组,则数组会先被展开,然后再计算点积

a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,7]])
np.vdot(a,b) #输出结果为 130
np.inner(a,b) 求两个一维向量的内积 a=np.array([1,2])
b=np.array([3,4])
np.inner(a,b) #输出结果为 11
np.matmul(a,b)

求两个数组的矩阵积

在求多维数组之间矩阵积时,效果与 dot一样

a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,7]])
np.matmul(a,b) #结果如下

array([[37, 40],
       [85, 92]])

np.linalg.det(a) 求指定矩阵的行列式 a = np.array([[1,2],[3,4]])
np.linalg.det(a) #j结果为 -2
np.linalg.solve(a,b) 求解线性方程组的解

x + y + z = 6,2y + 5z = -4,2x + 5y - z = 27

a=np.array([
    [1,1,1],
    [0,2,5],
    [2,5,-1]
])

b=np.array([
    [6],
    [-4],
    [27]
])

np.linalg.solve(a,b) #输出为:

array([[ 5.],
       [ 3.],
       [-2.]])

np.linalg.inv(arr) 求指定矩阵的逆矩阵 a=np.array([
    [1,1,1],
    [0,2,5],
    [2,5,-1]
])
np.linalg.inv(a)
np.linalg.eig(a) 求指定矩阵的特征值和特征向量  

四、读写操作

有时如果希望将数组保存下来,供下次继续使用,则此时会涉及到对numpy数据类型的读写操作,也即保存和载入的操作,下面会分别进行阐述

函数 说明 示例
np.save(filename,arr)

保存一个数组,将指定数组保存到指定文件内

filename为字符型,保存的文件类型为.npy

a=np.arange(1,5)

np.save('a.npy',a) #或者np.save('a',a),当没有写.npy时会自动添加

np.load(filename) 加载指定npy文件内的数组,一般只会加载一个数组 np.load('a.npy') 
np.savez(filename,arr1,arr2,arr3)

保存多个数组,将指定多个数组保存到指定文件内

filename为字符型,保存的文件类型为.npz

a=np.arange(1,5),b=np.arange(1,15),c=np.arange(20,25)

np.savez('arr.npz',a,b,c=c) #可指定存入数组的名字,便于后续直接取值

np.load(filename)

加载指定npz文件内的数组,可加载多个,加载后,可对结果进行遍历

也可通过存储时指定的数组名进行类字典型的访问

r=np.load('arr.npz')

r['c']

np.savetxt(filename,arr) 以txt格式存储指定数组,一般不常用

a=np.arange(1,5)

np.savetxt('a.txt',a)

np.loadtxt(filename) 加载以txt格式存储的数组数据,一般不常用 np.load('a.txt') 

 

上一篇:leetcode周赛 第 222 场周赛


下一篇:LeetCode_222.完全二叉树的节点个数