Cython: хранение юникода в массиве numpy

Я новичок в Cython, и у меня возникла повторяющаяся проблема, связанная с кодированием Unicode внутри массива Numpy.

Вот пример проблемы:

import numpy as np
cimport numpy as np

cpdef pass_array(np.ndarray[ndim=1,dtype=np.unicode] a):
    pass

cpdef access_unicode_item(np.ndarray a):
    cdef unicode item = a[0]

Пример ошибки:

In [3]: unicode_array = np.array([u"array",u"of",u"unicode"],dtype=np.unicode)

In [4]: pass_array(unicode_array)
ValueError: Does not understand character buffer dtype format string ('w')

In [5]: access_item(unicode_array)
TypeError: Expected unicode, got numpy.unicode_

Кажется, проблема в том, что значения не являются реальным юникодом, а вместо этого numpy.unicode_ . Есть ли способ кодировать значения в массиве как надлежащий Unicode (чтобы я мог печатать отдельные элементы для использования в коде Cython)?

1 ответ

В Py2.7

In [375]: arr=np.array([u"array",u"of",u"unicode"],dtype=np.unicode)

In [376]: arr
Out[376]: 
array([u'array', u'of', u'unicode'], 
      dtype='<U7')

In [377]: arr.dtype
Out[377]: dtype('<U7')

In [378]: type(arr[0])
Out[378]: numpy.unicode_

In [379]: type(arr[0].item())
Out[379]: unicode

В общем x[0] возвращает элемент x в обалденном подклассе. В этом случае np.unicode_ это подкласс unicode,

In [384]: isinstance(arr[0],np.unicode_)
Out[384]: True

In [385]: isinstance(arr[0],unicode)
Out[385]: True

Я думаю, что вы столкнетесь с такими же проблемами между np.int32 а также int, Но я не достаточно работал с Cython, чтобы быть уверенным.


Где ты видел cython код, который определяет строку (Unicode или байт) dtype?

http://docs.cython.org/src/tutorial/numpy.html имеет такие выражения, как

# We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime
# type info object.
DTYPE = np.int
# "ctypedef" assigns a corresponding compile-time type to DTYPE_t. For
# every type in the numpy module there's a corresponding compile-time
# type with a _t-suffix.
ctypedef np.int_t DTYPE_t
....
def naive_convolve(np.ndarray[DTYPE_t, ndim=2] f):

Цель [] часть заключается в повышении эффективности индексации.

Тогда нам нужно набрать содержимое объектов ndarray. Мы делаем это с помощью специального синтаксиса "буфера", в котором необходимо указать тип данных (первый аргумент) и количество измерений (аргумент только для ключевого слова "ndim", если не указан, то предполагается одномерный).

Я не думаю np.unicode поможет, потому что он не указывает длину символа. Полная строка dtype должна включать количество символов, например. <U7 в моем примере.

Нам нужно найти рабочие примеры, которые передают строковые массивы - либо в документации по Cython, либо в других вопросах, касающихся SO.


Для некоторых операций вы можете рассматривать массив Unicode как массив int32,

In [397]: arr.nbytes
Out[397]: 84

3 строки x 7 символов / строка * 4 байта / символ

In [398]: arr.view(np.int32).reshape(-1,7)
Out[398]: 
array([[ 97, 114, 114,  97, 121,   0,   0],
       [111, 102,   0,   0,   0,   0,   0],
       [117, 110, 105,  99, 111, 100, 101]])

Cython дает вам наибольшее улучшение скорости, когда вы можете обходить функции и методы Python. Это будет включать обход большей части строки Python и функциональности Юникода.

Другие вопросы по тегам