Python 从二维阵列中提取块
假设您有一个连续填充整数的二维数组,从左到右,从上到下。因此看起来Python 从二维阵列中提取块,python,python-3.x,numpy,Python,Python 3.x,Numpy,假设您有一个连续填充整数的二维数组,从左到右,从上到下。因此看起来 [[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19]] 假设现在有一个1D数组,上面的数组中显示了一些整数。假设这个数组是[6,7,11]。我想提取包含列表元素的二维数组的块/区块。有了这两个输入,结果应该是 [[ 6., 7.], [11., nan]] (我正在填充np.nanis,它不能被
[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]]
假设现在有一个1D数组,上面的数组中显示了一些整数。假设这个数组是[6,7,11]
。我想提取包含列表元素的二维数组的块/区块。有了这两个输入,结果应该是
[[ 6., 7.],
[11., nan]]
(我正在填充np.nan
is,它不能被重塑)
这是我写的。请问有没有更简单的方法
import numpy as np
def my_fun(my_list):
ids_down = 4
ids_across = 5
layout = np.arange(ids_down * ids_across).reshape((ids_down, ids_across))
ids = np.where((layout >= min(my_list)) & (layout <= max(my_list)), layout, np.nan)
r,c = np.unravel_index(my_list, ids.shape)
out = np.nan*np.ones(ids.shape)
for i, t in enumerate(zip(r,c)):
out[t] = my_list[i]
ax1_mask = np.any(~np.isnan(out), axis=1)
ax0_mask = np.any(~np.isnan(out), axis=0)
out = out[ax1_mask, :]
out = out[:, ax0_mask]
return out
一种方法是通过检查数组中的哪些元素包含在第二个列表中来查找。我们可以使用:
设置-
a = np.array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
b = np.array([6,7,11])
或者对于
b=np.array([10,12,16])
我们会得到:
m = np.isin(a, b)
a_components, _ = ndimage.measurements.label(m, np.ones((3, 3)))
bbox = ndimage.measurements.find_objects(a_components)
out = a[bbox[0]]
np.where(np.isin(out, b), out, np.nan)
array([[10., nan, 12.],
[nan, 16., nan]])
我们还可以通过执行以下操作使上述内容适用于多个边界框:
b = np.array([5, 11, 8, 14])
m = np.isin(a, b)
a_components, _ = ndimage.measurements.label(m, np.ones((3, 3)))
bbox = ndimage.measurements.find_objects(a_components)
l = []
for box in bbox:
out = a[box]
l.append(np.where(np.isin(out, b), out, np.nan))
print(l)
[array([[ 5., nan],
[nan, 11.]]),
array([[ 8., nan],
[nan, 14.]])]
此100%NumPy解决方案适用于连续和非连续的通缉号码数组
a = np.array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
n = np.array([6, 7, 11])
确定通缉号码的位置:
mask = np.isin(a, n)
np.where(mask, a, np.nan)\
[mask.any(axis=1)][:, mask.any(axis=0)]
#array([[ 6., 7.],
# [11., nan]])
选择包含所需编号的行和列:
mask = np.isin(a, n)
np.where(mask, a, np.nan)\
[mask.any(axis=1)][:, mask.any(axis=0)]
#array([[ 6., 7.],
# [11., nan]])
利用模板数组
A
的特定形式,我们可以直接将测试值转换为坐标:
A = np.arange(20).reshape(4,5)
test = [6,7,11]
y,x = np.unravel_index(test,A.shape)
yl,yr = y.min(),y.max()
xl,xr = x.min(),x.max()
out = np.full((yr-yl+1,xr-xl+1),np.nan)
out[y-yl,x-xl]=test
out
# array([[ 6., 7.],
# [11., nan]])
不适用于非连续选择(例如[6,7,11,19])。不确定这是否重要,只是FYI。@ DYZ取决于你所考虑的块/块。但你是对的,这与OP的代码不完全相同。@DYZ为真,但不难纠正,我认为选择总是连续的吗?例如,[6,7,11,19]是否允许?以@DYZ为例,正确答案是否包含[8,13,18]列的一列NaN?@DYZ,yes not continuous canhappen@Paul,对于这种输入,结果将与输入相同,但将ie[8,13,18]转换为一列,这是DYZ代码给出的(也是您的)。我想我没有从DYZ的例子中得到任何反馈。谢谢大家抽出时间来研究这个问题。所有这些都是非常有趣的方法。DYZ复制了我的逻辑,其他的非常接近,应该适合大多数人,特别是非连续的情况。再次感谢!