R - 通过删除 x、y 和 z 维度的全零 2D 矩阵来调整 3D 数组的大小

是否有任何一种 R、Python、Lua、Java、Matlab 或任何编程语言的函数可以通过删除三个维度上边界的全零矩阵,将 3D input_array 的大小从 c(6, 6, 6) 减小到 c(4, 4, 4)?

## 创建一个所有元素都为零的空数组
input_array <- array(data = c(0), dim = c(6, 6, 6))

## 用 1 填充数组的中央位置
input_array[, ,2:5] <- matrix(c(0, 0, 0, 0, 0, 0,
                                0, 1, 1, 1, 1, 0,
                                0, 1, 1, 1, 1, 0,
                                0, 1, 1, 1, 1, 0,
                                0, 1, 1, 1, 1, 0,
                                0, 0, 0, 0, 0, 0),
                                nrow = 6, ncol = 6)

## 显示 input_array
input_array

## 目标输出
output_array <- array(data = c(1), dim = c(4, 4, 4))

换句话说,我正在寻找一个函数,它以 input_array 作为输入,并以 output_array 作为输出。我希望在整个转换过程中保持数组的 3D 特性。我之所以研究这个问题,是因为我有非常大的 3D 数组,在边界周围有很多零,通过删除三个维度上的全零矩阵,我可以实现对这些数组大小的相当大减小,从而允许更有效的处理。

如果没有相关的函数,编写一个新函数的逻辑是什么?如果您有任何要分享的内容,请使用您喜欢的任何语言,非常感谢任何反馈或帮助。

点赞
用户7207392
用户7207392

以下是一种方法(python/numpy):

xcrit = np.where(np.any(input, axis=(0,1)))[0]
ycrit = np.where(np.any(input, axis=(0,2)))[0]
zcrit = np.where(np.any(input, axis=(1,2)))[0]
output = input[zcrit[0]:zcrit[-1]+1,ycrit[0]:ycrit[-1]+1,xcrit[0]:xcrit[-1]+1]

解释:np.any函数返回沿着传递的维度至少有一个单元格为True的数组。它返回一个形状像剩余维度的布尔数组。np.where函数找到其参数中True单元格的索引。在这个示例中,我们使用它来找到每个坐标轴上第一个和最后一个不全为零的切片的索引。

示例运行:

>>> input = np.zeros((6,6,6))
>>> input[1:-2,1:-2,2:-1] = 1
>>> xcrit = np.where(np.any(input, axis=(0,1)))[0]
>>> ycrit = np.where(np.any(input, axis=(0,2)))[0]
>>> zcrit = np.where(np.any(input, axis=(1,2)))[0]
>>> output = input[zcrit[0]:zcrit[-1]+1,ycrit[0]:ycrit[-1]+1,xcrit[0]:xcrit[-1]+1]
>>> # verify
... input.sum(), output.sum(), output.size
(27.0, 27.0, 27)
2017-02-10 06:00:17
用户4497050
用户4497050

你可以使用abind包在R中得到合理的结果,这个包非常方便用于处理数组:

abind::asub(input_array,    # 取出并子集
            lapply(1:3, function(d){    # 迭代维度
                apply(input_array != 0, d, any)    # 查找任何非零元素
            }))
## , , 1
##
##      [,1] [,2] [,3] [,4]
## [1,]    1    1    1    1
## [2,]    1    1    1    1
## [3,]    1    1    1    1
## [4,]    1    1    1    1
##
## , , 2
##
##      [,1] [,2] [,3] [,4]
## [1,]    1    1    1    1
## [2,]    1    1    1    1
## [3,]    1    1    1    1
## [4,]    1    1    1    1
##
## , , 3
##
##      [,1] [,2] [,3] [,4]
## [1,]    1    1    1    1
## [2,]    1    1    1    1
## [3,]    1    1    1    1
## [4,]    1    1    1    1
##
## , , 4
##
##      [,1] [,2] [,3] [,4]
## [1,]    1    1    1    1
## [2,]    1    1    1    1
## [3,]    1    1    1    1
## [4,]    1    1    1    1
2017-02-10 06:00:57
用户5508978
用户5508978

感谢所有分享他们想法或引用其他类似帖子的人。通过你们的回答,我得出了以下结论:

## 创建一个所有元素为零的空数组
input_array <- array(data = c(0), dim = c(6, 6, 6))

## 在数组中心位置填充1
input_array[, ,2:5] <- matrix(c(0, 0, 0, 0, 0, 0,
                                0, 1, 1, 1, 1, 0,
                                0, 1, 1, 1, 1, 0,
                                0, 1, 1, 1, 1, 0,
                                0, 1, 1, 1, 1, 0,
                                0, 0, 0, 0, 0, 0),
                                nrow = 6, ncol = 6)

## 显示input_array
input_array

## 目标输出
(output_array <- input_array[apply(input_array != 0, 3, any),
                             apply(input_array != 0, 2, any),
                             apply(input_array != 0, 1, any)])

我还没有对不同的输入进行测试,因此可能需要对不同的输入进行进一步测试。

2017-02-10 06:11:41