NumPy — 从零到入门
前言
Numpy是一个用于科学计算的包,虽然大多数数据分析工作不需要深入理解NumpPy包,但是精通面向数组的编程和思维方式是成为Python科学计算牛人的一大关键步骤。
一. NumPy库的介绍
1. 简介
NumPy(Numerical Python)是高性能科学计算和数据分析的基础包
它利用不同维度的数组进行数学计算操作。因此该库提供了大量的便于直接使用的库函数,可以很灵活与便捷的帮助研究人员进行数值计算。
目前,它已经在数据分析和机器学习被广泛使用,并拥有以下几个特点:
- 对整组数据进行快速运算的标准数学函数库,无需编写循环,即内置并行运算功能,当系统进行某种计算时,并且有多个核心时,NumPy会自动做并行计算。
- NumPy底层用C语言编写,内部解除了GIL(全局解释性锁),其对数组的操作速度不受python解释器的限制,效率远高于纯python代码。
- 拥有一个类似于列表的、强大的N维数组对象ndarray,它描述了相同类型的元素的集合。并且它还是一个具有矢量运算和复杂广播能力的快速且节省空间的多维数组
- 具有实用的线性代数、傅里叶变换和随机生成函数的功能。
总之,它是一个处理数值型运算效率非常高的包。
2. 安装
安装有两种办法,取其一即可,当然安装两者都行,不过要将python环境和anaconda的环境进行区分,否则很容易发生冲突与混淆。
(1). 安装python “大礼包软件” - anaconda
说到数据分析,很多人会想到安装anaconda,这是一个已经自带集成了很多python数据分析的常用库的软件,它对新手比较友好,不用去自己下载整理各种繁杂的库,当然,除了自带的库,它也支持搜索下载新库,以及改变已下载库的版本,删除库,查询库等等。除了操作库之外,它还拥有很多新功能,它内置自带各种软件如:jupyter notebook、spyder等等,功能很多很全面。
(2). 直接通过python内置库pip进行安装
当然,对于已经很熟悉数据分析的人来说,环境的配置可以变得简洁,直接通过:
pip install numpy
pip install XXX...
...
即把几个常用的库给安装下来了,如果下载爆红遇到Https连接超时time out问题,这里有几种办法:
- 如果你的时间比较充裕,或者观察下载耗费时间不会很长,每次超时爆红,再继续pip运行一遍,你会发现,每次进度条都会比上一次跑的多才断开,重复多次直到下载完成。
- pip安装时加上镜像源,即加上[ -m 镜像源 ] ,具体镜像源,参考我前面一篇博客:镜像源。这种方法有个弊端,就是有些库的版本可能会很陈旧,可能会出现问题。比如:我以前做Django项目时,创建虚拟环境,安装virtualenv,无法进入创建出来的虚拟环境中去。然而卸载掉后,安装官方版本后,没有出现任何问题。
- 对于有条件的人,可以选择买个VPN,挂着梯子下载库,因为服务器本身就在国外,然后你就会发现,几十分钟的库,几分钟甚至几十秒就下载完成了。
3. 性能对比
numpy中的数组对象为:ndarray。n是n个、多个的意思;d是dimension,表示维度;array则为数组的意思。
跟它比较类似为python中的list,我们先来看看ndarray和list的结构:
list_test = [1,2,3,4]
array_test = np.array([1,2,3,4])
display(list_test, array_test)
display(type(list_test), type(array_test))
结果:
数组array和列表list外形很相似,但是数据分析为什么要用到array,而不是直接使用list呢?
我们来进行下性能测试:
import numpy as np
import time
# 列表计算花费时间
t1_list = time.time()
con_list = []
for i in range(100000):
con_list.append(i**2)
t2_list = time.time()
t_spend_list = t2_list - t1_list
# array计算花费时间
t1_numpy = time.time()
con_array = np.arange(100000) ** 2
t2_numpy = time.time()
t_spend_numpy = t2_numpy - t1_numpy
display(t_spend_list, t_spend_numpy)
测试结果:
4. 内存中的存储形式
列表包含三个属性:列表的类型:列表类;列表的长度:元素个数;列表中的元素地址:指向元素对象的存储位置。每个元素对象包含:类型:该元素的类型;元素:该元素的值。
列表可以存储多个数据类型。
数组包含四个属性:类型:表示元素的属性,即,每个元素应为同一数据类型;数据:按顺序排列着每个元素的值,便于广播;维度和步幅。
综上可以看出,数组的存储结构使其性能大大提高,优于使用列表。
二、创建ndarray对象
在创建对象时,若不指定内部元素的类型,那么函数会自动为这个数组推断出一个较为合适的数据类型。数据类型保存在一个特殊的dtype属性对象中。所以,一般情况下,在偏差不大时,我们也可以不去指定元素数据类型。
1. array()函数 - 自由创建
它接收一切序列型的对象,比如:列表、元组、可迭代对象等等,当然也包括它自己。
用法:
np.array(序列型对象)
例子:
import numpy as np
n1 = np.array([1, 2, 3]) # 列表
n2 = np.array((4,5,6)) # 元组
n3 = np.array(range(7,10)) # 可迭代对象
# 输出:
array([1, 2, 3])
array([4, 5, 6])
array([7, 8, 9])
2. arange()函数 - 范围创建
在Python中,range()函数,只能接受整型参数。
在Numpy中,arange()函数可以接受数值型等等参数。
用法:
np.arange(start, end, step)
start - 起始,不存在时,默认从0开始
end - 结束,不包括,实质上取到end-1
step - 步长
例子:
import numpy as np
# 数值型
np.arange(10, 13, 1) # 整型
np.arange(3.0) # 浮点型
np.arange(True) # 布尔型
np.arange(4+4j) # 复数型
# 输出:
array([10, 11, 12])
array([0., 1., 2.])
array([0])
array([0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j])
3. random模块 - 随机创建
使用NumPy包中的random模块,它包含很多函数可以创建基于随机的数组。
具体函数可以参考:np.random模块的使用
用法:
np.random.randint(start, end, size)
start - 随机范围的下边界
end - 随机范围的上边界
size - 随机结果的形态
例子:
n1 = np.random.randint(5, 15, size=(4, 4))
# 输出:
array([[12, 11, 14, 6],
[ 5, 6, 13, 13],
[ 8, 14, 13, 12],
[ 8, 11, 10, 6]])
4. repeat()函数 - 复制创建
将输入值的整体或某部分,在原来的基础上,进行指定次数的复制,从而创建新的输出值。
用法:
np.repeat(a, repeats, axis=None)
a - array-like
repeats - 重复次数
axis - 执行方向
例子:
x = np.array([[1,2],[3,4]])
np.repeat(x, [1, 2], axis=0)
# 结果
array([[1, 2],
[3, 4],
[3, 4]])
5. full()函数 - 填充创建
指定输出的形状,再指定一个数填充入该结构中,输出该结果。
用法:
np.full(shape, fill_value, dtype=None, order='C')
shape - 列表或元祖表现的多维数组
fill_value - 填充值,只能为数值型
dtype - 指定填充值的数据类型
order - C或者F,是否将多维数组以C或者Fortrain的形式存在内存中。默认为C
例子:
np.full((2, 2), np.inf)
# 结果
array([[ inf, inf],
[ inf, inf]])
6. ones()、zeros() - 自动填充创建
指定形状,函数会直接自动填充内部值。
用法:
np.ones(shape, dtype=None, order='C')
np.zeros(shape, dtype=None, order='C')
# ones_like(a, dtype=None, order='K', subok=True)
# zeros_like(a, dtype=None, order='K', subok=True)
shape - 列表或元祖表现的多维数组
dtype - 指定填充值的数据类型
order - C或者F,是否将多维数组以C或者Fortrain的形式存在内存中。默认为C
例子:
a = np.ones((3, 3))
b = np.zeros((2,2))
print(a)
print(b)
# 打印
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
[[0. 0.]
[0. 0.]]
7. empty() - 内存创建
该函数值分配数组大小内存,而不产生实际值。具有相同效果的还有有empty_like()函数。
用法:
np.empty(shape, dtype=None, order='C')
# np.empty_like(prototype, dtype=None, order=None, subok=None)
shape - 列表或元祖表现的多维数组
dtype - 指定填充值的数据类型
order - C或者F,是否将多维数组以C或者Fortrain的形式存在内存中。默认为C
例子:
a = np.empty((3,3))
print(a)
print(a[0]) # 值为0
# 打印
[[0.00000000e+000 0.00000000e+000 0.00000000e+000]
[0.00000000e+000 0.00000000e+000 2.41104035e-321]
[1.37962320e-306 1.29060870e-306 2.22518251e-306]]
[0. 0. 0.]
认为empty()和empty_like()结果的值为0是不正确的,因为很多情况下,它返回的是未初始化的垃圾值。
8. eyes() - 对角创建
创建一个类单位矩阵,即对角线上为1,其余为0的数组。指定形状即可创建。
用法:
np.eye(N, M=None, k=0, dtype=float, order='C')
N - 输出的行数
M - 输出的列数。如果为空,默认大小等于N
k - 设定对角线索引位置。默认为主对角线,即0。正值,是上对角线;负值是下对角线。
dtype - 指定填充值的数据类型
order - 在内存中存储是否以行为主的C风格或者以列为主的Fortran风格
例子:
a = np.eye(5, k=-2)
b = np.eye(5, k=2)
print(a) # 右移两格
print(b) # 左移两格
# 打印
[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]]
[[0. 0. 1. 0. 0.]
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
三、ndarray的属性
属性为该对象的变量,而不是函数,无需加括号
1. dtype
(1). 查看数组类型
import numpy as np
n1 = np.array([1, 3, 5])
n1.dtype
# 结果
dtype('int32')
# window系统默认int32
(2). 修改数组类型
该属性可以进行修改,方法如下:
第一种:通过函数内置参数去修改,比如array函数中的dtype
import numpy as np
n1 = np.array([1, 3, 5], dtype=np.int64)
n1.dtype
# 结果
dtype('int64')
第二种:通过自身属性去修改
import numpy as np
n1 = np.array([1, 3, 5], dtype=np.int64)
n1.dtype
# 结果 dtype('int64')
# 第二种
n2 = n1.astype(np.int32)
# 有返回值,不改变原数组类型
# 无论如何都会拷贝一份新数组
# 第三种
# a.dtype = 'int32' 或 np.int32
# 无返回值,直接修改原数组类型
n2.dtype
# 结果
dtype('int32')
(3). 数组的常用数据类型:
类型 | 类型代码 | 说明 |
---|---|---|
int8, uint8 | i1, u1 | 有符号和无符号的8位(1个字节)整型 |
int16, uint16 | i2, u2 | 有符号和无符号的16位(2个字节)整型 |
int32, uint32 | i4, u4 | 有符号和无符号的32位(4个字节)整型 |
int64, uint64 | i8, u8 | 有符号和无符号的64位(8个字节)整型 |
float16 | f2 | 半精度浮点数 |
float32 | f4 或 f | 标准的单精度浮点数。与C的float兼容 |
float64 | f8 或 d | 标准的双精度浮点数。与C语言的double和python的float对象兼容 |
float128 | f16 或 g | 扩展精度浮点数 |
complex64, complex128, complex256 | c8, c16, c32 | 分别用两个32位,64位,128位浮点数表示的复数 |
bool | ? | 存储True和False值的布尔类型 |
object | O | python对象类型 |
string_ | S | 固定长度的字符串类型(每个字符一个字节)。例如:要创建一个长度为10的字符串,应使用S10 |
unicode_ | U | 固定长度的Unicode类型(字节数由平台决定)跟字符串的定义方式一样 |
NumPy比Python内置的数据类型多得多,这是为了能够高效处理海量数据而设计的。例如:int8数据类型比默认int64数据类型更节省内存空间。
注意: 浮点数(如float32和flost64)只能表示近似的分数值。在复杂计算中,可能会积累一些浮点错误,因此比较操作只能在一定小数位以内有效。
2. size
获取数组中元素总数
import numpy as np
n1 = np.array([[1, 3, 5], [2, 4, 6]])
n1
# 结果
array([[1, 3, 5],
[2, 4, 6]])
n1.size
# 结果 6
3. ndim
获取数组的维度
import numpy as np
n1 = np.array([[[1, 3, 5], [2, 4, 6]]])
n1
# 结果
array([[[1, 3, 5],
[2, 4, 6]]])
n1.ndim
# 结果
3
4. shape
获取数组的形状
import numpy as np
n1 = np.array([[[1, 3, 5], [2, 4, 6]]])
n1.shape
# 结果,返回一个元祖。一块,每块2行3列
(1, 2, 3)
对于形状改变的操作,可见下面第五章。
5. itemsize
数组中每个元素所占的字节大小
import numpy as np
n1 = np.array([[[1, 3, 5], [2, 4, 6]]])
n1.itemsize
# 结果。默认元素类型int32,一个字节8位,则占32/8=4个字节
4
四、 数组对象的操作
1. 基本操作
1.1 运算
数组不用编写循环,即可对数据执行批量操作。这通常就叫做矢量化(vectorization)。数组之间的任何算术运算,都会将运算运用到元素级。
(1). 相等形状数组间,加减乘除四则运算
arr1 = np.array([1, 2, 3, 4])
arr2 = np.array([2, 2, 5, 5])
print(arr1+arr2)
print(arr1-arr2)
print(arr1*arr2)
print(arr1/arr2)
# 打印
[3, 4, 8, 9]
[-1, 0, -2, -1]
[ 2,4, 15, 20]
[0.5, 1., 0.6, 0.8]
(2). 大小不等的数组间的运算
数组大小不等之间的运算叫做:广播(broadcasting),可以参考链接详细了解。
arr1 = np.array([1, 2, 3, 4])
arr3 = np.array([4])
print(arr1+arr3)
print(arr1-arr3)
print(arr1*arr3)
print(arr1/arr3)
[5, 6, 7, 8]
[-3, -2, -1, 0]
[ 4, 8, 12, 16]
[0.25, 0.5, 0.75, 1. ]
1.2 删除
用法:
np.delete(arr, obj, axis=None)
arr - 待操作的数组
obj - 待删除的元素的索引
axis - 方向。如果“axis”为空,则将“obj”应用于扁平数组。
例子:
arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
# 打印
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
# 删除操作
np.delete(arr, [1,3,5], None)
# 结果
array([ 1, 3, 5, 7, 8, 9, 10, 11, 12])
1.3 插入
用法1:指定位置插入
np.insert(arr, obj, values, axis=None)
arr - 待操作的数组
obj - 待插入的索引位置
values - 待插入的值
axis - 方向。如果“axis”为空,则将“obj”应用于扁平数组。
例子1:
a = np.array([[1, 1], [2, 2], [3, 3]])
# print
array([[1, 1],
[2, 2],
[3, 3]])
# 插入
np.insert(a, 1, 5, axis=1)
# 结果
array([[1, 5, 1],
[2, 5, 2],
[3, 5, 3]])
用法2:向后插入
np.append(arr, values, axis=None)
arr - 待操作的数组
values - 待插入的值
axis - 方向。如果“axis”为空,则将“obj”应用于扁平数组。
例子2:
np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]])
# 结果
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
当轴指定时,values值的形状shape属性必须匹配前面的数组arr
### 1.
# 形状匹配时
np.append([[1, 2, 3], [4, 5, 6]], [[7, 8, 9]], axis=0)
# 结果正确
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
### 2.
# 形状不匹配时
np.append([[1, 2, 3], [4, 5, 6]], [7, 8, 9], axis=0)
# 结果,报错
Traceback (most recent call last):
...
1.4 转换
要想矩阵转列表,可以使用tolist方法:
n1.tolist()
# 输出
[1, 2, 3]
2. 数组对象的索引
2.1. 普通索引
(1) 取单个索引
用法1: n1[行][列](看成2个一维数组法)
注意:这个n[ ][ ]的用法不是严格的表示n[行][列],只是便于记忆。因为我们可以拆开来看:一个二维数组,n[1]表示第二行,此时结果已经是一维数组了,并没有行与列之分,再来个[2],则单纯的指一维数组的索引。
import numpy as np
n1 = np.random.randint(2, 10, size=(4, 4))
n1
# 结果
array([[8, 2, 3, 4],
[3, 5, 3, 9],
[3, 9, 9, 9],
[3, 2, 5, 5]])
n1[1]
# 结果
array([3, 5, 3, 9])
n1[1][2]
# 结果
3
用法2:n1[行, 列](坐标点法)
注意:这个n[ , ]按照坐标点来理解,以点为基准,即行与列一一匹配对应,如(行,列),这样理解后面的列表和切片比较方便。
import numpy as np
n1 = np.random.randint(2, 10, size=(4, 4))
n1
# 结果
array([[8, 2, 3, 4],
[3, 5, 3, 9],
[3, 9, 9, 9],
[3, 2, 5, 5]])
n1[1, 2]
# 结果
3
(2) 取多行索引
import numpy as np
n1 = np.random.randint(2, 10, size=(4, 4))
n1
# 结果
array([[8, 2, 3, 4],
[3, 5, 3, 9],
[3, 9, 9, 9],
[3, 2, 5, 5]])
n1[ [行索引列表] ]:通过索引列表获取几行:
n1[[1,3]]
# 结果 取n1[1], n1[3]
array([[3, 5, 3, 9],
[3, 2, 5, 5]])
n1[ [行索引列表], [列索引列表] ]:每个行与列一一对应
[ , ]内,元素为列表即:多个不同的、无序的(行,列),…(行,列),[ , ]内为切片即:从(行,列)递增到(行,列)。
n1[[1, 3],[0, 2]]
# 结果 取n1[1][0], n1[3][2],等同于坐标点(1, 0)和(0, 2)
array([3, 5])
2.2 布尔索引(条件索引)
定义数组:
import numpy as np
n1 = np.random.randint(2, 10, size=(4, 4))
n1
# 结果
array([[8, 2, 3, 4],
[3, 5, 3, 9],
[3, 9, 9, 9],
[3, 2, 5, 5]])
建立条件:
condition = n1<5
condition
# 结果 小于5为True,否则为False
array([[False, True, True, True],
[ True, False, True, False],
[ True, False, False, False],
[ True, True, False, False]])
条件筛选:
n1[condition]
# 结果 对应索引为True的保留,为False的去除(原n1不变)
array([2, 3, 4, 3, 3, 3, 3, 2])
# 打印
[2 3 4 3 3 3 3 2]
反向条件筛选:
# 使用 ~ 符号表示取反,或者逻辑非 np.logical_not
n1[~condition]
或者
n1[np.logical_not(condition)]
# 结果 对应索引为True的保留,为False的去除(原n1不变)
array([2, 3, 4, 3, 3, 3, 3, 2])
# 打印
[8 5 9 9 9 9 5 5]
其他条件符号:
其中的条件运算可以有:==, !=, >, <, >=, <=, &(与) 和 |(或),同时也有在np模块中,对应的逻辑函数。
n1[(n1>3) & (n1<7)]
# 结果
array([4, 5, 5, 5])
注意:关键字and和or在布尔型数组中无效
2.3 花式索引
选出方形索引区域,使用ix_()函数
例子:
np.ix_([索引1],[索引2],[索引3])
索引的数量与维度对应,并且,每个索引列表内都是一维的。
例子:
arr1 = np.array([[8, 2, 3, 4],
[3, 5, 3, 9],
[3, 9, 9, 9],
[3, 2, 5, 5]])
print(arr1[np.ix_([0,2],[1,3])])
# 打印
[[2 4]
[9 9]]
3. 数组对象的切片
切片只能针对用法二:n1[行, 列]
import numpy as np
n1 = np.random.randint(2, 10, size=(4, 4))
n1
# 结果
array([[7, 4, 3, 6],
[8, 3, 3, 5],
[2, 5, 4, 7],
[6, 8, 4, 8]])
n1[0:2, 1:3]
# 结果,取第1,2行的第2,3列。注意与n1[[0,1],[1,2]]行列映射的区别
array([[4, 3],
[3, 3]])
取一列:
n1[:, 1]
# 结果 取第一列
array([4, 3, 5, 8])
为什么切片对方法一得不到结果?:
结果会不同,因为前面讲过,[][]这不是真正意义上的[行][列],只是人们便于记忆而错误习惯这样理解,而是应该分开来看,使用连续的中括号 - [][]指定一个值时,应该是n[行][索引];指定多行时,应该是[行][行],而不是[行][列]。
n1 = np.random.randint(2, 10, size=(4, 4))
n1
# n1结果
array([[5, 9, 2, 6],
[9, 6, 3, 2],
[8, 3, 5, 7],
[6, 9, 7, 8]])
切片:
n1[1:3][1:3]
结果:
array([[8, 3, 5, 7]])
如何理解呢?
就像我前面讲的,分开来看,并且结果指多行,对应上面的原理,应该是[行][行],理解如下:
第一步:
n2 = n1[1:3]
n2
# 结果,取出1,2行 (从0行开始)
array([[9, 6, 3, 2],
[8, 3, 5, 7]])
第二步:
n2[1:3]
# 结果,取出1,2行,但是2行没有,则只取出第1行 (从0行开始)
array([[8, 3, 5, 7]])
4. where条件逻辑函数
前面使用过条件逻辑表达式,但是还有一种,在处理复杂度高的条件时,更为简便的方法。
import numpy as np
n1 = np.random.randint(2, 10, size=(4, 4))
n1
# 结果
array([[7, 4, 3, 6],
[8, 3, 3, 5],
[2, 5, 4, 7],
[6, 8, 4, 8]])
(1). 使用条件表达式替换值(改变原数组)
n1[n1>5] = 0
n1
# 结果
array([[0, 4, 3, 0],
[0, 3, 3, 5],
[2, 5, 4, 0],
[0, 0, 4, 0]])
(2). 使用where函数来替换值(不改变原数组)
np.where(condition, x, y)
condition - 判断条件,或者布尔掩码(布尔索引)
x - 替换成为的值
y - 待替换的数组
若无x和y,则直接返回条件判断结果的索引
np.where([[True, False], [True, True]],
[[1, 2], [3, 4]],
[[9, 8], [7, 6]])
# 结果
array([[1, 8],
[3, 4]])
5. 去掉缺失值
在函数前使用波浪号~,表示"反义"
arr = np.array([1,2,3,np.nan,4,5,6,np.nan,9])
arr
# 打印arr
array([ 1., 2., 3., nan, 4., 5., 6., nan, 9.])
arr[~np.isnan(arr)]
# 结果
array([1., 2., 3., 4., 5., 6., 9.])
6. 去除重复值
对重复的值,删减保留唯一一项
有对应函数,可以直接删除多余项
np.random.seed(3)
n1 = np.random.randint(0,15,size=6)
n1
# 打印
array([10, 8, 9, 3, 8, 8])
rs = np.unique(n1)
rs
# 打印
array([ 3, 8, 9, 10])
7. 去除所有重复值
对重复的值,全部删除
无对应函数,需要手动实现
np.random.seed(45)
n1 = np.random.randint(0,15,size=(4,4))
n1
# 打印 n1
array([[11, 14, 3, 12],
[ 0, 13, 5, 3],
[ 4, 9, 8, 1],
[14, 5, 9, 6]])
# un表示所有值的数量
un = np.unique(n1, return_counts=True)
# 去除所有重复值,方法1
un[0][un[1]==1]
# 去除所有重复值,方法2
np.array(set(n1.flatten().tolist()))
五、 数组形状的操作
1. reshape方法和resize方法
import numpy as np
n1 = np.arange(12)
n1
# 结果
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
(1). reshape方法
reshape的参数值之积等于一维参数值,例如下面的3*4 = 12
# 或n1.reshape(3, -1),-1代表贪婪填充,可取的最大值
n1.reshape(3, 4)
# 结果
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
再次打印n1时, n1不改变:
n1
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
reshape有返回值,不改变n1的原值
(2). resize方法
n1.resize(3, 4)
# 结果
无
再次打印n1,n1改变:
n1
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
resize无返回值,直接改变n1原值
2. flatten方法和ravel方法
import numpy as np
n1 = np.random.randint(10,size=(4,4))
n1
# 结果
array([[8, 6, 0, 6],
[5, 1, 2, 4],
[9, 5, 9, 2],
[9, 5, 4, 1]])
(1). flatten方法
n1.flatten()
# 结果
array([8, 6, 0, 6, 5, 1, 2, 4, 9, 5, 9, 2, 9, 5, 4, 1])
再次打印n1:
n1
array([[8, 6, 0, 6],
[5, 1, 2, 4],
[9, 5, 9, 2],
[9, 5, 4, 1]])
(2). ravel属性
n1.ravel()
# 结果 同上
array([8, 6, 0, 6, 5, 1, 2, 4, 9, 5, 9, 2, 9, 5, 4, 1])
再次打印n1,同上:
n1
array([[8, 6, 0, 6],
[5, 1, 2, 4],
[9, 5, 9, 2],
[9, 5, 4, 1]])
区别:
n1.flatten()[0] = 100
n1
# 不改变原数组的值,重新拷贝一份
array([[8, 6, 0, 6],
[5, 1, 2, 4],
[9, 5, 9, 2],
[9, 5, 4, 1]])
n1.ravel()[0] = 100
n1
# 改变原数组的值,浅拷贝
array([[100, 6, 0, 6],
[5, 1, 2, 4],
[9, 5, 9, 2],
[9, 5, 4, 1]])
flatten和ravel都有返回值
,ravel是浅拷贝,它的地址还是指向原来的数组,改变任意一方,都会受影响;flatten是深拷贝,它已经被分配了新的地址,所以改变自身的值,原值不受影响。
3. 数组的拼接
(1). vstack:垂直堆叠
v是vertical的英文单词缩写,是垂直的意思,所以是进行上下垂直方向
上的堆叠,即:垂直堆叠。按照轴的标准看,则是axis=0,即按行拼接
,将每一个水平行都堆叠在一起。那么列数必须相等。(注意理解,这并不矛盾)
import numpy as np
n1 = np.random.randint(10, size=(4, 4))
n2 = np.random.randint(10, size=(1, 4))
display(n1, n2)
# 结果
array([[5, 4, 7, 2],
[7, 6, 4, 3],
[7, 2, 5, 7],
[0, 6, 9, 3]])
array([[0, 8, 4, 1]])
np.vstack([n1, n2])
# 结果
array([[5, 4, 7, 2],
[7, 6, 4, 3],
[7, 2, 5, 7],
[0, 6, 9, 3],
[0, 8, 4, 1]])
(2). hstack:水平堆叠
h是horizontal的英文缩写,表示垂直的意思,所以是进行水平方向
上的堆叠:即水平堆叠。按照轴的标准看,则是axis=1,即按列拼接
,将每一个垂直列都堆叠在一起。那么
行数必须相等。
import numpy as np
n1 = np.random.randint(10, size=(4, 4))
n2 = np.random.randint(10, size=(4, 1))
display(n1, n2)
# 结果
array([[1, 4, 7, 8],
[2, 6, 7, 3],
[9, 0, 1, 4],
[1, 3, 3, 7]])
array([[4],
[4],
[6],
[4]])
np.hstack([n1, n2])
# 结果
array([[1, 4, 7, 8, 4],
[2, 6, 7, 3, 4],
[9, 0, 1, 4, 6],
[1, 3, 3, 7, 4]])
(3). concatenate([], axis)
import numpy as np
n1 = np.random.randint(10, size=(4, 4))
n2 = np.random.randint(10, size=(4, 4))
display(n1, n2)
# 结果
array([[3, 5, 4, 6],
[8, 4, 1, 5],
[8, 7, 6, 9],
[5, 3, 7, 6]])
array([[6, 7, 9, 1],
[4, 1, 9, 7],
[6, 4, 0, 6],
[9, 9, 7, 9]])
np.concatenate([n1, n2])
# 结果 默认axis=0, 从第一层内容对应开始拼接(np.concatenate([n1, n2], axis=0))
array([[3, 5, 4, 6],
[8, 4, 1, 5],
[8, 7, 6, 9],
[5, 3, 7, 6],
[6, 7, 9, 1],
[4, 1, 9, 7],
[6, 4, 0, 6],
[9, 9, 7, 9]])
np.concatenate([n1, n2], axis=1)
# 结果 从第二层内容对应开始拼接
array([[3, 5, 4, 6, 6, 7, 9, 1],
[8, 4, 1, 5, 4, 1, 9, 7],
[8, 7, 6, 9, 6, 4, 0, 6],
[5, 3, 7, 6, 9, 9, 7, 9]])
(4). np.c_[a ,b]
a = np.arange(10).reshape(2, -1)
b = np.repeat(1, 10).reshape(2, -1)
# 打印a,b
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
array([[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]])
np.c_[a,b]
# 结果
array([[0, 1, 2, 3, 4, 1, 1, 1, 1, 1],
[5, 6, 7, 8, 9, 1, 1, 1, 1, 1]])
4. 数组的分割
创建一个 6 * 6 的二维数组:
import numpy as np
n1 = np.random.randint(10, size=(6, 6))
n1
# 结果
array([[9, 1, 9, 5, 7, 9],
[8, 9, 0, 6, 8, 1],
[5, 1, 5, 6, 4, 9],
[3, 2, 1, 9, 8, 8],
[3, 1, 5, 2, 2, 0],
[0, 3, 1, 4, 0, 3]])
(1). hsplit:水平方向分成多个水平子数组
注意:split理解为分离的意思,而不是切割的意思,否则,后面的结果会理解相反。
要想实现水平方向
的分离
,则需要从列方向
进行切割。
- hsplit(ndarray, x), x指定:均匀分成几部分,不可均分则报错
np.hsplit(n1, 2)
# 输出
[array([[9, 1, 9],
[8, 9, 0],
[5, 1, 5],
[3, 2, 1],
[3, 1, 5],
[0, 3, 1]]), array([[5, 7, 9],
[6, 8, 1],
[6, 4, 9],
[9, 8, 8],
[2, 2, 0],
[4, 0, 3]])]
- hsplit(ndarray, [x, y]), 用列表代表分割的索引,不一定要均分
np.hsplit(n1, [2, 4])
# 结果
[array([[9, 1],
[8, 9],
[5, 1],
[3, 2],
[3, 1],
[0, 3]]), array([[9, 5],
[0, 6],
[5, 6],
[1, 9],
[5, 2],
[1, 4]]), array([[7, 9],
[8, 1],
[4, 9],
[8, 8],
[2, 0],
[0, 3]])]
(2). vsplit:分成多个垂直子数组
- vsplit(ndarray, x), x指定:均匀分成几部分,不可均分则报错
np.vsplit(n1, 2)
# 输出
[array([[9, 1, 9, 5, 7, 9],
[8, 9, 0, 6, 8, 1],
[5, 1, 5, 6, 4, 9]]), array([[3, 2, 1, 9, 8, 8],
[3, 1, 5, 2, 2, 0],
[0, 3, 1, 4, 0, 3]])]
- vsplit(ndarray, [x, y]), 用列表代表分割的索引
np.vsplit(n1, [2, 4])
# 结果
[array([[9, 1, 9, 5, 7, 9],
[8, 9, 0, 6, 8, 1]]), array([[5, 1, 5, 6, 4, 9],
[3, 2, 1, 9, 8, 8]]), array([[3, 1, 5, 2, 2, 0],
[0, 3, 1, 4, 0, 3]])]
(3). split / array_split(array, indicate_or_sections, axis)
axis指定按照哪一层进行切割,默认从axis=0、第0层为标准进行切割, 即vsplit方法,将垂直方向分成多个垂直子数组
np.array_split(n1, [1, 4])
# 结果 9, (8, 5, 3), (3, 0) 或(np.arrat_split(n1, [1, 4], axis=0))
[array([[9, 1, 9, 5, 7, 9]]), array([[8, 9, 0, 6, 8, 1],
[5, 1, 5, 6, 4, 9],
[3, 2, 1, 9, 8, 8]]), array([[3, 1, 5, 2, 2, 0],
[0, 3, 1, 4, 0, 3]])]
np.arrat_split(n1, [1, 4], axis=1)
# 结果 9, (1,9,5), (7, 9)
[array([[9],
[8],
[5],
[3],
[3],
[0]]), array([[1, 9, 5],
[9, 0, 6],
[1, 5, 6],
[2, 1, 9],
[1, 5, 2],
[3, 1, 4]]), array([[7, 9],
[8, 1],
[4, 9],
[8, 8],
[2, 0],
[0, 3]])]
5. 数组的转置
转置(transpose)是重塑的一种特殊形式。
import numpy as np
n1 = np.random.randint(10, size=(3, 6))
n1
# 结果
array([[0, 0, 0, 4, 6, 1],
[1, 3, 1, 7, 8, 1],
[6, 7, 2, 8, 2, 0]])
(1). ndarray的 T 属性
n1.T
# 结果
array([[0, 1, 6],
[0, 3, 7],
[0, 1, 2],
[4, 7, 8],
[6, 8, 2],
[1, 1, 0]])
矩阵相乘,内积(线性代数-列行对应,不可直接 *-元素对应 ):
n1.dot(n1.T)
# 结果
array([[ 53, 77, 44],
[ 77, 125, 101],
[ 44, 101, 157]])
(2). transpose方法
用法:
array.transpose()
或
np.transpose(array)
例子:
n1.transpose() # 或 np.transpose(n1)
# 结果
array([[0, 1, 6],
[0, 3, 7],
[0, 1, 2],
[4, 7, 8],
[6, 8, 2],
[1, 1, 0]])
注意: 两个方法类似,不改变原来的数组形状
进行矩阵转置的目的:便于求标准矩阵
(3). swapaxes()方法
接收轴编号,对应轴进行交换
用法:
array.swapaxes(axis1, axis2, axis3)
或
np.swapaxes(array, axis1, axis2, axis3)
例子:
arr1 = np.array([[8, 2, 3, 4],
[3, 5, 3, 9],
[3, 9, 9, 9],
[3, 2, 5, 5]])
arr1.swapaxes(0, 1) # 横轴与纵轴进行交换
# 或者 np.swapaxes(arr1, 0, 1)
# 打印
[[8 3 3 3]
[2 5 9 2]
[3 3 9 5]
[4 9 9 5]]
六、 通用函数
通用函数,即ufunc(unusual function),是一种对ndarray对象中的数据执行元素级运算的函数。可以将其看做简单函数的矢量化包装器。许多ufunc都是简单的元素级变体,如sqrt和exp。
1. 一元函数(unary ufunc)
函数 | 描述 |
---|---|
np.abs()、fabs() | 绝对值,非复数值可以使用更快的fabs() |
np.sqrt() | 开根 |
np.square | 开方 |
np.exp() | 计算e^x |
np.log(), np.log10(), np.log20(), np.log1p() | 求以自然常数e, 10, 20, (1+x)为底的对数 |
np.sign() | 将数组中的值标签化,大于0变1,等于0为0,小于0为-1 |
np.ceil() | 朝着无穷大的方向取整,如3.14变4 |
np.floor() | 朝着无穷小的方向取整,如3.14变3 |
np.rint(), np.round() | 返回四舍五入后的值 |
np.modf() | 将整数和小数分隔开来, 形成两个数组 |
np.isnan() | 判断是否为nan |
np.isinf() | 判断是否是无穷 |
np.isfinite() | 判断是否是有穷 |
cos, cosh, sin, sinh, tan, tanh | 普通型和双曲型三角函数 |
arccos, arccosh, arcsin, arcsinh, arctan, arctanh | 反三角函数和双曲型反三角函数 |
np.logical_not() | 计算元素not x的真值,同~ |
2. 二元函数(binary ufunc)
函数 | 描述 |
---|---|
np.add() | 相加 |
np.subtract() | 相减 |
np.mutiply() | 相乘 (一一对应乘) |
np.dot() | 矩阵内积 (按公式乘) |
np.divide() | 相除 |
np.floor_divide() | 向下圆整除法(丢弃余数) |
np.mod() | 取余 |
np.power(arr,B) | 次方,arr内每个元素的B次方 |
np.greater(), np.greater_equal(), np.less(), np.less_equal(), np.equal(), np.not_equal() | >, >=, <, <=, =, != |
np.logical_and() | & 的函数表达式 |
np.logical_or() | | 的函数表达式 |
np.logical_xor() | ^ 的函数表达式 |
np.copysign() | 将后一个参数符号赋给前一个参数 |
np.ix_() | 生成一个索引器,用于Fancy indexing(花式索引) |
3. 聚合函数 - 数学与统计方法
通过数组上一组数学函数,对整个数组或者某个轴向数据进行统计计算。
下列聚合函数的聚合计算(aggregation,通常叫做约简(reduction))。
既可以当做数组的实例方法调用(如:arr1.sum()),也可以当做顶级Numpy函数使用(如:np.sum(arr1))。并且在使用的时候可以指定具体哪个轴(axis),计算轴方向上的统计结果。
函数 | NAN安全版本 | 描述 |
---|---|---|
np.sum(arr1) | np.nansum() | 计算元素的和 |
np.prod(arr1) | np.nanprod() | 计算元素的积 |
np.mean(arr1) | np.nanmean() | 计算元素平均值 |
np.std(arr1) | np.nanstd() | 计算元素的标准差 |
np.var(arr1) | np.nanvar() | 计算元素的方差 |
np.min(arr1) | np.nanmin() | 获得元素的最小值 |
np.max(arr1) | np.nanmax() | 获得数组中元素的最大值 |
np.argmin(arr1) | np.nanargmin() | 获得数组中最小值的索引 |
np.argmax(arr1) | np.nanargmax() | 获得最大值的索引 |
np.median(arr1) | np.nanmedian() | 获得元素的中位数 |
np.minimum(arr1, arr2) | np.fmin() | 获得多个数组中元素最小值 |
np.maximun(arr1, arr2) | np.fmax() | 获得多个数组中元素最大值 |
np.cumsum() | 元素的逐渐累计和数组 | |
np.cumprod() | 元素的逐渐累计积数组 |
numpy的sum函数比python内置sum函数效率要高,例如:
nums = np.random.rand(1000000)
%timeit sum(nums)
%timeit np.sum(nums)
sum(nums):
np.sum(nums):
4. 布尔函数- any()和all()
产生布尔数组的函数。
np.all(self, axis=None, out=None, keepdims=False)
np.any(self, axis=None, out=None, keepdims=False)
注意: 有self就代表,不仅可以以Numpy函数调用,也可以以数组实例方法调用。
不指定轴axis,则默认为操作所有元素,即变成一维来进行操作。
函数 | 描述 |
---|---|
np.any() | 是否有一个元素为True |
np.all() | 是否所有元素为True |
例子:查看所有数组是否都为0。
np.all(array==0)
or
(array==0).all()
5. 生成函数
部分前面零零散散介绍过了,用法相同。
函数 | 描述 |
---|---|
np.array(x) | 将输入转化为一个矩阵 |
np.arange(start,end,step) | 循环创建矩阵 |
np.ones(n) | 生成n长度的一维全1矩阵 |
np.ones_like() | 形状与参数相同的一维全1矩阵 |
np.zeros(n) | 生成n长度的一维全0矩阵 |
np.zeros_like(n) | 形状与参数相同的一维全1矩阵 |
np.empty(n) | 生成n长度的一维未初始化的矩阵 |
np.eye(n) | 创建一个n * n的单位矩阵 |
np.mershgrid(ndarray, ndarray,…) | 生成一个ndarray * ndarray * …的多维数组 |
np.where(cond,ndarray1,ndarray2) | 根据条件选取ndarray1或ndarray2 |
np.in1d(ndarray,[x,y,…]) | 检查ndarray中的元素是否等于[x,y,…]中的一个,返回bool数组 |
6. 矩阵函数
函数 | 说明 |
---|---|
np.diag(array) | 以一维数组的形式返回方阵的对角线(或非对角线)元素 |
np.diag([x,y,…]) | 将一维数组转化为方阵(非对角线元素为0) |
np.dot(ndarray, ndarray) | 矩阵相乘 |
np.trace(ndarray) | 计算矩阵对角线元素的和 |
np.mat / matrix | 创建矩阵 |
np.bmat(array) | 数组变矩阵 |
matrix.H | 求共轭转置,实部不变,虚部相反 |
matrix.I | 求逆矩阵(不能是奇异矩阵,即不可逆矩阵) |
matrix.T | 求矩阵的转置 |
7. 排序函数
跟Python内置列表类型一样,Numpy数组也可以通过sort方法排序。
函数 | 说明 |
---|---|
np.sort(ndarray) | 排序,返回副本,默认升序 |
np.sort(-ndarray) | 降序排序 |
np.argsort(ndarray) | 返回排序后的下标值 |
sort()函数用法:
np.sort(self, axis=-1, kind='quicksort', order=None)
axis - 沿着那个轴排序。默认为-1,意味着,默认以最内层或最大轴序号为标准排序。
kind - 排序算法,有'quicksort', 'mergesort', 'heapsort', 'stable'。默认为快速排序。
# order - 字符串或字符串列表。制定指定排序顺序列表。
例子:
arr1 = np.random.randint(1, 20, size=12)
print(arr1) # 排序前
arr1.sort()
print(arr1) # 排序后
print(arr1[int(0.05*len(arr1))]) # 5%分位数
# 打印
[19 12 15 7 15 9 9 14 7 19 11 14]
[ 7 7 9 9 11 12 14 14 15 15 19 19]
7
8. 唯一化和集合逻辑
arr1 = np.array([3, 9, 7, 3, 1, 5, 8, 1])
print(np.unique(arr1)) # 唯一值,并排序
print(np.in1d(arr1, [3, 9, 1])) # 包含值,则返回对应布尔值
# 打印
[1 3 5 7 8 9]
[ True True False True True False False True]
函数 | 说明 |
---|---|
np.unique(x) | 排除重复元素,并返回有序结果 |
np.interset1d(x, y) | 返回二者的交集、公共元素,并返回有序结果 |
np.union1d(x, y) | 返回二者的并集,并返回有序结果 |
np.in1d(x, y) | 得到一个"x中的元素是否包含y"的布尔型数组 |
np.setdiff1d(x, y) | 返回二者的差,即在x中而不再y中 |
np.setxor1d(x, y) | 返回二者的对称差,存在与一个数组中,但是不同时存在于两个数组中,简单说就是异或 |
8. 其他补充函数
函数 | 说明 |
---|---|
np.linspace(x, y, n) | 将制定的[x, y]平均分成n份,即等差数列 |
np.take(a, indexs) | 从a中根据下标index提取元素 |
np.apply_along_axis(func1d, axis,arr) | 沿着某个轴执行指定函数(文档有详细例子) |
np.unique(ar, return_index=False, return_inverse=False, return_counts=False, axis=None) | 去除数组中的重复元素 |
七、 数组文件
Numpy能够读写磁盘上的文本数据或二进制数据。
1. 二进制格式保存
默认情况下,数组是以未压缩的原始二进制格式保存在扩展名为.npy的文件中。
读写磁盘数组数据的三个主要函数:
用法:
# 单文件存储,文件结尾:.npy
np.save(file, array, allow_pickle=True, fix_imports=True)
# 多文件压缩存储,文件结尾:.npz
np.savez(file, *args, **kwds)
# 读取
np.load(file, mmap_mode=None, allow_pickle=False, fix_imports=True,
encoding='ASCII')
若文件路径末尾没有主动加上扩展名.npy,则该扩展名会被自动加上。然后就可以通过np.load()读取磁盘上的数组。
例子:
(1). 单文件:
存储:
arr1 = np.array([3, 9, 7, 3, 1, 5, 8, 1])
np.save("my_array", arr1)
读取:
print(np.load('my_array.npy'))
# [3 9 7 3 1 5 8 1]
(2). 多文件:
存储:
arr1 = np.array([3, 9, 7, 3, 1, 5, 8, 1])
arr2 = np.array([1, 2, 3, 4, 5, 6])
np.savez("my_zip", a=arr1, b=arr2)
result = np.load('my_zip.npz')
读取:
print(result['b'])
[1 2 3 4 5 6]
2. 文本格式保存
用法:
# 存储
np.savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='',
footer='', comments='# ', encoding=None)
# np.genfromtxt与np.savetxt类似,只不过是面向结构化数组和缺失数据处理
np.loadtxt(fname, dtype=float, comments='#', delimiter=None,
converters=None, skiprows=0, usecols=None, unpack=False,
ndmin=0, encoding='bytes', max_rows=None)
# savetxt
fname - 取的文件名
X - 数组对象名
fmt - 字符串或者字符串序列,如:(%10.5f),其他复杂格式可参考底层代码。
delimiter - 列分隔符,一般为','逗号分隔
newline - 行分隔符
header - 头注,写在文件开头
footer - 角注,写在文件结尾
comments - 标注符号,写在header和footer前面,默认为'#',也可写成'numpy.loadtxt'等。
encoding - 编码输出文件
# loadtxt
dtype - 输出文件数据类型,默认为float
converters - 一个字典,映射列序号给一个函数,该函数可以解析字符串为目标值
skiprows - 整型。跳过的行,默认为0行
usecols - 整型或者元组序列。主动选择要读取的列。
unpack - 返回被转化过的数组。默认False
ndim - 整型,返回至少该维度的数组
maxrows - 返回'skiprows'行后,读取'maxrows'行后的内容。默认读取所有行。
例子:
arr1 = np.array([3, 9, 7, 3, 1, 5, 8, 1])
np.savetxt("my_txt", arr1)
np.loadtxt('my_txt')
# [3. 9. 7. 3. 1. 5. 8. 1.]
以上参数可以自行尝试,深入了解可以结合官方文档。
八、线性代数
线性代数(如:矩阵乘法、矩阵分解、行列式以及其他方阵数学等)是任何数组库的重要组成部分。不像某些语言(如:MATLAB),通过*对两个二维数组相乘得到的是一个元素级的积,而不是矩阵点积。因此NumPy提供了一个用于矩阵乘法的dot()函数。
例子1:
m行k列的数组 点乘 k行n列的数组 得到一个m行n列的数组。(k必须对应相等)
x = np.array([[1, 2, 3], [4, 5, 6]])
y = np.array([[6, 23], [-1, 7], [8, 9]])
print(x.dot(y))
# np.dot(x, y)
[[ 28 64]
[ 67 181]]
例子2:
多维数组乘以一维数组,结果得到一维数组
np.dot(x, np.ones(3))
# [6., 5.]
NumPy中有一组标准的矩阵分解运算以及诸如求:逆、行列式等。他们跟MATLAB和R等语言所使用的是相同的行业标准级Fortran库,如:BLAS、LAPACK、Inter MKL等等,它也取决于你的Numpy版本。
from numpy.linalg import inv, qr
import numpy as np
X = np.random.randn(5, 5)
mat = X.T.dot(X)
print(inv(mat))
# 逆矩阵
[[ 2.38676625 0.0383446 1.22607032 -1.22301455 1.0457165 ]
[ 0.0383446 0.89091613 -0.85883745 -0.98421099 1.40459633]
[ 1.22607032 -0.85883745 2.17537261 0.88836567 -1.83227867]
[-1.22301455 -0.98421099 0.88836567 2.70466106 -3.56901905]
[ 1.0457165 1.40459633 -1.83227867 -3.56901905 5.19884975]]
result = mat.dot(inv(mat))
print(result)
# 结果为单位矩阵(矩阵 点乘 它的逆矩阵)
[[ 1.00000000e+00 -1.35244046e-16 -4.33027096e-16 -9.40317599e-16
6.35775695e-17]
[-9.61938278e-17 1.00000000e+00 1.45119917e-16 4.27620132e-16
1.34304975e-15]
[-1.96936202e-15 -1.45718601e-15 1.00000000e+00 3.04388831e-15
-1.89553893e-15]
[-7.19491779e-17 -3.02262390e-16 8.72327184e-16 1.00000000e+00
-6.47110058e-16]
[ 1.21385063e-16 -1.67329489e-16 -4.21602789e-16 -2.27367980e-16
1.00000000e+00]]
q, r = qr(mat)
print(r)
# 上三角矩阵
[[-3.61408516 0.84443702 3.54093823 -3.47532695 -0.63147377]
[ 0. -3.6491614 -2.81565423 -7.12586627 -4.94495531]
[ 0. 0. -1.76235213 -5.81463287 -4.72452019]
[ 0. 0. 0. -1.50171095 -1.05653428]
[ 0. 0. 0. 0. 0.14713904]]
print(q)
# 标准正交列矩阵
[[-0.85043878 -0.01382966 -0.41096514 0.16368423 0.28439014]
[-0.05424249 -0.77067525 0.12413786 -0.54821699 0.29523778]
[ 0.4553698 -0.30573961 -0.80115779 0.23297692 0.05504161]
[ 0.09014986 0.53724225 -0.35238216 -0.73203806 0.20782411]
[ 0.24150151 0.15415076 0.22286869 0.28724144 0.88641777]]
常用的np.linalg()函数
函数 | 说明 |
---|---|
diag | 以一维数组的形式返回方阵的对角线(或非对角线)元素,或将一维数组转换为方阵(非对角线元素为0) |
dot | 矩阵乘法 |
trace | 计算对角线元素和 |
det | 计算矩阵行列式 |
eig | 计算方阵的本征值和本征向量 |
inv | 计算方阵的逆 |
pinv | 计算方阵的Moore-Penrose伪逆 |
qr | 计算QR分解 |
svd | 计算奇异值分解(SVD) |
solve | 解线性方程组Ax=b,其中A为一个方阵 |
lstsq | 计算Ax=b的最小二乘解 |
九、随机生成数
numpy.random模块对Python内置的random模块进行了补充,增加了一些用于高效生成多种概率分布的样本值的函数。
例子1:
得到一个符合标准正态分布的4*4样本
samples = np.random.normal(size=(4,4))
# 打印
[[-1.24461343 -0.59702205 0.24199145 -1.91128939]
[ 0.72805342 0.46096565 0.17278008 0.92695652]
[-0.24785401 1.82771813 -0.42215406 0.27845425]
[-0.25153488 -1.71629335 0.50279265 -1.05585743]]
例子2:
比较Python内置random与NumPy模块的random运行速度
from random import normalvariate
N = 1000000
%timeit samples = [normalvariate(0, 1) for _ in xrange(N)]
# 1 loops, best of 3:1.33s per loop
%timeit np.random.normal(size=N)
# 10 loops, best of 3: 57.7ms per loop
部分numpy.random函数:
函数 | 说明 |
---|---|
seed | 确定随机数生成器的种子 |
permutation | 返回一个序列的随机排列 |
shuffle | 对一个序列就地随机排列 |
rand | 产生均匀分布的样本值 |
randint | 给定的上下限范围内随机选取整数 |
randn | 产生正态分布(平均值为0,标准差为1)的样本值,类似于MATLAB接口 |
binomial | 产生二项分布的样本值 |
normal | 产生正态(高斯)分布的样本值 |
beta | 产生Beta分布的样本值 |
chisquare | 产生卡方分布的样本值 |
gamma | 产生Gamma分布的样本值 |
uniform | 产生在[0, 1)中均匀分布的样本值 |
更多具体函数可参考:np.random模块的使用
参考资料与文档
参考:
数据分析三大神器之一:Numpy
修改时间
第一次修改:2020/5/4