Je sais comment accéder aux éléments d'un vecteur par des indices en faisant:
Traceback (most recent call last): File "main.py", line 43, in <module> print(currentGrid[indices]) IndexError: too many indices for array
ce qui donne la bonne réponse: [2 4 6]
Mais j'essaye de faites la même chose en utilisant une matrice 2D, quelque chose comme:
indices = list([(0,0),(1,1),(0,2)])
cela devrait afficher "[0.0 0.9]" pour la valeur en (0,0) et celle en (1,1) dans la matrice. Mais à la place, il affiche "[0,1 0,1]". Aussi si j'essaye d'utiliser 3 index avec:
currentGrid = numpy.array( [[0, 0.1], [0.9, 0.9], [0.1, 0.1]]) indices = list([(0,0),(1,1)]) print(currentGrid[indices])
J'obtiens maintenant l'erreur suivante:
test = numpy.array([1,2,3,4,5,6]) indices = list([1,3,5]) print(test[indices])
J'ai finalement besoin pour appliquer une simple opération max () sur tous les éléments de ces indices et avoir besoin du moyen le plus rapide de le faire à des fins d'optimisation.
Qu'est-ce que je fais mal? Comment puis-je accéder à des éléments spécifiques d'une matrice pour effectuer des opérations sur eux de manière très efficace (sans utiliser la compréhension de liste ni une boucle).
3 Réponses :
Le problème est la disposition des indices que vous passez au tableau. Si votre tableau est bidimensionnel, vos indices doivent être deux listes, l'une contenant les indices verticaux et l'autre les index horizontaux. Par exemple:
idx_i, idx_j = zip(*[(0, 0), (1, 1), (0, 2)]) print currentGrid[idx_j, idx_i] # [0.0, 0.9, 0.1]
Notez que le premier élément lors de l'indexation des tableaux est la dernière dimension, par exemple: (y, x). Je suppose que vous avez défini le vôtre comme (x, y) sinon vous obtiendrez une IndexError
Merci pour votre réponse. Je comprends que l'utilisation de deux listes est la bonne façon d'accéder aux éléments par index. Mais est-il possible alors de faire une opération sur chacun de ces éléments sans utiliser une boucle for? J'essaye de trouver un moyen moins intensif en CPU vers un max (val, 0.5) sur tous ces éléments
Si vous ne vous souciez que des valeurs extraites, vous pouvez utiliser la fonction map
ou une compréhension de liste. Les deux sont bien plus rapides qu'une boucle for
, mais évitez les fonctions lambda
+ map
( voir ça ). Si vous voulez utiliser ces valeurs "à l'intérieur" du tableau, numpy
peut avoir une fonction qui peut mapper une fonction à ces positions.
Les index 2D doivent être accédés comme ceci:
print(currentGrid[indices[:,0], indices[:,1]])
Les index de ligne et les index de colonne doivent être passés séparément sous forme de listes.
Merci, vous avez raison, cela fonctionne. Mais est-il possible de faire un max (valeur, 0,5) sur tous ces éléments sans utiliser une boucle for?
Il existe déjà de bonnes réponses à votre problème. Voici juste une solution rapide et sale pour votre code particulier:
maxfunction = numpy.vectorize(lambda i: max(i,0.5)) print(maxfunction(currentGrid[newIndices]))
Si vous ne voulez pas utiliser une boucle for, vous devez faire le suivant:
Supposons que vous ayez 3 valeurs de votre matrice 2D (avec les dimensions x1
et x2
auxquelles vous voulez accéder. Les valeurs ont le "coordonnées" (indices) V1 (x11 | x21), V2 (x12 | x22), V3 (x13 | x23)
. Ensuite, pour chaque dimension de votre matrice (2 dans votre cas) vous avez besoin pour créer une liste avec les indices de cette dimension de vos points. Dans cet exemple, vous créeriez une liste avec les indices x1
: [x11, x12, x13]
et une liste avec les indices x2
de vos points: [x21, x22, x23]
. Ensuite, vous combinez ces listes et les utilisez comme index pour la matrice:
import pandas as pd maxValues = pd.Series(currentGrid[newIndices]).apply(lambda x: max(x,0.5))
ou comment vous l'écrivez:
originalIndices = [(0,0),(1,1),(2,0)] x1 = [] x2 = [] for i in originalIndices: x1.append(i[0]) x2.append(i[1]) newIndices = [x1,x2] print(currentGrid[newIndices])
Maintenant avec les points que vous avez utilisés ((0,0), ( 1,1), (2,0))
- veuillez noter que vous devez utiliser (2,0) au lieu de (0,2), car il serait hors de portée sinon:
maxValue = max(currentGrid[indices])
Cela vous donnera 0, 0.9, 0.1
. Et sur cette liste, vous pouvez ensuite appliquer la commande max () si vous le souhaitez (juste pour considérer toute votre question):
indices = list([(0,1,2),(0,1,0)]) print(currentGrid[indices])
Ici un exemple comment vous pouvez transformer votre liste d'index d'origine pour lui donner la forme correcte:
indices = list([(x11,x12,x13),(x21,x22,x23)])
Je ne sais pas si vous pouvez applique max (x, 0.5)
à un tableau numpy en utilisant une boucle. Mais vous pouvez utiliser Pandas à la place. Vous pouvez convertir votre liste en une série pandas puis appliquer une fonction lambda:
indices = [[x11,x12,x13],[x21,x22,x23]]
Cela vous donnera un tableau pandas contenant 0.5,0.9,0.5 code >, que vous pouvez simplement renvoyer dans une liste
maxValues = list (maxValues)
.
Juste une remarque: en arrière-plan, vous aurez toujours une sorte de boucle en cours, également avec cette commande. Je doute que vous obtiendrez de bien meilleures performances grâce à cela. Si vous voulez vraiment améliorer les performances, utilisez une boucle for, avec numba (il vous suffit d'ajouter un décorateur à votre fonction) et l'exécuter en parallèle. Ou vous pouvez utiliser la bibliothèque multiprocessing
et la fonction Pool
, voir ici . Juste pour vous donner de l'inspiration.
J'ai vu par hasard cette page aujourd'hui, qui permet de faire exactement ce que vous voulez avec Numpy
. La solution (à considérer dans le vecteur newIndices
de mon Edit2) à votre problème est:
for i in indices: print(currentGrid[i[0],i[1]])
Merci pour votre réponse mais j'ai précisé que je ne souhaitais pas utiliser de boucle for
Oui, ça aide beaucoup! Merci beaucoup. Savez-vous s'il est possible d'appliquer le maximum individuellement sur chaque valeur? Je suppose que je n'ai pas été assez clair. Je veux faire quelque chose comme val = max (val, 0,5) pour chaque valeur à chaque index. Est-ce possible sans utiliser une boucle for pour des problèmes d'optimisation?
Aujourd'hui, j'ai accidentellement trouvé la solution à votre problème. Voir le Edit 4 dans ma réponse.