Преобразование массива строковых полей в числовой формат

У меня есть массив строк, сгруппированных в три поля:

x = np.array([(-1, 0, 1),
              (-1, 1, 0),
              (0, 1, -1),
              (0, -1, 1)],
             dtype=[('a', 'S2'),
                    ('b', 'S2'),
                    ('c', 'S2')])

Я хотел бы преобразовать в числовой массив (типа np.int8 для предпочтения, но не обязательно), в форме 4x3, вместо полей.

Мой общий подход состоит в том, чтобы преобразовать в массив 4x3 типа 'S2', а затем использовать astype чтобы сделать это численным. Единственная проблема заключается в том, что единственный подход, который я могу придумать, включает как view а также np.lib.stride_tricks.as_stridedчто не кажется очень надежным решением:

y = np.lib.stride_tricks.as_strided(x.view(dtype='S2'),
                                    shape=(4, 3), strides=(6, 2))
z = y.astype(np.int8)

Это работает для случая игрушек, показанного здесь, но я чувствую, что должен быть более простой способ распаковать массив с полями, имеющими один и тот же dtype. Что является более надежной альтернативой?

1 ответ

Решение

Добавлена ​​последняя версия numpy 1.16 structured_to_unstructured которая решает эту цель:

from numpy.lib.recfunctions import structured_to_unstructured
y = structured_to_unstructured(x)  # 2d array of 'S2'
z = y.astype(np.int8)

В предыдущей версии NumPy вы можете комбинировать x.data а также np.frombuffer создать другой массив из тех же данных в памяти без использования шагов. Это не приносит выигрыша в производительности, так как вычисления приводятся S2 в int8,

n = 1000

def f1(x):
    y = np.lib.stride_tricks.as_strided(x.view(dtype='S2'),
                                        shape=(n, 3),
                                        strides=(6, 2))
    return y.astype(np.int8)

def f2(x):
    y = np.frombuffer(x.data, dtype='S2').reshape((n, 3))
    return y.astype(np.int8)


x = np.array([(i%3-1, (i+1)%3-1, (i+2)%3-1)
              for i in xrange(n)],
             dtype='S2,S2,S2')

z1 = f1(x)
z2 = f2(x)
assert (z1==z2).all()
Другие вопросы по тегам