Как 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)
Другие вопросы по тегам