2017-10-17 6 views
0

J'essaie d'appliquer une fonction à toutes les lignes d'un tableau numpy, cela fonctionne si les listes dans la rangée ont la même taille, mais échoue chaque fois que la taille est différente .appliquer le long de l'axe numpy avec différentes tailles de tableau

La fonction à appliquer

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 

PAS 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) 

Suis-je utiliser la r outil de travail pour le travail? l'idée ici est de vectoriser le calcul sous une série de listes.

Merci

+0

À quoi ressemble 'parseRPN'? – Kyle

+0

ça marche pour moi si j'applique une autre fonction ('def test (a): retourne a;') au lieu de 'parseRPN' sur le premier tableau. Le problème peut-il être dans 'parseRPN'? –

+4

Juste une note: Vous n'obtiendrez aucun gain de performance. 'apply_along_axis' n'est pas vectorisé et les tableaux non rectangulaires n'autorisent pas non plus la vectorisation. –

Répondre

1

Votre code fonctionne bien si vous utilisez seulement map ou une compréhension de la liste. Je ne m'inquiéterais pas de savoir si l'application de numpy est nécessaire avant d'avoir réellement besoin d'améliorer les performances.

+0

est une carte plus rapide qu'une boucle explir pour? –

+0

Un gourou python pourrait être en mesure d'aller plus loin sur la carte par rapport à la boucle for, mais je m'attendrais à ce que leurs performances soient presque identiques dans cette situation. – Kyle

0

Avec un traitement « rangée » complexe comme celui-ci, vous pourriez aussi bien traiter le tableau comme une liste:

Avec des lignes de longueur égale, dat est un tableau de caractères 2d:

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') 

Avec plus ou moins Enfin, la matrice est 1d type d'objet listes contenant:

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) 

Dans les deux cas, une simple itération de ligne fonctionne très bien (map travaille également, mais dans Py3 vous devez utiliser 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 utilise également l'itération comme ceci. C'est bien quand le tableau est 3d ou supérieur, mais pour l'itération de rangée sur un tableau 1 ou 2d c'est trop.

Pour un tableau d'objets comme dat1, frompyfunc pourrait avoir un léger avantage de vitesse:

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

np.vectorize est plus lent, mais fonctionne également avec le tableau d'objets

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

Mais son application au 2 Le tableau de caractères requiert l'utilisation de son paramètre signature, qui est plus lent et plus complexe.

numpy n'a pas résolu ce problème. Ceci est vraiment une liste de problèmes de listes:

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]