NumPy基础

NumPy基础:数组和向量化计算

ndarray:多维数组对象

创建ndarray
import numpy as np
arr=np.array([[1.5,-0.1,3],[0,-3,6.5]])

data1=[1,2,3,4,5]
arr1 = np.array(data1)

# 可以用属性性ndim和shape来确认数组的维度和形状
print(arr1.ndim)
print(arr1.shape)

# 除非特意指定,否则numpy.array会尝试为新建的数组推断出合适的数据类型
print(arr1.dtype)

# 创建指定长度或形状的全0数组
arr2=np.zeros(10)
arr3=np.zeros((3,6))
# 没有任何具体值的数组
arr4=np.empty((2,3,2))
# 创建指定长度或形状的全1数组
arr5=np.ones(10)

# numpy.arange是Python内置的range函数的数组版
# 输出:array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])
np.arange(15)
一些重要的NumPy数组创建函数
  • array:通过推断数据类型或显式地指定数据类型,将输入数据(列表、元组、数组或其他序列类型)转换为 ndarray。默认复制输入数据
  • asarray:将输入转换为 ndarray,如果输入本身就是 ndarray则不再复制
  • arange:类似于 Python 内置的range,但返回的不是列表而是 ndarray
  • Ones:根据给定的形状和数据类型创建一个全1数组
  • ones_like:根据给定数组的形状和数据类型创建一个全1数组
  • Zeros:根据给定的形状和数据类型创建一个全0数组
  • zeros_like:根据给定数组的形状和数据类型创建一个全0数组
  • empty、empty_like:通过分配新内存创建数组,区别于 ones 和 zeros,不填充任何值
  • full:根据给定的形状和数据类型生成指定数值的数组
  • full_ like:根据给定的数组生成一个形状一样但内容是指定数值的数组
  • eye、identity:创建一个正方形N×N的特征矩阵(对角线位置上的值为1,其余位置的值为 0)
ndarray的数据类型
np.array([1,2,3],dtype=np.float64)
# 通过ndarray的astype方法可以将数组从一种数据类型转换或投射成另一种数据类型
arr = np.array([1,2,3,4,5])
# 即使新的数据类型与旧的数据类型相同,调用astype也总会创建一个新的数组(一个数据的备份)
float_arr = np.astype(np.float64)
NumPy数组的运算
# 大小相等的数组之间的任何算术运算都会将运算应用到元素级
arr = np.array([[1,2,3],[4,5,6]])
arr1 = arr*arr
arr2 = arr-arr

# 数组与标量的算术运算会将标量值传播到数组中的各个元素
arr3 = 1/arr
arr4 = arr ** 2

# 大小相同的数组之间的比较会生成布尔值数组
arr5 = arr2>arr1
基本的索引和切片

与列表最重要的区别在于,数组切片是原始数组的视图。这意味着数据不会被复制,视图上的任何修改都会直接反映到源数组上。

arr = np.arange(10)
# 获取索引值
num5 = arr[5]
# 获取切片
arr1 = arr[5:8]
# 赋值切片;该值会自动传播或广播到整个切片
arr[5:8] =12
# 你想得到ndarray切片的副本而非视图,就需要显式地复制数组
arr2 = arr[6:8].copy()
布尔型索引
names=np.array(["huihui","yunyun"])
print(names=="huihui") # 打印 [true,false]

names!="hiuhui"
~(names=="huihui")  # ~对条件求反
花式索引

花式索引(fancy indexing)是一个NumPy术语,是指用整数数组进行索引。

arr=np.zeros((8,4))
for i in range(8):
    arr[i]=i
# array([[0., 0., 0., 0.],
#        [1., 1., 1., 1.],
#        [2., 2., 2., 2.],
#        [3., 3., 3., 3.],
#        [4., 4., 4., 4.],
#        [5., 5., 5., 5.],
#        [6., 6., 6., 6.],
#        [7., 7., 7., 7.]])

arr[[4,3,0,6]]
# array([[4., 4., 4., 4.],
#        [3., 3., 3., 3.],
#        [0., 0., 0., 0.],
#        [6., 6., 6., 6.]])

arr1 = np.arange(32).reshape((8,4))
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [ 8,  9, 10, 11],
#        [12, 13, 14, 15],
#        [16, 17, 18, 19],
#        [20, 21, 22, 23],
#        [24, 25, 26, 27],
#        [28, 29, 30, 31]])

arr1[[1,5,7,2],[0,3,1,2]] # 最终选出的是元组(1, 0)、(5, 3)、(7, 1)和(2, 2)所对应的元素。无论花式索引数组是多少维的,结果总是一维的。
# array([ 4, 23, 29, 10])
数组转置和轴对换

转置是重塑的特殊形式,它返回的是源数据的视图,不会进行任何复制操作。数组不仅有transpose方法,还有一个特殊的T属性:

