Si vous tournez l'élément de numpy.array avec une instruction for, la vitesse d'exécution diminuera considérablement.
Pour contourner le problème, essayez ceci un peu plus vite
--list Notation inclusive --Utilisez np.où si les conditions sont complexes --Utilisez np.frompyfunc (mais soyez prudent lorsque vous l'utilisez)
J'ai appris cela, donc ce mémorandum.
C'est déjà écrit partout,
import numpy as np
a = np.array(range(10))
a2 = []
for x in a:
a2.append(x*2)
Si tu fais quelque chose comme ça
a2 = [x*2 for x in a]
L'histoire que vous devriez le faire. Ce sera beaucoup plus rapide à vivre.
Par exemple, si vous voulez jouer avec le tableau a, mais que vous voulez déterminer les conditions en fonction des éléments du tableau b.
A titre d'exemple, considérons le cas où les éléments du tableau a sont doublés si les éléments du tableau b sont pairs, et les éléments du tableau a sont triplés sinon.
Utilisez np.where pour éviter de vouloir utiliser un index comme C ++ et tournez-le avec for.
import numpy as np
a = np.array(range(10))
print "a = ", a
b = a + 100
print "b = ", b
#Cela ressemble à ceci lors de l'utilisation de l'index
result1 = []
for i in range(10) :
answer = a[i]*2 if b[i]%2 == 0 else a[i]*3
result1.append(answer)
print np.array(result1)
# np.Si vous utilisez where et la fonction, vous pouvez écrire sur une ligne et c'est rapide
def func_double(x) :
return x*2
def func_triple(x) :
return x*3
result2 = np.where(b%2 == 0, func_double(a), func_triple(a))
print result2
Comme vous l'avez commenté, si c'est une fonction de ce degré, vous pouvez incorporer la fonction telle qu'elle est dans la notation d'inclusion de liste.
(Cependant, personnellement, je n'aime pas incorporer des fonctions directement dans la notation d'inclusion de liste ... Il est difficile de changer diverses choses plus tard, j'oublie de les changer, et un jeune étudiant avec une génération de python liste la première langue Si vous écrivez un code long et merdique dans la notation incluse, ce sera net comme "C'est vraiment difficile à lire !!!" (rires))
Quand je cherchais quelque chose d'un peu plus rapide, j'ai trouvé la page suivante, donc je vous remercie de l'utiliser.
Le moyen le plus rapide d'appliquer une fonction arbitraire à tous les éléments d'une liste Python Fonction de carte d'expérimentation d'accélération Python-
Alors, utilisons frompyfunc.
import numpy as np
# prepare input arrays
a = np.array(range(10))
print "array a is", a
b = a + 100
print "array b is", b
def addition(x, y):
return x + y
np_addition = np.frompyfunc(addition, 2, 1)
print "print a + b using frompyfunc"
print np_addition(a, b)
print "print a + 1 using frompyfunc"
print np_addition(a, 1)
print "print 1 + b using frompyfunc"
print np_addition(1, b)
def subtruction(x, y):
return x - y
np_subtruction = np.frompyfunc(subtruction, 2, 1)
print "using np.where and frompyfuncs"
result2 = np.where(b%2 == 0, np_addition(a, b), np_subtruction(a, b))
print result2
Les arguments de la fonction universelle créée par frompyfunc sont le premier objet fonction, le deuxième nombre d'arguments et le troisième nombre de valeurs de retour. Avec cela, si vous insérez un tableau dans l'argument d'une fonction universelle, le résultat de l'application de la fonction à chaque élément sera renvoyé sous forme de tableau.
Et s'il y avait une chose aussi pratique, j'aurais dû l'utiliser rapidement. Même en termes d'expérience, cela semble environ 30% plus rapide que la notation d'inclusion de liste.
Donc, ce que je voulais vérifier, c'est ** Est-il possible de passer un tableau à l'argument de la fonction universelle créée par ce frompyfunc et de faire du reste juste un float **? L'histoire.
Le résultat n'est pas du tout un problème! ~~ En d'autres termes, il renvoie le résultat calculé en ne modifiant que la partie où le tableau est passé pour chaque élément. ~~ ~~ De plus, quel que soit l'argument utilisé comme tableau, il sera décidé arbitrairement. ~~
~~ Génial! !! : souriant: ~~
(Correction) Ce n'était pas un tel problème, mais la fonction que les opérateurs + et de numpy utilisaient dans les fonctions d'addition et de soustruction acceptait simplement le tableau d'arguments et le scalaire (correction). Larmes) Donc, si vous mettez une simple liste au lieu de np.array dans les arguments a et b, l'exemple ci-dessus mourra.
C'est pourquoi j'ai supprimé la partie que j'avais écrite auparavant. (Fin de la correction) </ div>
Cependant, frompyfunc a certains aspects à prendre en compte, je vais donc le décrire ci-dessous.
Dans la valeur de retour (numpy.array) de la fonction universelle créée par frompyfunc, dtype devient le type Object. (Le type de l'élément à l'intérieur est conservé)
C'est bien de simplement faire référence au contenu du tableau normalement, mais lorsque j'essaie de l'utiliser avec numpy.histogramadd, par exemple, je me fâche parce que je ne peux pas passer du type Object à d'autres types comme indiqué ci-dessous.
...numpy/lib/function_base.py", line 1014, in histogramdd
flatcount = bincount(xy, weights)
TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'
Pour éviter cela, vous pouvez convertir la valeur de retour numpy.array avec un type, mais ...
result2 = np.where(b%2 == 0, np_addition(a, b).astype(np.float64), np_subtruction(a, b).astype(np.float64))
Le problème est qu'un type est une fonction qui crée et renvoie un nouveau tableau, donc une copie du tableau se produit ici. Selon les conditions, ce temps de copie peut entraîner une vitesse d'exécution qui ne change pas même si elle est activée dans la notation d'inclusion de liste.
Dans les trois dernières lignes de l'exemple, il a été confirmé que la fonction universelle créée par np.where et frompyfunc peut être utilisée ensemble. Mais apparemment, cela est assez lent. C'était une erreur dans le programme que je pensais qu'il serait 10 fois plus lent à un moment donné, mais il semble que c'est environ deux fois plus lent. C'est pourquoi il semble difficile à utiliser dans des situations où la vitesse est importante.
Dans le cas d'un exemple simple comme celui donné ici, je pense que la notation d'inclusion de liste est presque la même.
Cependant, il y a des cas où vous ne voulez pas que la notation interne soit encombrée de fonctions et de conditions et que la lisibilité soit réduite, ou lorsque vous voulez faire un travail compliqué qui ne peut pas être écrit en une seule ligne en premier lieu. Dans un tel cas, je me suis rendu compte qu'il serait difficile de chercher et qu'il faudrait un temps inattendu pour écrire du code en utilisant le bon sens du langage que j'ai étudié il y a longtemps.
J'ai essayé divers plans pour accélérer le code que j'avais déjà écrit, mais à la fin, il est préférable de réécrire l'argument de la fonction qui est le matériau afin qu'il accepte à la fois le scalaire et le tableau depuis le début et se déplace rapidement. Je sens que c'est bien.
Si vous pouvez faire cela, la combinaison de np.where et des fonctions existantes aura l'air la plus propre et la plus rapide, et vous n'aurez pas à créer une fonction universelle avec frompyfunc.
Depuis que j'ai été une personne ayant appris les programmes en Fortran et C ++, j'ai écrit une fonction qui traite les données une par une, et écrit un programme qui n'est pas complètement hors de l'idée de le traiter en le tournant avec for. Si vous savez depuis le début que vous utiliserez numpy, numpy a de nombreuses fonctions qui gèrent rapidement les tableaux, j'ai donc pensé que c'était la bonne réponse de le concevoir pour traiter plusieurs enregistrements en tant que matrice depuis le début. pense.
Recommended Posts