我有一个np.ndarray
,看起来像这样:
print(x)
[[1 3 None None None None]
[0 2 3 4 None None]
[1 5 4 None None None]
[1 6 0 4 None None]
[7 6 5 1 3 2]
[4 7 2 8 None None]
[7 4 3 None None None]
[4 6 8 5 None None]
[7 5 None None None None]]
我将其提供给定义如下的cython函数:
cpdef y(int[:,::1] x):
...
这引发了错误:ValueError:缓冲区dtype不匹配,应为'int',但有Python对象
这很可能是由于数组中存在None
s,因为将它们修改为0
s会消除错误。但是None
的存在不应该构成问题,就像这里写的:Cython Extension Types
那么,这是怎么回事?有一个快速的解决方案吗?
答案 0 :(得分:0)
诸如dtype
之类的numpy数组的np.array([1, None])
是object
。 int[:,::1]
期望有int
的缓冲区,但是得到object
的缓冲区,这就是错误所在。
如何更正此情况取决于上下文,具体地说,None
是什么意思?
None
设置为0,然后将数组转换为int
数组a = np.array([[1, None]])
a[a==None] = 0
a = a.astype(np.int)
f(a) # then deal with 0
f(double[:, ::1])
a = np.array([[1, None]])
a = a.astype(np.float)
# a will be np.array([1.0, nan]),
# then deal with nan...
f(a)
f(object[:, ::1])
(这可能不是您的意图)所以,这取决于上下文。
答案 1 :(得分:0)
Numpys ma
模块(用于蒙版数组)可能会满足您的要求:
x = np.ma.array([[1, 3, 0, 0, 0, 0],
[0, 2, 3, 4, 0, 0]],
dtype=np.int,
mask=[[0, 0, 1, 1, 1, 1],
[0, 0, 0, 0, 1, 1]]) # True is "masked out"
在Cython中,您将其分为数据和掩码
def y(x):
cdef int[:,::1] x_data = x.data
cdef int8_t[:,::1] x_mask = x.mask.view(dtype=np.int8)
由于Cython对int8
的处理不好,因此我将其视为dtype=np.bool
。
您还可以考虑创建自己的数据结构-例如,看起来总是None
的行的末尾,因此您可以创建int
的2D数组,一维数组的行长(int
的一维数组)。然后,您将忽略行长以外的任何内容。
可能值得强调为什么不能将None
存储在int
数组中-为了获得使用int
数组的速度和空间效率,然后Numpy仅分配存储数字所需的空间。存储None
会涉及为每个数字分配一点额外的空间,以便说“实际上这个数字是不同的类型”,并且每个操作之前都要检查“这个数字实际上是数字吗? ”。您可以想象很快就会变得效率低下。