利用Python进行数据分析学习日志之NumPy入门学习
文章目录
前言
本系列博文为利用 Python 进行数据分析相关工具包的学习,主要包含NumPy、pandas和matplotlib. 学习主要参考莫烦Python网站上面的教程。
一、NumPy是什么?
NumPy是使用Python进行科学计算的基础软件包。除其他外,它包括:
- 功能强大的N维数组对象;
- 精密广播功能函数;
- 集成 C/C+和Fortran代码的工具;
- 强大的线性代数、傅立叶变换和随机数功能。
二、NumPy库的引入
代码如下:
import numpy as np
三、基础知识
3.1 NumPy属性
这里主要介绍数组以及矩阵的相关属性概念,包括维数、形状以及大小。
array = np.array([[1,2,3],[3,2,1]]) #矩阵创建
print('number of dim:', array.ndim) #矩阵维数
print('shape:', array.shape) #矩阵的形状,即行列数
print('size:', array.size) #矩阵的大小,即所含元素个数
3.2 NumPy创建array
3.2.1 数组的创建
a = np.array([ [1,2,3],
[3,2,1] ], dtype=np.int)
print(a.dtype)
上述代码中的dtype用于定义矩阵中元素的维数,默认维数与电脑(或Python)相同
- dtype可设置为np.int32, np.int64, np.float32, np.float64,想要精确一些尽量64,忽略精度可以用32.
3.2.2 生成元素全部为0的矩阵
a = np.zeros((3, 4))
print(a)
上述代码中(3,4)为矩阵的形状,即行列数。
3.2.3 生成元素全部为1的矩阵
a = np.ones((3, 4), dtype=np.int16)
print(a)
3.2.4 生成空矩阵
a = np.empty((3, 4))
print(a)
这里生成的矩阵中并不是空的,实际上其中元素无限接近于0.
3.2.5 生成有序数列或矩阵
a = np.arange(10, 20, 2)
print(a) #[10 12 14 16 18]
上述代码是生成10到20、步长为2的左闭右开的数列,10处缺省时默认为0,步长2缺省时默认为1。
a = np.arange(12).reshape((3,4))
print(a)
#[[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
上述代码中实际上是在生成[0,12)步长为1的数组后,对所得数组调用reshape函数,其具体应用方法参考NumPy v1.19 Manual.
3.2.6 生成一个“线段”
a = np.linspace(1, 10, 20)
print(a)
#[ 1. 1.47368421 1.94736842 2.42105263 2.89473684 3.36842105
# 3.84210526 4.31578947 4.78947368 5.26315789 5.73684211 6.21052632
# 6.68421053 7.15789474 7.63157895 8.10526316 8.57894737 9.05263158
# 9.52631579 10. ]
上述代码生成1到10共计20-1段的数列,即将1-10平均分成19段,首尾分别为1和10,相邻两个数间隔为(10-1)/19。同理,这里也可以用reshape()函数更改其形状。
a = np.linspace(1, 10, 20).reshape((4, -1))
print(a)
#[[ 1. 1.47368421 1.94736842 2.42105263 2.89473684]
# [ 3.36842105 3.84210526 4.31578947 4.78947368 5.26315789]
# [ 5.73684211 6.21052632 6.68421053 7.15789474 7.63157895]
# [ 8.10526316 8.57894737 9.05263158 9.52631579 10. ]]
这里的reshape()函数中的形状(4, -1)即将数组生成行数为4、列数为元素元素总个数除以4的矩阵(当然也可以行数为-1),这里需要注意,确定的行数或列数必须可以被总个数整除。
3.3 NumPy基础运算
3.3.1 加减运算
import numpy as np
a = np.array([10, 20, 30, 40])
b = np.arange(4)
print(a, b)
# [10 20 30 40] [0 1 2 3]
c = a - b
print(c)
#[10 19 28 37]
d = a + b
print(d)
#[10 21 32 43]
3.3.2 次幂运算
不同于大多数语言中用’^'计算次幂,python中次幂运算用‘’表示次幂,即ab表示a的b次幂。
e = b ** 2
print(e)
# [0 1 4 9]
3.3.3 三角函数运算
这里需要调用NumPy中相应的函数,例如调用numpy.sin(x)计算正弦函数sin(x).
f = np.sin(a) #计算a中每个元素的正弦值
print(f)
# [-0.54402111 0.91294525 -0.98803162 0.74511316]
3.3.4 判断array中大于(小于或等于)某一个值的元素个数
print(b<=3)
# [ True True True True]
print(b == 2)
# [False False True False]
3.3.5 计算矩阵乘法
数乘即每个矩阵对应元素相乘。点乘需要保证两个矩阵是可以相乘的,即前一个矩阵的列数等于后一个矩阵的行数。其中点乘需要调用NumPy中的dot()函数。
g = np.array([[1, 2], [3, 4]])
#[[1 2]
# [3 4]]
h = np.arange(4).reshape((2, -1))
#[[0 1]
# [2 3]]
M1 = g * h #矩阵数乘,对应元素相乘
#[[ 0 2]
# [ 6 12]]
M2 = np.dot(g, h) #或是M2 = g.dot(h)、或是g @ h,计算矩阵点乘,每行乘以每列对应元素再加和
#[[ 4 7]
# [ 8 15]]
3.3.6 计算矩阵的元素和、判断最大值和最小值
首先看一下对矩阵所有元素进行计算加和、判断最值。
j = np.random.random((2, 4))
print(j)
#[[0.37040613 0.36480597 0.91319211 0.11411096]
# [0.41391197 0.13464011 0.2771767 0.7987852 ]]
print(np.amin(j)) #0.11411095689812578
print(np.amax(j)) #0.913192105329094
print(np.sum(j)) #3.3870291471923597
上述代码生成形状为2行4列的矩阵,其中每个元素为0到1中的随机数。
接下来应用参数axis对矩阵指定行(或列)进行计算和判断。当axis=1时,为每一列;当axis=0时,为每一行。
j = np.random.random((2, 4))
print(j)
#[[0.05339626 0.65814892 0.44381627 0.66499018]
# [0.90859657 0.12559796 0.72829558 0.31055733]]
print(np.amin(j, axis = 0)) #[0.05339626 0.12559796 0.44381627 0.31055733]
print(np.amax(j, axis = 1)) #[0.66499018 0.90859657]
print(np.sum(j, axis = 1)) #[1.82035163 2.07304744]
3.3.6 输出矩阵最大值、最小值的索引
k = np.arange(2, 14).reshape((3, 4))
l = np.random.permutation(k)
print(l)
#[[ 6 7 8 9]
# [10 11 12 13]
# [ 2 3 4 5]]
print(np.argmin(l)) #返回所有元素的最小值的索引
# 8
print(np.argmax(l)) #返回所有元素的最大值的索引
# 7
上述代码中permutation()函数用于改变矩阵中0轴元素的顺序(将原矩阵的行元素打乱顺序),其作用与shuffle()函数相同,但是permutation()不会改变原来的数组,而shuffle()函数是直接在原矩阵的基础上操作。
3.3.7 计算矩阵平均值和中位数
这里均值和中位数的计算可以计算全部元素(axis缺省),也可以计算每列(axis=0)或每行(axis=1)的均值和中位数。
print(np.mean(l, axis=0)) #或l.mean(),计算平均值的第一种方法,
# [6. 7. 8. 9.]
print(np.average(l, axis=1)) #计算平均值的第二种方法
# [ 7.5 11.5 3.5]
print(np.median(l)) #计算矩阵中元素的中位数
# 7.5
3.3.8 计算矩阵逐步累加和相邻元素差值
print(np.cumsum(l)) #计算矩阵中元素逐步累加的过程,第i个值为前i个值的加和
# [ 6 13 21 30 40 51 63 76 78 81 85 90]
print(np.diff(l))
# [[1 1 1] 第i行第j列元素为原矩阵中第i行中第j+1列元素将去第j列元素,所以列数比原矩阵少一
# [1 1 1]
# [1 1 1]]
3.3.9 找出矩阵中非零的元素
print(np.nonzero(k))
#(array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], dtype=int64), array([0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], dtype=int64))
上述nonzero()函数返回的两个列表分别表示矩阵中非零元素的行数和列数,即第0行元素中第0个元素非零,…,第2行元素中第3列元素非零。
3.3.10 对矩阵中的每行元素进行排序
m = np.array([[2, 1], [4, -1]])
print(m)
# [[ 2 1]
# [ 4 -1]]
print(np.sort(m)) #每行单独从下到大进行排序
# [[ 1 2]
# [-1 4]]
3.3.11 矩阵转置
print(np.transpose(m)) #或直接m.T也可以计算转置,注意这里只能是大写的T
# [[ 2 4]
# [ 1 -1]]
print((m.T).dot(m)) #计算矩阵m的转置乘以矩阵m
# [[20 -2]
# [-2 2]]
3.3.12 矩阵截取
print(l)
#[[ 6 7 8 9]
# [10 11 12 13]
# [ 2 3 4 5]]
print(np.clip(l, 5, 11))
# [[ 6 7 8 9]
# [10 11 11 11]
# [ 5 5 5 5]]
矩阵的截取应用的clip(a, a_min, a_max, out=None)函数中a即表示被截取的矩阵,其中所有小于a_min的元素全部变成a_min,大于a_max的元素全部变成a_max,介于二者之间的元素不变,且元素相对位置不变。
3.4 NumPy索引
3.4.1 基础索引
A = np.arange(3, 15)
print(A)
# [ 3 4 5 6 7 8 9 10 11 12 13 14]
print(A[3]) # 6
B = np.arange(3, 15).reshape((3, -1))
print(B)
# [[ 3 4 5 6]
# [ 7 8 9 10]
# [11 12 13 14]]
print(B[2,3]) # 输出矩阵索引为第2行第3列的元素,这里也可以用B[2][3]
# 14
print(B[2]) # 输出矩阵B的索引为2的行,不建议使用
# [11 12 13 14]
print(B[1, :]) #输出矩阵索引为1的行
# [ 7 8 9 10]
print(B[: ,2]) #输出矩阵索引为2的列
# [ 5 9 13]
print(B[1, 0:2] #输出矩阵行索引为1,列索引为0至2的元素,其中0:2为左闭右开,即0,1
# [7 8]
3.4.2 布尔索引
NumPy中可以在取数时,给数组传入一个布尔数组,数组会取出True对应的行。
names = np.array(['Bob', 'John', 'Will', 'Bob', 'Will', 'Bob'])
data = np.random.randn(6, 4)
data
# array([[ 0.38210835, 0.67328158, 0.5573354 , 1.48824932],
# [-0.73506988, 0.67065178, -2.59804042, 0.11707668],
# [ 1.52473778, 1.42407336, -0.48955581, -0.18488492],
# [-0.5666914 , 0.17211688, -0.15428296, -0.17665439],
# [ 0.446389 , -0.13624556, -0.23508981, 0.41386663],
# [ 1.46760403, -1.27354405, -0.01596382, -0.3089944 ]])
names == 'Bob'
# array([ True, False, False, True, False, True])
data[names == 'Bob'] # 取出True对应的行,即第0、3、5行
# array([[ 0.38210835, 0.67328158, 0.5573354 , 1.48824932],
# [-0.5666914 , 0.17211688, -0.15428296, -0.17665439],
# [ 1.46760403, -1.27354405, -0.01596382, -0.3089944 ]])
注1:这里的= =也可以用!=以达到相反的目的,或是在使用= =的前面加上~以示取反;
注2:在结合多个条件生成布尔逻辑值时,需要使用&(and)和 |(or)用以联合条件。
names != 'Bob'
# array([False, True, True, False, True, False])
data[~(names == 'Bob')]
# array([[-0.73506988, 0.67065178, -2.59804042, 0.11707668],
# [ 1.52473778, 1.42407336, -0.48955581, -0.18488492],
# [ 0.446389 , -0.13624556, -0.23508981, 0.41386663]])
mask = (name == 'Bob') | (names == 'John')
# mask = (names == 'Bob') | (names == 'John')
# array([[ 0.38210835, 0.67328158, 0.5573354 , 1.48824932],
# [-0.73506988, 0.67065178, -2.59804042, 0.11707668],
# [-0.5666914 , 0.17211688, -0.15428296, -0.17665439],
# [ 1.46760403, -1.27354405, -0.01596382, -0.3089944 ]])
3.4.3 神奇索引
神奇索引是NumPy中的术语,用于描述使用整数数组进行数据索引。
arr = np.empty((8, 4))
for i in range(8):
arr[i] = i
arr
# 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行元素。
arr[[4, 3, 0, 6]]
# array([[4., 4., 4., 4.],
# [3., 3., 3., 3.],
# [0., 0., 0., 0.],
# [6., 6., 6., 6.]])
当然这里也可以使用负的索引,从尾部进行选择。
arr[[-1, -3]]
# array([[7., 7., 7., 7.],
# [5., 5., 5., 5.]])
还可以根据每个索引元组对应的元素选出一个一维数组。
arr1 = np.arange(12).reshape((3, -1))
arr1
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
arr1[[1, 0], [2, 3]]
# array([6, 3])
上述代码选出数组arr1中索引为(1,2)和(0,3)的元素,生成的为一维数组。
3.4.4 索引的应用
接下来在for循环中使用索引调用矩阵对应的行、列和元素。
for row in B:
print(row) #逐次输出矩阵B的每行元素
# [3 4 5 6]
# [ 7 8 9 10]
# [11 12 13 14]
for col in B.T:
print(col) #逐次输出矩阵B的每列元素
# [ 3 7 11]
# [ 4 8 12]
# [ 5 9 13]
# [ 6 10 14]
for item in B.flat:
print(item)
# 3
# 4
# 5
# 6
# 7
# 8
# 9
# 10
# 11
# 12
# 13
# 14
注:上述代码中B.flat函数是用矩阵B中的元素生成一个迭代器,与其相似的函数是flatten(),flatten是将矩阵做拉直运算,将矩阵按行展开称一个向量
print(B.flatten()) #将矩阵B做拉直运算,形成一个向量
# [ 3 4 5 6 7 8 9 10 11 12 13 14]
B.flatten().shape
# (12,)
四、NumPy对array进行处理
4.1 NumPy中array的合并
在对array进行合并的过程需要注意,array之间的维度要满足条件。
A = np.array([1, 1, 1])
B = np.array([2, 2, 2])
print(np.vstack((A,B))) #将两数组上下合并
# [[1 1 1]
# [2 2 2]]
C = np.vstack((A,B))
print(A.shape, C.shape)
# (3,) (2, 3)
D = np.hstack((A, B)) #将两数组左右合并
print(D)
# [1 1 1 2 2 2]
print(D.shape)
# (6,)
注意,这里NumPy中是不能对向量做转置的,需要将向量转置时可以考虑如下函数。
E = A[:, np.newaxis]
F = A[np.newaxis, :]
print(E)
# [[1]
# [1]
# [1]]
print(F)
# [[1 1 1]]
print(E.shape, F.shape)
# (3, 1) (1, 3)
上述代码中的np.newaxis是对数据加了一个维度。
经过上述”将向量转置“后,我们可以对转置后的两个array进行合并。
E = A[:, np.newaxis]
F = B[:, np.newaxis]
G = np.hstack((E, F))
print(G)
# [[1 2]
# [1 2]
# [1 2]]
下面使用concatenate()函数对array进行合并,它通过调用参数axis可以调用出同vstack和hstack相同的效果。当axis=0时,是按列对array进行合并;当axis=1时,是按行对array进行合并。
H_1 = np.concatenate((E, F, F, E), axis=0)
print(H_1)
# [[1]
# [1]
# [1]
# [2]
# [2]
# [2]
# [2]
# [2]
# [2]
# [1]
# [1]
# [1]]
H_2 = np.concatenate((E, F, F, E), axis=1)
print(H_2)
#[[1 2 2 1]
# [1 2 2 1]
# [1 2 2 1]]
4.2 NumPy中array的分割
A = np.arange(12).reshape((3, 4))
print(A)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
得到矩阵A后,对其做分割处理。首先看一下等分,第一种等分的方法是调用vsplit()和hsplit()函数:
print(np.vsplit(A, 3))
# [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8, 9, 10, 11]])]
print(np.hsplit(A, 2))
# [array([[0, 1],
# [4, 5],
# [8, 9]]), array([[ 2, 3],
# [ 6, 7],
# [10, 11]])]
第二种等分方法是调用split()函数,通过对其参数axis进行赋值而等分矩阵。
print(np.split(A, 2, axis = 1)) #对矩阵A按列分割,等分成2块,axis=1表示行(1)不变
# [array([[0, 1],
# [4, 5],
# [8, 9]]), array([[ 2, 3],
# [ 6, 7],
# [10, 11]])]
print(np.split(A, 3, axis = 0))
# [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8, 9, 10, 11]])]
最后来看一下对矩阵进行不等分割,这里需要用到array_split()函数:
print(np.array_split(A, 3, axis = 1)) # 对列进行不均等分
# [array([[0, 1],
# [4, 5],
# [8, 9]]), array([[ 2],
# [ 6],
# [10]]), array([[ 3],
# [ 7],
# [11]])]
print(np.array_split(A, 2, axis = 0)) # 对行进行不均等分
# [array([[0, 1, 2, 3],
# [4, 5, 6, 7]]), array([[ 8, 9, 10, 11]])]
4.3 NumPy的copy和deep copy
python中我们可以使用is来判断两个对象是否完完全全一样(即同一个实体的两个不同的名字)。示例如下:
a = np.arange(4)
b = a
b is a
# True
d = b
d is a
# True
若二者完完全全一样,此时更改其中一项的值,则另一项也随之变化。
a[0] = 11
print(b)
# array([11, 1, 2, 3])
b[0] = 12
print(a)
# array([12, 1, 2, 3])
d[1:3] = [22, 33]
print(b)
# array([12, 22, 33, 3])
上例说明a, b, d完完全全一致,即三者指向的其实是一个实体(此处有些向C++中的指针)。
如果我们只想将a的值赋给b,而不是改变其中一个也会引起另一个随之变化(即深度复制,deep copy),则此时使用函数copy(),看下面的例子说明:
a = np.arange(4)
print(a)
# [0 1 2 3]
b = a.copy() #deep copy
print(b)
# [0 1 2 3]
a[1] = 44
print(a, b)
# [ 0 44 2 3] [0 1 2 3]
b is a
# False
上个例子中,a.copy()仅仅是将a的值赋给b了,二者是不同的实体。
五、通用函数
通用函数是对简单函数(接收一个或多个标量数值,并产生一个或多个标量结果的函数)的向量化封装。通用函数分为一元通用函数和二元通用函数,一元通用函数指的是接收一个数组,而二元通用函数指的是接收两个数组的函数。例如numpy.maximum(x, y)是逐个元素地将x和y中对应元素的最大值计算出来。
也有一些通用函数返回的是多个数组,比如modf,它返回一个浮点值数组的小数部分和整数部分。
下面两张表展示常见的一元通用函数和二元通用函数。这里略去了简单常见的函数。
一元通用函数名 | 描述 |
---|---|
ceil | 计算大于等于给定数值的最小整数 |
floor | 计算小于等于给定数值的最大整数 |
rint | 将元素保留至整数位,并保持dtype |
isnan | 返回数组中的元素是否是一个NaN,形式为布尔值数组 |
isfinite、isinf | 返回数组中的元素是否有限、无限,形式为布尔值数组 |
logical_not | 对数组的元素按位取反(与~arr效果一致) |
二元通用函数名 | 描述 |
---|---|
subtract | 在第二个数组中减去第一个数组中出现过的元素 |
multiply | 将数组的对应元素相减 |
divide, floor_divide | 除或整除(放弃余数) |
power | 将第二个数组的元素作为第一个数组对应元素的幂次方 |
maximum、fmax | 逐个元素计算最大值,fmax忽略NaN |
minimum、fmin | 逐个元素计算最小值,fmin忽略NaN |
mod | 计算除法的余数 |
copysign | 将第一个数组的符号值改为第二个数组的符号值 |
六、使用数组进行面向数组编程
实际上在3.3 NumPy基础运算介绍的内容也算是利用数组进行面向数组编程的一部分知识,这里做一些补充知识点。
6.1 布尔值数组的方法
在4.3中已经介绍过了布尔值在函数索引中的应用,需要注意的是,布尔值会被强制为1(True)和0(False)。因此,sum函数通常可以用于计算布尔值数组中Ture的个数:
arr = np.random.randn(100)
(arr > 0).sum() #计算正值的个数,这里由于arr是随机生成的,所以大于0的元素的个数不确定
# 51
对于布尔值数组,有两个非常有用的方法any和all。any检查数组中是否至少有一个True,而all函数检查是否每个值否是True。
bools = np.array([False, True, False, True, False])
bools.any()
# True
bools.all()
# False
这些方法也可适用于非布尔值数组,所有非0的元素都会按True处理。
bools = np.array([1, 2, 0, True, 0])
bools.all()
# False
6.2 将条件逻辑作为数组操作
numpy.where函数是三元表达式 x if condition else y 的向量化版本。当所含数据过多时,后者计算效率极低,此时使用where函数可以提高代码运行效率。
下面看一个例子感受一下:
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 = np.where(cond, xarr, yarr)
result
# array([1.1, 2.2, 1.3, 1.4, 2.5])
where在数据分析中的典型用法时根据一个数组来生成一个新的数组。这有些类似于Excel中的ifs函数。
6.3 排序
和Python的内置列表类型相似,NumPy数组可以使用sort方法按位置排序:
arr = np.random.randn(6)
arr
# array([-0.73510737, -1.07927236, 0.53692689, -2.57609325, 0.31806468,
# -0.12499394])
arr.sort()
arr
# array([-2.57609325, -1.07927236, -0.73510737, -0.12499394, 0.31806468,
# 0.53692689])
对于多维数组,可以根据传奇的axis值,沿着轴向对每个一维数据段进行排序。
arr = np.random.randn(3, 4)
arr
# array([[-1.42332168, -0.72633186, 0.80752484, 0.06467022],
# [ 2.63189596, -0.1524498 , 0.83682201, 2.49361032],
# [ 0.76270131, -0.91876434, 0.39171873, -1.06169937]])
arr.sort(1) #axis输入1时,按行对数据进行排列
arr
# array([[-1.42332168, -0.72633186, 0.06467022, 0.80752484],
# [-0.1524498 , 0.83682201, 2.49361032, 2.63189596],
# [-1.06169937, -0.91876434, 0.39171873, 0.76270131]])
顶层的np.sort方法返回的是已经排序好的数组拷贝,而不是对原数组按位置排序。下面的例子计算的是一个数组的分位数,并选出分位数对应的值,这是一种应急的方法:
large_arr = np.random.randn(10000)
large_arr.sort()
large_arr[int(0.05 * len(large_arr))] #百分之五下分位数
# -1.645307313048546
一些与排序相关的其他种类的数据操作(比如根据一张表中的某一列进行排序),也会在后面的pandas中介绍。
6.4 唯一值与其他集合逻辑
NumPy中包含一些针对一维ndarray的基础集合操作。常用的一个方法是np.unique,返回的是一个数组中唯一值排序后形成的数组(返回的是排序后结果):
names = np.array(['Bob', 'John', 'Will', 'Bob', 'Will', 'Bob'])
np.unique(names)
# array(['Bob', 'John', 'Will'], dtype='<U4')
将np.unique和纯Python实现(set)相比较:
set(names)
{'Bob', 'John', 'Will'}
另一个函数np.in1d可以检查一个数组中的值是否在另一个数组中,并返回一个布尔值数组:
values = np.array([3, 2, 4, 2, 1, 2])
np.in1d(values, [3, 4])
# array([ True, False, True, False, False, False])
下表是NumPy中集合函数的列表。
方法 | 描述 |
---|---|
unique(x) | 计算x的唯一值,并排序 |
intersect1d(x, y) | 计算x和y的交集,并排序 |
union1d(x, y) | 计算x和y的并集,并排序 |
in1d(x, y) | 计算x中的元素是否出现在y中,返回一个布尔值数组 |
setdiff1d(x, y) | 差集,在x中却不在y中的x的元素 |
setxors1d(x, y) | 异或集,在x或y中,但不属于x、y交集的元素 |
七、线性代数
线性代数,比如矩阵乘法、分解、行列数等方阵数学,是所有数组类库的重要组成部分。3.3 NumPy基础运算 中讲解了一些矩阵乘积的相关知识,这里讲解NumPy中的linalg包。
numpy.linalg拥有一个矩阵分解的标准函数库,以及其他常用函数,例如求逆和行列式分解,这些函数都是通过在MATLAB和R等其他语言使用的相同的行业标准线性代码库来实现。
下表是最常用的线性代数函数列表:
线性代数函数 | 函数的描述 |
---|---|
dot | 矩阵点乘 |
trace | 计算矩阵的迹 |
det | 计算矩阵的行列式 |
eig | 计算矩阵的特征值和特征向量 |
inv | 计算方阵的逆 |
pinv | 计算矩阵的广义逆(Moore-Penrose逆) |
qr | 计算QR分解 |
svd | 计算奇异值分解(SVD) |
solve | 求解x的线性系统Ax=b,其中A是方阵 |
lstsq | 计算Ax=b的最小二乘解 |
diag | 返回矩阵对角元(数组),或将一维数组转换成方阵,非对角元素为0 |
八、随机抽样
numpy.random模块填补了Python内建的random模块的不足,可以高效地生成多种概率分布下的完整样本值数组。
8.1 伪随机数生成
随机抽样时需要确定随机种子(实际上,不指定随机种子时,系统会根绝时间等信息生成一个随机数),NumPy中可以使用random.seed函数指定随机种子:
np.random.seed(1234)
numpy.random中的数据生成函数使用一个全局随机数种子。为避免全局状态,可以使用numpy.random.RandomState创建一个随机数生成器,使数据独立于其他的随机数状态:
rng = np.random.RandomState(1234)
rng.randn(10)
# array([ 0.47143516, -1.19097569, 1.43270697, -0.3126519 , -0.72058873,
# 0.88716294, 0.85958841, -0.6365235 , 0.01569637, -2.24268495])
8.2 取样相关函数
下表时numpy.random中可用的部分函数。
函数 | 描述 |
---|---|
seed | 向随机数生成器传递随即状态种子 |
permutation | 返回一个序列的随机排列,或者返回一个乱序的整数范围序列 |
shuffle | 随机排列一个序列 |
randint | 根据给定的由低到高的范围抽取随机整数 |
rand | 从均匀分布中抽取样本 |
binomial | 从二项分布中抽取样本 |
randn | 从标准正态分布中抽取样本 |
normal | 从正态(高斯)分布中抽取样本 |
beta | 从beta分布中抽取样本 |
chisquare | 从卡方分布中抽取样本 |
gamma | 从伽马分布中抽取样本 |
uniform | 从均匀[0,1)分布中抽取样本 |
下面看一个生成服从均值为0,方差为0.1的正态分布、形状为(2,3)的随机矩阵的例子。
mu, sigma = 0, 0.1 # mean and standard deviation
s = np.random.normal(mu, sigma, size=(2, 3))
s
# array([[ 0.02986603, 0.13700459, -0.03886263],
# [-0.17914647, -0.00366775, 0.05036309]])
总结
以上就是NumPy基础学习的内容,本文仅仅简单介绍了NumPy的使用,而NumPy提供了大量能使我们快速便捷地处理数据的函数和方法。
注:建议搭配NumPy中文网以及NumPy v1.19 Manual一起学习。