从列表创建结构化数组

Jér*_*ôme 7 python numpy structured-array

我有一个简单的元素列表,我正试图从中制作一个结构化数组.

这种天真的方法失败了:

y = np.array([1,2,3], dtype=[('y', float)])
TypeError: expected an object with a buffer interface
Run Code Online (Sandbox Code Playgroud)

将每个元素放在一个元组中:

# Manuel way
y = np.array([(1,), (2,), (3,)], dtype=[('y', float)])
# Comprehension
y = np.array([tuple((x,)) for x in [1,2,3]], dtype=[('y', float)])
Run Code Online (Sandbox Code Playgroud)

如果我先从列表中创建一个数组,它也可以工作:

y = np.array(np.array([1,2,3]), dtype=[('y', float)])
Run Code Online (Sandbox Code Playgroud)

我有点不解.numpy如果提供一个简单的列表,后者如何工作却无法解决问题呢?

推荐的方式是什么?创建该中间体array可能不会产生很大的性能影响,但这不是次优的吗?

我也很惊讶那些不起作用:

# All lists
y = np.array([[1,], [2,], [3,]], dtype=[('y', float)])
TypeError: expected an object with a buffer interface
# All tuples
y = np.array(((1,), (2,), (3,)), dtype=[('y', float)])
ValueError: size of tuple must match number of fields.
Run Code Online (Sandbox Code Playgroud)

我是结构化数组的新手,我不记得numpy对输入类型的挑剔.肯定有一些我想念的东西.

hpa*_*ulj 6

如何np.array处理各种输入的细节隐藏在编译代码中。正如有关创建对象 dtype 数组的许多问题所显示的那样,它可能很复杂且令人困惑。基本模型是从嵌套列表创建多维数值数组。

np.array([[1,2,3],[4,5,6]])
Run Code Online (Sandbox Code Playgroud)

在实现结构化数组时,开发人员采用 将tuple记录与另一个嵌套维度区分开来。这在结构化数组的显示中很明显。

这也是定义结构化数组时的一项要求,尽管该list of tuples要求在某种程度上隐藏在文档中。

In [382]: dt=np.dtype([('y',int)])
In [383]: np.array(alist,dt)

TypeError: a bytes-like object is required, not 'int'
Run Code Online (Sandbox Code Playgroud)

这是我的版本“1.12.0”错误消息。你的情况似乎不一样。

正如您所注意到的,列表推导式可以将嵌套列表转换为元组列表。

In [384]: np.array([tuple(i) for i in alist],dt)
Out[384]: 
array([(1,), (2,), (3,)], 
      dtype=[('y', '<i4')])
Run Code Online (Sandbox Code Playgroud)

在回答 SO 问题时,这是我最常使用的方法。或者迭代设置预分配数组的字段(通常记录比字段多得多,因此循环并不昂贵)。

看起来将数组包装在结构化数组调用中等同于astype调用:

In [385]: np.array(np.array(alist),dt)
Out[385]: 
array([[(1,)],
       [(2,)],
       [(3,)]], 
      dtype=[('y', '<i4')])
In [386]: np.array(alist).astype(dt)
Out[386]: 
array([[(1,)],
       [(2,)],
       [(3,)]], 
      dtype=[('y', '<i4')])
Run Code Online (Sandbox Code Playgroud)

但请注意维数的变化。元组列表创建了一个 (3,) 数组。该astype转换后的(3,1)数字数组成(3,1)的结构阵列。

元组告诉的部分内容np.array是 - 将数组维度和记录之间的划分放在“这里”。它解释

[(3,), (1,), (2,)]
[record, record, record]
Run Code Online (Sandbox Code Playgroud)

哪里[[1],[2],[3]]可能会产生自动翻译

[[record],[record],[record]]
Run Code Online (Sandbox Code Playgroud)

当 dtype 是数字(非结构化)时,它会忽略列表和元组之间的区别

In [388]: np.array([tuple(i) for i in alist],int)
Out[388]: 
array([[1],
       [2],
       [3]])
Run Code Online (Sandbox Code Playgroud)

但是当 dtype 是复合的时,开发人员选择使用元组层作为重要信息。


考虑一个更复杂的结构化数据类型

In [389]: dt1=np.dtype([('y',int,(2,))])
In [390]: np.ones((3,), dt1)
Out[390]: 
array([([1, 1],), ([1, 1],), ([1, 1],)], 
      dtype=[('y', '<i4', (2,))])
In [391]: np.array([([1,2],),([3,4],)])
Out[391]: 
array([[[1, 2]],

       [[3, 4]]])
In [392]: np.array([([1,2],),([3,4],)], dtype=dt1)
Out[392]: 
array([([1, 2],), ([3, 4],)], 
      dtype=[('y', '<i4', (2,))])
Run Code Online (Sandbox Code Playgroud)

显示(和输入)在列表中的元组中有列表。而这只是开始

In [393]: dt1=np.dtype([('x',dt,(2,))])
In [394]: dt1
Out[394]: dtype([('x', [('y', '<i4')], (2,))])
In [395]: np.ones((2,),dt1)
Out[395]: 
array([([(1,), (1,)],), ([(1,), (1,)],)], 
      dtype=[('x', [('y', '<i4')], (2,))])
Run Code Online (Sandbox Code Playgroud)

将元组列表转换为结构化的 numpy 数组