Как hstack массивы пустых записей?
[Более ранняя версия этого поста имела неточный заголовок "Как добавить один столбец в массив пустых записей?" На вопрос, заданный в том более раннем названии, уже был получен частичный ответ, но этот ответ не совсем то, о чем просила основная часть предыдущей версии этого поста. Я переписал название и существенно отредактировал пост, чтобы сделать различие более понятным. Я также объясняю, почему мой ответ, упомянутый ранее, не соответствует тому, что я ищу.]
Предположим, у меня есть два numpy
массивы x
а также y
каждый из которых состоит из r "record" (он же "структурированный") массивов. Пусть форма x
быть (г, с х) и форма 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, 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
а также y
определенный в примере выше, новый массив записей, z
эквивалентно горизонтальной конкатенации x
а также y
и сделать это без изменения либо x
или же y
?
Я предполагаю, что для этого потребуется всего одна или две строки кода. Конечно, я ищу код, который не требует сборки z
, запись за записью, перебирая x
а также y
, Кроме того, код может предполагать, что x
а также y
имеют одинаковое количество записей, и что между x.dtype.names
а также y.dtype.names
, Кроме этого, код, который я ищу, ничего не должен знать о x
а также y
, В идеале, это должно быть независимо от количества массивов, к которым нужно присоединиться. IOW, исключая проверку ошибок, код, который я ищу, может быть телом функции hstack_rec
так что новый массив z
будет результатом hstack_rec((x, y))
,
1 ... хотя я должен признать, что после моей до сих пор совершенной записи неудач с numpy.lib.recfunctions.append_fields
Мне стало немного любопытно, как вообще можно использовать эту функцию, независимо от ее отношения к вопросу этого поста.
2 ответа
Я никогда не использую повторные массивы, и поэтому кто-то еще придумает что-нибудь более приятное, но, возможно, 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')])
Это очень поздний ответ, но, возможно, он будет полезен кому-то еще. Я использовал это решение после того, как задавал один и тот же вопрос по большинству одинаковых критериев.
Он не генерирует новый массив 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)