Numpy: Le comportement d'indexation avec des ellipses n'est pas intuitif.

Créé le 27 juil. 2020  ·  6Commentaires  ·  Source: numpy/numpy

L'indexation de tableaux avec des ellipses peut être extrêmement contre-intuitive. Par exemple, dans l'exemple suivant, l'introduction d'ellipses redondantes modifie la forme de la sortie:

a = np.array([[[False]]])
a[0:0, 0, ..., [0]]
Out[23]: array([], shape=(1, 0), dtype=bool)
a[0:0, 0,  [0]]
Out[24]: array([], shape=(0, 1), dtype=bool)

Je ne pense pas que ce soit le comportement souhaité, mais il semble provenir directement de décisions de conception en ce qui concerne la façon dont l' indexation complexe est gérée .

Informations sur la version Numpy / Python:

1.17.3 3.7.5 (par défaut, 25 octobre 2019, 10:52:18)
[Clang 4.0.1 (tags / RELEASE_401 / final)]

04 - Documentation 33 - Question 57 - Close?

Commentaire le plus utile

Je conviens que tout cela est déroutant, et je n'aurais même pas été certain sans vérifier ce qui se passe ici. Mais cela me semble être le bon choix.

Pourquoi devrait-il être vraiment «invisible»? ... doit se comporter de la même manière pour n'importe quel nombre de dimensions. Pour ce faire, il doit déclencher la transposition dans tous les cas. C'est-à-dire imaginer quelque chose organisé comme series, ..., color... est défini par l'utilisateur et peut être 0-d. Si vous deviez écrire un programme pour gérer ces données, vous auriez besoin que l'indexation soit transposée de manière prévisible, peu importe à quoi ... développe (ou ne se développe pas).

En fin de compte, c'est tout simplement déroutant, et nous devrions prendre .oindex , et .vindex etc. plus sérieusement pour le résoudre: https://numpy.org/neps/nep- 0021-advanced-indexing.html

Tous les 6 commentaires

Cela ressemble à un cas de coin particulièrement méchant - je suppose que nous considérons le ... comme forçant les deux indices avancés, 0 et [0] , à être considérés comme non adjacents - même si les axes qu'ils indexent _sont_ adjacents.

Nous avons rencontré ce problème lors de la tentative de réplication de l'indexation numpy. Je pense que c'est une étrange interaction entre deux règles:

  • L'ellipse se développe en un tuple de tranches complètes, chacune étant considérée comme un index de base
  • Les index avancés et basiques d'ordre mixte déclenchent une opération de transposition.

Ce cas particulier est déclenché car un tuple 0-d (lorsque ... est utilisé avec tous les index présents) est toujours considéré comme un bloc d'index de base, alors qu'il devrait vraiment être invisible.

Je conviens que tout cela est déroutant, et je n'aurais même pas été certain sans vérifier ce qui se passe ici. Mais cela me semble être le bon choix.

Pourquoi devrait-il être vraiment «invisible»? ... doit se comporter de la même manière pour n'importe quel nombre de dimensions. Pour ce faire, il doit déclencher la transposition dans tous les cas. C'est-à-dire imaginer quelque chose organisé comme series, ..., color... est défini par l'utilisateur et peut être 0-d. Si vous deviez écrire un programme pour gérer ces données, vous auriez besoin que l'indexation soit transposée de manière prévisible, peu importe à quoi ... développe (ou ne se développe pas).

En fin de compte, c'est tout simplement déroutant, et nous devrions prendre .oindex , et .vindex etc. plus sérieusement pour le résoudre: https://numpy.org/neps/nep- 0021-advanced-indexing.html

Je suis d' accord avec l'argument de

Je ne connaissais pas cette proposition, merci pour la référence @seberg!

Permettez-moi de reformuler pour m'assurer de bien comprendre votre argument. Disons que nous étiquetons les indices avancés A et les indices de base B et comme ci-dessus, j'appelle l'opération de réorganisation une transposition (généralisée). Dans votre exemple, nous avons quatre cas:

  • [A1, ..., A2] et [B1, ... A1] : ces cas déclenchent la transposition en [A1, A2, ....] et [A1, B1, ...] quelle que soit la façon dont ... développe.
  • [A1, ..., B1] et [B1, ..., B2] : ce n'est pas le cas.

Ces règles sont cohérentes une fois que vous savez à quelle classe (A ou B) series et color appartiennent, indépendamment de la façon dont ... développe. Cela équivaut à traiter le ... comme un bloc (potentiellement 0-d) d'indices de base. Traiter le 0-d ... comme un cas spécial serait mauvais car la transposition serait conditionnelle au fait que l'utilisateur passe dans un tableau 2D ou 3-ou-plus-D. Je suis d'accord, c'est un mauvais endroit où être.

Mon intuition que les blocs 0-d devraient être no-op était motivée par le comportement des tuples, où pour tout i ,

i: int
M: Tuple[int, ...]
N = ()
assert M[:i] + N + M[i:] == M

Cela entre en conflit avec la convention d'indexation numpy qui aboutit aux quatre cas ci-dessus en fonction de ce qu'est i . Cela a plus à voir avec l'opération de transposition elle-même, plutôt que la façon dont ... est traité, et c'est un argument pour la proposition NEP21.

Au cours du développement, nous changerions la façon dont nous procédions à l'indexation et insérerions ... pour pérenniser le code et être vraiment confus lorsque les formes se transposaient comme par magie. Il était simplement exacerbé par le fait que le cas vide ... était particulièrement contre-intuitif.

Merci d'avoir jeté un coup d'œil! Je peux soumettre un doc PR si vous le souhaitez.

@antonl un doc PR est toujours le bienvenu, il y a de nombreuses améliorations possibles ici.

Cette page vous a été utile?
0 / 5 - 0 notes