• 初识numpy的多维数组对象ndarray


    PS:内容来源于《利用Python进行数据分析》

    一、创建ndarray

      1、array :将一个序列(嵌套序列)转换为一个数组(多维数组) 

    In[2]: import numpy as np
    In[3]: arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
    In[4]: arr
    Out[4]: array([1, 2, 3, 4, 5, 6, 7, 8, 9])
    
    In[5]: arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    In[6]: arr
    Out[6]: 
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])
    View Code

      2、arange:类似于内置的range,返回的是一个ndarray对象。通过reshape指定数组维度

    In[8]: arr = np.arange(1, 10).reshape(3, 3)
    In[9]: arr
    Out[9]: 
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])
    View Code

      3、ones、ones_like、zeros、zeros_like:根据指定shape和dtype创建一个全1或全0数组;ones_like或zeros_like另一个数组为参数,根据参数数组的shape和dtype创建全1或全0数组

    arr = np.ones((2, 4), dtype = np.int32)
    arr
    Out[11]: 
    array([[1, 1, 1, 1],
           [1, 1, 1, 1]])
    arr2 = np.zeros_like(arr)
    arr2
    Out[13]: 
    array([[0, 0, 0, 0],
           [0, 0, 0, 0]])
    View Code

      4、empty、empy_like:类似ones、ones_like,只是分配的内存空间不填充任何值,即数组的元素是未初始化的

    arr = np.empty((3, 3), dtype = np.float64)
    arr
    Out[15]: 
    array([[ 0.,  0.,  0.],
           [ 0.,  0.,  0.],
           [ 0.,  0.,  0.]])
    arr1 = np.empty_like(arr)
    arr1
    Out[17]: 
    array([[ 0.,  0.,  0.],
           [ 0.,  0.,  0.],
           [ 0.,  0.,  0.]])
    View Code

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

    In[18]: arr = np.eye(4, dtype = np.float32)
    In[19]: arr
    Out[19]: 
    array([[ 1., 0., 0., 0.],
    [ 0., 1., 0., 0.],
    [ 0., 0., 1., 0.],
    [ 0., 0., 0., 1.]], dtype=float32)
    In[20]: arr1 = np.identity(4, dtype = np.int32)
    In[21]: arr1
    Out[21]: 
    array([[1, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1]])
    View Code

     二、ndarray的shape和dtype

      ndarray是通用的同构数据多维容器,其中的所有元素必须是相同的数据类型。

      ndarray.shape 获取一个表示数组各维度大小的元组。 ndarray.dtype获取数组元素的数据类型。

      numpy的数据类型有:int8 int16 int32 int64 uint8 uint16 uint32 uint64 float16 float32 float64 float128 complex64 complex128 complex256 bool object(O) string_(S) unicode_(U)

    In[2]: import numpy as np
    In[3]: arr = np.arange(16).reshape((2, 2, 4))
    In[4]: arr.shape
    Out[4]: (2, 2, 4)
    In[5]: arr.dtype
    Out[5]: dtype('int32')
    View Code

      可以通过ndarray的astype方法显示地转换dtype。如果转换过程失败了(类型转换不能实现),会引发TypeError。调用astype会创建一个新的数组,即使新旧dtpye相同也会如此

    In[16]: arr = np.array(10)
    In[17]: arr.dtype
    Out[17]: dtype('int32')
    In[18]: float_arr = arr.astype(np.float32)
    In[19]: float_arr.dtype
    Out[19]: dtype('float32')
    In[20]: str = np.array(['1.3', '-4.5', '33'], dtype = np.string_)
    In[21]: str.dtype
    Out[21]: dtype('S4')
    In[22]: num = str.astype(np.float32)
    In[23]: num.dtype
    Out[23]: dtype('float32')
    View Code

    三、数组和标量之间的矢量化运算

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

    In[26]: arr = np.arange(1, 10).reshape((3, 3))
    In[27]: arr
    Out[27]: 
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])
    In[28]: arr ** 2
    Out[28]: 
    array([[ 1,  4,  9],
           [16, 25, 36],
           [49, 64, 81]])
    In[29]: arr - arr
    Out[29]: 
    array([[0, 0, 0],
           [0, 0, 0],
           [0, 0, 0]])
    In[30]: arr * arr.T
    Out[30]: 
    array([[ 1,  8, 21],
           [ 8, 25, 48],
           [21, 48, 81]])
    View Code

    四、基本的索引和切片

      数组切片形式上和Python列表的截取功能相似,但是数组切片获取的是原始数组的视图,这意味着不会创建新的数组,数据也不会被复制,在视图上的任何修改都会直接作用源数组上。

    In[2]: import numpy as np
    In[3]: arr = np.arange(10)
    In[4]: arr
    Out[4]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    In[5]: arr[1:6]
    Out[5]: array([1, 2, 3, 4, 5])
    In[6]: arr[1:6] = [5, 4, 3, 2, 1]
    In[7]: arr
    Out[7]: array([0, 5, 4, 3, 2, 1, 6, 7, 8, 9])
    View Code

      数组的索引用以获取数组的元素(与C的数组相同)。在多维数组中,如果忽略了后面维度的索引,则返回对象为维度低一点的ndarray对象。通过索引获取的数组子集,也是源数组的视图

      通过索引访问数组,arr[i][j][k] 与 arr[i, j, k] 是等价的。

    In[8]: arr = np.arange(1, 13).reshape((2, 2, 3))
    In[9]: arr
    Out[9]: 
    array([[[ 1,  2,  3],
            [ 4,  5,  6]],
    
           [[ 7,  8,  9],
            [10, 11, 12]]])
    In[10]: arr[0]
    Out[10]: 
    array([[1, 2, 3],
           [4, 5, 6]])
    In[11]: arr[0][0][0]
    Out[11]: 1
    In[12]: arr[0, 0, 0]
    Out[12]: 1
    In[13]: arr[0][1]
    Out[13]: array([4, 5, 6])
    In[14]: arr[0, 1]
    Out[14]: array([4, 5, 6])
    View Code

      切片索引:

    In[15]: arr
    Out[15]: 
    array([[[ 1,  2,  3],
            [ 4,  5,  6]],
    
           [[ 7,  8,  9],
            [10, 11, 12]]])
    In[16]: arr[:, 1, 0:2]
    Out[16]: 
    array([[ 4,  5],
           [10, 11]])
    View Code

      布尔型索引:布尔索引元素的个数必须与数组相应维度上元素个数相同,否则会引发IndexError异常。 数组索引位相对应的布尔值为True的元素会被选取。 

      与切片不同,通过布尔索引选取数组中的数据,将总是创建数据的副本,即使返回一模一样的数组也是如此

    In[23]: arr
    Out[23]: 
    array([[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]])
    In[24]: num = np.arange(1, 8)
    In[25]: num
    Out[25]: array([1, 2, 3, 4, 5, 6, 7])
    In[26]: arr[num % 2 == 0]
    Out[26]: 
    array([[2, 2, 2, 2],
           [4, 4, 4, 4],
           [6, 6, 6, 6]])
    In[27]: arr[(num % 2 != 0) | (num == 4)]
    Out[27]: 
    array([[1, 1, 1, 1],
           [3, 3, 3, 3],
           [4, 4, 4, 4],
           [5, 5, 5, 5],
           [7, 7, 7, 7]])
    In[28]: arr[(num % 2 != 0) & (num < 4)]
    Out[28]: 
    array([[1, 1, 1, 1],
           [3, 3, 3, 3]])
    View Code

       花式索引:花式索引(Fancy indexing)是一个numpy术语,指的是利用整数数组进行索引。 与切片不同,花式索引也总是将数据复制到新数组中

       传入一个用于指定顺序的整数列表或ndarray,以获取特定顺序选取的行子集。如果使用负数索引,将会从末尾开始选取行。

    In[33]: arr = np.empty((8, 3), dtype = np.int32)
    In[34]: for i in range(8):
       ...:     arr[i] = i
       ...: arr    
    Out[34]: 
    array([[0, 0, 0],
           [1, 1, 1],
           [2, 2, 2],
           [3, 3, 3],
           [4, 4, 4],
           [5, 5, 5],
           [6, 6, 6],
           [7, 7, 7]])
    In[35]: arr[[4, 2, 0, 5]]
    Out[35]: 
    array([[4, 4, 4],
           [2, 2, 2],
           [0, 0, 0],
           [5, 5, 5]])
    In[36]: arr[[-1, -5, -7]]
    Out[36]: 
    array([[7, 7, 7],
           [3, 3, 3],
           [1, 1, 1]])
    View Code

       一次传入多个索引有一点特别,返回的是一个一维数组(而不是所期望的其他维度也指定顺序),其中的元素对应各个索引元组。

      下面代码实际选取了元素: arr[1, 0]、arr[5, 2]、 arr[6, 1]、 arr[2, 2] 

    In[40]: arr = np.arange(24).reshape(8, 3)
    In[41]: arr
    Out[41]: 
    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[42]: arr[[1, 5, 6, 2],[0, 2, 1, 2]]
    Out[42]: array([ 3, 17, 19,  8])
    View Code

      如果希望返回其他维度也按数组指定顺序,可采用下面的方法:

      方法一实际是通过一个数组获取指定顺序的子集,然后在获取子集的基础上,利用切片索引再次获取子集(第一个维度通过:获取全部元素;第二个维度通过花式索引获取指定顺序)。方法二使用np.ix_()函数,将两个一维整数数组转换为一个用户选取子集的索引器。 有趣的是,指定顺序数组的元素个数可以超过源数组的元素个数(其索引不能溢出,可以重复)。

    In[43]: arr[[1, 5, 6, 2]][:, [0, 2, 1, 2]]
    Out[43]: 
    array([[ 3,  5,  4,  5],
           [15, 17, 16, 17],
           [18, 20, 19, 20],
           [ 6,  8,  7,  8]])
    In[44]: arr[np.ix_([1, 5, 6, 2], [0, 2, 1, 2])]
    Out[44]: 
    array([[ 3,  5,  4,  5],
           [15, 17, 16, 17],
           [18, 20, 19, 20],
           [ 6,  8,  7,  8]])
    View Code

     五、数组的转置和轴对换

      转置(transpose)是重塑的一种特殊形式,它返回的是源数据的视图,不会进行任何复制操作

      1、ndarray的特殊属性T,返回数组的转置:(np.dot函数计算的是矩阵的内积)

    In[49]: arr = np.arange(1, 10).reshape((3, 3))
    In[50]: arr
    Out[50]: 
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])
    In[51]: arr.T
    Out[51]: 
    array([[1, 4, 7],
           [2, 5, 8],
           [3, 6, 9]])
    In[52]: np.dot(arr, arr.T)
    Out[52]: 
    array([[ 14,  32,  50],
           [ 32,  77, 122],
           [ 50, 122, 194]])
    View Code

      2、通过transpose函数返回数组的转置:transpose需要得到一个由轴编号组成的元组作为参数。

       所谓的轴编号即shape获取的元组的下标,比如有数组arr = np.arange(16).reshape((2, 2, 4)),arr.shape的值为元组(2, 2, 4),其下标元组为(0, 1, 2)。则,arr 与 arr.transpose(0, 1, 2) 的值是相同的。

    In[62]: arr = np.arange(16).reshape((2, 2, 4))
    In[63]: arr
    Out[63]: 
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7]],
    
           [[ 8,  9, 10, 11],
            [12, 13, 14, 15]]])
    In[64]: arr.transpose(0, 1, 2)
    Out[64]: 
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7]],
    
           [[ 8,  9, 10, 11],
            [12, 13, 14, 15]]])
    View Code

      变更下标元组的顺序作为参数传递给transpose函数,即可实现相应的轴对换。例如arr.transpose(1, 0, 2),将第一轴和第二轴转置对换,第三轴元素不变。

    In[65]: arr.transpose(1, 0, 2)
    Out[65]: 
    array([[[ 0,  1,  2,  3],
            [ 8,  9, 10, 11]],
    
           [[ 4,  5,  6,  7],
            [12, 13, 14, 15]]])
    In[66]: arr.transpose(0, 2, 1)
    Out[66]: 
    array([[[ 0,  4],
            [ 1,  5],
            [ 2,  6],
            [ 3,  7]],
    
           [[ 8, 12],
            [ 9, 13],
            [10, 14],
            [11, 15]]])
    In[67]: arr.transpose(1, 2, 0)
    Out[67]: 
    array([[[ 0,  8],
            [ 1,  9],
            [ 2, 10],
            [ 3, 11]],
    
           [[ 4, 12],
            [ 5, 13],
            [ 6, 14],
            [ 7, 15]]])
    In[68]: arr.transpose(2, 0, 1)
    Out[68]: 
    array([[[ 0,  4],
            [ 8, 12]],
    
           [[ 1,  5],
            [ 9, 13]],
    
           [[ 2,  6],
            [10, 14]],
    
           [[ 3,  7],
            [11, 15]]])
    View Code

      3、swapaxes方法:此方法需要接受一对轴编号(只能是两个轴编号做为参数,不能多也不能少,且变换参数顺序对结果无影响)。

      PS:结果理解小技巧——swapaxes(0, 2) 第二轴不变,可以视为2 x 4的数组转置 [ [(0, 4), (1, 5), (2, 6), (3, 7)], [(8, 12), (9, 13), (10, 14), (11, 15)]],结果是4 x 2 数组

    In[77]: arr
    Out[77]: 
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7]],
    
           [[ 8,  9, 10, 11],
            [12, 13, 14, 15]]])
    In[78]: arr.swapaxes(0, 1)
    Out[78]: 
    array([[[ 0,  1,  2,  3],
            [ 8,  9, 10, 11]],
    
           [[ 4,  5,  6,  7],
            [12, 13, 14, 15]]])
    In[79]: arr.swapaxes(1, 0)
    Out[79]: 
    array([[[ 0,  1,  2,  3],
            [ 8,  9, 10, 11]],
    
           [[ 4,  5,  6,  7],
            [12, 13, 14, 15]]])
    In[80]: arr.swapaxes(0, 2)
    Out[80]: 
    array([[[ 0,  8],
            [ 4, 12]],
    
           [[ 1,  9],
            [ 5, 13]],
    
           [[ 2, 10],
            [ 6, 14]],
    
           [[ 3, 11],
            [ 7, 15]]])
    View Code

     

       

  • 相关阅读:
    js 函数柯里化和闭包的使用
    人员轨迹运动效果
    D3绘制柱状图
    D3选择元素和绑定数据
    h5--uni.setNavigationBarColor 动态修改顶部背景颜色
    友链
    canvas 整个透明
    JS将某个数组分割为N个对象一组(如,两两一组,三三一组等)
    小程序正则表达式
    微信小程序--设置和获取剪切板内容
  • 原文地址:https://www.cnblogs.com/FoxShark/p/7411883.html
Copyright © 2020-2023  润新知