2015-12-17 27 views
2

我正在設置一個numpy數組和冪律方程。問題是,當x是負數且n不是整數時,我的域的一部分嘗試執行numpy.power(x,n)。在這部分域中,我希望值爲0.0。下面是一個具有正確行爲的代碼,但是有更多的Pythonic方法來執行此操作嗎?Numpy數組變量避免錯誤計算

# note mesh.x is a numpy array of length nx 
myValues = npy.zeros((nx)) 
para = [5.8780046, 0.714285714, 2.819250868] 
for j in range(nx): 
    if mesh.x[j] > para[1]: 
     myValues[j] = para[0]*npy.power(mesh.x[j]-para[1],para[2]) 

    else: 
     myValues[j] = 0.0 

回答

1

是「numpythonic」嗎?它應該是一個詞。以下是真的既不是Python的,也不unpythonic,但它是比使用for迴路,和close(R)的方式更有效Travis可能會做到這一點:

import numpy 
mesh_x = numpy.array([0.5,1.0,1.5]) 
myValues = numpy.zeros_like(mesh_x) 
para = [5.8780046, 0.714285714, 2.819250868] 
mask = mesh_x > para[1] 
myValues[mask] = para[0] * numpy.power(mesh_x[mask] - para[1], para[2]) 
print(myValues) 

對於您可能希望非常大的問題避免創建臨時數組:

mask = mesh.x > para[1] 
myValues[mask] = mesh.x[mask] 
myValues[mask] -= para[1] 
myValues[mask] **= para[2] 
myValues[mask] *= para[0] 
+0

第一個剪輯引發異常。回溯(最近一次調用最後一次): 文件「C:\ Users \ choutman \ Documents \ confocal beads \ Modeling \ Carl_1D_coupled_time.py」,line 85,in myValues [mask] = para [0] * npy.power文件「C:\ Python27 \ lib \ site-packages \ fipy \ variables \ unaryOperatorVariable.py」,第67行,在_calcValue_ 中的文件:mesh.x [mask] - para [1],para [2]){{clip}返回self.op(self.var [0] .value) 文件「C:\ Python27 \ lib \ site-packages \ fipy \ variables \ variable.py」,行1572,在 return self._UnaryOperatorVariable(lambda a :a [index], IndexError:不支持的迭代器索引 –

+0

我不能複製你的問題我編輯了我的答案,包括一個完整的例子,如果你的'mesh.x'不是一個標準的' numpy.array',而是一個'matr ix'或其他派生類 - 可以這樣嗎?如果是這樣,也許可以說'mask =(numpy.asarray(mesh.x)> para [1])'是安全的。 – jez

+0

是的,確切地說。 mesh.x是從FiPy派生的類。當我按照你的建議將它作爲一個numpy數組轉換時,它可以正常工作。謝謝。 –

1

下面是與np.where一種方法功率計算和0之間作出選擇的價值觀 -

import numpy as np 
np.where(mesh.x>para[1],para[0]*np.power(mesh.x-para[1],para[2]),0) 

說明:

  1. np.where(mask,A,B)選擇從A或B取決於mask元素的元素。因此,對於所有mesh.x元素一次完成矢量化比較,在我們的情況下爲mesh.x>para[1]
  2. para[0]*np.power(mesh.x-para[1],para[2])爲我們提供了掩模元素爲True時要選擇的元素。否則,我們選擇0,這是np.where的第三個參數。
+0

+1教給我關於'numpy.where'的這種用法,但我沒有意識到,但是對於'mesh.x **的所有**元素都會發生減法,求冪和乘法的事實回到0。 '然後選擇事後。這不會使結果成爲一個複雜的數組,因爲違反條件的情況? – jez

+0

呃,顯然不是,如果'mesh.x'開頭並不複雜:相反它會在不好的位置返回'nan'。我再次學習一些東西。 *但是*你*做*得到'RuntimeWarning:在電源遇到無效值' – jez

+0

@jez我認爲這些*壞*位置將被'0'填充的其他部分掩蓋,對吧? – Divakar

0

更多的解釋@jez和@Divakar給出的答案與簡單的例子比答案本身。他們都依靠某種形式的boolean indexing

>>> 
>>> a 
array([[-4.5, -3.5, -2.5], 
     [-1.5, -0.5, 0.5], 
     [ 1.5, 2.5, 3.5]]) 
>>> n = 2.2 
>>> a ** n 
array([[   nan,   nan,   nan], 
     [   nan,   nan, 0.21763764], 
     [ 2.44006149, 7.50702771, 15.73800567]]) 

np.where爲此,它根據布爾數組選擇兩個值之一。

>>> np.where(np.isnan(a**n), 0, a**n) 
array([[ 0.  , 0.  , 0.  ], 
     [ 0.  , 0.  , 0.21763764], 
     [ 2.44006149, 7.50702771, 15.73800567]]) 
>>> 
>>> b = np.where(a < 0, 0, a) 
>>> b 
array([[ 0. , 0. , 0. ], 
     [ 0. , 0. , 0.5], 
     [ 1.5, 2.5, 3.5]]) 
>>> b **n 
array([[ 0.  , 0.  , 0.  ], 
     [ 0.  , 0.  , 0.21763764], 
     [ 2.44006149, 7.50702771, 15.73800567]]) 

左手側使用布爾索引和右手邊。這與np.where

>>> 
>>> a[a >= 0] = a[a >= 0] ** n 
>>> a 
array([[ -4.5  , -3.5  , -2.5  ], 
     [ -1.5  , -0.5  , 0.21763764], 
     [ 2.44006149, 7.50702771, 15.73800567]]) 
>>> a[a < 0] = 0 
>>> a 
array([[ 0.  , 0.  , 0.  ], 
     [ 0.  , 0.  , 0.21763764], 
     [ 2.44006149, 7.50702771, 15.73800567]]) 
>>>