2017-02-10 12 views
1

Есть ли какая-либо функция в R, Python, Lua, Java, Matlab или любом языке программирования, которая может уменьшить размер 3D input_array от c (6, 6, 6) до c (4, 4, 4) путем удаления всех нулевых матриц на периферии трех измерений?R - Измените размер 3D-массива, удалив все-нулевые 2D-матрицы из размеров x, y и z.

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

Так, другими словами, я ищу функцию, которая принимает input_array в качестве входных данных и плюет output_array как выход. Я хочу сохранить 3D-характер массива во время преобразования. Причина, по которой я рассматриваю это, заключается в том, что у меня очень большие 3D-массивы с множеством нулей по периферии и путем удаления матриц всех нулей из трех измерений, я могу добиться значительного уменьшения размеров этих массивов и, следовательно, позволить для более эффективной обработки.

В случае отсутствия функции, что может быть логикой для написания новой функции, чтобы это сделать? Используйте любой язык, который вы предпочитаете, если у вас есть что поделиться, любая обратная связь или помощь очень ценятся.

+0

Предполагается, что нужно сбрить поверхности на основании того, все ли они ноль (если так: неоднократно?) Или только один с каждой стороны? –

+0

несколько раз, пока поверхность является полностью нулевой, это может быть одна поверхность или несколько. – mansanto

+0

Выберите язык. Все еще работает более элегантно в R, но функционально: 'input_array [apply (input_array, 1, function (x) {any (x! = 0)}), apply (input_array, 2, function (x) {any (x! = 0)}), apply (input_array, 3, function (x) {any (x! = 0)})] ' – alistaire

ответ

3

Вы можете сделать достаточно хорошо в R с помощью abind пакет, который пригодится для работы с массивами:

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 
+0

Спасибо за подсказку ответ, он отлично работает в данном примере. – mansanto

1

Вот один вариант (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 находит индексы истинных ячеек своего аргумента. в этом примере мы используем его, чтобы найти индексы первого и последнего не-все-нулевой срез по каждой координате

Пример запуска:

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

Спасибо за всех тех, кто разделяет их мысли или цитироваться другие подобные сообщения. Я достиг этого через ваши ответы:

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

Я не тестировал его с различными входами, так далее тестирования для различных входов может должен быть выполнен.