【问题标题】:Truly recursive `tolist()` for NumPy structured arraysNumPy 结构化数组的真正递归`tolist()`
【发布时间】:2016-09-15 12:04:49
【问题描述】:

据我了解,将 NumPy 数组转换为原生 Python 列表的推荐方法是使用 ndarray.tolist

唉,这在使用结构化数组时似乎无法递归工作。实际上,结果列表中引用了一些 ndarray 对象,但未转换:

>>> dtype = numpy.dtype([('position', numpy.int32, 3)])
>>> values = [([1, 2, 3],)]
>>> a = numpy.array(values, dtype=dtype)
>>> a.tolist()
[(array([1, 2, 3], dtype=int32),)]

我确实写了一个简单的函数来解决这个问题:

def array_to_list(array):
    if isinstance(array, numpy.ndarray):
        return array_to_list(array.tolist())
    elif isinstance(array, list):
        return [array_to_list(item) for item in array]
    elif isinstance(array, tuple):
        return tuple(array_to_list(item) for item in array)
    else:
        return array

使用时会提供预期的结果:

>>> array_to_list(a) == values
True

这个函数的问题在于它通过重新创建它输出的每个列表/元组来复制ndarray.tolist 的工作。不是最优的。

所以问题是:

  • ndarray.tolist 的这种行为是否可以预料?
  • 有没有更好的方法来实现这一点?

【问题讨论】:

  • 对我来说,结构化数组作为带有列表值的字典(反之亦然)比列表列表更有意义。
  • Dict 确实有意义,但列表列表也是如此,因为结构化数组的字段在 dtype 中定义为有序列表。最重要的是,NumPy 理解用于初始化数组的 values 变量,即使它是以非字典格式定义的,所以列表列表在这里绝对是一个有效的结构。

标签: python numpy structured-array


【解决方案1】:

为了概括一下,我将在您的 dtype 中添加另一个字段

In [234]: dt = numpy.dtype([('position', numpy.int32, 3),('id','U3')])

In [235]: a=np.ones((3,),dtype=dt)

repr 显示确实使用列表和元组:

In [236]: a
Out[236]: 
array([([1, 1, 1], '1'), ([1, 1, 1], '1'), ([1, 1, 1], '1')], 
  dtype=[('position', '<i4', (3,)), ('id', '<U3')])

但正如您所注意到的,tolist 不会扩展元素。

In [237]: a.tolist()
Out[237]: [(array([1, 1, 1]), '1'), (array([1, 1, 1]), '1'), 
   (array([1, 1, 1]), '1')]

同样,这样的数组可以从完全嵌套的列表和元组中创建。

In [238]: a=np.array([([1,2,3],'str')],dtype=dt)
In [239]: a
Out[239]: 
array([([1, 2, 3], 'str')], 
  dtype=[('position', '<i4', (3,)), ('id', '<U3')])
In [240]: a.tolist()
Out[240]: [(array([1, 2, 3]), 'str')]

从这个不完整的递归中重新创建数组没有问题:

In [250]: np.array(a.tolist(),dtype=dt)
Out[250]: 
array([([1, 2, 3], 'str')], 
      dtype=[('position', '<i4', (3,)), ('id', '<U3')])

这是我第一次看到有人将tolist 与这样的结构化数组一起使用,但我并不感到惊讶。我不知道开发人员是否会认为这是一个错误。

为什么需要这个数组的纯列表/元组渲染?

我想知道numpy/lib/recfunctions.py 中是否有一个函数可以解决这个问题。

【讨论】:

  • 我在编写单元测试并希望将数组的内容与代表预期值的相应本机 Python 列表进行比较时偶然发现了这个问题。我知道可能还有其他方法可以解决这个问题,但我喜欢将数据从 NumPy 转换为 Python 的想法,因此我可以使用 assertIsEqual 测试,其实现在不相等时显示差异。归根结底,ndarray.tolist 似乎是一种有效的序列化方法,所以我觉得不在这里工作令人惊讶。也许我会在 NumPy 的 repo 上提交一个问题,看看他们是怎么说的。
猜你喜欢
  • 2012-06-17
  • 2019-05-08
  • 1970-01-01
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
  • 2016-03-29
  • 2012-08-12
  • 2016-04-28
相关资源
最近更新 更多