美文网首页Python之路Python
Numpy笔记(NumPy ndarray)

Numpy笔记(NumPy ndarray)

作者: 生信start_site | 来源:发表于2020-06-13 11:11 被阅读0次

    本篇笔记是根据学习《Python for data analysis》这本英文教程里的Numpy这一部分来记录的。这本书在网上的评价还是很高的,里面讲的东西也比较细,鉴于是英文的,所以我就打算只挑部分来看,时间充裕的同学可以从头到尾的细看一遍。

    书的封面长这样

    Numpy,是Numerical Python的简写,它是Python里数字计算的最重要的一个基础包。

    The NumPy ndarray: A Multidimensional Array Object

    Numpy ndarray:一个多维数组对象
    Numpy 的一个关键的特点是其N-维数组对象,或者叫做ndarray,它是一个快速的,灵活的大数据python“容器”。Arrays使得你可以对整个block使用简单的语法来进行数学计算。举个例子,导入Numpy并且生成一个小的随机数组:

    #首先进入ipython,具体方法请见我前一篇文章
    #这里你可以使用shell,或者web界面,根据你喜好来
    $ ipython
    Python 3.7.6 (default, Jan  8 2020, 19:59:22)
    Type 'copyright', 'credits' or 'license' for more information
    IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help.
    
    In [1]: import numpy as np #导入Numpy
    
    In [2]: data = np.random.randn(2,3) #生成随机数组,2个数组,每个里面3个元素
    
    In [3]: data
    Out[3]:
    array([[ 0.01738749, -0.05367916,  0.72654692],
           [ 1.45506185, -0.71293169,  1.35346708]])
    

    对数组进行数学运算:

    In [4]: data*10
    Out[4]:
    array([[ 0.17387488, -0.53679156,  7.26546924],
           [14.55061854, -7.12931685, 13.53467077]])
    
    In [5]: data+data
    Out[5]:
    array([[ 0.03477498, -0.10735831,  1.45309385],
           [ 2.91012371, -1.42586337,  2.70693415]])
    

    ndarray是用于存放同种数据的多维“容器”,也就是说,所有的元素必须是同样的类型。每一个数组都有自己的shape,用shape可以查看每一个维度的大小;使用dtype可以查看数组内的数据类型:

    In [6]: data.shape
    Out[6]: (2, 3)
    
    In [7]: data.dtype
    Out[7]: dtype('float64')
    

    NOTE: Whenever you see “array,” “NumPy array,” or “ndarray” in the text,
    with few exceptions they all refer to the same thing: the ndarray object.

    Creating ndarrays

    创建一个ndarray的最简单的方法就是使用array功能。比如说:

    In [8]: data1 = [6, 7.5, 8, 0, 1]
    
    In [9]: arr1 = np.array(data1)
    
    In [10]: arr1
    Out[10]: array([6. , 7.5, 8. , 0. , 1. ])
    

    或者你想创建嵌套序列,比如等长列表,将会被转换为多维数组:

    In [11]: data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]
    
    In [12]: arr2 = np.array(data2)
    
    In [13]: arr2
    Out[13]:
    array([[1, 2, 3, 4],
           [5, 6, 7, 8]])
    

    因为data2是一个由list组成的list,所以arr2的shape是一个二维的数组。你可以用ndimshape来检查:

    In [14]: arr2.ndim #看维度
    Out[14]: 2
    
    In [15]: arr2.shape
    Out[15]: (2, 4)
    
    In [16]: arr2.dtype
    Out[16]: dtype('int64') #数组内数据类型是int整数
    

    另外,np.array还有很多其他的功能来创建新的arrays。比如说,它可以创建全是1或者全是0的array。还可以创建一个空的array,即没有确定值:

    In [17]: np.zeros(10) #创建全是0的一维数组
    Out[17]: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
    
    In [18]: np.zeros((3,6)) #创建全是0的二维数组
    Out[18]:
    array([[0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0.]])
    
    In [19]: np.empty((2,3,2)) #创建空数组
    Out[19]:
    array([[[6.95334423e-310, 0.00000000e+000],
            [0.00000000e+000, 0.00000000e+000],
            [0.00000000e+000, 0.00000000e+000]],
    
           [[0.00000000e+000, 0.00000000e+000],
            [0.00000000e+000, 0.00000000e+000],
            [0.00000000e+000, 0.00000000e+000]]])
    

    有的时候,np.empty创建的空数组,返回值不是0,而是一堆乱七八糟的值,也就是“garbage” values。

    Data Types for ndarrays

    在你创建一个ndarray的时候,你可以指定这个ndarray里的数据类型是什么,比如说:

    In [20]: arr1 = np.array([1, 2, 3], dtype=np.float64)
    
    In [21]: arr1
    Out[21]: array([1., 2., 3.])
    
    In [22]: arr2 = np.array([1, 2, 3], dtype=np.int32)
    
    In [23]: arr2
    Out[23]: array([1, 2, 3], dtype=int32)
    
    In [24]: arr1.dtype
    Out[24]: dtype('float64')
    
    In [25]: arr2.dtype
    Out[25]: dtype('int32')
    

    此外,你也可以更改一个数组的数据类型:

    In [26]: arr = np.array([1, 2, 3, 4, 5])
    
    In [27]: arr.dtype
    Out[27]: dtype('int64')
    
    In [28]: float_arr = arr.astype(np.float64) #把整数类型改成浮点类型
    
    In [29]: float_arr.dtype
    Out[29]: dtype('float64')
    

    相反,你也可以把浮点类型改成整数,但是小数部分就会被截掉:

    In [30]: arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
    
    In [31]: arr
    Out[31]: array([ 3.7, -1.2, -2.6,  0.5, 12.9, 10.1])
    
    In [32]: arr.astype(np.int32)
    Out[32]: array([ 3, -1, -2,  0, 12, 10], dtype=int32)
    

    如果你的数组内是字符串类型,也可以使用这种方法进行转换:

    In [33]: numeric_strings = np.array(['1.25', '-9.6', '42'], dtype=np.string_)
    
    In [34]: numeric_strings.astype(float)
    Out[34]: array([ 1.25, -9.6 , 42.  ])
    

    在使用numpy.string_进行数据类型转换的时候需要注意,有的时候会在没有任何提示下截断你的数据。

    Arithmetic(运算) with NumPy Arrays

    array很重要,因为它们使你能够对数据批量处理操作,而不需要编写任何for循环。NumPy用户称之为向量化。任何算术必须在相同大小数组之间进行操作:

    In [35]: arr = np.array([[1., 2., 3.], [4., 5., 6.]])
    
    In [36]: arr
    Out[36]:
    array([[1., 2., 3.],
           [4., 5., 6.]])
    
    In [37]: arr*arr
    Out[37]:
    array([[ 1.,  4.,  9.],
           [16., 25., 36.]])
    
    In [38]: 1/arr
    Out[38]:
    array([[1.        , 0.5       , 0.33333333],
           [0.25      , 0.2       , 0.16666667]])
    
    In [39]: arr**0.5
    Out[39]:
    array([[1.        , 1.41421356, 1.73205081],
           [2.        , 2.23606798, 2.44948974]])
    

    你还可以比较两个不同的array的大小,这里比较的时候是数组之间相同位置进行比较:

    In [40]: arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])
    
    In [41]: arr2
    Out[41]:
    array([[ 0.,  4.,  1.],
           [ 7.,  2., 12.]])
    
    In [42]: arr2>arr
    Out[42]:
    array([[False,  True, False],
           [ True, False,  True]])
    
    Basic Indexing(索引) and Slicing(切片)

    在Numpy里,你有很多种方法可以在data里选择一个subset,或者选择出某一个元素。对于一维数组来说是非常简单的:

    In [43]: arr=np.arange(10)
    
    In [44]: arr
    Out[44]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    
    In [45]: arr[5]
    Out[45]: 5
    
    In [46]: arr[5:8]
    Out[46]: array([5, 6, 7])
    
    In [47]: arr[5:8]=12 #从索引的第5位到第7位改成12(这里涉及python的索引规则)
    
    In [48]: arr
    Out[48]: array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])
    

    对数组进行“切片”:

    In [49]: arr_slice=arr[5:8]
    
    In [50]: arr_slice
    Out[50]: array([12, 12, 12])
    

    对切出来的“片段”进行修改:

    In [51]: arr_slice[1]=12345
    
    In [52]: arr #对切片的修改会影响整个原始数组
    Out[52]:
    array([    0,     1,     2,     3,     4,    12, 12345,    12,     8,
               9])
    

    对于二维数组来说:

    In [53]: arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    
    In [54]: arr2d[2]
    Out[54]: array([7, 8, 9])
    
    In [55]: arr2d[0][2]
    Out[55]: 3
    
    In [56]: arr2d[0,2] #这样的表示方法可以参考下面的示意图来进行理解
    Out[56]: 3
    

    那如果是多维数组呢?比如现在有一个2 × 2 × 3 array:

    In [57]: arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
    
    In [58]: arr3d
    Out[58]:
    array([[[ 1,  2,  3],
            [ 4,  5,  6]],
    
           [[ 7,  8,  9],
            [10, 11, 12]]])
    
    In [59]: arr3d[0]
    Out[59]:
    array([[1, 2, 3],
           [4, 5, 6]])
    

    更改多维数组里的数据:

    In [60]: old_values=arr3d[0].copy()
    
    In [61]: arr3d[0]=42 #更改其中一个元素,使得这个元素里的所有值都变成42
    
    In [62]: arr3d
    Out[62]:
    array([[[42, 42, 42],
            [42, 42, 42]],
    
           [[ 7,  8,  9],
            [10, 11, 12]]])
    
    In [63]: arr3d[0]=old_values #再改回来
    
    In [64]: arr3d
    Out[64]:
    array([[[ 1,  2,  3],
            [ 4,  5,  6]],
    
           [[ 7,  8,  9],
            [10, 11, 12]]])
    

    对多维数组切片:

    In [65]: arr3d[1,0]
    Out[65]: array([7, 8, 9])
    
    In [66]: arr2d
    Out[66]:
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])
    
    In [67]: arr2d[:2]
    Out[67]:
    array([[1, 2, 3],
           [4, 5, 6]])
    
    In [68]: arr2d[:2,1:] #在二维数组里取第0和1个索引对应的list,然后在这两个list里取从索引1开始,到最后的元素
    Out[68]:
    array([[2, 3],
           [5, 6]])
    
    In [69]: arr2d[1,:2] #取索引是1的list,然后在这个list里取从开始到索引为2(不包括2)的元素
    Out[69]: array([4, 5])
    

    有关二维数组的切片的索引位置,可以参考下图:

    将数组里小于0的数都设置为0:

    In [70]: data = np.random.randn(7, 4)
    
    In [71]: data
    Out[71]:
    array([[ 1.07484753, -1.37075898, -1.76641029,  1.39686773],
           [ 1.12808743,  0.38325471,  2.26384631,  1.21861537],
           [-0.37522887, -1.2066686 , -0.07729884,  1.76493675],
           [ 0.51771666,  0.14024697,  0.91802525,  0.88580838],
           [-0.17494945, -0.14744639,  0.82242766, -0.060019  ],
           [ 1.11820368, -1.18942934,  1.34140358, -0.9074736 ],
           [ 0.01312651, -2.17228966,  0.97890648,  1.51395293]])
    
    In [72]: data[data<0]=0
    
    In [73]: data
    Out[73]:
    array([[1.07484753, 0.        , 0.        , 1.39686773],
           [1.12808743, 0.38325471, 2.26384631, 1.21861537],
           [0.        , 0.        , 0.        , 1.76493675],
           [0.51771666, 0.14024697, 0.91802525, 0.88580838],
           [0.        , 0.        , 0.82242766, 0.        ],
           [1.11820368, 0.        , 1.34140358, 0.        ],
           [0.01312651, 0.        , 0.97890648, 1.51395293]])
    
    Fancy Indexing

    花式索引是NumPy采用的术语,用于描述对整数数组进行索引:

    In [74]: arr=np.empty((8,4)) #比如先创建一个8*4的空数组
    
    In [75]: arr #这就是上面说到的,有时候你创建的空数组不是每次都会是0
    Out[75]:
    array([[ 6.95334381e-310,  0.00000000e+000,  6.93002310e-310,
             4.34669976e-118],
           [ 6.93002307e-310,  6.93002310e-310,  1.04440620e+181,
             6.93002307e-310],
           [ 6.93002310e-310, -1.76250980e-304,  6.93002307e-310,
             6.93002310e-310],
           [ 8.10582968e-283,  6.93002307e-310,  6.93002310e-310,
             2.58280046e+280],
           [ 6.93002308e-310,  6.93002461e-310,  1.20122413e+036,
             6.93002307e-310],
           [ 6.93002461e-310,  6.39556658e-245,  6.93002307e-310,
             6.93002461e-310],
           [ 9.69473502e+012,  6.93002307e-310,  6.93002461e-310,
             2.99497312e+029],
           [ 6.93002307e-310,  6.93002461e-310, -2.36433447e+212,
             6.93002307e-310]])
    
    In [76]: for i in range(8): #给这个空数组赋值
        ...:     arr[i]=i
        ...:
    
    In [77]: arr
    Out[77]:
    array([[0., 0., 0., 0.],
           [1., 1., 1., 1.],
           [2., 2., 2., 2.],
           [3., 3., 3., 3.],
           [4., 4., 4., 4.],
           [5., 5., 5., 5.],
           [6., 6., 6., 6.],
           [7., 7., 7., 7.]])
    

    选择你想提取的subset,并按照特定顺序排列:

    In [78]: arr[[4,3,0,6]]
    Out[78]:
    array([[4., 4., 4., 4.],
           [3., 3., 3., 3.],
           [0., 0., 0., 0.],
           [6., 6., 6., 6.]])
    
    In [79]: arr[[-3,-5,-7]] #负数表示从倒数顺序来取subset
    Out[79]:
    array([[5., 5., 5., 5.],
           [3., 3., 3., 3.],
           [1., 1., 1., 1.]])
    
    通用函数
    In [1]: import numpy as np
    
    In [2]: arr = np.arange(10)
    
    In [3]: arr
    Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    
    In [4]: np.sqrt(arr)   #计算每一个元素的开方
    Out[4]:
    array([0.        , 1.        , 1.41421356, 1.73205081, 2.        ,
           2.23606798, 2.44948974, 2.64575131, 2.82842712, 3.        ])
    
    In [5]: np.exp(arr)     #numpy.exp():返回e的幂次方,e是一个常数为2.71828
    Out[5]:
    array([1.00000000e+00, 2.71828183e+00, 7.38905610e+00, 2.00855369e+01,
           5.45981500e+01, 1.48413159e+02, 4.03428793e+02, 1.09663316e+03,
           2.98095799e+03, 8.10308393e+03])
    
    Unique

    针对一维数组,这个函数是把数组里“不重复的”元素挑选出来。

    In [11]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
    
    In [12]: np.unique(names)
    Out[12]: array(['Bob', 'Joe', 'Will'], dtype='<U4')
    
    In [13]: ints = np.array([3, 3, 3, 2, 2, 1, 1, 4, 4])
    
    In [14]: np.unique(ints)
    Out[14]: array([1, 2, 3, 4])
    

    相关文章

      网友评论

        本文标题:Numpy笔记(NumPy ndarray)

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