NumPy - 从另一个二维数组中选择一个子矩阵
NumPy - Selecting a submatrix from another 2d array
这是我原来的二维数组A
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 2, 2, 2, 2, 2, 0, 0, 0],
[0, 2, 2, 2, 2, 2, 2, 0, 0, 0],
[0, 2, 2, 2, 2, 2, 2, 0, 0, 0],
[0, 2, 2, 2, 2, 2, 2, 0, 0, 0],
[0, 2, 2, 8, 8, 8, 2, 0, 0, 0],
[0, 2, 2, 8, 8, 8, 2, 0, 0, 0],
[0, 0, 0, 8, 8, 8, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
假设我想 return 一个 3x3 中间为 8 的子矩阵。我用这个表达式 A == 8
做了一个布尔掩码,它看起来像这样。
array([[False, False, False, False, False, False, False, False, False,
False],
[False, False, False, False, False, False, False, False, False,
False],
[False, False, False, False, False, False, False, False, False,
False],
[False, False, False, False, False, False, False, False, False,
False],
[False, False, False, False, False, False, False, False, False,
False],
[False, False, False, True, True, True, False, False, False,
False],
[False, False, False, True, True, True, False, False, False,
False],
[False, False, False, True, True, True, False, False, False,
False],
[False, False, False, False, False, False, False, False, False,
False],
[False, False, False, False, False, False, False, False, False,
False]])
这就是我卡住的地方。我如何 return 具有该布尔掩码的子矩阵?如果我这样做 A[A == 8]
,它 return 是一个像这样的 8 平面数组
array([8, 8, 8, 8, 8, 8, 8, 8, 8])
另一种方法是使用 np.where(A == 8)
获取行号和列号,其中 returns (array([5, 5, 5, 6, 6, 6, 7, 7, 7]), array([3, 4, 5, 3, 4, 5, 3, 4, 5]))
。我如何 return 矩阵使用它们?
这个问题有更好的方法吗?
如评论中所述,A[A==some_value]
正确地 returns 一个 rank-1 值数组 some_value
。这是有道理的,因为值 some_value
并不总是组织在一个块中(例如 some_value = 2
),或者值 some_value
的数量无法放入二维数组。
但是如果你确定有这样的块,你可以通过以下方式获取:
import numpy as np
inds = np.where(A==8)
slice_x = slice(inds[0].min(), inds[0].max() + 1) # slice(6, 9, None)
slice_y = slice(inds[1].min(), inds[1].max() + 1) # slice(3, 6, None)
A[slice_x, slice_y]
# array([[8, 8, 8],
# [8, 8, 8],
# [8, 8, 8]])
或者,您可以使用 scipy.ndimage.find_objects
获取切片:
from scipy import ndimage
slice_x, slice_y = ndimage.find_objects(A==8)[0] # (slice(6, 9, None), slice(3, 6, None))
您可以捕获 row
和 column
索引,然后仅使用 np.ix_
方法从这些索引捕获 return 子矩阵:
x, y = np.where(A==8) #[5 5 5 6 6 6 7 7 7], [3 4 5 3 4 5 3 4 5]
x, y = np.unique(x), np.unique(y) # [5,6,7], [3,4,5]
print(A[np.ix_(x, y)]) #prints [[8 8 8], [8 8 8], [8 8 8]]
这甚至在更一般的情况下也应该有效,尽管并不总是如预期的那样:
def submatrix(A):
x, y = np.where(A==8)
x, y = np.unique(x), np.unique(y)
return A[np.ix_(x, y)]
>>> A = np.array([
[8, 2, 8, 2, 8, 0],
[2, 8, 8, 8, 2, 0],
[2, 8, 4, 8, 3, 0],
[0, 8, 8, 8, 0, 0],
[8, 0, 8, 0, 8, 0],
[0, 0, 0, 0, 0, 0]])
>>> submatrix(A)
array([[8, 2, 8, 2, 8],
[2, 8, 8, 8, 2],
[2, 8, 4, 8, 3],
[0, 8, 8, 8, 0],
[8, 0, 8, 0, 8]])
>>> A = np.array([
[8, 2, 8, 2, 8, 0],
[2, 2, 8, 8, 2, 0],
[2, 2, 4, 3, 3, 0],
[0, 2, 8, 8, 0, 0],
[8, 0, 8, 0, 8, 0],
[0, 0, 0, 0, 0, 0]])
>>> submatrix(A) # skipping empty rows and columns
array([[8, 8, 2, 8],
[2, 8, 8, 2],
[0, 8, 8, 0],
[8, 8, 0, 8]])
由于 np.unique
returns 已排序数组,您可以像这样填充构建 x
、y
的空白:
def submatrix(A):
x, y = np.where(A==8)
x, y = np.unique(x), np.unique(y)
x, y = np.arange(x[0], x[-1]+1), np.arange(y[0], y[-1]+1)
return A[np.ix_(x, y)]
您可以尝试以下方法
data = A[np.any(A==8,axis=1)]
data.T[np.all(data==8,axis=0)]
这应该给,
array([[8, 8, 8],
[8, 8, 8],
[8, 8, 8]])
这是我原来的二维数组A
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 2, 2, 2, 2, 2, 0, 0, 0],
[0, 2, 2, 2, 2, 2, 2, 0, 0, 0],
[0, 2, 2, 2, 2, 2, 2, 0, 0, 0],
[0, 2, 2, 2, 2, 2, 2, 0, 0, 0],
[0, 2, 2, 8, 8, 8, 2, 0, 0, 0],
[0, 2, 2, 8, 8, 8, 2, 0, 0, 0],
[0, 0, 0, 8, 8, 8, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
假设我想 return 一个 3x3 中间为 8 的子矩阵。我用这个表达式 A == 8
做了一个布尔掩码,它看起来像这样。
array([[False, False, False, False, False, False, False, False, False,
False],
[False, False, False, False, False, False, False, False, False,
False],
[False, False, False, False, False, False, False, False, False,
False],
[False, False, False, False, False, False, False, False, False,
False],
[False, False, False, False, False, False, False, False, False,
False],
[False, False, False, True, True, True, False, False, False,
False],
[False, False, False, True, True, True, False, False, False,
False],
[False, False, False, True, True, True, False, False, False,
False],
[False, False, False, False, False, False, False, False, False,
False],
[False, False, False, False, False, False, False, False, False,
False]])
这就是我卡住的地方。我如何 return 具有该布尔掩码的子矩阵?如果我这样做 A[A == 8]
,它 return 是一个像这样的 8 平面数组
array([8, 8, 8, 8, 8, 8, 8, 8, 8])
另一种方法是使用 np.where(A == 8)
获取行号和列号,其中 returns (array([5, 5, 5, 6, 6, 6, 7, 7, 7]), array([3, 4, 5, 3, 4, 5, 3, 4, 5]))
。我如何 return 矩阵使用它们?
这个问题有更好的方法吗?
如评论中所述,A[A==some_value]
正确地 returns 一个 rank-1 值数组 some_value
。这是有道理的,因为值 some_value
并不总是组织在一个块中(例如 some_value = 2
),或者值 some_value
的数量无法放入二维数组。
但是如果你确定有这样的块,你可以通过以下方式获取:
import numpy as np
inds = np.where(A==8)
slice_x = slice(inds[0].min(), inds[0].max() + 1) # slice(6, 9, None)
slice_y = slice(inds[1].min(), inds[1].max() + 1) # slice(3, 6, None)
A[slice_x, slice_y]
# array([[8, 8, 8],
# [8, 8, 8],
# [8, 8, 8]])
或者,您可以使用 scipy.ndimage.find_objects
获取切片:
from scipy import ndimage
slice_x, slice_y = ndimage.find_objects(A==8)[0] # (slice(6, 9, None), slice(3, 6, None))
您可以捕获 row
和 column
索引,然后仅使用 np.ix_
方法从这些索引捕获 return 子矩阵:
x, y = np.where(A==8) #[5 5 5 6 6 6 7 7 7], [3 4 5 3 4 5 3 4 5]
x, y = np.unique(x), np.unique(y) # [5,6,7], [3,4,5]
print(A[np.ix_(x, y)]) #prints [[8 8 8], [8 8 8], [8 8 8]]
这甚至在更一般的情况下也应该有效,尽管并不总是如预期的那样:
def submatrix(A):
x, y = np.where(A==8)
x, y = np.unique(x), np.unique(y)
return A[np.ix_(x, y)]
>>> A = np.array([
[8, 2, 8, 2, 8, 0],
[2, 8, 8, 8, 2, 0],
[2, 8, 4, 8, 3, 0],
[0, 8, 8, 8, 0, 0],
[8, 0, 8, 0, 8, 0],
[0, 0, 0, 0, 0, 0]])
>>> submatrix(A)
array([[8, 2, 8, 2, 8],
[2, 8, 8, 8, 2],
[2, 8, 4, 8, 3],
[0, 8, 8, 8, 0],
[8, 0, 8, 0, 8]])
>>> A = np.array([
[8, 2, 8, 2, 8, 0],
[2, 2, 8, 8, 2, 0],
[2, 2, 4, 3, 3, 0],
[0, 2, 8, 8, 0, 0],
[8, 0, 8, 0, 8, 0],
[0, 0, 0, 0, 0, 0]])
>>> submatrix(A) # skipping empty rows and columns
array([[8, 8, 2, 8],
[2, 8, 8, 2],
[0, 8, 8, 0],
[8, 8, 0, 8]])
由于 np.unique
returns 已排序数组,您可以像这样填充构建 x
、y
的空白:
def submatrix(A):
x, y = np.where(A==8)
x, y = np.unique(x), np.unique(y)
x, y = np.arange(x[0], x[-1]+1), np.arange(y[0], y[-1]+1)
return A[np.ix_(x, y)]
您可以尝试以下方法
data = A[np.any(A==8,axis=1)]
data.T[np.all(data==8,axis=0)]
这应该给,
array([[8, 8, 8],
[8, 8, 8],
[8, 8, 8]])