【问题标题】:View of recarray as ndarray作为 ndarray 的 recarray 视图
【发布时间】:2018-08-04 17:08:08
【问题描述】:

在以前的 numpy 版本中,我可以这样做:

data = np.array([(0,1,2),(3,4,5),(6,7,8)], dtype=np.dtype([('a','<f8'), ('b','<f8'),('c','<f8')]))


data_nd = data[['a','b']].view(('<f8',2))

这将使我看到原始的recarray data 作为np.float32 类型的二维ndarray。

在 numpy 版本 1.14 中,当我尝试上面的第二行时出现错误:

ValueError: Changing the dtype to a subarray type is only supported if the total itemsize is unchanged

这是因为 data[['a','b']] 的 itemsize 仍然是 24。好吧,这很好,但是有没有办法获取更新 itemsize 的这些数据列的副本,以便我可以制作我想要的视图?

例如,即使复制(或深复制)data[['a','b']] 仍会导致项目大小为 24,我不明白。

【问题讨论】:

  • 我还没有完全消化这些 1.14 更改的后果。您可能需要求助于tolist 中介,或按名称复制字段。

标签: python python-2.7 numpy numpy-ndarray


【解决方案1】:

你是否意识到没有元组你的recarray 是3x3 复制的字段值:

In [46]: data
Out[46]: 
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.), (8., 8., 8.)]],
      dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])

无论如何,整个数组的视图仍然有效,您可以对其使用传统的列切片:

In [47]: data.view(('float',(3,)))
Out[47]: 
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.],
        [8., 8., 8.]]])
In [48]: _.shape
Out[48]: (3, 3, 3)

tolist 是转换到/从结构化数组的旧备用。它仍然有效:

In [49]: np.array(data[['a','b']].tolist())
Out[49]: 
array([[[0., 0.],
        [1., 1.],
        [2., 2.]],

       [[3., 3.],
        [4., 4.],
        [5., 5.]],

       [[6., 6.],
        [7., 7.],
        [8., 8.]]])

更改 data 创建以包含元组,实际上并不会改变视图行为,但可能更接近您想要的(或者我想要的):

In [50]: data1 = np.array([(0,1,2),(3,4,5),(6,7,8)], dtype=np.dtype([('a','<f8')
    ...: , ('b','<f8'),('c','<f8')]))
In [51]: data1
Out[51]: 
array([(0., 1., 2.), (3., 4., 5.), (6., 7., 8.)],
      dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])

请注意,子字段显示现在包含偏移参数。

In [53]: data1[['a','b']]
Out[53]: 
array([(0., 1.), (3., 4.), (6., 7.)],
      dtype={'names':['a','b'], 'formats':['<f8','<f8'], 'offsets':[0,8], 'itemsize':24})

底层数据库是相同的,因此 3 列视图可以使用和不使用子字段索引:

In [54]: data1[['a','b']].view((float,(3,)))
Out[54]: 
array([[0., 1., 2.],
       [3., 4., 5.],
       [6., 7., 8.]])
In [55]: data1.view((float,(3,)))
Out[55]: 
array([[0., 1., 2.],
       [3., 4., 5.],
       [6., 7., 8.]])

我还没有阅读最新的变化。相反,我使用了过去有效的各种技巧。与结构化数组相互转换从未如此简单和万无一失。

【讨论】:

  • 感谢您指出缺少元组。我确实想要它们,并且我已经更新了原始问题以反映这一点。我已经决定使用整个数组的视图,并按照您提到的那样对其进行切片。
猜你喜欢
  • 1970-01-01
  • 2019-04-07
  • 1970-01-01
  • 1970-01-01
  • 2016-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-29
相关资源
最近更新 更多