14

たまたま、の配列がnumpy空のタプルによってインデックス付けされている可能性があることを発見しました。

In [62]: a = arange(5)

In [63]: a[()]
Out[63]: array([0, 1, 2, 3, 4])

numpy wikiZeroRankArrayでいくつかのドキュメントを見つけました:

(サーシャ)まず、x[...]とx[()]の選択は同じである必要があります。これは、...が「必要な数:必要な数」の構文糖衣であり、ゼロの場合は同じであるためです。ランクは...=(:、)* 0 =()につながります。次に、ランクゼロの配列とnumpyスカラータイプはnumpy内で交換可能ですが、ndarrayが使用できない一部のPythonコンストラクトではnumpyスカラーを使用できます。

したがって、0-d配列の場合a[()]a[...]は同等であると想定されます。高次元配列用でもありますか?それらは強く次のように見えます:

In [65]: a = arange(25).reshape(5, 5)

In [66]: a[()] is a[...]
Out[66]: False

In [67]: (a[()] == a[...]).all()
Out[67]: True

In [68]: a = arange(3**7).reshape((3,)*7)

In [69]: (a[()] == a[...]).all()
Out[69]: True

しかし、それは糖衣構文ではありません。高次元配列ではなく、0次元配列でもありません。

In [76]: a[()] is a
Out[76]: False

In [77]: a[...] is a
Out[77]: True

In [79]: b = array(0)

In [80]: b[()] is b
Out[80]: False

In [81]: b[...] is b
Out[81]: True

そして、空のリストによるインデックス作成の場合があります。これは、まったく別のことを行いますが、空のリストを使用したインデックス作成と同等のように見えますndarray

In [78]: a[[]]
Out[78]: array([], shape=(0, 3, 3, 3, 3, 3, 3), dtype=int64)

In [86]: a[arange(0)]
Out[86]: array([], shape=(0, 3, 3, 3, 3, 3, 3), dtype=int64)

In [82]: b[[]]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)

IndexError: 0-d arrays can't be indexed.

したがって、()...は類似しているように見えますが、完全に同一ではなく、インデックスを付ける[]ことはまったく別のことを意味します。そしてa[]b[]またははSyntaxErrorsです。リストを使用したインデックス作成はインデックス配列で文書化されており、同じドキュメントの最後にタプルを使用したインデックス作成に関する短い通知があります。

それは疑問を残します:

a[()]との違いはa[...]設計によるものですか?では、デザインは何ですか?

(どういうわけか、空の `()`はMatlabマトリックスで何をするのかを思い出させる質問ですか?

編集:

実際、スカラーでさえ空のタプルによって索引付けされる場合があります。

In [36]: numpy.int64(10)[()]
Out[36]: 10
4

3 に答える 3

8

の扱いA[...]は特殊なケースであり、常に自分自身を返すAように最適化されています。

if (op == Py_Ellipsis) {
    Py_INCREF(self);
    return (PyObject *)self;
}

同等である必要がある他のすべて、たとえば、、、はA[:]A[(Ellipsis,)]代わりに、の全体のビューを返します。A[()]A[(slice(None),) * A.ndim]AbaseA

>>> A[()] is A
False
>>> A[()].base is A
True

これは不必要で時期尚早の最適化のように思われます。これA[(Ellipsis,)]A[()]常に同じ結果をもたらすためです(の全体像A)。https://github.com/numpy/numpy/commit/fa547b80f7035da85f66f9cbabc4ff75969d23cdを見ると、0d配列(以前はhttps://github.com/numpy/numpy... )でのインデックス作成が適切に機能しなかったため、元々必要だったようです。 / commit / 4156b241aa3670f923428d4e72577a9962cdf042要素をスカラーとして返します)、一貫性を保つためにすべての配列に拡張します。それ以来、インデックス付けは0d配列で修正されているため、最適化は必要ありませんが、痕跡的に固執することができます(そして、おそらくA[...] is Atrueに依存するコードがいくつかあります)。

于 2013-02-04T18:12:21.877 に答える
5

あなたが与えた例では、空のタプルと省略記号は同様の結果をもたらしますが、一般的にそれらは異なる目的を果たします。配列にインデックスを付ける場合A[i, j, k] == A[(i, j, k)]、具体的にはA[...] == A[(Ellipsis,)]。ここで、タプルは単に要素にインデックスを付けるためのコンテナとして機能します。これは、インデックスを変数として操作する必要がある場合に役立ちます。たとえば、次のことができます。

index = (0,) * A.ndim
A[index]

タプルは要素にインデックスを付けるためのコンテナであるため、他のインデックス(たとえば、)と組み合わせることはできないことに注意してA[(), 0] == A[[], 0]くださいA[(), 0] != A[..., 0]

配列Aは、よりも少ないインデックスでインデックスを作成できるためA.ndim、空のタプルを使用したインデックスはその動作の自然な拡張であり、状況によっては便利です。たとえば、上記のコードsnipitはA.ndim == 0

要するに、タプルはインデックス要素のコンテナとして機能し、空にすることができますが、省略記号は可能なインデックス要素の1つです。

于 2013-02-04T17:38:46.477 に答える
5

Numpyの公式ドキュメントによると、違いは明らかです。

空の(タプル)インデックスは、ゼロ次元配列への完全なスカラーインデックスです。がゼロ次元のx[()]場合はスカラーを返し、それ以外の場合はビューを返します。x一方、x[...]常にビューを返します

省略記号(...)が存在するがサイズがない(つまり、ゼロを置き換える :)場合でも、結果は常に配列になります。高度なインデックスが存在しない場合はビュー、それ以外の場合はコピー。

>>> import numpy as np
>>> # ---------------------------------- #
>>> # when `x` is at least 1 dimensional #
>>> # ---------------------------------- #
>>> x = np.linspace(0, 10, 100)
>>> x.shape
(100,)
>>> x.ndim
1
>>> a = x[()]
>>> b = x[...]
>>> id(x), id(a), id(b)
(4559933568, 4561560080, 4585410192)
>>> id(x.base), id(a.base), id(b.base)
(4560914432, 4560914432, 4560914432)
>>> # ---------------------------- #
>>> # when `z` is zero dimensional #
>>> # ---------------------------- #
>>> z = np.array(3.14)
>>> z.shape
()
>>> z.ndim
0
>>> a = z[()]
>>> b = z[...]
>>> type(a), type(b)
(<class 'numpy.float64'>, <class 'numpy.ndarray'>)
>>> id(z), id(a), id(b)
(4585422896, 4586829384, 4561560080)
>>> id(z.base), id(a.base), id(b.base)
(4557260904, 4557260904, 4585422896)
>>> b.base is z
True
于 2018-10-24T03:19:23.453 に答える