简体   繁体   English

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

[英]R - Resize a 3D array by removing all-zeros 2D matrices of the x, y, and z dimensions

Is there any function in R, Python, Lua, Java, Matlab or any programming language that can reduce the size of the 3D input_array from c(6, 6, 6) to c(4, 4, 4) by deleting all-zero matrices on the periphery of the 3 dimensions? R,Python,Lua,Java,Matlab或任何编程语言中是否有任何函数可以通过删除全零来将3D input_array的大小从c(6,6,6)减小到c(4,4,4)矩阵在3维的外围?

## Create an empty array with all zeros
input_array <- array(data = c(0), dim = c(6, 6, 6)) 

## Populate the central locations of the array with 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) 

## Show the input_array
input_array 

## The target output
output_array <- array(data = c(1), dim = c(4, 4, 4)) 

So, in other words, I am looking for a function that takes the input_array as an input and spits the output_array as an output. 因此,换句话说,我正在寻找一个将input_array用作输入并将output_array用作输出的函数。 I want to maintain the 3D nature of the array throughout the conversion. 我想在整个转换过程中保持阵列的3D性质。 The reason I am looking into this, is that I have very large 3D arrays with lots of zeros around the periphery and by removing all-zeros matrices out of the three dimensions, I can achieve considerable reduction in the sizes of these arrays and hence allow for more efficient processing. 我要研究的原因是,我有非常大的3D数组,外围有很多零,并且通过从三个维度中删除全零矩阵,我可以实现这些数组大小的显着减少,因此允许以提高处理效率。

In case there is no function out there, what could be a logic to write a new function so as to get this done? 如果那里没有函数,那么编写一个新函数以完成此任务的逻辑是什么? Use whatever language you prefer if you have anything to share, any feedback or help is very much appreciated. 如果您有任何可分享的内容,请使用您喜欢的任何语言,非常感谢您提供任何反馈或帮助。

You can do reasonably well in R with the help of the abind package, which is handy for dealing with arrays: 借助abind包,您可以在R中做得相当好,这对于处理数组非常方便:

abind::asub(input_array,    # take this and subset
            lapply(1:3, function(d){    # iterate over its dimensions
                apply(input_array != 0, d, any)    # look for any non-zero elements
            }))
## , , 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

Thanks for all of those who shared their thoughts or cited other similar posts. 感谢所有分享想法或引用其他类似文章的人。 I reached this through your answers: 我通过您的答案达到了这一点:

## Create an empty array with all zeros
input_array <- array(data = c(0), dim = c(6, 6, 6)) 

## Populate the central locations of the array with 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) 

## Show the input_array
input_array 

## The target output
(output_array <- input_array[apply(input_array != 0, 3, any),
                             apply(input_array != 0, 2, any),
                             apply(input_array != 0, 1, any)])  

I haven't tested it with different inputs, so further testing for different inputs may need to be performed. 我没有用不同的输入进行测试,因此可能需要对不同的输入进行进一步的测试。

Here's one option ( python / numpy ): 这是一个选项( 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]

explanation np.any returns True if along the dimensions passed at least one cell is True. 说明如果沿着传递的维度至少一个单元格为True,则np.any返回True。 it returns a boolean array shaped like the remaining dimensions 它返回一个形状类似于其余维度的布尔数组

np.where finds the indices of the True cells of its argument. np.where查找其参数的True单元的索引。 in this example we use it to find the indices of the first and last not-all-zero slice along each coordinate 在此示例中,我们使用它来查找沿每个坐标的第一个和最后一个非零切片的索引

Sample run: 样品运行:

>>> 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM