[英]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 False
和1
-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 的类型检查带来一些松弛,因此可以重新解释具有相同元素大小(例如uint8
、 int8
和bool
)的 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.