"Fancy Indexing with Broadcasting and Boolean Masking" 是如何工作的?
How does "Fancy Indexing with Broadcasting and Boolean Masking" work?
我在 Jake Vanderplas 的数据科学手册中看到了这段代码。我不清楚在这里使用广播和花式索引的概念。请解释。
In[5]: X = np.arange(12).reshape((3, 4))
X
Out[5]: array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In[6]: row = np.array([0, 1, 2])
col = np.array([2, 1, 3])
In[7]: X[row[:, np.newaxis], col]
Out[7]: array([[ 2, 1, 3],
[ 6, 5, 7],
[10, 9, 11]])
它说:"Here, each row value is matched with each column vector, exactly as we saw in broadcasting of arithmetic operations. For example:"
In[8]: row[:, np.newaxis] * col
Out[8]: array([[0, 0, 0],
[2, 1, 3],
[4, 2, 6]])
如果你使用整数数组来索引另一个数组
你基本上遍历给定的索引并沿着你正在索引的轴选择相应的元素(可能仍然是一个数组)并将它们堆叠在一起。
arr55 = np.arange(25).reshape((5, 5))
# array([[ 0, 1, 2, 3, 4],
# [ 5, 6, 7, 8, 9],
# [10, 11, 12, 13, 14],
# [15, 16, 17, 18, 19],
# [20, 21, 22, 23, 24]])
arr53 = arr55[:, [3, 3, 4]]
# pick the elements at (arr[:, 3], arr[:, 3], arr[:, 4])
# array([[ 3, 3, 4],
# [ 8, 8, 9],
# [13, 13, 14],
# [18, 18, 19],
# [23, 23, 24]])
因此,如果您使用长度为 k
(或长度 l
)的行(或列)索引对 (m, n)
数组进行索引,则结果形状为:
A_nm[row, :] -> A_km
A_nm[:, col] -> A_nl
如果您使用两个数组 row
和 col
来索引一个数组
您同时遍历两个索引并将元素(可能仍然是数组)堆叠在各自的位置。
这里 row
和 col
必须具有相同的长度。
A_nm[row, col] -> A_k
array([ 3, 13, 24])
arr3 = arr55[[0, 2, 4], [3, 3, 4]]
# pick the element at (arr[0, 3], arr[2, 3], arr[4, 4])
现在终于可以回答您的问题了:可以在索引数组时使用广播。有时不希望只有元素
(arr[0, 3], arr[2, 3], arr[4, 4])
被选中,而是扩展版本:
(arr[0, [3, 3, 4]], arr[2, [3, 3, 4]], arr[4, [3, 3, 4]])
# each row value is matched with each column vector
这个matching/broadcasting和其他算术运算完全一样。
但是这里的例子在某种意义上可能是不好的,因为所示乘法的结果对于索引并不重要。
这里的重点是组合和结果形状:
row * col
# performs a element wise multiplication resulting in 3
numbers
row[:, np.newaxis] * col
# performs a multiplication where each row value is *matched* with each column vector
这个例子想强调 row
和 col
的匹配。
我们可以看看并尝试不同的可能性:
n = 3
m = 4
X = np.arange(n*m).reshape((n, m))
row = np.array([0, 1, 2]) # k = 3
col = np.array([2, 1, 3]) # l = 3
X[row, :] # A_nm[row, :] -> A_km
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
X[:, col] # A_nm[:, col] -> A_nl
# array([[ 2, 1, 3],
# [ 6, 5, 7],
# [10, 9, 11]])
X[row, col] # A_nm[row, col] -> A_l == A_k
# array([ 2, 5, 11]
X[row, :][:, col] # A_nm[row, :][:, col] -> A_km[:, col] -> A_kl
# == X[:, col][row, :]
# == X[row[:, np.newaxis], col] # A_nm[row[:, np.newaxis], col] -> A_kl
# array([[ 2, 1, 3],
# [ 6, 5, 7],
# [10, 9, 11]])
X[row, col[:, np.newaxis]]
# == X[row[:, np.newaxis], col].T
# array([[ 2, 6, 10],
# [ 1, 5, 9],
# [ 3, 7, 11]])
我来这里是为了寻找这个问题的答案,hpaulj 的评论对我有帮助。我将对其进行扩展。
在以下代码段中,
import numpy as np
X = np.arange(12).reshape((3, 4))
row = np.array([0, 1, 2])
col = np.array([2, 1, 3])
Y = X[row.reshape(-1, 1), col]
我们传递给 X 的 索引 正在广播。
下面的代码遵循 numpy 广播规则但使用更多内存,完成相同的切片:
# Make the row and column indices 'conformable'
R = np.repeat(row.reshape(-1, 1), 3, axis=1) # repeat row index across columns
C = np.repeat(col.reshape(1, -1), 3, axis=0) # repeat column index across rows
Y = X[R, C] # Y[i, j] = X[R[i, j], C[i, j]]
我在 Jake Vanderplas 的数据科学手册中看到了这段代码。我不清楚在这里使用广播和花式索引的概念。请解释。
In[5]: X = np.arange(12).reshape((3, 4))
X
Out[5]: array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In[6]: row = np.array([0, 1, 2])
col = np.array([2, 1, 3])
In[7]: X[row[:, np.newaxis], col]
Out[7]: array([[ 2, 1, 3],
[ 6, 5, 7],
[10, 9, 11]])
它说:"Here, each row value is matched with each column vector, exactly as we saw in broadcasting of arithmetic operations. For example:"
In[8]: row[:, np.newaxis] * col
Out[8]: array([[0, 0, 0],
[2, 1, 3],
[4, 2, 6]])
如果你使用整数数组来索引另一个数组 你基本上遍历给定的索引并沿着你正在索引的轴选择相应的元素(可能仍然是一个数组)并将它们堆叠在一起。
arr55 = np.arange(25).reshape((5, 5))
# array([[ 0, 1, 2, 3, 4],
# [ 5, 6, 7, 8, 9],
# [10, 11, 12, 13, 14],
# [15, 16, 17, 18, 19],
# [20, 21, 22, 23, 24]])
arr53 = arr55[:, [3, 3, 4]]
# pick the elements at (arr[:, 3], arr[:, 3], arr[:, 4])
# array([[ 3, 3, 4],
# [ 8, 8, 9],
# [13, 13, 14],
# [18, 18, 19],
# [23, 23, 24]])
因此,如果您使用长度为 k
(或长度 l
)的行(或列)索引对 (m, n)
数组进行索引,则结果形状为:
A_nm[row, :] -> A_km
A_nm[:, col] -> A_nl
如果您使用两个数组 row
和 col
来索引一个数组
您同时遍历两个索引并将元素(可能仍然是数组)堆叠在各自的位置。
这里 row
和 col
必须具有相同的长度。
A_nm[row, col] -> A_k
array([ 3, 13, 24])
arr3 = arr55[[0, 2, 4], [3, 3, 4]]
# pick the element at (arr[0, 3], arr[2, 3], arr[4, 4])
现在终于可以回答您的问题了:可以在索引数组时使用广播。有时不希望只有元素
(arr[0, 3], arr[2, 3], arr[4, 4])
被选中,而是扩展版本:
(arr[0, [3, 3, 4]], arr[2, [3, 3, 4]], arr[4, [3, 3, 4]])
# each row value is matched with each column vector
这个matching/broadcasting和其他算术运算完全一样。 但是这里的例子在某种意义上可能是不好的,因为所示乘法的结果对于索引并不重要。 这里的重点是组合和结果形状:
row * col
# performs a element wise multiplication resulting in 3
numbers
row[:, np.newaxis] * col
# performs a multiplication where each row value is *matched* with each column vector
这个例子想强调 row
和 col
的匹配。
我们可以看看并尝试不同的可能性:
n = 3
m = 4
X = np.arange(n*m).reshape((n, m))
row = np.array([0, 1, 2]) # k = 3
col = np.array([2, 1, 3]) # l = 3
X[row, :] # A_nm[row, :] -> A_km
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
X[:, col] # A_nm[:, col] -> A_nl
# array([[ 2, 1, 3],
# [ 6, 5, 7],
# [10, 9, 11]])
X[row, col] # A_nm[row, col] -> A_l == A_k
# array([ 2, 5, 11]
X[row, :][:, col] # A_nm[row, :][:, col] -> A_km[:, col] -> A_kl
# == X[:, col][row, :]
# == X[row[:, np.newaxis], col] # A_nm[row[:, np.newaxis], col] -> A_kl
# array([[ 2, 1, 3],
# [ 6, 5, 7],
# [10, 9, 11]])
X[row, col[:, np.newaxis]]
# == X[row[:, np.newaxis], col].T
# array([[ 2, 6, 10],
# [ 1, 5, 9],
# [ 3, 7, 11]])
我来这里是为了寻找这个问题的答案,hpaulj 的评论对我有帮助。我将对其进行扩展。
在以下代码段中,
import numpy as np
X = np.arange(12).reshape((3, 4))
row = np.array([0, 1, 2])
col = np.array([2, 1, 3])
Y = X[row.reshape(-1, 1), col]
我们传递给 X 的 索引 正在广播。
下面的代码遵循 numpy 广播规则但使用更多内存,完成相同的切片:
# Make the row and column indices 'conformable'
R = np.repeat(row.reshape(-1, 1), 3, axis=1) # repeat row index across columns
C = np.repeat(col.reshape(1, -1), 3, axis=0) # repeat column index across rows
Y = X[R, C] # Y[i, j] = X[R[i, j], C[i, j]]