2017-10-17 78 views
0

我想應用一個函數的numpy數組的所有行,它的工作原理如果行中的列表具有相同的大小,但失敗時,只要有一個不同的大小。沿軸numpy應用與不同大小的陣列

的功能不OK

dat=np.array([['4','5','*','6','+','3','/'],['4','4','*','6','*'],['4','5','*','6','+'],['4','5','*','6','+']]) 
lout=np.apply_along_axis(parseRPN,0,dat) 

print(dat) 
print(lout) 

OK

dat=np.array([['4','5','*','6','+'],['4','4','*','6','*'],['4','5','*','6','+'],['4','5','*','6','+']]) 
lout=np.apply_along_axis(parseRPN,0,dat) 

print(dat) 
print(lout) 

我是否使用R應用

from math import * 
import operator 



def parseRPN(expression,roundtointeger=False): 
    """Parses and calculates the result of a RPN expression 
     takes a list in the form of ['2','2','*'] 
     returns 4 
    """"" 

    def safe_divide(darg1, darg2): 
     ERROR_VALUE = 1. 
     # ORIGINAL ___ Here we can penalize asymptotes with the var PENALIZE_ASYMPITOTES 

     try: 
      return darg1/darg2 
     except ZeroDivisionError: 
      return ERROR_VALUE 

    function_twoargs = {'*': operator.mul, '/': safe_divide, '+': operator.add, '-': operator.sub} 
    function_onearg = {'sin': sin, 'cos': cos} 
    stack = [] 
    for val in expression: 
     result = None 
     if val in function_twoargs: 
      arg2 = stack.pop() 
      arg1 = stack.pop() 
      result = function_twoargs[val](arg1, arg2) 
     elif val in function_onearg: 
      arg = stack.pop() 
      result = function_onearg[val](arg) 
     else: 
      result = float(val) 
     stack.append(result) 

    if roundtointeger == True: 
     result=stack.pop() 
     result=round(result) 
    else: 
     result=stack.pop() 
    return result 

該工作的ight工具?這裏的想法是將計算向量化爲一系列列表。

感謝

+0

'parseRPN'是什麼樣的? – Kyle

+0

如果我在第一個數組上應用另一個函數('def test(a):return a;')而不是'parseRPN',它對我有用。問題可能在'parseRPN'中? –

+4

只是一個說明:你不會得到任何性能收益。 'apply_along_axis'不是矢量化的,非矩形數組不允許矢量化 –

回答

1

您的代碼工作正常,如果你只是用map或列表理解。

map(parseRPN, dat) 

我不會擔心搞清楚numpy的應用,直到你真的需要提高性能。

+0

映射更快然後循環的explicir? –

+0

一個蟒蛇大師可能會更深入地圖vs for循環,但我希望他們的表現在這種情況下幾乎是相同的。 – Kyle

0

有了這樣一個複雜的「行」處理,你還不如把數組作爲一個列表:

等長行,dat是一個二維字符數組:

In [138]: dat=np.array([['4','5','*','6','+'],['4','4','*','6','*'],['4','5','*' 
    ...: ,'6','+'],['4','5','*','6','+']]) 
In [139]: dat 
Out[139]: 
array([['4', '5', '*', '6', '+'], 
     ['4', '4', '*', '6', '*'], 
     ['4', '5', '*', '6', '+'], 
     ['4', '5', '*', '6', '+']], 
     dtype='<U1') 

有了變化長度,所述陣列是包含一維對象類型的列表:

In [140]: dat1=np.array([['4','5','*','6','+','3','/'],['4','4','*','6','*'],['4 
    ...: ','5','*','6','+'],['4','5','*','6','+']]) 
In [141]: dat1 
Out[141]: 
array([list(['4', '5', '*', '6', '+', '3', '/']), 
     list(['4', '4', '*', '6', '*']), 
     list(['4', '5', '*', '6', '+']), 
     list(['4', '5', '*', '6', '+'])], dtype=object) 

在任一種情況下,一個簡單的行迭代工作正常(map也適用,但在Py3中,您必須使用list(map(...)))。

In [142]: [parseRPN(row) for row in dat] 
Out[142]: [26.0, 96.0, 26.0, 26.0] 
In [143]: [parseRPN(row) for row in dat1] 
Out[143]: [8.666666666666666, 96.0, 26.0, 26.0] 

apply_along_axis也使用這樣的迭代。當數組爲3d或更高時很好,但對於1或2d數組的行迭代它是過度的。

對於一個對象數組像dat1frompyfunc可能有一個溫和的速度優勢:

In [144]: np.frompyfunc(parseRPN,1,1)(dat1) 
Out[144]: array([8.666666666666666, 96.0, 26.0, 26.0], dtype=object) 

np.vectorize是慢,但還與對象數組

In [145]: np.vectorize(parseRPN)(dat1) 
Out[145]: array([ 8.66666667, 96.  , 26.  , 26.  ]) 

但它應用到2D字符數組需要使用其參數signature,這個參數更慢,更復雜。

numpy對此問題沒有幫助。這真是一個列表問題列表:

In [148]: dat=[['4','5','*','6','+'],['4','4','*','6','*'],['4','5','*','6','+'] 
    ...: ,['4','5','*','6','+']] 
In [149]: [parseRPN(row) for row in dat] 
Out[149]: [26.0, 96.0, 26.0, 26.0]