Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

choisir une dimension parmi n et extraire tout ce qu'il y a dedans

+3 votes

J'ai un stack de données rangées dans un array à trois dimensions, par exemple:

import numpy as np
mon_array  = np.random.rand(2,3,5)

Je veux maintenant récupérer tout ce qu'il y a sur la dimension 2 (on commence à 1), à l'index 1. je peux taper:

mes_datas = mon_array[:,1,:]

oui mais voilà, comment faire si je veux pouvoir passer la dimension que je veux comme un paramètre?
J'ai tenté un eval (bouh bouh) à partir d'un string de commande, mais ça ne fonctionne pas.

dimension = 2
depth = 1
cmd_str = [':' if idx!=dimension-1 else str(depth) for idx in range(3)]
mes_datas = eval("mon_array"+str(cmd_str)) 
>>> mon_array['1', ':', ':']

En fait je voudrais pouvoir déclarer les deux points ":" comme autre chose qu'une string, ou les "déstringuer" dans mon eval.

demandé 25-Mar-2015 par furankun (1,434 points)
reclassée 25-Mar-2015 par max

2 Réponses

+3 votes
 
Meilleure réponse

Passer ':' dans les crochets est interprété comme 'slice(None)'.
Mettre plusieurs indices entre crochet est interprété comme passer un tuple.

En clair,

value = a[:, 1, :]

est équivalent à

idx = (slice(None), 1, slice(None))
value = a[idx]

Libre à toi de construire le tuple 'idx' qui te convient maintenant.

[edit bis]
Vu le comportement de numpy sur les derniers indices manquants, une solution pour toi serait

idx = tuple([slice(None) if idx!=dimension-1 else depth for idx in range(3)])
mes_datas = mon_array[idx]

ou encore

idx = tuple([slice(None)] * (dimension - 1) + [depth])
mes_datas = mon_array[idx]
répondu 25-Mar-2015 par bubulle (2,256 points)
edité 30-Mar-2015 par bubulle

en mixant vos deux posts, je tombe sur

>>> dimension = 2
>>> depth = 1
>>> idx = tuple([slice(None) if idx!=dimension-1 else depth for idx in range(3)])
>>> idx
(slice(None, None, None), 1, slice(None, None, None))
>>> mes_datas = mon_array[idx]

ce qui doit être le résultat recherché...

En fait, numpy interprète de la même manière les deux lignes suivantes:

>>> mon_array[:, 1, :]
>>> mon_array[:, 1]

raison pour laquelle je propose de construire idx sans les slice(None) finaux.

Une remarque en passant :
tuple(arg) accepte n'importe quel iterable en argument. En particulier, tu peux écrire directement

>>> idx = tuple(slice(None) if idx!=dimension-1 else depth for idx in range(3))

au lieu de

>>> idx = tuple([slice(None) if idx!=dimension-1 else depth for idx in range(3)])

Ceci évite la construction d'une liste et enlève 2 caractères :)

Je confirme la dernière solution:

>>> idx = tuple([slice(None) if idx!=dimension-1 else depth for idx in range(3)])

par contre

idx = tuple([slice(None)] * (dimension - 1) + [depth])

ne marche pas: ça modifie la longueur de idx en fonction de dimension et il m'en faut un qui soit toujours avec trois indices.

furankun, si ta réponse fonctionne remonte la en réponse de la question initiale, ce serait plus clair et plus pratique si jamais un autre personne passe par là et a le même problème.
kiss

0 votes

Je confirme la dernière solution:

>>> idx = tuple([slice(None) if idx!=dimension-1 else depth for idx in range(3)])

par contre

idx = tuple([slice(None)] * (dimension - 1) + [depth])

ne marche pas: ça modifie la longueur de idx en fonction de dimension et il m'en faut un qui soit toujours avec trois indices.

répondu 31-Mar-2015 par furankun (1,434 points)
...