views:

79

answers:

2

I am assigning a 3D array, which contains some information for a number of different loadcases. Each row in the array defines a particular loadcase (of which there are 3) and I would like to remove the loadcase (i.e. the row) if ALL the elements of the row (in 3D) are equal to zero.

The code I have at the moment is:

Array = zeros(3,5) %# Initialise array
Numloadcases = 3;

Array(:,:,1) = [10 10 10 10 10;
                0   0  0  0  0;
                0   0  0  0  0;]; %# Expand to a 3D array 

Array(:,:,2) = [10 10 10 10 10;
                0  0  0  0  0;
                0  0  0  0  0;];

Array(:,:,3) = [10 10 10 10 10;
                0  0  0  0  0;
                0  0  20  0  0;];

Array(:,:,4) = [10 10 10 10 10;
                0  0  0  0  0;
                0  0  20  0  0;];

%# And to remove the second row:

for i = 1:Numloadcases
  if sum(Array(i,:,:)) == 0
    Array(i,:,:) = [];
  end
end

At the moment, the for loop I have to remove the rows causes an indexing error, as the size of the array changes in the loop.

Can anyone see a work around for this?

+3  A: 

Here is an alternative to looping, using the function ALL and logical indexing:

isAllZero = all(all(Array == 0,3),2);  %# Logical index of rows with all zeroes
Array = Array(~isAllZero,:,:);  %# Keep rows that have non-zero values
%# Or...
Array(isAllZero,:,:) = [];      %# Set rows with all zeroes to the empty matrix
gnovice
A: 

the matlab command "any" tells you if there are any nonzero elements.

sum(Array(i,:,:) == 0) will produce true for some mixtures of positive and negative elements (e.g. [1 1 -2]) which is probably not the way to do it.

I would love to be clever and tell you how to do this with no for loops, but the overhead on a for loop here is small and the code is probably clearer if you keep your for loop. Your mistake is this line: Array(i,:,:) = [] which probably causes Matlab to yell at you about a mismatch in the number of elements

the fix is to keep track of what elements you want to delete, then take care of that at the end of the loop

valid = false([1 Numloadcases]); %preallocate
for i = 1:Numloadcases
   valid(i) = any(any(Array(i,:,:)));
end
Array = Array(valid,:,:);

If Array is a general ND array you probably don't want to tile up a bunch of any commands, so this alternate formulation will work

valid = false([1 Numloacases]);
for i = 1:Numloadcases
   valid(i) = any(reshape(Array(i,:,:), 1, []);
end
Array = Array(valid,:,:);
Marc
One problem... `Array(i,:,:)` is actually a 3-D array (1-by-5-by-4 using the example in the question). You therefore have to apply ANY at least twice: `valid(i) = any(any(Array(i,:,:)));`.
gnovice
Marc
You should also be able to say "valid(i) = any(Array(i,:))"
Nzbuu