arr = np.arange(15).reshape((3,5))
# 简单的转置可以使用.T,其实就是进行轴对换
arr1 = arr.T # 5行3列

# 利用numpy.dot计算矩阵内积
arr2 = np.dot(arr.T,arr)

# 另一种做矩阵乘法的方式是使用@中缀运算符
arr3=arr.T @ arr

# darray还有一个swapaxes方法,它需要接收一对轴编号,对换标记的轴以重排数据
arr3 = arr.swapaxes(0,1)

生成伪随机数

numpy.random模块对Python内置的random模块补充了一些函数,用于从多种概率分布中有效地生成整个样本值数组。

# numpy.normal得到一个标准正态分布
samples=np.random.standard_normal(size=(4,4))

# numpy.random.standard_normal等函数使用的是numpy.random模块下的默认随机数生成器,在代码中也可以直接配置生成器
rng = np.random.default_rng(seed=12345)
data=rng.standard_normal((2,3))
  • permutation:返回一个序列的随机排列,或返回一个随机排列的范围
  • shuffle:随机打乱一个序列
  • uniform:从均匀分布中抽取样本
  • integers:从一个由低到高的范围抽取随机整数
  • Standard_normal:从均值为0,标准差为1的正态分布中抽取样本
  • binomial:从二项分布中抽取样本
  • normal:从正态(高斯)分布中抽取样本
  • beta:从beta 分布中抽取样本
  • chisquare:从卡方分布中抽取样本
  • gamma:从gamma分布中抽取样本
  • uniform(0,1):从[0,1)范围的均匀分布中抽取样本

通用函数:快速的元素级数组函数

通用函数(ufunc)是一种对ndarray中的数据执行元素级运算的函数。你可以将其看作简单函数的快速向量化封装器,这些函数接收一个或多个标量值,并生成一个或多个标量值的结果。

# 通用函数用于简单的元素级转换,如numpy.sqrt和numpy.exp:
arr = np.arange(10)
arr1 = np.sqrt(arr) # 计算原始数据平方根
arr2 = np.exp(arr)  # 如果你想计算 e的3次方,你会使用 np.exp(3)。

# 另外一些(如numpy.add或numpy.maximum)接收2个数组(因此也叫二元ufunc)
x = np.random.standard_normal(8)
y = np.random.standard_normal(8)
arr = np.maximum(x,y)

# 虽然并不常见,但有些ufunc的确可以返回多个数组。numpy.modf就是一个例子,它是Python内置函数math.divmod的向量化版本,会返回浮点数数组的小数部分和整数部分:
arr = np.random.standard_normal(7) *5
remainder,whole_part = np.modf(arr)

# ufunc可以接收一个out可选参数,这样就能对存在的数组直接赋值,而不必新建数组:
out = np.zeros_like(arr)
np.add(arr,1)
np.add(arr,1,out=out)
一元通用函数:
  • abs, fabs逐元素地计算整数、浮点数或复数的绝对值
  • sqrt计算各元素的平方根,等价于arr **0.5
  • square计算各元素的平方,等价于arr**2
  • exp计算各元素的自然指数e
  • log、log10、log2、分别为自然对数(底数为e)、底数为10的对数、底数为2的对数
  • log1p和log(1+x)
  • sign计算各元素的符号:1(正数)、0(零)、-1(负数)
  • ceil计算各元素的最大整数值,即大于等于该值的最小整数
  • floor计算各元素的最小整数值,即小于等于该值的最大整数
  • rint将各元素值四舍五入到最接近的整数,保留dtype
  • modf将数组的小数部分和整数部分以两个独立数组的形式返回
  • isnan返回表示“哪些值是NaN(不是一个数值)”的布尔型数组
  • isfinite、isinf分别返回表示“哪些元素是有限的(非inf,非NaN)”和“哪些元素是无限的”的布尔型数组
  • cos、cosh、sin、正则三角函数和双曲三角函数
  • sinh、tan、tanharccos、arccosh、arcsin、arcsinh、arctan、arctanh反三角函数
  • logical_not对数组的元素按位取反,等价于~arr
二元通用函数
  • add在数组中添加相应的元素
  • subtract从第一个数组的元素中减去第二个数组的元素
  • multiply将数组中对应的元素相乘
  • divide、floor_divide除或整除(截断余数)
  • power第一个数组中的各元素以第二个数组中的相应元素做幂次方
  • maximum、fmax逐个元素计算最大值,fmax忽略NaN
  • minimum、fmin逐个元素计算最小值,fmin忽略NaN
  • mod元素级的求模计算(除法的余数)
  • copysign将第二个数组中元素值的符号复制给第一个数组中的元素
  • greater、greater_equal、ess、less_equal,equal、not_equal执行元素级的比较运算,返回布尔型数组。相当于中缀运l算符>、>=、<、<=、==、!=
  • logical_and执行元素级的逻辑与(&)运算
  • logical_or执行元素级的逻辑或(|)运算
  • logical_xor执行元素级的逻辑异或(^)运算

