您的位置:首页 > 编程语言 > Python开发

Numpy快速处理数据--ufunc运算(三)

2015-05-28 20:50 567 查看
ufunc是universal function的缩写,它是一种能对数组中每个元素进行操作的函数。Numpy内置的许多ufunc函数都是C语言实现的,计算速度非常快,简单看个例子:

>>> x = np.linspace(0,2*np.pi,10)
>>> y=np.sin(x)
>>> y
array([  0.00000000e+00,   6.42787610e-01,   9.84807753e-01,
         8.66025404e-01,   3.42020143e-01,  -3.42020143e-01,
        -8.66025404e-01,  -9.84807753e-01,  -6.42787610e-01,
        -2.44929360e-16])
>>>
上述代码中先用linspace( )产生一个从0到2*PI的等差数组,然后将其传给np.sin( )计算每个元素的正弦值。函数计算完成后,返回一个计算结果的数组。如果通过out参数指定计算结果的保存位置,则计算结果将保存在out参数中,如:

>>> np.sin(x, out =y)
array([  0.00000000e+00,   6.42787610e-01,   9.84807753e-01,
         8.66025404e-01,   3.42020143e-01,  -3.42020143e-01,
        -8.66025404e-01,  -9.84807753e-01,  -6.42787610e-01,
        -2.44929360e-16])
>>> y
array([  0.00000000e+00,   6.42787610e-01,   9.84807753e-01,
         8.66025404e-01,   3.42020143e-01,  -3.42020143e-01,
        -8.66025404e-01,  -9.84807753e-01,  -6.42787610e-01,
        -2.44929360e-16])
>>>
对于计算单个元素,则建议采用Math库里对应的函数,np.sin( )对应math.sin( ),因为对于np.sin( )为了实现数组计算,底层做了很多复杂的处理,因此对于单个元素,math库里的函数计算速度快得多;而对于数组元素,则采用numpy库里的函数计算

在读取计算结果时,通过下标获取数组元素的类型为Numpy中定义的类型,将其转换为python的标准类型需耗时间。针对此问题,可以采用数组提供的item( )方法,用来获取数组中单个元素,并直接返回标准的python数据类型,如:

>>> a = np.arange(6.0).reshape(2,3)
>>> a.item(1,2)  #与a[1,2]类似
5.0
>>> type(a.item(1,2))
<class 'float'>
>>> type(a[1,2])
<class 'numpy.float64'>
>>>
一、数组的四则运算



二、比较和布尔运算

使用“==”、“>”等比较运算符比较两个数组,将返回一个布尔数组,它的每个元素的值是两个数组对应元素比较的结果,如:

>>> np.array([1,2,3])==np.array([3,2,1])
array([False,  True, False], dtype=bool)
>>> np.array([1,2,3])<np.array([3,2,1])
array([ True, False, False], dtype=bool)
>>>



由于Python的布尔运算使用and,or和Not等关键字,无法被重载,因此数组的布尔运算智能通过ufunc对应的函数来操作,这些函数以"logical_"开头,如下:



以“bitwise_"开头的函数是比特运算函数,包括bitwise_and、bitwise_not、bitwise_or和bitwise_xor等,也可以使用&、~、|、^等操作符来计算。对于布尔数组来说,位运算和布尔运算的结果相同,但是位运算符的优先级高于比较运算符。

自定义ufunc函数

通过Numpy提供的标准ufunc函数可以满足大多要求,但有些特殊情况需要自定义函数来实现。这时,可以采用python来实现,然后使用frompyfunc( )函数将一个计算单个元素的函数转换为ufunc函数。例如,用一个分段函数来描述三角波,它的样子如图所示:



Python函数定义如下:

def triangle_wave(x,c,c0,hc):
    x = x - int(x)   #周期为1,取小数部分计算
    if x>=c:
        r = 0.0
    elif x<c0:
        r = x/c0*hc
    else:
        r = (c-x)/(c-c0)*hc
    return r
1)通过列表推导计算

先使用列表推导计算一个列表,然后用array( )转换为数组,这种方法每次都要使用列表推导,而且对于多维数组,比较复杂,计算如下:

x = np.linspace(0,2,1000)
y1 = np.array([triangle_wave(t,0.6,0.4,1.0) for t in x])
2)fromnpyfunc( )函数计算

通过frompyfunc( )可以将计算单个值的函数转换为一个能对数组中每个元素计算的ufunc函数。frompyfunc( )的调用格式为:

frompyfunc(func,nin,nout)
其中,ufunc是计算单个元素的函数,nin是输入参数的个数,nout是func返回值的个数。如:

triangle_wave_ufunc = np.frompyfunc(triangle_wave,4,1)
y2 = triangle_wave_ufunc(x,0.6,0.4,1.0)
代码简洁高效。值得注意:triangle_wave_ufunc( )所返回数组的元素类型是object,因此还需要调用数组的astype()方法将其转换为双精度浮点数组



3)vectorize( )函数计算

使用vectorize( )可以实现和frompyfunc( )类似的功能,但他可以通过otypes参数指定返回数组的元素类型。otypes参数可以是一个表示元素类型的字符串,也可以是一个类型列表,使用列表可以描述多个返回数组的元素类型,如将上面的代码改成vectorize( ),则为:

triangle_wave_vec = np.vectorize(triangle_wave, otypes[np.float])
y3 = triangle_wave_vec(x,0.6,0.4,1.0)
到这里,ufunc函数的强大自不必言,如果将其与图像处理、信号处理等数组形式的应用结合起来,可以发挥强大作用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: