scipy.ndimage.generic_filter返回类型错误

问题描述:

我正在使用scipy.ndimage.generic_filter来计算数组的局部模态值。我正在比较两种方法来查看哪种方法更快(因为第一种方法非常慢)。我的第一个方法是;scipy.ndimage.generic_filter返回类型错误

import numpy as np 
import scipy.stats as stats 
import scipy.ndimage 

def modal(arr): 
    return stats.mode(arr, axis=None)[0][0] 

x = np.random.randint(0, 100, size=(10, 10)) 
scipy.ndimage.filters.generic_filter(x, modal, size=3) 

我的第二种方法是;

def modal(arr): 
    return np.argmax(np.bincount(arr.flatten())) 

x = np.random.randint(0, 100, size=(10, 10)) 
scipy.ndimage.filters.generic_filter(x, modal, size=3) 

但与第二种方法我得到这个:

TypeError         Traceback (most recent call last) 
<ipython-input-122-2e9030c57d71> in <module>() 
     1 #%timeit -n 5 -r 1 
----> 2 scipy.ndimage.filters.generic_filter(x, modal, size=3) 

C:\Python27\ArcGIS10.2\lib\site-packages\scipy\ndimage\filters.pyc in generic_filter(input, function, size, footprint, output, mode, cval, origin, extra_arguments, extra_keywords) 
    1161  mode = _ni_support._extend_mode_to_code(mode) 
    1162  _nd_image.generic_filter(input, function, footprint, output, mode, 
-> 1163       cval, origins, extra_arguments, extra_keywords) 
    1164  return return_value 

<ipython-input-118-86ea9b03ed30> in modal(arr) 
     1 def modal(arr): 
----> 2  return np.argmax(np.bincount(arr.flatten())) 
     3  return stats.mode(arr, axis=None)[0][0] 

TypeError: array cannot be safely cast to required type 

当我运行此:

stats.mode(x, axis=None)[0][0] == np.argmax(np.bincount(x.flatten())) 

它返回True

为什么generic_filter抛出类型错误当使用numpy.bincount方法而不是时方法返回值是否相同?

我在Windows 7上使用Python 2.7.3,Numpy 1.6.1和Scipy 0.14.0(我坚持使用这个版本的Numpy和Python,因为这是ESRI ArcGIS附带的)。我尝试安装scikit-image来计算模态过滤器,但是我在安装时遇到了其他错误,并认为解决这个问题更简单!

您可以通过将打印语句在modal调查此错误:

def modal(arr): 
    print(arr) 
    return np.argmax(np.bincount(arr.flatten())) 

你会看到输出如下

[ 92. 92. 31. 92. 92. 31. 87. 87. 18.] 

这表明arr包含浮动,而不是整数。 np.bincount的文档声明其第一个参数必须是非负整数的一维数组。

因此,您可以使用astype('int64')将浮点数作为整数来避免错误。

import numpy as np 
import scipy.stats as stats 
import scipy.ndimage 

def modal(arr): 
    return stats.mode(arr, axis=None)[0][0] 

def modal2(arr): 
    count = np.bincount(arr.astype('int64')) 
    return np.argmax(count) 

x = np.random.randint(0, 100, size=(10, 10)) 

out = np.empty_like(x, dtype='float') 
scipy.ndimage.filters.generic_filter(x, modal, size=3, output=out) 
print(out) 

scipy.ndimage.filters.generic_filter(x, modal2, size=3, output=out) 
print(out) 

PS。由于arr已经是一维的,因此可以删除对flatten的呼叫。