Numpy

作者: 不倒翁4 | 来源:发表于2020-11-07 21:22 被阅读0次

    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
    

    相关文章

      网友评论

          本文标题:Numpy

          本文链接:https://www.haomeiwen.com/subject/uvpivktx.html