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 .
1.17.3 3.7.5 (par défaut, 25 octobre 2019, 10:52:18)
[Clang 4.0.1 (tags / RELEASE_401 / final)]
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:
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
où ...
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.
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é commeseries, ..., color
où...
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