1. Numpy介绍
Numpy是python开源的科学计算工具包,具有高级的数值编程工具。它是许多高级工具的开发基础,如后续要介绍的pandas包就是在Numpy的基础上开发来的。学习Numpy我们主要关注3个核心点:
(1)强大的N维数组对象:ndarray
(2)对数组结构数据进行计算(无需遍历循环)
(3)随机数、线性代数、傅里叶变换等功能
2. 创建数组
在介绍如何使用Numpy创建数组之前,我们需要简要说明一下,通常我们使用Numpy包时会使用如下语句进行导入。
import numpy as np
注意:数组与列表的区别,数组的格式:中括号,但是元素之间没有逗号,而列表是有逗号的
使用Numpy创建数组主要有如下几种方式:
(1)使用array()
函数,其中括号内可以是列表、元组、数组、生成器等
ar1 = np.array(['Bob', True, 88, {'age':23}])
ar2 = np.array(('a', 5, True, None))
ar3 = np.array(range(10))
print(ar1) >>>['Bob' True 88 {'age': 23}]
print(ar2) >>>['a' 5 True None]
print(ar3) >>> [0 1 2 3 4 5 6 7 8 9]
(2)使用arange()
函数,类似于range(),在给定间隔内返回均匀间隔的值
print(np.arange(10)) ------------------------------[0 1 2 3 4 5 6 7 8 9]
print(np.arange(0,10,2)) --------------------------[0 2 4 6 8]
print(np.arange(5.0, 13, 3)) ----------------------[ 5. 8. 11.]
print(np.arange(10000)) --------------------------[ 0 1 2 ... 9997 9998 9999]
注意:如果数组太大而无法打印,Numpy会自动跳过数组的中心部分,只打印边角
(3)使用linspace()
函数,返回在间隔[start, stop]上计算的num个均匀间隔样本
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
- start:起始值
- stop:结束值
- num:生成样本数,默认为50
- endpoint:如果为真,则[start, stop]是左闭右闭,否则为左闭右开,默认为左闭右闭
- retstep:如果为真,返回一个包含2个元素的元组,第一个元素为array,第二个为步长实际值,其中步长为样本元素之间的距离
ar1 = np.linspace(10, 20, num=10)
ar2 = np.linspace(10, 20, num=10, endpoint=False)
ar3 = np.linspace(10, 20, num=10, retstep=True)
ar4 = np.linspace(10, 20, num=10, endpoint=False, retstep=True)
print(ar1) >>>[10. 11.11111111 12.22222222 13.33333333 14.44444444 15.55555556 16.66666667 17.77777778 18.88888889 20. ]
print(ar2) >>>[10. 11. 12. 13. 14. 15. 16. 17. 18. 19.]
print(ar3) >>>(array([10. , 11.11111111, 12.22222222, 13.33333333, 14.44444444, 15.55555556, 16.66666667, 17.77777778, 18.88888889, 20. ]), 1.1111111111111112)
print(ar4) >>>(array([10., 11., 12., 13., 14., 15., 16., 17., 18., 19.]), 1.0)
3. Numpy常用的属性
array.ndim:数组的维度/秩,描述的是轴axes的数量
array.shape:数组的行列数,对n行m列的数组,shape为(n,m)
array.size:数组的元素的总个数n*m
array.dtype:数组中元素的类型,类似于type,但是type是函数,dtype是属性/方法
array.itemsize:数组中每个元素的 字节 大小,int32为4字节,float64为8字节
array.data:包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。
import numpy as np
ar = np.array([[1,2,3,4,5], [6, 7, 8, 9, 10]]) #二维数组
print(ar, type(ar)) >>>[[ 1 2 3 4 5] [ 6 7 8 9 10]] <class 'numpy.ndarray'>
print(ar.ndim) >>> 2
print(ar.shape) >>>(2,5)
print(ar.size) >>> 10
print(type(ar), ar.dtype) >>> <class 'numpy.ndarray'> int32
print(ar.itemsize) >>> 4
print(ar.data) >>> <memory at 0x000001EA046502E8>
注意:对于二维数组而言,如果两个列表元素个数不一致,那么此时生成的是一个一维数组
ar1 = np.array([[1,2,3,4], ['a', 'b', 'c', 'd']])
print(ar1, ar1.ndim)
ar2 = np.array([[1,2,3,4], ['a', 'b', 'c', 'd', 'f']])#两个列表元素个数不一致,此时会变成一维数组
print(ar2, ar2.ndim)
------------------------------------
[['1' '2' '3' '4'] ['a' 'b' 'c' 'd']] 2
[list([1, 2, 3, 4]) list(['a', 'b', 'c', 'd', 'f'])] 1
4. 创建特殊数组
(1)创建值全部为0的数组:zeros(), zeros_like(),
np.zeros(shape, dtype=float, order='C')
np.empty(shape, dtype=float, order='C')
print(np.zeros(10))#创建10个数值为0的一维数组
print(np.empty(10))#创建10个数值为0的一维数组
print(np.zeros((3,5)))#创建15个数值为0的二维数组
print(np.zeros((2,5), dtype=np.int))
--------------------------------------------
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
[[0 0 0 0 0]
[0 0 0 0 0]]
np.zeros_like(array, dtype=None, order='K', subok=True, shape=None)
ar = np.array([list(range(5)), list(range(6,11))])
print(ar)
print(np.zeros_like(ar))
-------------------------------------
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[[0. 0. 0.]
[0. 0. 0.]]
[[ 0 1 2 3 4]
[ 6 7 8 9 10]]
[[0 0 0 0 0]
[0 0 0 0 0]]
(2)创建值全部为1的数组:ones(), ones_like()
具体的创建方式与上述创建值全部为0的数组的方式一样
(3)创建一个单位矩阵:eye(),identity()
np.eye(N, M=None, k=0, dtype=<class 'float'>, order='C')
np.identity()
print(np.eye(3))
----------------------
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
(4)在已有的矩阵外围填充0
np.pad(array, pad_width, mode='constant', **kwargs)
ar = np.arange(9).reshape(3,3)
print(np.pad(ar, pad_width=1))
------------------------------------
[[0 0 0 0 0]
[0 0 1 2 0]
[0 3 4 5 0]
[0 6 7 8 0]
[0 0 0 0 0]]
(5)生成对角矩阵
np.diag()
ar = np.arange(1,5)
print(np.diag(ar))
---------------------------------
[[1 0 0 0]
[0 2 0 0]
[0 0 3 0]
[0 0 0 4]]
(6)获取数组中非零元素的索引
np.nonzero(array)
lst = [1,2,0,0,4,0]
ar = np.array(lst)
print(np.nonzero(ar))
----------------------------
(array([0, 1, 4], dtype=int64),)
(7)获取N维数组第xx个元素的index
np.unravel_index(indices, shape, order='C')
ar = np.random.randint(15, size=(6,7,8))
print(np.unravel_index(100,(6,7,8)))
---------------------------
(1, 5, 4)
5. Numpy通用函数
(1)数组的形状:array.T, array.reshape(), array.resize
改变数组的形状常用的几个函数有:转置、shape改变、shape与size改变,注意这3个函数都是会生成新的数组,不会改变原始数组
array.T
:数组的转置函数
ar = np.array([[1,2,3], ['a', 'b', 'c']])
print(ar)
print(ar.T)
-------------------
[['1' '2' '3'] ['a' 'b' 'c']]
[['1' 'a'] ['2' 'b'] ['3' 'c']]
array.reshape(shape)
:不会改变原始数组array,而是会生成一个新的数组,所以元素数量需要一致!!
np.reshape(array, shape)
:使用numpy自带的reshape函数,该函数不会改变原始数组
ar = np.array([[1,2,3, 4, 5], ['a', 'b', 'c', 'd', 'e']])
print(ar)
ar_new = ar.reshape((1,10))
print(ar)
print(ar_new)
print(np.reshape(ar, (1,10)))
print(ar)
--------------------------------
[['1' '2' '3' '4' '5']
['a' 'b' 'c' 'd' 'e']]
[['1' '2' '3' '4' '5']
['a' 'b' 'c' 'd' 'e']]
[['1' '2' '3' '4' '5' 'a' 'b' 'c' 'd' 'e']]
[['1' '2' '3' '4' '5' 'a' 'b' 'c' 'd' 'e']]
[['1' '2' '3' '4' '5']
['a' 'b' 'c' 'd' 'e']]
np.resize(array, new_shape)
:返回具有指定形状的新数组,如有必要可重复填充所需数量的元素,这点与reshape是不同的
array.resize(new_shape)
:这种方式会改变原始array的值,通常我们建议用前面一种
print(np.resize(np.arange(5),(2,4)))
ar = np.arange(10)
print(np.resize(ar, (2,6)))
print(ar.resize(2,6))
print(ar)
---------------------------
[[0 1 2 3]
[4 0 1 2]]
[[0 1 2 3 4 5]
[6 7 8 9 0 1]]
None
[[0 1 2 3 4 5]
[6 7 8 9 0 0]]
(2)数组的复制
array.copy()
:python的赋值逻辑,指向内存中生成的一个值 ,如下ar1和ar2指向同一个值,所以ar1改变,ar2一起改变,因此需要复制函数
ar1 = np.arange(10)
ar2 = ar1
print(ar1 is ar2)
ar3 = ar1.copy()
ar3[2] = 100
print(ar1, ar3)
----------------------
True
[0 1 2 3 4 5 6 7 8 9] [ 0 1 100 3 4 5 6 7 8 9]
(3)数组类型转换:array.astype()
array.astype(dtype, order='K', casting='unsafe', subok=True, copy=True)
ar1 = np.arange(10, dtype=float)
ar2 = ar1.astype(np.int64)
print(ar1, ar1.dtype)
print(ar2, ar2.dtype)
--------------------------
[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.] float64
[0 1 2 3 4 5 6 7 8 9] int64
(4)数组的堆叠:np.hstack(), np.vstack(), np.stack()
数组的堆叠函数本质是数组的连接函数,与列表、字典不同的是,数组的连接函数使用的是np.hstack(), np.vstack(), np.stack()
np.hstack(tup)
:传入的多个数组必须以元组的形式传入,横向连接(按行的方式进行堆叠),此处多个数组的形状必须一样
np.vstack(tup)
:传入的多个数组必须以元组的形式传入,纵向连接(按列的方式进行堆叠),数组的形状可以不一样
a = np.array([[1], [2], [3]])
b = np.array([['a'], ['b'], ['c']])
print(a)
print(b)
print(np.hstack((a,b)))
print(np.vstack((a,b)))
-------------------------
[[1]
[2]
[3]]
[['a']
['b']
['c']]
[['1' 'a']
['2' 'b']
['3' 'c']]
[['1']
['2']
['3']
['a']
['b']
['c']]
np.stack(arrays, axis=0)
:沿着新轴连接数组的序列,形状必须一样!
- axis,假设两个数组[1 2 3]和[4 5 6],shape均为(1,3)
- axis=0:[[1 2 3] [4 5 6]],shape为(2,3),即以行的方式进行堆叠
- axis=1:[[1 4] [2 5] [3 6]],shape为(3,2),即以列的方式进行堆叠
a = np.arange(5)
b = np.arange(5, 10)
print(np.stack((a,b)))
print(np.stack((a,b), axis=1))
--------------------------------
[[0 1 2 3 4]
[5 6 7 8 9]]
[[0 5]
[1 6]
[2 7]
[3 8]
[4 9]]
(5)数组的拆分:np.hsplit(), np.vsplit()
np.hsplit(ary, indices_or_sections)
:将数组水平(逐列)拆分为多个子数组 ,按列拆分,输出结果为列表,列表中元素为数组
numpy.vsplit(ary, indices_or_sections)
::将数组垂直(行方向)拆分为多个子数组,按行拆
ar = np.arange(16).reshape(4,4)
print(ar)
print(np.hsplit(ar, 2))
print(np.vsplit(ar,4))
-------------------------------------
[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11] [12 13 14 15]]
[array([[ 0, 1], [ 4, 5], [ 8, 9], [12, 13]]), array([[ 2, 3], [ 6, 7], [10, 11], [14, 15]])]
[array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8, 9, 10, 11]]), array([[12, 13, 14, 15]])]
(6)数组的简单运算
ar = np.arange(6).reshape(2,3)
print(ar+10)
print(ar * 2)
print(1/(ar+1))
print(ar ** 0.5)#幂次
print(ar.mean())#平均值
print(ar.max())
print(ar.min())
print(ar.std())#标准差
print(ar.var())#方差
print(ar.sum(), np.sum(ar, axis =0))#求和,np.sum() → axis为0,按列求和;axis为1,按行求和
print(np.sort(np.array([1,4,3,2,5,6])))#排序
6. Numpy索引以及切片
(1)基本索引切片
本小节主要介绍一维数组、二维数组与三维数组的索引与切片
- 一维数组索引与切片:与列表类似
ar = np.arange(20)
print(ar) >>> [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
print(ar[4]) >>> 4
print(ar[:3]) >>> [0, 1, 2]
print(ar[::2]) >>> [ 0 2 4 6 8 10 12 14 16 18]
- 二维数组索引与切片:
ar = np.arange(16).reshape(4, 4)
print(ar)
print(ar[2])#第3行
print(ar[2][2])#第3行第3列
print(ar[1:3])#索引为1-2的行
print(ar[2,2])
print(ar[:2,2:])
---------------------------------------
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
[ 8 9 10 11]
10
[[ 4 5 6 7]
[ 8 9 10 11]]
10
[[2 3]
[6 7]]
如下例子会生成一个类似于棋盘的8*8个网格
ar = np.ones(shape=(8,8))
ar[1::2, ::2] = 0
ar[::2,1::2] = 0
print(ar)
- 三维数组索引与切片
ar = np.arange(12).reshape(3, 2, 2)
print(ar)
print(ar[2][1])
print(ar[2][1][0])
----------------------------------
[[[ 0 1]
[ 2 3]]
[[ 4 5]
[ 6 7]]
[[ 8 9]
[10 11]]]
[10 11]
10
(2)布尔型索引与切片
import numpy as np
ar = np.arange(12).reshape(3,4)
print(ar)
i = np.array([True, False, True])
j = np.array([True, True, False, False])
print(i)
print(j)
print(ar[i])
print(ar[:, j])
print(ar[i, j])
-------------------------------------
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[ True False True]
[ True True False False]
[[ 0 1 2 3]
[ 8 9 10 11]]
[[0 1]
[4 5]
[8 9]]
[0 9]
我们可以使用布尔型的矩阵进行数据的筛选
ar = np.arange(12).reshape(3,4)
print(ar>5) #构造了一个布尔型矩阵
print(ar[ar>5])
--------------------------------------
[[False False False False]
[False False True True]
[ True True True True]]
[ 6 7 8 9 10 11]
(3)数值索引以及切片值的更改与复制
数值索引与切片值的更改:
ar = np.arange(10)
print(ar)
ar[5] = 100
ar[7:9] = 200
print(ar)
----------------------------------------
[0 1 2 3 4 5 6 7 8 9]
[ 0 1 2 3 4 100 6 200 200 9]
数组的复制,与列表类似,如果直接将数组赋值给另一个数组,会造成其中一个数组值的更改影响另一个数组的值。因此数组的复制函数也是有必要的:
ar = np.arange(10)
b = ar.copy()
b[7:9] = 200
print(ar)
print(b)
------------------------------
[0 1 2 3 4 5 6 7 8 9]
[ 0 1 2 3 4 5 6 200 200 9]
7. Numpy随机数
numpy.random包含了多种概率分布的随机样本函数,是数据分析的辅助的重点工具之一
(1)随机生成标准正态分布
np.random.normal()
:normal (Gaussian) distribution,标准正态分布的样本值
sample = np.random.normal(size=(4,4))
print(sample)
-----------------------------------------------
[[-0.19947068 1.08386722 -0.8007086 -0.29973608]
[-1.4138948 0.11978172 1.1266943 -0.38618087]
[-2.20107989 -0.03437717 -2.11068913 0.55943784]
[ 0.01115924 -0.94572094 -0.8717386 1.97596254]]
(2)随机生成[0,1)浮点数
np.random.rand()
:生成一个[0,1)之间的随机浮点数/N维浮点数组:均匀分布
ar = np.random.rand()
print(ar, type(ar))
print(np.random.rand(4))
print(np.random.rand(2,3))
------------------------------------------
0.39545806581361387 <class 'float'>
[0.14330156 0.4138819 0.72934196 0.13847742]
[[0.10330226 0.42875629 0.51752984]
[0.30286978 0.26096506 0.37244292]]
(3)随机生成一个N维整型数组
np.random.randint(low, high=None, size=None, dtype='l')
:生成一个整数/N维整数数组,若high不为None时,取[low, high)之间的随机整数,否则取值[0, low)之间随机整数,且high必须要大于low;dtype参数只能是int类型
print(np.random.randint(3))
print(np.random.randint(2, 10))
print(np.random.randint(10, size=5))
print(np.random.randint(10, size=(2,5)))#生成2行5列的数组,值在[0,10)
print(np.random.randint(10, 50, size=(2,5)))
---------------------------------------------------
1
5
[4 7 7 2 7]
[[2 3 8 6 2]
[9 8 0 6 2]]
[[16 10 11 26 15]
[17 11 35 28 44]]
8. Numpy数据的输入与输出
在列表的内容里学习过如何打开文件,进行数据的读写,Numpy也有相应的函数进行数据的读写。主要分为.npy
文件与.txt
文件的读写
(1).npy文件的存取
对于.npy文件,numpy中可以使用np.save(file, arr, allow_pickle=True, fix_imports=True)
进行存储,使用np.load(file, mmap_mode=None, allow_pickle=False, fix_imports=True, encoding='ASCII')
函数进行读取
如下例子在桌面上生成一个test.npy,并将数组存入该文件
import os
os.chdir(r'C:\Users\Bob\Desktop')
ar = np.random.rand(5,5)
print(ar)
np.save('test.npy', ar)
print('finishied')
---------------------------
[[0.06423913 0.75382215 0.56869953 0.98410291 0.39004041]
[0.26626693 0.41471567 0.33343208 0.44380002 0.85317088]
[0.97158141 0.64644351 0.03857217 0.81016871 0.8411624 ]
[0.18725582 0.57724439 0.29543981 0.14655409 0.1001154 ]
[0.5611382 0.12391804 0.07974878 0.08417997 0.74273726]]
finishied
ar_load = np.load('test.npy')
print(ar_load)
----------------------------
[[0.06423913 0.75382215 0.56869953 0.98410291 0.39004041]
[0.26626693 0.41471567 0.33343208 0.44380002 0.85317088]
[0.97158141 0.64644351 0.03857217 0.81016871 0.8411624 ]
[0.18725582 0.57724439 0.29543981 0.14655409 0.1001154 ]
[0.5611382 0.12391804 0.07974878 0.08417997 0.74273726]]
(2).txt文件的存取
对于.txt文件,numpy中可以使用np.savetxt()
进行存储,使用np.loadtxt()
函数进行读取
如下例子在桌面上生成一个test.txt,并将数组存入该文件
ar = np.random.rand(5,5)
print(ar)
np.savetxt('test.txt', ar, delimiter=',', fmt='%.2f') #以逗号分隔开每个元素,存储时保留2为小数点
print('finished')
ar_load = np.loadtxt('test.txt',delimiter=',')
print(ar_load, ar_load.dtype)
----------------------------------------------
[[0.55412062 0.22607233 0.78282203 0.36200306 0.46374254]
[0.98622828 0.52656624 0.20647287 0.50212248 0.01737296]
[0.36278898 0.58702447 0.68746675 0.43975599 0.32049743]
[0.16226933 0.11427889 0.80376318 0.04888106 0.49355556]
[0.51634686 0.77667928 0.61162141 0.04089656 0.49566949]]
finished
[[0.55 0.23 0.78 0.36 0.46]
[0.99 0.53 0.21 0.5 0.02]
[0.36 0.59 0.69 0.44 0.32]
[0.16 0.11 0.8 0.05 0.49]
[0.52 0.78 0.61 0.04 0.5 ]] float64
存储到桌面的文件内容为
0.55,0.23,0.78,0.36,0.46
0.99,0.53,0.21,0.50,0.02
0.36,0.59,0.69,0.44,0.32
0.16,0.11,0.80,0.05,0.49
0.52,0.78,0.61,0.04,0.50
网友评论