• python--numpy学习(一)


    NumPy 部分功能如下:

    • ndarray,一个具有矢量运算符和复杂广播能力的快速节省空间的多维数组
    • 用于对数组数据进行快速运算的标准数学函数
    • 用于读写磁盘数据的工具以及用于操作内存映射文件的工具
    • 线性代数丶随机数生成以及傅里叶变换功能
    • 用于继承由C丶C++ 丶Fortran等语言编写的代码的工具

    NumPy 最重要的一个特点就是其N维数组对象(ndarray),该对象是一个快速而灵活的大数据集容器 。可以利用这个数组对象对整块数据进行一些数学运算,其语法跟标量之间的运算一样。

    统一进入方式:ipython --pylab

    > ipython --pylab
    Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)]
    Type 'copyright', 'credits' or 'license' for more information
    IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.
    Using matplotlib backend: TkAgg
    In [5]: import numpy as np
    In [6]: data=np.array([[0.9526,-0.246,-0.8856],[0.5639,0.2379,0.9104]])
    
    In [7]: data
    Out[7]:
    array([[ 0.9526, -0.246 , -0.8856],
           [ 0.5639,  0.2379,  0.9104]])
    
    In [8]: data * 10
    Out[8]:
    array([[ 9.526, -2.46 , -8.856],
           [ 5.639,  2.379,  9.104]])
    
    In [9]: data + data
    Out[9]:
    array([[ 1.9052, -0.492 , -1.7712],
           [ 1.1278,  0.4758,  1.8208]])

    ndarray是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的。每个数组都有一个shape(一个表示个维度大小的元组)和一个dtype(一个用于说明数组数据类型的对象)

    In [29]: test_data=np.array([[1,2,3],[4,5,6],[7,8,9]])
    
    In [30]: data
    Out[30]:
    array([[ 0.9526, -0.246 , -0.8856],
           [ 0.5639,  0.2379,  0.9104]])
    
    In [31]: test_data
    Out[31]:
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])
    
    In [32]: data.shape
    Out[32]: (2, 3)     #表示2行3列
    
    In [33]: test_data.shape
    Out[33]: (3, 3)    #表示3行3列
    In [34]: data.dtype
    Out[34]: dtype('float64')
    
    In [35]: test_data.dtype
    Out[35]: dtype('int32')

    创建ndarry

    创建数组最简单的办法就是使用array函数。它接受一切序列型的对象(包括其他数组),然后产生一个新的传入数据的NumPy数组。

    In [1]: import numpy as np
    
    In [2]: data1=[6,7.5,8,0,1]
    
    In [3]: arr1=np.array(data1)
    
    In [4]: arr1
    Out[4]: array([6. , 7.5, 8. , 0. , 1. ])

    因为里面有7.5为浮点数,所以:

    In [5]: arr1.dtype
    Out[5]: dtype('float64')

    查询出的数据类型为float64

    除非显示说明,np.array会尝试为新建的这个数组推断出一个较为合适的数据类型。数据类型保存在一个特殊的dtype对象中。

    嵌套序列

    比如一组等长的列表组成的列表,将会转换成一个多维数组 :

    In [6]: data2=[[1,2,3,4],[3,4,5,6],[5,6,7,8]]
    
    In [7]: arr2=np.array(data2)
    
    In [8]: arr2
    Out[8]:
    array([[1, 2, 3, 4],
           [3, 4, 5, 6],
           [5, 6, 7, 8]])
    
    In [9]: arr2.ndim
    Out[9]: 2
    
    In [10]: arr2.shape
    Out[10]: (3, 4)
    
    In [11]: arr2.dtype
    Out[11]: dtype('int32')

    其中ndim和shape介绍:

    ndim:数组的维数。如二维可以通过array[x][y]获取,三维是通过array[x][y][z]获取

    shape:返回值是一个元组,里面每个数字表示每一维的长度。

    In [13]: arr3=np.ones([2,3,4])
    
    In [14]: arr3
    Out[14]:
    array([[[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]],
    
           [[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]]])
    
    In [15]: arr3.ndim
    Out[15]: 3
    
    In [16]: arr3.shape
    Out[16]: (2, 3, 4)

    除了np.array之外,还有一些函数可以新建数组。比如zeros和ones分别可以创建制定长度或形状的全0或全1数组。emtpy可以创建一个没有任何具体值的数组。

    In [17]: np.zeros(10)
    Out[17]: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
    
    In [19]: np.zeros((3,6))
    Out[19]:
    array([[0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0.]])
    
    In [20]: np.zeros((3,6,7))
    Out[20]:
    array([[[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., 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., 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.]]])
    
    In [21]: np.ones((2,3))
    Out[21]:
    array([[1., 1., 1.],
           [1., 1., 1.]])
    
    In [22]: np.ones(5)
    Out[22]: array([1., 1., 1., 1., 1.])
    
    In [27]: np.empty((2,3,1))
    Out[27]:
    array([[[1.],
            [1.],
            [1.]],
    
           [[1.],
            [1.],
            [1.]]])
    
    In [28]: np.empty((2,3,2))
    Out[28]:
    array([[[0., 0.],
            [0., 0.],
            [0., 0.]],
    
           [[0., 0.],
            [0., 0.],
            [0., 0.]]])
    View Code

    注意:np.empty返回的是一些未初始化的垃圾值,并不一定返回全0数组 。

    arange是python内置函数range的数组版:

    In [31]: np.arange(10)
    Out[31]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

    数组函数创建:

    array:  将输入数据(列表,元组,数组或其他序列类型)转换为ndarry。 要么推断出dtype,要么显示制定dtype。默认直接复制输入数据

    asarray:将输入转换成ndarry,如果本身就是一个ndarry就不进行复制。

    arange:类似内置的range,但返回的是一个ndarry而不是列表。

    ones 丶ones_like:根据指定的形状和dtype创建一个全1数组。ones_like 以另一个数组为参数,并根据其形状和dtype创建一个全1数组 。

    zeros丶zeros_like:类似ones 丶ones_like,不过创建的是全0数组。

    empty丶empty_like :创建新数组,只分配内存空间但不填充任何值

    eye丶identity :创建一个N  * N 单位矩阵(对角线为1,其余为0)

    In [42]: np.eye(5)
    Out[42]:
    array([[1., 0., 0., 0., 0.],
           [0., 1., 0., 0., 0.],
           [0., 0., 1., 0., 0.],
           [0., 0., 0., 1., 0.],
           [0., 0., 0., 0., 1.]])
    
    In [43]: np.identity(5)
    Out[43]:
    array([[1., 0., 0., 0., 0.],
           [0., 1., 0., 0., 0.],
           [0., 0., 1., 0., 0.],
           [0., 0., 0., 1., 0.],
           [0., 0., 0., 0., 1.]])

    ndarry的数据类型

    dtype(数据类型)是一个特殊的对象,它包含有ndarry将一块内存解释为特定数据类型所需的信息:

    In [45]: arr1=np.array([1,2,3],dtype=np.float64)
    
    In [46]: arr1
    Out[46]: array([1., 2., 3.])
    
    In [47]: arr2=np.array([1,2,3],dtype=np.int32)
    
    In [48]: arr1.dtype
    Out[48]: dtype('float64')
    
    In [49]: arr2.dtype
    Out[49]: dtype('int32')

    一个数组创建后,系统会自动地将python类型映射到等价的dtype上 。

    可以通过ndarry的astype方法显式的转换dtype:( astype --> as type 修改类型; dtype--> 的type,查询出当前类型 )

    In [51]: arr=np.array([1,2,3,4,5])
    
    In [52]: arr.dtype
    Out[52]: dtype('int32')
    
    In [53]: float_arr=arr.astype(np.float64)
    
    In [54]: float_arr.dtype
    Out[54]: dtype('float64')

    上面将整数转换成了浮点数,如果将浮点数转换成整数,那么小数部分将会截断 :

    In [56]: arr=np.array([1.2,3.6,5.3,4.8,7.0,5.11,8.12])
    
    In [57]: arr
    Out[57]: array([1.2 , 3.6 , 5.3 , 4.8 , 7.  , 5.11, 8.12])
    
    In [58]: arr.astype(np.int32)
    Out[58]: array([1, 3, 5, 4, 7, 5, 8])

    还有另外一个用法:

    In [65]: float_array
    Out[65]: array([1.2 , 5.8 , 2.89, 7.53])
    
    In [66]: int_array
    Out[66]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    
    In [67]: float_array.dtype
    Out[67]: dtype('float64')
    
    In [68]: int_array.dtype
    Out[68]: dtype('int32')
    
    In [69]: int_array.astype(float_array.dtype)
    Out[69]: array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
    
    In [70]: int_array.dtype
    Out[70]: dtype('int32')
    
    In [71]: int_arr=int_array.astype(float_array.dtype)
    
    In [72]: int_arr.dtype
    Out[72]: dtype('float64')

    从上面可以看到int_array原始数据类型为int32,float_array为float64,执行int_array.astype(float_array.dtype)后是将int_array数据类型设置为float_array的一样,但是70行再次查询时发现int_array数据类型仍然是int32,只有定义一个新数组来接受时,新数组类型才是float64

    总结:astype使用方法ndarry.astype(np.dtype) 返回一个新的,dtype为传入的新的dtype的新数组,原始数组数据类型保持不变 。

    数组和标量之间的运算

    大小相等的数组之间的任何算术运算都会将运算应用到元素级:

    In [89]: arr1
    Out[89]:
    array([[1, 2, 3],
           [4, 5, 6]])
    
    In [90]: arr2
    Out[90]:
    array([[1, 2, 3],
           [4, 5, 2]])
    
    In [91]: arr1 * arr2
    Out[91]:
    array([[ 1,  4,  9],
           [16, 25, 12]])
    
    In [92]: arr1 + arr2
    Out[92]:
    array([[ 2,  4,  6],
           [ 8, 10,  8]])
    
    In [93]: arr1 ** 2
    Out[93]:
    array([[ 1,  4,  9],
           [16, 25, 36]], dtype=int32)
    
    In [94]: 1 / arr1
    Out[94]:
    array([[1.        , 0.5       , 0.33333333],
           [0.25      , 0.2       , 0.16666667]])

    不同大小的数组之间的运算叫做广播。

     基本的索引和切片

    In [1]: arr=np.arange(10)
    
    In [2]: arr
    Out[2]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    
    In [3]: arr[5:8]
    Out[3]: array([5, 6, 7])
    
    In [4]: arr[5:8]=12
    
    In [5]: arr
    Out[5]: array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])
    
    In [6]: arr_slice=arr[5:8]
    
    In [7]: arr_slice
    Out[7]: array([12, 12, 12])
    
    In [8]: arr_slice[1]
    Out[8]: 12
    
    In [9]: arr_slice[1]=12345
    
    In [10]: arr
    Out[10]:
    array([    0,     1,     2,     3,     4,    12, 12345,    12,     8,
               9])
    
    In [11]: arr_slice[:]=64
    
    In [12]: arr
    Out[12]: array([ 0,  1,  2,  3,  4, 64, 64, 64,  8,  9])

    可以发现,当你将一个标量值赋值给一个切片时(如arr[5:8]=12) ,该值会自动传播到整个选区。跟列表最重要的区别在于,数组切片是原始数组的视图。这意味着数据不会被复制,视图上的任何修改都会直接反映到源数组上。

    对于高维度数组,能做的事情更多。在一个二维数组中,各索引位置上的元素不再是标量而是一维数组。

    In [13]: arr2d=np.array([[1,2,3],[4,5,6],[7,8,9]])
    
    In [14]: arr2d[2]
    Out[14]: array([7, 8, 9])    #第三个数组
    
    In [15]: arr2d[0][2]       #第一个数组的第三个
    Out[15]: 3

    在多维数组中,如果省略了后面的索引,则返回对象是一个维度低一点的ndarry 。

    比如,在下面的一个2 * 2 * 3的数组arr3d中:

    In [16]: arr3d=np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
    
    In [17]: arr3d
    Out[17]:
    array([[[ 1,  2,  3],
            [ 4,  5,  6]],
    
           [[ 7,  8,  9],
            [10, 11, 12]]])
    
    In [18]: arr3d[0]  #先去掉最外面的[],然后取第一个列表 
    Out[18]:
    array([[1, 2, 3],
           [4, 5, 6]])
    
    In [19]: arr3d[0][1]   #从最外面的[]看起,先取第一个列表,再从里面取第二个 
    Out[19]: array([4, 5, 6])

    标量和数组都可以赋值给arr3d[0]

    In [20]: old_values=arr3d[0].copy()   #先将arr3d[0]的值赋给old_values
    
    Out[22]:
    array([[1, 2, 3],
           [4, 5, 6]])
    
    In [23]: arr3d[0]=42   #修改值后
    
    In [24]: arr3d
    Out[24]:
    array([[[42, 42, 42],
            [42, 42, 42]],
    
           [[ 7,  8,  9],
            [10, 11, 12]]])
    
    In [25]: arr3d[0]=old_values   #重新赋值
    
    In [26]: arr3d
    Out[26]:
    array([[[ 1,  2,  3],
            [ 4,  5,  6]],
    
           [[ 7,  8,  9],
            [10, 11, 12]]])

    切片索引

    ndarry的切片语法跟python列表这样的一维对象差不多:

    In [1]: arr=np.array([0,1,2,3,4,64,64,64,8,9])
    
    In [2]: arr[1:6]
    Out[2]: array([ 1,  2,  3,  4, 64])

    高维度对象的花样更多,可以在一个或多个轴上进行切片,也可以跟整数索引混合使用。

    In [4]: arr2d
    Out[4]:
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])
    
    In [5: arr2d[:2]   #取第一个(下标为0)和第二个(下标为1)
    Out[5]:
    array([[1, 2, 3],
           [4, 5, 6]])

    可以一次传入多个切片,就像传入多个索引一样:

    In [8]: arr2d[:2,:1]
    Out[8]:
    array([[1],
           [4]])

    通过整数索引和切片混合,可以得到低维度的切片:

    In [9]: arr2d[1,:2]
    Out[9]: array([4, 5])  #先取下标1的,即第二个列表,然后切片[:2]取前2个
    
    In [10]: arr2d
    Out[10]:
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])

    切片跟切片混合的,只能得到相同维数的数组视图。但是数组索引跟切片混合可以得到低维度的数组视图。数组索引跟数组索引混合,得到的是低维度的视图或数值:

    下面介绍数组索引和数组索引混合:

    In [19]: arr3d   #原始数组
    Out[19]:
    array([[[ 1,  2,  3],
            [ 4,  5,  6]],
    
           [[ 7,  8,  9],
            [10, 11, 12]]])
    
    In [21]: arr3d[1]   #取第二个数组
    Out[21]:             #得到一个二维数组
    array([[ 7,  8,  9],
           [10, 11, 12]])
    
    In [22]: arr3d[1,1]    #取第二个数组,然后再取第二个
    Out[22]: array([10, 11, 12])   #得到一个一维数组
    
    In [24]: arr3d[1,1,1]  #取第二个数组,然后再取第二个,然后再取第二个
    Out[24]: 11   #得到一个数值
  • 相关阅读:
    为页面上某些文本框添加离开验证输入事件
    学习之UML类图符号
    djangomagic blog
    验证码识别基础方法及源码
    LINQ TO XML实用解析
    解决ASP.NET中的各种乱码问题
    ASP.NET 1.1 ~ 4.0 中的哈希碰撞漏洞
    断点续传下载文件
    SQL Server资源
    Python图片浏览器
  • 原文地址:https://www.cnblogs.com/catxjd/p/9058324.html
Copyright © 2020-2023  润新知