裁剪矩阵的纳米行和列,但保持方形

Mun*_*kin 6 python numpy crop matrix nan

我有一个方形矩阵,大于1000行和列.在"边界"的许多领域nan,例如:

grid = [[nan, nan, nan, nan, nan],
        [nan, nan, nan, nan, nan],
        [nan, nan,   1, nan, nan],
        [nan,   2,   3,   2, nan],
        [  1,   2,   2,   1, nan]]
Run Code Online (Sandbox Code Playgroud)

现在我想消除我所拥有的所有行和列nan.这将是1.和2.行和最后一列.但是我也希望接收一个方阵,因此消除的行数必须等于消除列的数量.在这个例子中,我想得到这个:

grid = [[nan, nan, nan, nan],
        [nan, nan,   1, nan],
        [nan,   2,   3,   2],
        [  1,   2,   2,   1]]
Run Code Online (Sandbox Code Playgroud)

我确定我可以通过循环来解决这个问题:检查每一列和行,如果只有nan内部,最后我使用numpy.delete删除我找到的行和列(但只有最小数量,因为得到一个广场).但我希望任何人都可以帮助我找到更好的解决方案或一个好的图书馆.

M4r*_*ini 2

这是可行的,压缩行\列的索引是关键,因此它们始终具有相同的长度,从而保留矩阵的方形。

nans_in_grid = np.isnan(grid)
nan_rows = np.all(nans_in_grid, axis=0)
nan_cols = np.all(nans_in_grid, axis=1)

indicies_to_remove = zip(np.nonzero(nan_rows)[0], np.nonzero(nan_cols)[0])
y_indice_to_remove, x_indice_to_remove = zip(*indicies_to_remove)

tmp = grid[[x for x in range(grid.shape[0]) if x not in x_indice_to_remove], :]
grid = tmp[:, [y for y in range(grid.shape[1]) if y not in y_indice_to_remove]]
Run Code Online (Sandbox Code Playgroud)

继续 E 先生的解决方案,然后填充结果也可以。

def pad_to_square(a, pad_value=np.nan):
    m = a.reshape((a.shape[0], -1))
    padded = pad_value * np.ones(2 * [max(m.shape)], dtype=m.dtype)
    padded[0:m.shape[0], 0:m.shape[1]] = m
    return padded

g = np.isnan(grid) 
grid = pad_to_square(grid[:, ~np.all(g, axis=0)][~np.all(g, axis=1)])
Run Code Online (Sandbox Code Playgroud)

另一个解决方案,建立在另一个答案的基础上。对于较大的矩阵,速度明显更快。

shape = grid.shape[0]

first_col  = (i for i,col in enumerate(grid.T) if np.isfinite(col).any() == True).next()
last_col  = (shape-i-1 for i,col in enumerate(grid.T[::-1]) if np.isfinite(col).any() == True).next()
first_row = (i for i,row in enumerate(grid) if np.isfinite(row).any() == True).next()
last_row  = (shape-i-1 for i,row in enumerate(grid[::-1]) if np.isfinite(row).any() == True).next()

row_len = last_row - first_row
col_len = last_col - first_col
delta_len = row_len - col_len
if delta_len == 0:
    pass
elif delta_len < 0:
    first_row = first_row - abs(delta_len)
    if first_row < 0:
        delta_len = first_row
        first_row = 0
        last_row += abs(delta_len)
elif delta_len > 0:
    first_col -= abs(delta_len)
    if first_col < 0:
        delta_len = first_col
        first_col = 0
        last_col += abs(delta_len)

grid =  grid[first_row:last_row+1, first_col:last_col+1]
Run Code Online (Sandbox Code Playgroud)