简体   繁体   English

带有 Cython 的布尔 numpy 数组

[英]Boolean numpy arrays with Cython

I have a numpy boolean array:我有一个 numpy 布尔数组:

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

If I try to initialise a Cython MemoryView with it, like this:如果我尝试用它初始化 Cython MemoryView,如下所示:

cdef bint[:,:] mymem = myarr

I get this error:我收到此错误:

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

If I do this instead, it works fine:如果我这样做,它工作正常:

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

How can I store a boolean numpy array using Cython MemoryViews?如何使用 Cython MemoryViews 存储布尔 numpy 数组?

This information seems to be not easy to find, my reference is pretty old (2011), but not much seems to have changed since then.这个信息似乎不太容易找到, 我的参考资料很旧(2011),但从那时起似乎没有太大变化。

Numpy's bool-array uses a 8bit-value for False/True (this is not obvious per se - C++'s std::vector<bool> uses for example 1 bit per value) with 0 -meaning False and 1 -meaning True . Numpy 的 bool-array 对 False/True 使用 8 位值(这本身并不明显 - C++ 的std::vector<bool>使用例如每个值 1 位),其中0 -meaning False1 -meaning True You can use cast=True for an unit8 -array in order to use it as a bool -array, for example:您可以对unit8使用cast=True以将其用作bool -array,例如:

 %%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

And now:现在:

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

Setting cast=True gives some slack to Cython's type-checking, so the numpy-arrays with the same element-size (for example uint8 , int8 and bool ) can be reinterpreted.设置cast=True会给 Cython 的类型检查带来一些松弛,因此可以重新解释具有相同元素大小(例如uint8int8bool )的 numpy 数组。 This however would not work if element-sizes were different: for example np.int8 (1byte) and np.int16 (2bytes).但是,如果元素大小不同,这将不起作用:例如np.int8 (1byte) 和np.int16 (2bytes)。

I ran into the same problem some time ago.前段时间我遇到了同样的问题。 Unfortunately I did not find a direct solution to this.不幸的是,我没有找到直接的解决方案。 But there is another approach: Since an array of boolean vales has the same data type size as uint8 , you could use a memory view with this type as well.但是还有另一种方法:由于布尔值数组与uint8具有相同的数据类型大小,因此您也可以使用这种类型的内存视图。 Values in the uint8 memory view can also be compared to boolean values, so the behavior is mostly equal to an actual bint memory view: 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)

Output:输出:

0
2
3

I found it simplest to do:我发现最简单的做法是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM