如何hstack数组的numpy记录?

时间:2013-02-18 19:57:33

标签: python numpy recarray

[这篇文章的早期版本有不准确的标题“如何将一列添加到numpy记录数组?”问题中的问题已经部分answered,但这个答案并不完全是该帖子早期版本的正文所要求的。我已经重新编写了标题,并对该帖子进行了大量编辑,以使区别更加清晰。我也解释了为什么我之前提到的答案不符合我的要求。]


假设我有两个numpy数组xy,每个数组都由 r “record”(又名“结构化”)数组组成。让x的形状为( r c x ),y的形状为( r c y )。我们还假设x.dtype.namesy.dtype.names之间没有重叠。

例如,对于 r = 2, c x = 2, c y = 1:

import numpy as np
x = np.array(zip((1, 2), (3., 4.)), dtype=[('i', 'i4'), ('f', 'f4')])
y = np.array(zip(('a', 'b')), dtype=[('s', 'a10')])

我希望“横向”连接xy以生成记录z数组,其形状( r < / em>, c x + c y )。此操作不应修改xy

一般来说,z = np.hstack((x, y))不会这样做,因为dtypex中的y不一定匹配。例如,继续上面的例子:

z = np.hstack((x, y))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-def477e6c8bf> in <module>()
----> 1 z = np.hstack((x, y))
TypeError: invalid type promotion


现在,有一个函数numpy.lib.recfunctions.append_fields看起来就像它可以做一些接近我正在寻找的东西,但我无法从中得到任何东西它:我尝试过的所有东西要么失败了,要么产生错误,或产生一些我想要得到的东西。

有人可以向我显示显式代码(使用n.l.r.append_fields或其他 1 ),这些代码会从x和{{{ 1}}在上面的例子中定义了一个 new 记录数组y,相当于zx的水平串联,并且没有修改yx

我认为这只需要一行或两行代码。当然,我正在寻找不需要构建y,按记录记录,迭代zx的代码。此外,代码可能会假设yx具有相同数量的记录,并且yx.dtype.names之间没有重叠。除此之外,我正在寻找的代码对y.dtype.namesx一无所知。理想情况下,关于要连接的数组的数量也应该是不可知的。 IOW,省略错误检查,我正在寻找的代码可能是函数y的主体,因此新数组hstack_rec将是结果z


1 ...虽然我不得不承认,在我hstack_rec((x, y))失败的最佳记录之后,我对这怎么样有点好奇函数可以 使用 ,无论它与此帖子的问题相关。

2 个答案:

答案 0 :(得分:4)

我从不使用重新排列,所以其他人会想出一些更流畅的东西,但也许merge_arrays会起作用?

>>> import numpy.lib.recfunctions as nlr
>>> x = np.array(zip((1, 2), (3., 4.)), dtype=[('i', 'i4'), ('f', 'f4')])
>>> y = np.array(zip(('a', 'b')), dtype=[('s', 'a10')])
>>> x
array([(1, 3.0), (2, 4.0)], 
      dtype=[('i', '<i4'), ('f', '<f4')])
>>> y
array([('a',), ('b',)], 
      dtype=[('s', '|S10')])
>>> z = nlr.merge_arrays([x, y], flatten=True)
>>> z
array([(1, 3.0, 'a'), (2, 4.0, 'b')], 
      dtype=[('i', '<i4'), ('f', '<f4'), ('s', '|S10')])

答案 1 :(得分:0)

这是一个非常晚的答案,但也许对其他人有帮助。在用大多数相同的标准提出同样的问题后,我使用了这个解决方案。

它不会生成新的numpy数组,但使用zipitertools.chain会更快。就我而言,我需要按顺序访问每一行的每个值。以下是模拟此用例的基准:

import numpy
from numpy.lib.recfunctions import merge_arrays
from itertools import chain

a = numpy.empty(3, [("col1", int), ("col2", float)])
b = numpy.empty(3, [("col3", int), ("col4", "U1")])

结果:

%timeit [i for i in (row for row in merge_arrays([a,b], flatten=True))]
52.9 µs ± 2 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit [i for i in (row for row in (chain(i,k) for i,k in zip(a,b)))]
3.47 µs ± 52 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)