问题描述
据我了解,将NumPy数组转换为本地Python列表的推荐方法是使用 ndarray.tolist
.
From what I understand, the recommended way to convert a NumPy array into a native Python list is to use ndarray.tolist
.
A,使用结构化数组时,这似乎无法递归工作.确实,某些ndarray
对象在未转换的结果列表中被引用:
Alas, this doesn't seem to work recursively when using structured arrays. Indeed, some ndarray
objects are being referenced in the resulting list, unconverted:
>>> 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),)]
我确实编写了一个简单的函数来解决此问题:
I did write a simple function to workaround this issue:
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
使用时可以提供预期的结果:
Which, when used, provides the expected result:
>>> array_to_list(a) == values
True
此功能的问题在于,它通过重新创建输出的每个列表/元组来复制ndarray.tolist
的作业.并非最佳.
The problem with this function is that it duplicates the job of ndarray.tolist
by recreating each list/tuple that it outputs. Not optimal.
所以问题是:
-
ndarray.tolist
的这种行为是预期的吗? - 有没有更好的方法来实现这一目标?
- is this behaviour of
ndarray.tolist
to be expected? - is there a better way to make this happen?
推荐答案
只是概括一下,我将在您的dtype中添加另一个字段
Just to generalize this a bit, I'll add an another field to your dtype
In [234]: dt = numpy.dtype([('position', numpy.int32, 3),('id','U3')])
In [235]: a=np.ones((3,),dtype=dt)
repr
显示确实使用列表和元组:
The repr
display does use lists and tuples:
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
不会展开元素.
but as you note, tolist
does not expand the elements.
In [237]: a.tolist()
Out[237]: [(array([1, 1, 1]), '1'), (array([1, 1, 1]), '1'),
(array([1, 1, 1]), '1')]
类似地,可以从完全嵌套的列表和元组创建这样的数组.
Similarly, such an array can be created from the fully nested lists and tuples.
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')]
通过这种不完全的递归重新创建数组没有问题:
There's no problem recreating the array from this incomplete recursion:
In [250]: np.array(a.tolist(),dtype=dt)
Out[250]:
array([([1, 2, 3], 'str')],
dtype=[('position', '<i4', (3,)), ('id', '<U3')])
这是我第一次看到有人将tolist
与这样的结构化数组一起使用,但是我并不感到惊讶.我不知道开发人员是否会认为这是一个错误.
This is the first that I've seen anyone use tolist
with a structured array like this, but I'm not too surprised. I don't know if developers would consider this a bug or not.
为什么需要此数组的纯列表/元组渲染?
Why do you need a pure list/tuple rendering of this array?
我想知道numpy/lib/recfunctions.py
中是否有一个函数可以解决这个问题.
I wonder if there's a function in numpy/lib/recfunctions.py
that addresses this.
这篇关于NumPy结构化数组的真正递归`tolist()`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!