ディメンション情報を失うことなくNumpyインデックススライス


98

私はnumpyを使用していて、ディメンション情報を失わずに行にインデックスを付けたいです。

import numpy as np
X = np.zeros((100,10))
X.shape        # >> (100, 10)
xslice = X[10,:]
xslice.shape   # >> (10,)  

この例では、xsliceは1次元になっていますが、(1,10)にしたいです。Rでは、X [10、:、drop = F]を使用します。numpyに似たものはありますか?ドキュメントでそれを見つけることができず、同様の質問が表示されませんでした。

ありがとう!

回答:


59

おそらくそれが最も簡単であるかx[None, 10, :]、それと同等です(しかし、より読みやすい)x[np.newaxis, 10, :]

なぜそれがデフォルトではないのかというと、個人的には、シングルトンの次元を持つ配列が常に存在することは非常に煩わしいことです。派手な開発者も同じように感じたと思います。

また、numpyはブロードキャスティング配列を非常にうまく処理するため、通常、スライスの元となった配列の次元を保持する理由はほとんどありません。もしそうなら、それから次のようなこと:

a = np.zeros((100,100,10))
b = np.zeros(100,10)
a[0,:,:] = b

機能しないか、実装がはるかに困難になります。

(または、少なくとも、スライス時にディメンション情報をドロップする背後にあるnumpy devの推論での私の推測です)


6
@リサ:x[None, 10]あなたがやりたいことをします。
naught101 2016年

うん。Nonesを刻んでいるdimの隣に置きます。
Mad Physicist

1
この例では、への割り当てでタプルの余分な括弧が欠落していbます。それはあるはずですb = np.zeros((100,10))
Jerzy

2つだけでなく、合計3つのインデックスを使用する理由は何ですか?つまりX[10,None](例としてコードを使用)。
greenoldman 2017

8
" 通常、配列の次元を保持する理由はほとんどありません " ...まあ、それは確かに、完全に、完全に行列の乗算(np.matmul()または@)を台無しにするでしょう。これでやけどした。
ジャン=フランソワ・コルベット

89

別の解決策は

X[[10],:]

または

I = array([10])
X[I,:]

インデックスのリスト(または配列)によってインデックス付けが実行されるとき、配列の次元は保持されます。寸法を維持するか、絞り込むかを選択できるので、これは素晴らしいことです。


2
これにより、配列データがコピーされます
2014年

これは常にそうであるとは限りません。参照してください。 x = np.array([[1,2,3,4]]) その後x[[0],[1,2]] 、1次元でスライスすると 、 array([2, 3]) 列または行のベクトルを選択するときに、スライスを単純にしてから使用するのが最善です np.reshape。つまり、私の例ではnp.reshape(x[0,[1,2]],[1,2])
Alexander

1
他の人は、最後にセミコロンに注意してください-それは重要です、X[[10]]と解釈されX[10]、形状が小さくなるでしょう。同様にX[[10, 20]] == X[10, 20]、形状はさらに小さくなります
Ben Usman

1
警告:この方法のインデックス付けと整数のインデックス付けを混在させないでください!あなたが持っていた場合aの形状で(10, 20, 30)、そのa[0, :, [0]]形状を持つことになり(1, 20)、ない(20, 1)後者のインデックスにまで放送されているので、a[[0], :, [0]]これはかなり頻繁にあなたが期待するものではありません!一方a[0, :, :1]、あなたを与えるだろう(20, 1)と予想通り。さらに、単一のインデックスを持つ奇妙なエッジケースについては、上記のコメントを参照してください。全体として、この方法にはエッジケースが多すぎるようです。
ベン・ウスマン

30

私はいくつかの合理的な解決策を見つけました。

1)使用 numpy.take(X,[10],0)

2)この奇妙なインデックスを使用する X[10:11:, :]

理想的には、これがデフォルトである必要があります。ディメンションが削除される理由を理解できませんでした。しかし、それはnumpyの議論です...


1
'dimensions'は、Pythonリストにインデックスを付けるときに削除alist[0]され、スライスするときに保持されます。
hpaulj 2018年

4
オプション2(slice(n, n+1)indexの抽出のように書くことができますn)は、n次元の場合に自然に拡張する唯一のオプションであるため、受け入れられる答えである必要があります。
norok2

オプション2はX[10:11, :]、Python 3.7.5(つまり、11の後の余分なコロンなし)のように書くことができるようです
Joe

6

これが私がもっと好きな代替案です。単一の番号でインデックスを作成する代わりに、範囲でインデックスを作成します。つまり、を使用しますX[10:11,:]。(10:1111は含まれないことに注意してください)。

import numpy as np
X = np.zeros((100,10))
X.shape        # >> (100, 10)
xslice = X[10:11,:]
xslice.shape   # >> (1,10)

これにより、より多くの次元でも理解しやすくなり、Noneどの軸がどのインデックスを使用するかをジャグリングおよび把握する必要がなくなります。また、通常のインデックス作成で使用したものi:i+1に対してのみ、配列サイズに関する追加の簿記を行う必要はありませんi

b = np.ones((2, 3, 4))
b.shape # >> (2, 3, 4)
b[1:2,:,:].shape  # >> (1, 3, 4)
b[:, 2:3, :].shape .  # >> (2, 1, 4)


0

これは、実行時に長さが1である可能性のある配列でインデックスを作成している場合は特に厄介です。その場合、次のようになりnp.ix_ます。

some_array[np.ix_(row_index,column_index)]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.