[这篇文章的早期版本有不准确的标题“如何将一列添加到numpy记录数组?”问题中的问题已经部分answered,但这个答案并不完全是该帖子早期版本的正文所要求的。我已经重新编写了标题,并对该帖子进行了大量编辑,以使区别更加清晰。我也解释了为什么我之前提到的答案不符合我的要求。]
假设我有两个numpy
数组x
和y
,每个数组都由 r “record”(又名“结构化”)数组组成。让x
的形状为( r , c x ),y
的形状为( r , c y )。我们还假设x.dtype.names
和y.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')])
我希望“横向”连接x
和y
以生成新记录z
数组,其形状( r < / em>, c x + c y )。此操作不应修改x
或y
。
一般来说,z = np.hstack((x, y))
不会这样做,因为dtype
和x
中的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
,相当于z
和x
的水平串联,并且没有修改y
或x
?
我认为这只需要一行或两行代码。当然,我正在寻找不需要构建y
,按记录记录,迭代z
和x
的代码。此外,代码可能会假设y
和x
具有相同数量的记录,并且y
和x.dtype.names
之间没有重叠。除此之外,我正在寻找的代码对y.dtype.names
和x
一无所知。理想情况下,关于要连接的数组的数量也应该是不可知的。 IOW,省略错误检查,我正在寻找的代码可能是函数y
的主体,因此新数组hstack_rec
将是结果z
。
1 ...虽然我不得不承认,在我hstack_rec((x, y))
失败的最佳记录之后,我对这怎么样有点好奇函数可以 使用 ,无论它与此帖子的问题相关。
答案 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数组,但使用zip
和itertools.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)