これは、numpyが高度なインデックスを使用して配列形状をブロードキャストする方法です。0
最初のインデックスとy
最後のインデックスにaを渡すと、numpyはと0
同じ形になるようにをブロードキャストしますy
。次の同等性が成立しますx[0,:,:,y] == x[(0, 0, 0),:,:,y]
。ここに例があります
import numpy as np
x = np.arange(120).reshape(2,3,4,5)
y = np.array([0,2,4])
np.equal(x[0,:,:,y], x[(0, 0, 0),:,:,y]).all()
# returns:
True
ここで、2つのセットのインデックスを効果的に渡すため、高度なインデックスAPIを使用して(この場合は)インデックスのペアを作成します。
x[(0, 0, 0),:,:,y])
# equivalent to
[
x[0,:,:,y[0]],
x[0,:,:,y[1]],
x[0,:,:,y[2]]
]
# equivalent to
rows = np.array([0, 0, 0])
cols = y
x[rows,:,:,cols]
# equivalent to
[
x[r,:,:,c] for r, c in zip(rows, columns)
]
これには、の長さと同じ最初の次元がありy
ます。これはあなたが見ているものです。
例として、次のチャンクで説明されている4次元の配列を見てください。
x = np.arange(120).reshape(2,3,4,5)
y = np.array([0,2,4])
# x looks like:
array([[[[ 0, 1, 2, 3, 4], -+ =+
[ 5, 6, 7, 8, 9], Sheet1 |
[ 10, 11, 12, 13, 14], | |
[ 15, 16, 17, 18, 19]], -+ |
Workbook1
[[ 20, 21, 22, 23, 24], -+ |
[ 25, 26, 27, 28, 29], Sheet2 |
[ 30, 31, 32, 33, 34], | |
[ 35, 36, 37, 38, 39]], -+ |
|
[[ 40, 41, 42, 43, 44], -+ |
[ 45, 46, 47, 48, 49], Sheet3 |
[ 50, 51, 52, 53, 54], | |
[ 55, 56, 57, 58, 59]]], -+ =+
[[[ 60, 61, 62, 63, 64],
[ 65, 66, 67, 68, 69],
[ 70, 71, 72, 73, 74],
[ 75, 76, 77, 78, 79]],
[[ 80, 81, 82, 83, 84],
[ 85, 86, 87, 88, 89],
[ 90, 91, 92, 93, 94],
[ 95, 96, 97, 98, 99]],
[[100, 101, 102, 103, 104],
[105, 106, 107, 108, 109],
[110, 111, 112, 113, 114],
[115, 116, 117, 118, 119]]]])
x
非常にわかりやすいシーケンシャルフォームがあり、これを使用して何が起こっているかを示すことができます...
最初の次元は2つのExcelワークブックを持つようなもので、2番目の次元は各ワークブックに3つのシートを持つようなものです。3番目の次元はシートごとに4行を持つようなもので、最後の次元は各行(またはシートごとの列)に対して5つの値です。
このように見て、を求めるのはx[0,:,:,0]
、「最初のワークブックでは、各シート、各行、最初の値/列を教えてください」ということです。
x[0,:,:,y[0]]
# returns:
array([[ 0, 5, 10, 15],
[20, 25, 30, 35],
[40, 45, 50, 55]])
# this is in the same as the first element in:
x[(0,0,0),:,:,y]
しかし、高度なインデックス作成を使用すると、x[(0,0,0),:,:,y]
「最初のワークブックでは、各シート、各行、y
th番目の値/列を取得できます。OKの各値に対して実行してくださいy
」
x[(0,0,0),:,:,y]
# returns:
array([[[ 0, 5, 10, 15],
[20, 25, 30, 35],
[40, 45, 50, 55]],
[[ 2, 7, 12, 17],
[22, 27, 32, 37],
[42, 47, 52, 57]],
[[ 4, 9, 14, 19],
[24, 29, 34, 39],
[44, 49, 54, 59]]])
頭がおかしいのは、numpyがブロードキャストして、インデックス配列の外側の次元に一致することです。したがって、上記と同じ操作を実行する必要がある場合は、「Excelワークブック」の両方について、ループして連結する必要はありません。最初の次元に配列を渡すことができますが、互換性のある形状でなければなりません。
整数を渡すと、にブロードキャストされy.shape == (3,)
ます。配列を最初のインデックスとして渡す場合、配列の最後の次元のみがと互換性があればよいy.shape
。つまり、最初のインデックスの最後の次元は3または1でなければなりません。
ix = np.array([[0], [1]])
x[ix,:,:,y].shape
# each row of ix is broadcast to length 3:
(2, 3, 3, 4)
ix = np.array([[0,0,0], [1,1,1]])
x[ix,:,:,y].shape
# this is identical to above:
(2, 3, 3, 4)
ix = np.array([[0], [1], [0], [1], [0]])
x[ix,:,:,y].shape
# ix is broadcast so each row of ix has 3 columns, the length of y
(5, 3, 3, 4)
ドキュメントで短い説明が見つかりました:https : //docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing
編集:
元の質問から、希望するサブスライスのワンライナーを取得するには、以下を使用できますx[0][:,:,y]
。
x[0][:,:,y].shape
# returns
(2, 50, 3)
ただし、割り当てようとしている場合これらのサブスライスている場合は、元の配列の共有メモリビューを確認するように十分注意する必要があります。そうでない場合、割り当ては元の配列ではなくコピーになります。
共有メモリは、あなたがあなたの配列をサブセットする整数またはスライスを使用しているとき、すなわち、発生しますx[:,0:3,:,:]
かx[0,:,:,1:-1]
。
np.shares_memory(x, x[0])
# returns:
True
np.shares_memory(x, x[:,:,:,y])
# returns:
False
元の質問と私の例の両方で y
両方で、intでもスライスでもないため、常にのコピーに割り当てられます。
だが!以下のためのあなたの配列があるためy
、スライスのように表すことができ、あなたはCAN実際経由して、あなたの配列の割り当て可能なビューを取得:
x[0,:,:,0:21:10].shape
# returns:
(2, 50, 3)
np.shares_memory(x, x[0,:,:,0:21:10])
# returns:
True
# actually assigns to the original array
x[0,:,:,0:21:10] = 100
ここでは、スライスを使用して、にある0:21:10
すべてのインデックスを取得しrange(0,21,10)
ます。私たちは、使用する必要が21
ない20
だけのように、ストップポイントがスライスから除外されているため、range
関数の。
したがって、基本的には、サブスライス基準に適合するスライスを作成できれば、割り当てを行うことができます。