代码之家  ›  专栏  ›  技术社区  ›  squirl

带Cython的布尔numpy数组

  •  7
  • squirl  · 技术社区  · 6 年前

    我有一个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)
    

    如何使用Cython MemoryView存储布尔numpy数组?

    3 回复  |  直到 6 年前
        1
  •  8
  •   ead    6 年前

    这些信息似乎不容易找到, my reference 很老了(2011年),但从那以后似乎没有太大变化。

    Numpy的bool数组使用8位值表示False/True(这本身并不明显-C++'s std::vector<bool> 例如,使用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=真 给Cython的类型检查留出了一些时间,因此numpy数组具有相同的元素大小(例如 uint8 , int8 布尔 )可以重新解释。但是,如果元素大小不同,这将不起作用:例如 np.int8 (1字节)和 np.int16 (2字节)。

        2
  •  4
  •   Eli Korvigo    6 年前

    不久前我遇到了同样的问题。不幸的是,我没有找到一个直接的解决办法。但还有另一种方法:因为布尔值数组的数据类型大小与 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
    
        3
  •  0
  •   SapphireSun    6 年前

    我发现这样做最简单:

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