代码之家  ›  专栏  ›  技术社区  ›  JE_Muc

numpy结构数组中的子数组不连续

  •  2
  • JE_Muc  · 技术社区  · 6 年前

    我目前尝试将大量数组打包到numpy结构化数组。 根据 to the numpy documentation

    子数组总是有一个C-连续的内存布局。

    但是,如果我创建一个结构化数组:

    x = np.zeros((2,), dtype=[('a', (np.float64, 5)), ('b', (np.float64, 5))])
    x['a'].flags
    # Out: C_CONTIGUOUS : False
    #      F_CONTIGUOUS : False
    #      OWNDATA : False
    #      ...
    

    x.flags
    # Out: C_CONTIGUOUS : True
    #      F_CONTIGUOUS : True
    #      OWNDATA : True
    #      ...
    

    使用“外部”形状 (1,)

    x = np.zeros((1,), dtype=[('a', (np.float64, 5)),('b',(np.float64, 7))])
    x['a'].flags
    # Out: C_CONTIGUOUS : True
    #      F_CONTIGUOUS : False
    #      OWNDATA : False
    #      ...
    

    省略 (1,) 产生数组 ndim=1 仅用于结构化数组的行 .

    令我困惑的是,当我直接为每个子阵列指定阵列形状时,会给出连续性:

    x = np.zeros((), dtype=[('a', (np.float64, (2, 5))), ('b', (np.float64, (2, 5)))])
    
    x['a'].flags
    #Out: C_CONTIGUOUS : True
    #     F_CONTIGUOUS : False
    #     OWNDATA : False
    

    总是 有一个C-连续的内存布局,但这似乎只适用于行或给定每个数组的形状时。
    这种行为从何而来?正在定义“外部”形状(我不知道怎么称呼它…)告诉numpy ,同时指定每个子数组的形状直接连续存储每个子数组?
    当所有子数组的第一个维度相等而第二个维度不相等时,处理这个问题的最佳方法是什么?我应该直接指定每个形状以保持它们的连续性吗?

    1 回复  |  直到 6 年前
        1
  •  3
  •   hpaulj    6 年前

    和你的 dtype

    x[0]['a'], x[0]['b']
    x[1]['a'], x[1]['b']
    ....
    

    也就是说,一份 x 由字段“a”的5个元素和字段“b”的5个元素组成,依此类推,用于下一条记录。

    subarrays are C contiguous ,它指的是一个记录中包含一个字段的元素的布局。

    跨记录的字段“A”的视图将不连续-“b”的元素将分隔不同记录的元素。

    同样的事情也适用于二维数组中的列切片:

    In [32]: w = np.zeros((2,10))
    In [33]: w.flags
    Out[33]: 
      C_CONTIGUOUS : True
      F_CONTIGUOUS : False
      ...
    In [34]: w[:,:5].flags    # w[:,5:] elements are in between
    Out[34]: 
      C_CONTIGUOUS : False
      F_CONTIGUOUS : False
      ...
    

    当子阵列为2d时(如上一个示例中所示),此连续性注释更为相关:

    In [35]: dt=np.dtype([('a', (np.float64, 5)), ('b', (np.float64, (2,2)))])
    In [36]: x=np.zeros((2,2,),dt,order='F')
    In [37]: x.flags
    Out[37]: 
      C_CONTIGUOUS : False
      F_CONTIGUOUS : True
    
    In [39]: x[0,0]['b'].flags
    Out[39]: 
      C_CONTIGUOUS : True
      F_CONTIGUOUS : False
    

    而整个阵列 F 连续,“b”元素仍然是“C”连续的。


    定义数组:

    In [40]: x = np.array([(1,[2,3]),(4,[5,6])], dtype=[('a',int),('b',int,2)])
    In [41]: x
    Out[41]: array([(1, [2, 3]), (4, [5, 6])], dtype=[('a', '<i8'), ('b', '<i8', (2,))])
    

    将数组视为简单的int-dtype(不总是可能的):

    In [42]: x.view(int)
    Out[42]: array([1, 2, 3, 4, 5, 6])
    

    In [44]: x['b']
    Out[44]: 
    array([[2, 3],
           [5, 6]])
    

    “a”的值介于:

    In [47]: x['a']
    Out[47]: array([1, 4])