NumPy简介
NumPy,是Numerical Python的简称,它是目前Python数值计算中最为重要的基础包,大多数计算包都提供了基于NumPy的科学函数功能。NumPy提供了许多高级的数值编程工具,如:矩阵数据类型、矢量处理,以及精密的运算库。专为进行严格的数字处理而产生。
一.NumPy ndarray:多维数组对象
NumPy 最重要的一个特点是其 N 维数组对象 ndarray,ndarray是一个快速、灵活的大型数据集容器,以 0 下标为开始进行集合中元素的索引。
1.ndarray包含的每一个元素均为相同类型。
2.每一个数组都有一个shape属性,用来表征数组每一维度的数量。
3.每一个数组都有一个dtype属性,用来描述数组的数据类型。
4.ndarray 中的每个元素在内存中都有相同存储大小的区域。
使用array函数接受对象生成数组:
data1 = [1,1.5,2,8,0,1]
arr1 = np.array(data1)
print(arr1)
运行结果:
若没有指定,np.array会自动推断生成数组的数据类型,数据类型被存放在dtype中
print(arr1.dtype)
接收列表:
data2 = [[1,2,3,4],[5,6,7,8]]
arr2 = np.array(data2)
print(arr2)
运行结果:
data2是一个包含列表的列表,所以arr2自动转换为了二维数组。
除了np.array,还有很多其他函数可以创建新数组。
数组生成函数:
函数名 | 描述 |
---|---|
array | 将输入数据(可以是列表、元组、数组以及其他序列)转换为ndarray,如不显式指明数据类型,将自动判断;默认复制所有的输入数据 |
asarray | 将输入转换为ndarray,但如果输入已经是ndarray则不再复制 |
arange | Python内建函数range的数组版,返回一个数组 |
ones | 根据给定形状和数据类型生成全1数组 |
ones_like | 根据所给的数组生成一个形状一样的全1数组 |
zeros | 根据给定形状和数据类型生成生成全0数组 |
zeros_like | 根据所给的数组生成一个形状一样的全0数组 |
empty | 根据给定形状生成一个没有初始化数值的空数组 |
empty_like | 根据所给数组生成一个形状一样但没有初始化数值的空数组 |
full | 根据给定的形状和数据类型生成指定数值的数组 |
full_like | 根据所给的数组生成一个形状一样但内容是指定数值的数组 |
eye,identity | 生成一个N*N特征矩阵(对角线位置都是1,其余位置都是0) |
二.ndarray的数据类型
类型 | 类型代码 | 说明 |
int8、uint8 | i1、u1 | 有符号和无符号的8位(1个字节)整数 |
int16、uint16 | i2、u2 | 有符号和无符号的16位(2个字节)整数 |
int32、uint32 | i4、u4 | 有符号和无符号的32位(4个字节)整数 |
int64、unint64 | i8、u8 | 有符号和无符号的64位(8个字节)整数 |
float16 | f2 | 半精度浮点数 |
float32 | f4或f | 标准的单精度浮点数 |
float64 | f8或d | 标准的双精度浮点数 |
float128 | f16或g | 扩展精度浮点数 |
complex64、complex128、complex256 | c8、c16、c32 | 分别用两个32位、64位或128位浮点数表示的复数 |
bool | ? | 存储True和False值的布尔类型 |
object | O | Python对象类型 |
string_ | S | 固定长度的字符串长度(每个字符1个字节) |
unicode_ | U | 固定长度的unicode长度(每个字符1个字节) |
arr = np.array([1,2,3,4,5])
print(arr.dtype)
float_arr = arr.astype(np.float64)
print(float_arr.dtype)
运行结果:
- 如果把浮点数转换成整数,则小数点后的部分将被消除。
- 如果因为某些原因导致转换类型失败,将会抛出一个ValueError。
三.NumPy数组算术
arr = np.array([[1.,2.,3.],[4.,5.,6.]])
print("arr=")
print(arr)
print("arr*arr=")
print(arr * arr)
print("arr-arr=")
print(arr - arr)
print("1/arr=")
print(1 / arr)
print("arr**0.5=")
print(arr ** 0.5)
运行结果:
同尺寸数组之间比较会产生一个布尔值数组:
arr = np.array([[1.,2.,3.],[4.,5.,6.]])
arr2 = np.array([[0.,4.,1.],[7.,2.,12.]])
print(arr2>arr)
运行结果:
四.基础索引与切片
ndarray对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样。
ndarray 数组可以基于 0 - n 的下标进行索引,切片对象可以通过内置的 slice 函数,并设置 start, stop , step 参数进行,从原数组中切割出一个新数组。
arr = np.arange(10)
arr_slice = slice(2,7,2) # 从索引 2 开始到索引 7 停止,间隔为2
print (arr[arr_slice])
运行结果:
我们也可以通过冒号分隔切片参数 start:stop:step 来进行切片操作
arr = np.arange(10)
arr_slice = arr[2:7:2] # 从索引 2 开始到索引 7 停止,间隔为2
print (arr_slice)
运行结果:
如果你传入一个数值给数组切片,例如arr[3:6] = 10,数值被传递给整个切片:
arr = np.arange(10)
#原来的数组
print(arr)
arr[3:6] = 10
#切片后的数组
print(arr)
运行结果:
当我们改变了数组的切片时,其变化也会体现在原数组上:
arr[3:6] = 10
arr_slice = arr[3:6]
print(arr_slice)
#改变切片的值
arr_slice[1] = 12345
#切片后的数组
print(arr)
运行结果:
五.NumPy 高级索引
整数数组索引
在一个二维数组中,每个索引值对应的元素不再是一个值,而是一个一维数组:
arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(arr[2])
print(arr[0][2])
运行结果:
在二维数组的索引上,我们可以将a[x][y]中x轴看做行,y轴看做列。
对数组进行切片索引:
可以借助切片 : 或 … 与索引数组组合:
a = np.array([[1,2,3], [4,5,6],[7,8,9]])
b = a[1:3, 1:3]
c = a[1:3,[1,2]]
d = a[...,1:]
print(b)
print(c)
print(d)
运行结果:
布尔索引
布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。
x = np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]])
print(x[x>5])
运行结果:
与数学操作类似,数组的比较操作也可以向量化的:
names = np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])
print(names == 'Bob')
print(names != 'Bob')
运行结果:
当要选择三个名字中的两个时,可以对多个布尔值条件进行联合,需要使用数学操作符如&(and)和|(or):
mask = (names == 'Bob') | (names == 'Will')
print(mask)
运行结果:
花式索引
花式索引是NumPy用来描述使用整型数组。
设有一个8*4的数组:
arr = np.empty((8,4))
for i in range(8):
arr[i] = i
print(arr)
运行结果:
也可以通过传递一个包含指明所需顺序的列表或数组来完成:
arr = np.empty((8,4))
for i in range(8):
arr[i] = i
# print(arr)
print(arr[[4,3,0,6]])
运行结果:
六.数组转置和换轴
修改数组形状
函数 | 描述 |
reshape | 不改变数据的条件下修改形状 |
flat | 数组元素迭代器 |
flatten | 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组 |
ravel | 返回展开数组 |
翻转数组
函数 | 描述 |
transpose | 对换数组的维度 |
ndarray.T | 和 self.transpose() 相同 |
rollaxis | 向后滚动指定的轴 |
swapaxes | 对换数组的两个轴 |
arr = np.arange(15).reshape((3,5))
print(arr)
print(arr.T)
运行结果:
对于更高维度的数组,transpose方法可以接收包含轴编号的元组,用于置换轴:
arr = np.arange(16).reshape((2,2,4))
print(arr)
print(arr.transpose((1,0,2)))
运行结果:
在这里可以看做为一个立体坐标轴,将原数组arr利用transpose原样输出的话是arr.transpose((0, 1, 2)),在这里arr.transpose((1,0,2))就是2轴不变,将0轴和1轴互相调换。
ndarray有一个swapaxes方法,该方法接收一对轴编号作为参数,并对轴进行调整用于重组数据:
arr = np.arange(16).reshape((2,2,4))
print(arr)
print(arr.swapaxes(1,2))
运行结果:
七.通用函数:快速的逐元素数组函数
通用函数,ufunc。某些简单函数接收一个或多个标量数值,并产生一个或多个标量结果,而通用函数就是对这些简单函数的向量化封装。
一元通用函数
函数 | 描述 |
abs、fabs | 逐元素地计算整数、浮点数或复数的绝对值 |
sqrt | 计算每个元素的平方根 |
square | 计算每个元素的平方 |
exp | 计算每个元素的自然指数值e^x |
log、log10、log2、log1p | 分别对应:自然对数、对数10为底、对数2为底、log(1+x) |
sign | 计算每个元素的符号值:1(正数)、0(0)、-1(负数) |
ceil | 计算每个元素的最高整数值 |
floor | 计算每个元素的最小整数值 |
rint | 将元素保留到整数位,并保持dtype |
modf | 分别将数组的小数部分和整数部分按数组形式返回 |
isnan | 返回数组中的元素是否是一个NaN,形式为布尔值数组 |
isfinite、isinf | 分别返回数组中的元素是否有限、是否无限,形式为布尔值数组 |
cos、cosh、sin、sinh、tan、tanh | 常规的双曲三角函数 |
arccos、arccosh、arcsin、arcsinh、arctan、arctanh | 反三角函数 |
logical_not | 对数组的元素按位取反 |
二元通用函数
函数 | 描述 |
add | 将数组中对应的元素相加 |
subtract | 从第一个数组中减去第二个数组中的元素 |
multiply | 数组元素相乘 |
divide、floor_divide | 除法或向下圆整除法(丢弃余数) |
power | 对第一个数组中的元素A,根据第二个数组中的相应元素B,计算A^B |
maximum、fmax | 元素级的最大值计算。fmax将忽略NAN |
minimum、fmin | 元素级的最小值计算。fmax将忽略NAN |
mod | 元素级的求模计算(除法的余数) |
copysign | 将第二个数组中的值的符号复制给第一个数组中的值。 |
greater、greater_equal、less、less_equal、equal、not_equal | 执行元素级的比较运算,最终产生布尔型数组。相当于运算符>丶>=丶<丶<=丶==丶!= |
logical_and、logical_or、logical_xor | 执行元素级的真值逻辑运算。相当于运算符&丶|丶^(与或异) |
八.使用数组进行面向数组编程
使用NumPy数组可以使你利用简单的数组表达式完成多种数据操作任务,而无须写些大量循环。这种利用数组表达式来替代显示循环的方法,称为向量化。
假设我们想要对一些网格数据来计算函数sqrt(x ^ 2 + y ^ 2)的值。np.meshgrid函数接收两个一维数组,并根据两个数组的所有(x,y)对生成一个二维矩阵:
points = np.arange(-5,5,0.01)
xs,ys = np.meshgrid(points,points)
z = np.sqrt(xs ** 2 + ys ** 2)
print(z)
运行结果:
将条件逻辑作为数组操作:
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])
result = [(x if c else y)
for x,y,c in zip(xarr,yarr,cond)]
print(result)
运行结果:
numpy.where函数是三元表达式x if condition else y
的向量化版本,上述代码可以通过np.where简单地完成:
result = np.where(cond,xarr,yarr)
print(result)
运行结果:
数学和统计方法:
sum | 沿着轴向计算所有元素的累和,0长度的数组,累和为0 |
mean | 数学平均,0长度的数组平均值为NaN |
std、var | 标准差和方差,可以选择自由度调整(默认分母是n) |
min、max | 最小值和最大值 |
argmin、argmax | 最小值和最大值的位置 |
cumsum | 从0开始元素累积和 |
cumprod | 从1开始元素累积积 |
布尔值数组的方法:
sum函数:可以用于计算布尔值数组中True的个数
arr = np.random.randn(100)
#正值的个数
print((arr > 0).sum())
运行结果:
any函数:检查数组中是否至少有一个True
bools = np.array([False,False,True,False])
print(bools.any())
运行结果:
all函数:检查是否每个值都是True
bools = np.array([False,False,True,False])
print(bools.all())
运行结果:
排序:
Numpy数组可以使用sort方法按位置排序
numpy.sort(a, axis, kind, order)
a: 要排序的数组
axis: 沿着它排序数组的轴,如果没有数组会被展开,沿着最后的轴排序, axis=0 按列排序,axis=1 按行排序
kind: 默认为’quicksort’(快速排序)
order: 如果数组包含字段,则是要排序的字段
arr = np.random.randn(6)
#未排序的数组
print(arr)
arr.sort()
#排序后的数组
print(arr)
运行结果:
唯一值与其他集合逻辑:
unique函数:返回一个无元素重复的数组或列表
ints = np.array([3,3,2,2,1,1,5,5,4,4])
print(np.unique(ints))
运行结果:
其他数组集合操作:
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或y中,但不属于x、y交集的元素 |
九.线性代数
NumPy 提供了线性代数函数库 linalg,该库包含了线性代数所需的所有功能。
常用numpy.linalg函数:
函数 | 描述 |
dot | 两个数组的点积,即元素对应相乘。 |
vdot | 两个向量的点积 |
inner | 两个数组的内积 |
matmul | 两个数组的矩阵积 |
determinant | 数组的行列式 |
solve | 求解线性矩阵方程 |
inv | 计算矩阵的乘法逆矩阵 |
x.dot(y)等价于np.dot(x,y)
x = np.array([[1,2,3],[4,5,6]])
y = np.array([[1,2],[3,4],[7,8]])
print(x.dot(y))
print(np.dot(x,y))
运行结果:
十.伪随机数生成
numpy.random模块对Python内置的random进行了补充,增加了一些用于高效生成多种概率分布的样本值的函数。
函数 | 描述 |
seed | 向随机数生成器传递随机状态种子 |
permutation | 返回一个序列的随机排列,或者返回一个乱序的整数范围序列 |
shuffle | 随机排列一个序列 |
rand | 从均匀分布中抽取样本 |
randint | 根据给定的由低到高的范围抽取随机整数 |
randn | 从均值0方差1的正态分布中抽取样本 |
binomial | 从二项分布中抽取样本 |
normal | 从正态分布中抽取样本 |
beta | 从beta分布中抽取样本 |
chisquare | 从卡方分布中抽取样本 |
gamma | 从伽马分布中抽取样本 |
uniform | 从均匀分布中抽取样本 |
sample = np.random.normal(size = (4,4))
print(sample)
运行结果:
伪随机数是由具有确定行为的算法根据随机数生成器中的随机数种子生成的,
可以通过np.random.seed更改NumPy的随机种子。