Python NumPy-从另一个二维数组中选择子矩阵
这是我原来的2d阵列APython NumPy-从另一个二维数组中选择子矩阵,python,arrays,numpy,math,linear-algebra,Python,Arrays,Numpy,Math,Linear Algebra,这是我原来的2d阵列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, 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]]
假设我想在中间返回一个8的3x3子矩阵。我用这个表达式制作了一个布尔掩码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]])
这就是我被困的地方。如何返回带有布尔掩码的子矩阵?如果我执行A[A==8]
,它将返回一个8的平面数组,如下所示
array([8, 8, 8, 8, 8, 8, 8, 8, 8])
另一种方法是使用np获取行数和列数,其中(A==8)
返回(数组([5,5,5,6,6,6,7,7,7])、数组([3,4,5,3,4,5,3,4,5])
。如何使用它们返回矩阵
有没有更好的方法解决这个问题?如评论中所述,
A[A==some\u value]
正确地返回值的秩1数组some\u value
。这是有意义的,因为并非总是将值某些值
组织在一个块中(例如某些值=2
),或者值的数量某些值
无法放入2D数组中
但是,如果确定存在这样的块,则可以执行以下操作来获得它:
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))
您可以捕获
行
和列
索引,然后仅使用以下方法从这些索引返回子矩阵:
即使在更一般的情况下,这也应该有效,尽管并非总是如预期的那样:
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
返回已排序的数组,因此您可以通过以下方式填补空白:构造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]])
像这样的布尔索引返回1d结果。通常,这种索引不会返回一个整洁的值块。但是如果你知道结果会是这样的块,那就重新塑造它们。@hpaulj我不知道它的形状是否符合预期,因为你并不总是有矩形,例如
A[A==2]
。现在,如果确定8
仅显示在块中,则可以使用argmin/argmax
检测形状。
array([[8, 8, 8],
[8, 8, 8],
[8, 8, 8]])