zoukankan      html  css  js  c++  java
  • python科学计算_numpy_广播与下标

    多维数组下标

    多维数组的下标是用元组来实现每一个维度的,如果元组的长度比维度大则会出错,如果小,则默认元组后面补 : 表示全部访问;

    如果一个下标不是元组,则先转换为元组,在转换过程中,列表和数组的转换有所不同。

    一个列表会被转换成各个元素组成的元组,然后进行访问(此时如果不全为整数的话,则不会共享存储区域,因为无法通过改变步长来保持存储结构不变);如:lidx=[[0],[1],[2]];如果用lidx来访问一个数组,则会被转换成:([0],[1],[2]),即访问(0,1,2)上的元素;

    一个数组会进行补 : 操作转成长度一致的元组,如三维数组a:

    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, 24],
    [25, 26, 27, 28, 29],
    [30, 31, 32, 33, 34],
    [35, 36, 37, 38, 39]],

    [[40, 41, 42, 43, 44],
    [45, 46, 47, 48, 49],
    [50, 51, 52, 53, 54],
    [55, 56, 57, 58, 59]]])

    如果使用一个数组来访问:aidx=np.array([[0],[1],[2]]):

    array([[0],
    [1],
    [2]])

    则会被补全为:(aidx,:,:),访问结果为:

    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, 24],
    [25, 26, 27, 28, 29],
    [30, 31, 32, 33, 34],
    [35, 36, 37, 38, 39]]],


    [[[40, 41, 42, 43, 44],
    [45, 46, 47, 48, 49],
    [50, 51, 52, 53, 54],
    [55, 56, 57, 58, 59]]]])

    结果的形状是访问下标数组的形状和原数组形状的组合:原数组形状为(3,4,5),下标数组形状为:(3,1);访问得到的数组形状为:(3,1,4,5);访问数组在0轴位置替代原数组形状;

    相当于a(aidx,:,:),如果访问:a(:,aidx,:),则访问的形状应该为(3,3,1,5),即在1轴位置替代原数组形状;

    广播

    再复习一下广播,详细规则见随笔:http://www.cnblogs.com/lyon2014/p/4696989.html

    如上例的a数组,a.shape = (3,4,5),如果使用数组来访问,则会在对应的位置替代原数组的形状,如果下标中有多个数组,且形状不一致,则会进行广播,如:

    i0 = np.array([[1,2,1],[0,1,0]])  , i0.shape=(2,3)

    i1 = np.array([[[0]],[[1]]]), i1.shape=(2,1,1)

    i2 = np.array([[[2,3,2]]]), i2.shape=(1,1,3)

    按照广播的规则,i0的维数比最大维数3少,进行补1操作得到新的形状为:(1,2,3),再比较各个轴的长度:

    1 2 3
    2 1 1
    1 1 3 
    --------
    2 2 3

    最后结果的形状为(2,2,3),且满足第三条规则,可以进行计算;广播后的三个数组(记为:ind0,ind1,ind2)为:

    ind0:

    array([[[1, 2, 1],
    [0, 1, 0]],

    [[1, 2, 1],
    [0, 1, 0]]])

    ind1:

    array([[[0, 0, 0],
    [0, 0, 0]],

    [[1, 1, 1],
    [1, 1, 1]]])

    ind2:

    array([[[2, 3, 2],
    [2, 3, 2]],

    [[2, 3, 2],
    [2, 3, 2]]])

    此时,使用广播后的三个数组访问数组a(i0,i1,i2),得到的数组形状应该只与下标数组有关,即广播后的数组形状:(2,2,3);

    如果a使用其中的两个数组访问:a(:,i0,i1),由于i0和i1广播后的形状为 (2,2,3),在1、2轴替换a数组的形状,最后得到的形状为:(3,2,2,3);

    如果a使用其中两个数组访问,并且两个数组不连续:a(i0,:,i1),则第二轴会作为最后一维,即形状应该为广播后形状加上切片轴的形状:(2,2,3,4)

    布尔数组作为下标

    布尔数组作为下标时,相当于用nonzero()处理后的元组作为下标;

    如:b2 = np.array([[True,False,True],[True,False,False]]) 作为下标,相当于:

    np.nonzero(b2) = (array([0, 0, 1]), array([0, 2, 0]))

    a[b2] = a[np.nonzero(b2)] = a[ array([0, 0, 1]), array([0, 2, 0]), : ], 前两轴由于作为元组访问,最后得到的形状为(3,),最后访问到的形状为:(3,5)

  • 相关阅读:
    JSTL&EL
    Response
    HTTP、Request
    Tomcat、Servlet
    单片机概念及应用
    JQuery高级
    Jquery基础
    JavaScript
    HTML、CSS
    跟着文档学习gulp1.2创建任务(task)
  • 原文地址:https://www.cnblogs.com/lyon2014/p/4735306.html
Copyright © 2011-2022 走看看