利用数组进行面向数组编程

NumPy数组使你可以将许多种数据处理任务表述为简洁的数组表达式,而无须编写循环。用数组表达式代替循环的做法通常称为向量化。一般来说,向量化数组运算要比等价的纯Python方式快得多,尤其是各种数值计算。

points = np.arange(-5,5,0.01)
xs,ys = np.meshgrid(points,points)
z = np.sqrt(xs ** 2+ys**2)
将条件逻辑表述为数组运算
# numpy.where函数是三元表达式x if condition else y的向量化版本
xarr = np.array([1.1,1.2,1.3.1.4,1.5])
yarr = np.array([2.1,2.2,2.3,2.4,2.5])
cond = np.array([True,False,True,True,False])
resul = [(x if c else y) for x,y,c in zip(xarr,yarr,cond)]

# numpy.where的第二个和第三个参数不必是数组,其中一个或两个可以是标量值
resul1 = np.where( cond,xarr,yarr)
# numpy.where的第二个和第三个参数不必是数组,其中一个或两个可以是标量值
result3 = np.where(cond,2,-2)
result4 = np.where(cond,2,arr)
数学和统计方法
arr = np.random.standard_normal((5,4))
value = arr.sum()
value1 = np.mean(arr)
value2 = np.sum(arr)
# mean和sum等函数可以接收一个axis可选参数,用于计算该轴向上的统计值,最终结果是一个低一维的数组
arr1 = arr.mean(axis=1)
  • SUm对数组中全部或某轴向的元素求和,零长度的数组的和为0
  • mean算术平均数,零长度的数组的 mean 为 NaN
  • std、var标准差和方差
  • min、max最小值和最大值
  • argmin、argmax最小值元素的索引和最大值元素的索引
  • cumSum从0开始的元素累计和
  • cumprod从1开始的元素累计积
布尔型数组的方法
arr = np.random.standard_normal(100)
value = (arr>0).sum()

bools=np.array([False,True,False,True])
bool1=bools.any()
bools=bools.all()
排序
arr = np.random.standard_normal(100)
arr.sort()
# arr.sort(axis=0)对每一列进行排序,arr.sort(axis=1)对每一行进行排序:
arr1 = np.random.standard_normal((5,3))
arr.sort(axis=0)

# 顶级方法numpy.sort返回的是已排序数组的副本(类似于Python的内置函数sorted),而不是就地修改数组。
arr2 = np.array([5,-10,7,1,0,-3])
sorted_arr2 = np.sort(arr2)
唯一化和其他集合逻辑
names = np.array(["Bob","huihui","yunyun"])
# numpy.unique,它用于找出数组中的唯一值并返回已排序的结果:
names1 = np.unique(names)
# numpy.unique和等价的纯Python实现相比较
names2 = sorted(set(names)) # 在大多数场景中,NumPy版本更为快速,并且返回的是NumPy数组而非Python列表
  • unique(x)计算x中的唯一值,并返回有序结果
  • intersect1d(x,y)计算x和y的交集,并返回有序结果
  • union1d(x,y)计算x和y的并集,并返回有序结果
  • in1d(x,y)计算x中的元素是否包含于y,返回布尔型数组
  • setdiff1d(x,y)计算在x中且不在y中的元素差集
  • setxor1d(x,y)计算存在于一个数组中但不同时存在于两个数组中的异或元素集

线性代数

x=np.array([[1,2,3],[4,5,6]])
y = np.array([[6,23],[-1,7],[8,9]])
# NumPy提供了一个用于矩阵乘法的dot函数 
z = x.dot(y) # x.dot(y)等价于np.dot(x, y)

# numpy.linalg中有一组标准的矩阵分解运算以及求逆和求行列式等方法
from numpy.linalg import inv,qr
X=np.random.standard_normal((5,5))
mat = X.T @ X
arr1 = inv(mat)
arr2 = mat @ inv(mat)
常用的numpy.linalg函数
  • diag以一维数组的形式返回方阵的对角线(或非对角线)元素,或将一维数组转换为方阵(非对角线元素为0)
  • top矩阵乘法
  • trace计算对角线元素的和
  • det计算矩阵行列式
  • eig计算方阵的特征值和特征向量
  • inv计算方阵的逆矩阵
  • pinv计算矩阵的Moore-Penrose伪逆
  • qr计算QR分解
  • svd计算奇异值分解(SVD)
  • solve求解线性方程组Ax=b中的x,其中A为一个方阵
  • lstsq计算Ax=b的最小二乘解
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容