我有一个看起来像这样的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
那么发生了什么?有这个快速的解决方案吗?
像dtype
这样的numpy数组的np.array([1, None])
是object
。 int[:,::1]
期望int
的缓冲区,但得到object
的缓冲区,这就是错误说。
如何纠正这个问题应该取决于具体情况,具体来说,None
是什么意思?
None
s设置为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])
(这可能不是您的意图)所以,这取决于具体情况。
Numpys ma
模块(用于Masked Array)可能会做你想要的:
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)
我认为它是一个int8
,因为Cython与dtype=np.bool
的关系并不好。
您还可以考虑创建自己的数据结构 - 例如,它看起来总是行的结尾是None
,因此您可以创建int
s的二维数组和一维数组行长度(qdxswpois的一维数组) )。然后你会忽略行长以外的任何东西。
可能值得强调的是为什么你不能将int
存储在None
数组中 - 为了获得使用int
数组的速度和空间效率,Numpy只分配存储数字所需的空间。存储int
将涉及为每个数字分配一点额外的空间来说“实际上这个是不同的类型”,并且对于每个操作在它之前进行检查“这个数字实际上是一个数字吗?”。可以想象,快速变得低效。