Преобразование массива строковых полей в числовой формат
У меня есть массив строк, сгруппированных в три поля:
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()