这篇笔记是针对numpy的简单使用,所有函数只对经常会用到的参数进行说明,今后这篇笔记也会不断在项目实践的过程中不断修改和补充内容,如果笔记中的内容出现问题,欢迎各位在评论区反映,我会及时修改的!
#定义整形数组
np.array([1,4,2,5,3])
注意numpy智能定义同一类型的数据,如果数据不匹配,Numpy会向上转换
如果希望明确数组的数据类型,可以用dtype关键字:
np.array([1,2,3,4,5],dtype='float32')
#output:array([1.,2.,3.,4.,5.,],dtype='float32)
创造数组
- np.zeros(10,dtype=int) 创建一个长度为10的数组,数组的值都是0
- **np.ones((3,5),dtype=float) ** 创建一个3×5的浮点矩阵,矩阵的值都是1
- np.full((3,5),3.14) 创建一个3×5的浮点型数组,数组值都是3.14
- np.arange(0,20,2) 创建一个线性序列数组,从0开始,到20结束,步长为2(当然还是左闭右开)|结果:array([0,2,4,6,8,10,12,14,16,18])
- np.linspace(0,1,5) 创建一个5个元素的数组,这5个数均匀地分配到0~1 结果:array([0.,0.25,0.5,0.75,1.])
- np.random.normal(0,1,(3,3)) 创建一个3×3的均值为0标准差为1的正态分布的随机数组
- np.random.randint(0,10,(3,3)) 创建一个3×3的[0,10)区间内随机整形数组
- np.eye(3) 创建一个3×3的单位矩阵
- np.empty(3) 创建一个由3个未初始化数组
NUMPY库中数据类型:
名称 | 描述 |
---|---|
bool_ | 布尔型数据类型(True 或者 False) |
int_ | 默认的整数类型(类似于 C 语言中的 long,int32 或 int64) |
intc | 与 C 的 int 类型一样,一般是 int32 或 int 64 |
intp | 用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64) |
int8 | 字节(-128 to 127) |
int16 | 整数(-32768 to 32767) |
int32 | 整数(-2147483648 to 2147483647) |
int64 | 整数(-9223372036854775808 to 9223372036854775807) |
uint8 | 无符号整数(0 to 255) |
uint16 | 无符号整数(0 to 65535) |
uint32 | 无符号整数(0 to 4294967295) |
uint64 | 无符号整数(0 to 18446744073709551615) |
float_ | float64 类型的简写 |
float16 | 半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位 |
float32 | 单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位 |
float64 | 双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位 |
complex_ | complex128 类型的简写,即 128 位复数 |
complex64 | 复数,表示双 32 位浮点数(实数部分和虚数部分) |
complex128 | 复数,表示双 64 位浮点数(实数部分和虚数部分) |
每个数组都至少有以下几种属性:(假设x是一个numpy定义的数组)
属性 | 说明 |
---|---|
x.ndim | x的维度 |
x.shape | x每个维度的大小 |
x.size | x数组的总大小(有几个数字就是几) |
x.dtype | x的数据类型 |
x.itemsize | x每个数组元素字节大小 |
x.nbytes | x数组总字节大小(也就是itemsize×size) |
numpy.random中有种子值功能,使用示范:
import numpy as np
np.random.seed(12345)
x=np.random.randint(3,size=(2,3))#随便定义了一个2×3的数组,如果是三维就是size就是(2,2,5)这样的,一维直接传个数字就可以
x_temp=np.random.randint(3,size=(2,3))
print(x,'\n\n',x_temp)
#输出:
#[[2 1 1]
# [1 0 1]]
#[[2 2 1]
# [2 1 1]]
跟python列表的操作几乎完全相同,大概以下几点:
print(x1)#array[(1,2,3,4,5)]
print(x1[0])#1
print(x1[-1],x1[-2])#5 4
print(x2)#array([[1,2,3],
# [4,5,6],
# [7,8,9]])
print(x2[0,1])#4
print(x2[0])#array[(1,2,3)]
同样,跟列表相同,ndarray可以通过索引修改数值,但是对整形进行浮点型的修改,浮点型会被截断,以下面为例:
x1=np.array([1,2,3],dtype='int8')
x1[0]=3.14
print(x1)#array[(3,2,3)]
这里也是,和python列表操作几乎相同,需要注意的是以下几点:
切片:x[start=0:stop=总列数(维数):step=1]
step可以是负数,这个时候就是倒序,-2表示每隔2个取一次值逆序
stop是维度的大小,从1开始!!!而不是从0开始!!!这里跟取索引不一样
ndaary允许多维度裁切例如:
x1=np.array([[1,2,3],[4,5,6],[7,8,9]]) x1[:1,:3]#array([1,2,3])
跟python列表不一样的一点是:如果你对ndarray数组的切片部分进行修改,那么原来被切片的数组也会被更改,众所周知,python列表的切片属于浅拷贝,而ndarray的切片则是属于深拷贝,切片得到的不是副本而是数组数据的视图
那么怎么创建数组的副本呢?这里用**copy()**方法可以实现
>>> x
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
>>> x_copy=x.copy()
>>> x_copy
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
>>> x_copy[0,0]=5
>>> print(x_copy,x)
[[5 2 3]
[4 5 6]
[7 8 9]] [[1 2 3]
[4 5 6]
[7 8 9]]
可以看到修改了x_copy,但是原来的x并没有改变
下面这个例子演示reshape()的作用:
>>> grid=np.arange(1,10).reshape((3,3))
>>> grid
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
有一点要注意的是reshape中可以传入参数-1,意思是取符合要求的任意值的意思
还有一个np.newaxis,作用是在原来的对应维度基础上再加+1,这里作简要介绍:
>>> import numpy as np
>>> b = np.array([1, 2, 3, 4, 5, 6])
>>> c = b[np.newaxis,:] #也可以写作c = b[np.newaxis]
>>> b.shape
(6,)
>>> c.shape
(1, 6)
>>> c
array([[1, 2, 3, 4, 5, 6]])
>>> b
array([1, 2, 3, 4, 5, 6])
>>> d=b[:,np.newaxis]
>>> d.shape
(6, 1)
>>> d
array([[1],
[2],
[3],
[4],
[5],
[6]])
主要用3个方法,np.concatenate([a,b],axis=沿着a,b的哪个轴排(从0开始算)),np.vstack(竖着排),np.hstack(横着排),np.dstack(沿着高排(第三个维度))
>>> import numpy as np
>>> x=np.array([1,2,3])
>>> y=np.array([4,5,6])
>>> np.concatenate([x,y])
array([1, 2, 3, 4, 5, 6])
>>> z=np.array[7,8,9]
>>> z=np.array([7,8,9])
>>> np.concatenate([x,y,z])#还可以3个一起拼
array([1, 2, 3, 4, 5, 6, 7, 8, 9])#np.vstack(),np.hstack(),np.dstack()使用方法类似
和拼接对应,数组的分裂包括np.split(),np.hsplit(),np.vsplit(),np.dsplit()
可以给上面的函数传入一个索引列表作为分裂的地方,但是注意N个分裂点会得到N+1个子数组
>>> a
array([1, 2, 3, 4, 5, 6])
>>> x1,x2,x3=np.split(a,[2,4])
>>> x1,x2,x3
(array([1, 2]), array([3, 4]), array([5, 6]))
#np.vsplit()横着切示例
>>> b=np.arange(16).reshape(4,4)
>>> b
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
>>> b1,b2=np.split(b,[2])
>>> b1,b2
(array([[0, 1, 2, 3],
[4, 5, 6, 7]]), array([[ 8, 9, 10, 11],
[12, 13, 14, 15]]))
>>> import numpy as np
>>> x=np.arange(4)
>>> x
array([0, 1, 2, 3])
>>> x+1
array([1, 2, 3, 4])
>>> x*2
array([0, 2, 4, 6])
>>> x-1
array([-1, 0, 1, 2])
>>> x**2
array([0, 1, 4, 9], dtype=int32)
>>> x/2
array([0. , 0.5, 1. , 1.5])
>>> x//2
array([0, 0, 1, 1], dtype=int32)
更高级的运算包括积分,微分等可以参加scipy库
**np.abs(x)或者np.absolute(x)**会将x数组每个元素取绝对值后返回(复数是取模)
>>> theta=np.linspace(0,np.pi,3)
>>> theta
array([0. , 1.57079633, 3.14159265])
>>> np.sin(theta)
array([0.0000000e+00, 1.0000000e+00, 1.2246468e-16])
>>> np.cos(theta)
array([ 1.000000e+00, 6.123234e-17, -1.000000e+00])
>>> np.tan(theta)
array([ 0.00000000e+00, 1.63312394e+16, -1.22464680e-16])
>>> np.arcsin(np.sin(theta))
array([0.00000000e+00, 1.57079633e+00, 1.22464680e-16])
>>> np.arccos(np.cos(theta))
array([0. , 1.57079633, 3.14159265])
>>> np.arctan(np.tan(theta))
array([ 0.00000000e+00, 1.57079633e+00, -1.22464680e-16])
指数
>>> x=[1,2,3]
>>> x
[1, 2, 3]
>>> np.exp(x)#e^x
array([ 2.71828183, 7.3890561 , 20.08553692])
>>> np.exp2(x)#x^2
array([2., 4., 8.])
>>> np.power(3,x)#x^3
array([ 3, 9, 27], dtype=int32)
>>> x=[0,0.001,0.1,0.000001]
>>> np.expm1(x)#expm1可以很好处理数字比较小的数组
array([0.00000000e+00, 1.00050017e-03, 1.05170918e-01, 1.00000050e-06])
对数
>>> x=[1,2,4,8]
>>> np.log(x)#ln(x)
array([0. , 0.69314718, 1.38629436, 2.07944154])
>>> np.log2(x)#log2(x)
array([0., 1., 2., 3.])
>>> x=[0,0.001,0.1,0.000001]
>>> np.log1p(x)#log1p()可以很好地处理数字比较小的数组
array([0.00000000e+00, 9.99500333e-04, 9.53101798e-02, 9.99999500e-07])
这里总结一些Numpy通用的函数特性:
在Numpy方法里对默认参数添加out可以指定输出结果存放位置
>>> import numpy as np
>>> x=np.arange(5)
>>> y=np.empty(5)
>>> np.add(x,y,out=y)
array([6.897987e-307, 1.000000e+000, 2.000000e+000, 3.000000e+000,
4.000000e+000])
>>> y
array([6.897987e-307, 1.000000e+000, 2.000000e+000, 3.000000e+000,
4.000000e+000])
运用一个特定的运算然后reduce数组,那么会对这个数组所有元素执行这个特定的运算,直到只剩下一个元素
>>> a=np.arange(1,6)
>>> a
array([1, 2, 3, 4, 5])
>>> np.add.reduce(a)
15
>>> np.multiply.reduce(a)
120
>>> np.add.accumulate(a)#accumulate会记录每一次结果然后存在一个列表里
array([ 1, 3, 6, 10, 15], dtype=int32)
任何通用函数都可以使用outer方法获得两个不同输入组所有元素所有可能组合的函数运算结果,示例:
>>> a=np.arange(1,6)
>>> b=np.arange(1,9)
>>> np.multiply.outer(a,b)
array([[ 1, 2, 3, 4, 5, 6, 7, 8],
[ 2, 4, 6, 8, 10, 12, 14, 16],
[ 3, 6, 9, 12, 15, 18, 21, 24],
[ 4, 8, 12, 16, 20, 24, 28, 32],
[ 5, 10, 15, 20, 25, 30, 35, 40]])
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yYGx7sk9-1593186847714)(C:\Users\lenovo\Desktop\20200305181508573.png)]
NaN安全版本的意思是忽略缺失的值,即浮点型NaN值(None),使用示例:
>>> import numpy as np
>>> a=np.random.random((3,4))
>>> a
array([[0.37707692, 0.86106332, 0.66644271, 0.5394221 ],
[0.76895796, 0.03158724, 0.89165444, 0.14614102],
[0.39874422, 0.49795612, 0.77608353, 0.27810938]])
>>> np.max(a)
0.8916544366477124
>>> np.min(a)
0.031587237141908364
>>> a.sum()
6.233238962862272
>>> a.sum(axis=0)#axis的意思是数组将被折叠的维度
array([1.5447791 , 1.39060668, 2.33418068, 0.96367251])
>>> a.max(axis=1)
array([0.86106332, 0.89165444, 0.77608353])
在第3部分所写的是一元操作,这种向量化操作很好的提升了算法的运算效率(python底层的数据类型是用C封装的,如果用循环的方法给数组每个元素加1,那么每次加1前都会对数组的元素类型进行检查之类没有必要的操作,算法速度非常非常慢甚至是不可接受无法适用的)
广播可以理解成对数组的二元操作
Numpy的广播遵循一系列严格的规则,设定这组规则是为了决定两个数组间的操作:
为了更好的理解,下面给出示例:
>>> import numpy as np
>>> a=np.ones((2,3))
>>> b=np.arange(3)
>>> a
array([[1., 1., 1.],
[1., 1., 1.]])
>>> b#b的维度小,b复制一行,变成[[0,1,2],[0,1,2]]
array([0, 1, 2])
>>> a+b#根据规则1,两个维度数不匹配,那、那么小维度数组的形状将在最左边补1
array([[1., 2., 3.],
[1., 2., 3.]])
再举一个两个数组互相扩大对应维度最终匹配的例子:
>>> a=np.arange(3).reshape((3,1))
>>> b=np.arange(3)
>>> a+b#规则2:如果两个数组的形状在任何一个维度都匹配不上,那么数组的形状会沿着维度为1的维度扩展以匹配另外一个数组的形状
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4]])
运算符 | 对应的通用函数 |
---|---|
& | np.bitwise_and |
| | np,bitwise_or |
^ | np.bitwise_xor |
~ | np.bitwise_not |
== | np.equal |
!= | np.not_equal |
< | np.less |
<= | np.less_equal |
> | np.greater |
>= | np.greater_equal |
>>> a=np.arange(9).reshape((3,3))
>>> a
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> np.count_nonzero(a<6)#计算有多少个元素小于6
6
>>> np.sum(a<6)#跟上面一样,True是1,FALSE是0所以sum等于6
6
>>> np.any(a>8)#有没有元素大于8
False
>>> np.all(a<5)#所有元素小于5
False
>>> np.all(a<10)
True
把布尔逻辑运算符作为掩码,选取对应数组的元素:
>>> mask=a<5
>>> mask
array([[ True, True, True],
[ True, True, False],
[False, False, False]])
>>> a[mask]
array([0, 1, 2, 3, 4])
>>> mask=(a>=5)&(a<=7)#在5到7之间的元素
>>> a[mask]
array([5, 6, 7])
花哨的索引,就是指使用索引数组来进行索引
>>> x=np.random.randint(100,size=10)
>>> x
array([42, 65, 78, 21, 88, 80, 84, 61, 40, 12])
>>> [x[1],x[4],x[3]]
[65, 88, 21]
>>> index=[1,2,3]
>>> x[index]
array([65, 78, 21])
>>> index=np.array([[1,2],[2,1]])
>>> x[index]
array([[65, 78],
[78, 65]])
#找[1,0],[2,1]位置的值
>>> x=x[:9]
>>> x
array([42, 65, 78, 21, 88, 80, 84, 61, 40])
>>> x.resize((3,3))
>>> x
array([[42, 65, 78],
[21, 88, 80],
[84, 61, 40]])
>>> row=[1,2]
>>> col=[0,1]
>>> row=np.array([1,2])
>>> col=np.array([0,1])
>>> x[row,col]
array([21, 61])
np.sort(x,axis=):会返回排好序的数组,axis=1按行排序,axis=0按列排序
np.argsort(x,axis=):会返回排序好数组的索引,axis=1按行排序,axis=0按列排序
结构化数组是ndarray,其数据类型是由一系列命名字段组织的简单数据类型组成。例如:
>>> x = np.array([('Rex', 9, 81.0), ('Fido', 3, 27.0)],
... dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])
>>> x
array([('Rex', 9, 81.), ('Fido', 3, 27.)],
dtype=[('name', 'U10'), ('age', '), ('weight', ')])
x
是一个长度为2的一维数组,其数据类型是一个包含三个字段的结构:
如果您x
在位置1处索引,则会得到一个结构:
>>> x[1]
('Fido', 3, 27.0)
您可以通过使用字段名称建立索引来访问和修改结构化数组的各个字段:
>>> x['age']
array([9, 3], dtype=int32)
>>> x['age'] = 5
>>> x
array([('Rex', 5, 81.), ('Fido', 5, 27.)],
dtype=[('name', 'U10'), ('age', '), ('weight', ')])
结构化数据类型旨在能够模仿C语言中的“结构”,并共享类似的内存布局。它们用于连接C代码和低级操作结构化缓冲区,例如用于解释二进制blob。出于这些目的,它们支持诸如子数组,嵌套数据类型和联合之类的专用功能,并允许控制结构的内存布局。
Numpy数据类型:
字符 | 对应类型 |
---|---|
b | 布尔型 |
i | (有符号) 整型 |
u | 无符号整型 integer |
f | 浮点型 |
c | 复数浮点型 |
m | timedelta(时间间隔) |
M | datetime(日期时间) |
O | (Python) 对象 |
S, a | (byte-)字符串 |
U | Unicode |
V | 原始数据 (void) |
可以参考的一些资料
Numpy中文文档:https://www.numpy.org.cn/
Numpy菜鸟教程:https://www.runoob.com/numpy/numpy-tutorial.html
Numpy英文文档:https://numpy.org/
第一次修改于:2020年6月27日