Логические массивы numpy с Cython

У меня есть логический массив numpy:

myarr = np.array([[False, True], [True, False]])

Если я попытаюсь инициализировать с ним Cython MemoryView, вот так:

cdef bint[:,:] mymem = myarr

Я получаю эту ошибку:

ValueError: Does not understand character buffer dtype format string ('?')

Если я сделаю это вместо этого, он отлично работает:

cdef np.int_t[:,:] mymem = np.int_(myarr)

Как я могу сохранить логический массив numpy с помощью Cython MemoryViews?


person vktec    schedule 01.03.2018    source источник


Ответы (3)


Я столкнулся с той же проблемой некоторое время назад. К сожалению, я не нашел прямого решения этой проблемы. Но есть и другой подход: поскольку массив логических значений имеет тот же размер типа данных, что и uint8, вы также можете использовать представление памяти с этим типом. Значения в представлении памяти uint8 также можно сравнивать с логическими значениями, поэтому поведение в основном соответствует реальному представлению памяти bint:

cimport cython
cimport numpy as np
import numpy as np
ctypedef np.uint8_t uint8

cdef int i
cdef np.ndarray array = np.array([True,False,True,True,False], dtype=bool)
cdef uint8[:] view = np.frombuffer(array, dtype=np.uint8)
for i in range(view.shape[0]):
    if view[i] == True:
        print(i)

Выход:

0
2
3
person Padix Key    schedule 02.03.2018

Эту информацию не так просто найти, мой справочник довольно старый (2011 год), но с тех пор мало что изменилось.

Логический массив Numpy использует 8-битное значение для False/True (само по себе это неочевидно - std::vector<bool> C++ использует, например, 1 бит на значение) с 0-значением False и 1-значением True. Вы можете использовать cast=True для unit8-массива, чтобы использовать его как bool-массив, например:

 %%cython
 import numpy as np
 cimport numpy as np
 def to_bool_array(lst):
    cdef np.ndarray[np.uint8_t, ndim = 1, cast=True] res
    res=np.array(lst, dtype=bool)
    return res

И сейчас:

 >>> to_bool_array([True,False,True,False])
 array([ True, False,  True, False], dtype=bool)

Установка cast=True дает некоторую слабину проверке типов Cython, поэтому массивы numpy с одинаковым размером элемента (например, uint8, int8 и bool) могут быть переинтерпретированы. Однако это не сработало бы, если бы размеры элементов были разными: например, np.int8 (1 байт) и np.int16 (2 байта).

person ead    schedule 06.03.2018

Я нашел это проще всего сделать:

cdef uint8_t[:] arr_memview8 = data.astype(np.uint8)
bool* ptr = <bool*>&arr_memview8[0]
person SapphireSun    schedule 30.07.2018