zoukankan      html  css  js  c++  java
  • Numpy学习笔记

    numpy是一个在Python中做科学计算的基础库,重在数值计算,也是大部分PYTHON科学计算库的基础库,多用于在大型、多维数组上执行数值运算。

    数组的定义

    import numpy as np
    # numpy数组的定义方法
    a = np.arange(1, 6, 2)
    b = np.array([1, 3, 5])
    c = np.array(range(1, 6, 2))
    
    # 这样产生的a,b,c三个结果是一样的,均为[1, 3, 5]
    
    # 这里看一下数组的类型和数组元素的类型的定义和修改,type(a)表示的是数组a的类型,a.dtype则表示的是数组a中元素的类型。
    In [1]: import numpy as np
    In [2]: a = np.array([1, 2, 3])
    In [3]: print(a, type(a), a.dtype)
    		  [1 2 3] <class 'numpy.ndarray'> int32
    In [4]: a = np.array([1, 2, 3], dtype = "float64")
    In [5]: print(a, type(a), a.dtype)
    		  [1. 2. 3.] <class 'numpy.ndarray'> float64
    In [6]: a = a.astype("int64")
    In [7]: print(a, type(a), a.dtype)
    		  [1 2 3] <class 'numpy.ndarray'> int64
    
    #要保留固定位数的小数需要用到np.round()
    In [1]: import random
    In [2]: import numpy as np
    In [3]: "%.2f"%random.random()
    Out[3]: '0.56'
    In [4]: round(random.random(), 2)
    Out[4]: 0.73
    In [5]: a = np.round(np.array([random.random() for i in range(10)]), 2)
    In [6]: a
    Out[6]: array([0.7 , 0.95, 0.6 , 0.03, 0.27, 0.96, 0.17, 0.48, 0.3 , 0.23])
    In [7]: np.round(a, 1)
    Out[7]: array([0.7, 1. , 0.6, 0. , 0.3, 1. , 0.2, 0.5, 0.3, 0.2])
    

    数组的形状

    以下的代码是在Jupyter Notebook中完成的:

    # 数组的形状
    In [1]: import numpy as np
    In [2]: a = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
    In [3]: a
    Out[3]: array([[[ 1, 2, 3],
    				[ 4, 5, 6]],
    				[[ 7, 8, 9],
    				[10, 11, 12]]])
    In [4]: a.shape
    Out[4]: (2, 2, 3)
    # 上面元组中的元素个数即是这个数组的维数,例如这个就是个三维数组,他一共有 2 块,每块有 2 行, 3 列,即(2, 2, 3)
    In [5]: a.reshape((3, 4))
    Out[5]: array([[ 1, 2, 3, 4],
    			   [ 5, 6, 7, 8],
    			   [ 9, 10, 11, 12]])
    In [6]: a.reshape((12,))
    Out[6]: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
    In [7]: a
    Out[7]: array([[[ 1, 2, 3],
    		  		[ 4, 5, 6]],
    				[[ 7, 8, 9],
    				[10, 11, 12]]])
    # 从这里看以看出a.reshape并不能改变a的形状和维度,如果需要改变a的维度和形状,需要重新对a进行赋值,如下↓:
    In [8]: a = a.reshape((4,3))
    In [9]: a
    Out[9]: array([[ 1, 2, 3],
    			   [ 4, 5, 6],
                   [ 7, 8, 9],
                   [10, 11, 12]])
    # 计算一个二维数组的元素个数,可以使用如下的方法,shape[0]是这个二维数组的行数,shape[1]即是这个数组的列数。
    In [10]: a.shape[0] * a.shape[1]
    Out[10]: 12
    # 所以将一个二维数组变为一维数组便有了如下的方法:
    In [11]: a = a.reshape((a.shape[0] * a.shape[1],))
    In [12]: a
    Out[12]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])
    # 当然一个现成简单的方法是使用flatten这个函数
    In [13]: a.flatten()
    Out[13]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])
    

    数组的计算

    # 数组直接对一个数进行加减乘除,产生的结果是数组中的每个元素都会加减乘除这个数。
    In [14]: a * 2
    Out[14]: array([[ 2, 4, 6],
                    [ 8, 10, 12],
                    [14, 16, 18],
                    [20, 22, 24]])
    In [15]: a / 0
        D:Anaconda3libsite-packagesipykernel\__main__.py:1: RuntimeWarning: divide by zero           encountered in true_divide
          if __name__ == '__main__':
    Out[15]: array([[inf, inf, inf],
                    [inf, inf, inf],
                    [inf, inf, inf],
                    [inf, inf, inf]])
    # 接下来我们看一下数组与数组之间的计算
    In [17]: b = np.arange(12,24).reshape((4,3))
    In [18]: b
    Out[18]: array([[12, 13, 14],
                    [15, 16, 17],
                    [18, 19, 20],
                    [21, 22, 23]])
    In [19]: a + b
    Out[19]: array([[13, 15, 17],
                    [19, 21, 23],
                    [25, 27, 29],
                    [31, 33, 35]])
    In [20]: c = np.array([1,2,3])
    In [21]: a+c
    Out[21]: array([[ 2, 4, 6],
                    [ 5, 7, 9],
                    [ 8, 10, 12],
                    [11, 13, 15]])
    In [22]: d = np.arange(10,14).reshape((4,1))
    In [23]: d
    Out[23]: array([[10],
                    [11],
                    [12],
                    [13]])
    In [24]: a + d
    Out[24]: array([[11, 12, 13],
                    [15, 16, 17],
                    [19, 20, 21],
                    [23, 24, 25]])
    # 从上面可以看出,和线性代数中不同的是,m*n列的m行的一维数组或者n列的一维数组也是可以计算的。
    
    # 要求数组中所有元素的和或者每行或者每列的和应该怎么做?我们可以使用np.sum()函数
    In [17]: c = a + d
    In [18]: c
    Out[18]: array([[11, 12, 13],
                   [15, 16, 17],
                   [19, 20, 21],
                   [23, 24, 25]])
    In [19]: np.sum(c)
    Out[19]: 216
    In [20]: np.sum(c, axis = 0)
    Out[20]: array([68, 72, 76])
    In [21]: np.sum(c, axis = 1)
    Out[21]: array([36, 48, 60, 72])
    
    

    这是为什么呢?这里要提到numpy的广播原则:

    如果两个数组的后缘维度(从末尾开始算起的维度)轴长度相符其中一方的长度为1,则认为它们是广播兼容的。广播会在缺失维度和(或)轴长度为1的维度上进行。

    在上面的代码中,a的维度是(4,3),c的维度是(1,3);d的维度是(4,1)。所以假设有两个数组,第一个的维度是(x_1, y_1, z_1),另一个数组的维度是(x_2, y_2, z_2),要判断这两个数组能不能进行计算,可以用如下方法来判断:

    if z_1 == z_2 or z_1 == 1 or z_2 == 1:
        if y_1 == y_2 or y_1 == 1 or y_2 == 1:
            if x_1 == x_2 or x_1 == 1 or x_2 == 1:
                可以运算
            else:
                不可以运算
        else:
            不可以运算
    else:
        不可以运算
    

    这里需要注意:(3,3,2)和(3,2)是可以运算的,因为对于二维数组(3,2)也可以表示为(1,3,2),套用上述的规则是完全适用的,同理:(4,2,5,4)和(2,1,4)也是可以进行运算的。

    轴(axis)

    在numpy中可以理解为方向,使用0,1,2...数字表示,对于一个一维数组,只有一个0轴,对于2维数组(shape(2,2)),有0轴和1轴,对于三维数组(shape(2,2, 3)),有0,1,2轴。

    二维数组的轴如下图所示:

    2维数组的轴

    三维数组的轴:

    3维数组的轴

    numpy读数据

    使用如下语句来读取CSV文件:np.loadtxt(fname,dtype=np.float,delimiter=None,skiprows=0,usecols=None,unpack=False)
    参数含义

    数组转置:(两种方法)

    • .transpose()
    • .swapaxes(1, 0)

    取数组中的值

    import numpy as np
    
    us_file_path = "./youtube_video_data/US_video_data_numbers.csv"
    uk_file_path = ".youtube_video_dataGB_video_data_numbers.csv"
    
    t1 = np.loadtxt(us_file_path, delimiter=",", dtype="int64")
    print(t1)
    
    print("*" * 100)
    # 取行
    # print(t1[2])
    # print(t1[2,])
    
    # 取连续的多行
    # print(t1[2:])
    # print(t1[2: ,])
    
    # 取不连续的多行
    # print(t1[[2, 9, 3]])
    # print(t1[[2, 9, 3],])
    
    # 取列
    # print(t1[:,2])
    
    # 取连续的多列
    # print(t1[:,2:])
    
    # 取不连续的多列
    # print(t1[:, [0, 2]])
    
    # 取元素
    # print(t1[1, 3])
    
    # 取连续多行和多列
    # print(t1[1:4, 1:4])
    
    # 取多个不相邻的点(0,1), (2, 2), (2, 3)
    # print(t1[[0, 1, 2], [2, 2, 3]])
    

    numpy中数值修改

    # 取值然后赋值即可
    In [1]: import numpy as np
    
    In [2]: t2 = np.arange(24).reshape(4, 6)
    
    In [3]: t2
    Out[3]:
    array([[ 0,  1,  2,  3,  4,  5],
           [ 6,  7,  8,  9, 10, 11],
           [12, 13, 14, 15, 16, 17],
           [18, 19, 20, 21, 22, 23]])
    
    In [4]: t2<10
    Out[4]:
    array([[ True,  True,  True,  True,  True,  True],
           [ True,  True,  True,  True, False, False],
           [False, False, False, False, False, False],
           [False, False, False, False, False, False]])
    
    In [5]: t2[t2<10] = 3
    
    In [6]: t2
    Out[6]:
    array([[ 3,  3,  3,  3,  3,  3],
           [ 3,  3,  3,  3, 10, 11],
           [12, 13, 14, 15, 16, 17],
           [18, 19, 20, 21, 22, 23]])
    
    In [7]: np.where(t2<10, 0, 10)
    Out[7]:
    array([[ 0,  0,  0,  0,  0,  0],
           [ 0,  0,  0,  0, 10, 10],
           [10, 10, 10, 10, 10, 10],
           [10, 10, 10, 10, 10, 10]])
    

    clip操作

    t.clip(10, 12)
    # 这句话的意思是将数组t中小于10的数变为10,大于12的数变为12
    

    拼接操作和换行换列操作

    In [12]: a = np.arange(12).reshape(4,3)
    
    In [13]: b = np.arange(12,24).reshape(4,3)
    
    In [14]: a
    Out[14]:
    array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11]])
    
    In [15]: b
    Out[15]:
    array([[12, 13, 14],
           [15, 16, 17],
           [18, 19, 20],
           [21, 22, 23]])
    # 竖直拼接
    In [17]: np.vstack((a,b))
    Out[17]:
    array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11],
           [12, 13, 14],
           [15, 16, 17],
           [18, 19, 20],
           [21, 22, 23]])
    # 水平拼接
    In [18]: np.hstack((a,b))
    Out[18]:
    array([[ 0,  1,  2, 12, 13, 14],
           [ 3,  4,  5, 15, 16, 17],
           [ 6,  7,  8, 18, 19, 20],
           [ 9, 10, 11, 21, 22, 23]])
    
    # 两行互换
    Out[21]: 0
    
    In [22]: a[[0,1],:] = a[[1,0],:]
    
    In [23]: a
    Out[23]:
    array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11]])	
    

    将一维行向量转置为一维列向量的办法.reshape(-1, 1)

    构造全为0或1的包含n个元素的一维向量的方法:

    # 列向量
    np.zeros((n, 1))
    np.ones((n, 1))
    # 行向量
    np.zeros((1, n))
    np.ones((1, n))
    

    numpy生成全0矩阵、全1矩阵、单位矩阵的方法以及求每行/列最大最小值的方法。

    In [1]: import numpy as np
    In [2]: np.zeros((4, 3))
    Out[2]: array([[0., 0., 0.],
                   [0., 0., 0.],
                   [0., 0., 0.],
                   [0., 0., 0.]])
    In [3]: np.ones((4, 3))
    Out[3]: array([[1., 1., 1.],
                   [1., 1., 1.],
                   [1., 1., 1.],
                   [1., 1., 1.]])
    In [5]: a = np.eye(4)
    In [6]: a
    Out[6]: array([[1., 0., 0., 0.],
                   [0., 1., 0., 0.],
                   [0., 0., 1., 0.],
                   [0., 0., 0., 1.]])
    In [7]: np.argmax(a, axis = 0)
    Out[7]: array([0, 1, 2, 3], dtype=int64)
    In [8]: np.argmin(a, axis = 1)
    Out[8]: array([1, 0, 0, 0], dtype=int64)
    

    numpy生成随机数的方法

    np.random.后加下列参数(.seed()的使用方法是先进行np.random.seed(s)再进行上述操作)

    参数 解释
    .rand(d0, d1, ..., dn) 创建d0-dn维度的均匀分布的随机数数组,浮点数,范围0-1
    .randn(d0, d1, ..., dn) 创建d0-dn维度的标准正态分布随机数,浮点数,平均数0,标准差1
    .randint(low, high, (shape)) 从给定上下限范围内随机取整数,形状是shape
    .uniform(low, high, (size)) 产生具有均匀分布的数组(浮点数),low起始值,high结束值,size形状
    .normal(loc, scale, (size)) 从指定正态分布中随机抽取样本,分布中心是loc(概率分布的均值),标准差是scale,形状是size
    .seed(s) 随机数种子,s是给定的种子值。因为计算机生成的是伪随机数,所以通过设定相同的随机数种子,可以每次生成相同的随机数

    numpy数组的复制

    • a = b[:]:视图的操作,会创建新的对象a,但是a的数据完全由b保管,改变b同时会引起a的改变;

    • a = b.copy():复制,a和b互不影响。

    In [1]: import numpy as np
    In [2]: a = np.random.randint(0, 20, (4, 4))
    In [3]: a
    Out[3]: array([[ 1, 6, 5, 2],
    			   [ 8, 12, 13, 8],
    			   [19, 13, 9, 1],
    			   [ 8, 2, 5, 5]])
    In [4]: b = a[0:2,0:2]
    In [5]: b
    Out[5]: array([[ 1, 6, 5],
    			   [ 8, 12, 13],
    			   [19, 13, 9]])
    In [6]: a[0, 0] = 0
    In [7]: a
    Out[7]: array([[ 0, 6, 5, 2],
    			   [ 8, 12, 13, 8],
    			   [19, 13, 9, 1],
    			   [ 8, 2, 5, 5]])
    In [8]: b
    Out[8]: array([[ 0, 6, 5],
    			   [ 8, 12, 13],
    			   [19, 13, 9]])
    

    nan和inf

    nan(NAN,Nan):not a number表示不是一个数字,inf表示无穷大,-inf表示负无穷大。

    什么时候numpy中会出现nan:当我们读取本地的值的类型为float的文件,有缺失的时候;或者当做了一个不合适的计算(比如无穷大(inf)减去无穷大)的时候,这个地方的值就会变成nan。

    指定nan或者inf的方法:a[:] = np.nan;a[:] = np.inf

    关于nan需要注意的地方:

    1. 两个nan是不相等的

    2. 利用(1)中的特性可以统计出一个数组中包含nan的个数

    In [1]: import numpy as np
    # 创建一个不含0的5阶非0方阵
    In [2]: a = np.random.randint(1, 20, (5, 5))
    In [3]: a
    Out[3]: array([[12, 11, 2, 16, 16],
                   [19, 9, 7, 19, 8],
                   [14, 1, 2, 11, 12],
                   [ 5, 13, 15, 5, 13],
                   [ 6, 12, 4, 13, 6]])
    # np.count_nonzero()这个函数用来统计数组中的非0值得个数
    In [4]: np.count_nonzero(a)
    Out[4]: 25
    # 将数组的第3行全部变为0
    In [5]: a[2,:] = 0
    In [6]: a
    Out[6]: array([[12, 11, 2, 16, 16],
    [19, 9, 7, 19, 8],
    [ 0, 0, 0, 0, 0],
    [ 5, 13, 15, 5, 13],
    [ 6, 12, 4, 13, 6]])
    In [8]: np.count_nonzero(a)
    # count_nonzero()的结果从25变为20
    Out[8]: 20
    # 因为nan的数值类型是float,而我们生成的数组类型为int,所以先把数组的类型转化为float
    In [10]: a = a.astype(float)
    # 将下面3个元素的值变为nan
    In [11]: a[[1, 2, 3],[0, 3, 4]] = np.nan
    In [12]: a
    Out[12]: array([[12., 11., 2., 16., 16.],
                    [nan, 9., 7., 19., 8.],
                    [ 0., 0., 0., nan, 0.],
                    [ 5., 13., 15., 5., nan],
                    [ 6., 12., 4., 13., 6.]])
    # 因为np.nan!=np.nan,所以在值为nan的位置会出现True,其他位置则会出现false
    In [13]: a!=a
    Out[13]: array([[False, False, False, False, False],
                    [ True, False, False, False, False],
                    [False, False, False, True, False],
                    [False, False, False, False, True],
                    [False, False, False, False, False]])
    # 与a!=a等价的还有一种方法即np.isnan(a)他的结果也是上述这个数组
    In [15]: np.count_nonzero(a!=a)
    # 于是np.count_nonzero(a!=a)又可以写为np.count_nonzero(np.isnan(a))
    Out[15]: 3
    In [16]: (a!=a).astype(int)
    # True的值即为1,False的值为0,所以non_zero()函数可以统计一个数组中包含nan的个数
    Out[16]: array([[0, 0, 0, 0, 0],
                    [1, 0, 0, 0, 0],
                    [0, 0, 0, 1, 0],
                    [0, 0, 0, 0, 1],
                    [0, 0, 0, 0, 0]])
    

    那么我们为什么要统计数组中nan的个数?

    numpy中常用统计函数

    类型 函数
    求和 t.sum(axis=None)
    均值 t.mean(a,axis=None) 受离群点的影响较大
    中值 np.median(t,axis=None)
    最大值 t.max(axis=None)
    最小值 t.min(axis=None)
    极值 np.ptp(t,axis=None) 即最大值和最小值之差
    标准差 t.std(axis=None)

    那么如何将数组中值为nan 的元素换为该列/行的均值?

    import numpy as np
    
    
    def fill_ndarray(t):
        for i in range(t.shape[1]):
            temp_col = t[:, i]          # 当前列
            nan_num = np.count_nonzero(np.isnan(temp_col))          # 计算当前列中nan的个数
            if nan_num != 0:
                # 计算均值
                temp_non_nan_col = temp_col[temp_col == temp_col]
                temp_col_mean = temp_non_nan_col.mean()
                # 替换当前列中nan为均值
                temp_col[np.isnan(temp_col)] = temp_col_mean
        return t
    
    
    a = np.arange(12).reshape(4, 3).astype(float)
    
    a[2, 1:3] = np.nan
    
    print(a)
    print("*" * 100)
    print(fill_ndarray(a))
    
    
  • 相关阅读:
    (转)运行pip报错:Fatal error in launcher: Unable to create process using '"'
    (转)pycharm autopep8配置
    Hash
    Java 8 Lambda表达式
    位运算
    PHP数组操作大全
    php final static const成员属性用法
    Java编程性能优化
    java中double变量保留小数问题
    encodeURIComponent编码后java后台的解码
  • 原文地址:https://www.cnblogs.com/dereen/p/numpy.html
Copyright © 2011-2022 走看看