Luiz
Luiz

Reputation: 85

Deleting empty rows in a 3D cell array in Matlab

I have a large 3D CELL ARRAY (x1) which I have to delete the empty rows. How can I do this?

Example of my cell array (some pieces of the variable):

val(:,:,1) = 

[20]    []    []    []    []    []    []    []
[ 0]    []    []    []    []    []    []    []
[ 0]    []    []    []    []    []    []    []
[]      []    []    []    []    []    []    []

(...)

val(:,:,42) = 


[ 34225]    [   215]    [    0]    [   0]    [    0]    [    0]    [    0]    [    0]
[ 85200]    [   545]    [    0]    [   0]    [    0]    [    0]    [    0]    [    0]
[ 65074]    [   190]    [ 1000]    [   0]    [    0]    [    0]    [    0]    [    0]
[ 81570]    [  1385]    [ 2475]    [   0]    [    0]    [    0]    [    0]    [    0]    
[ 67236]    [   530]    [  365]    [   0]    [    0]    [    0]    [    0]    [    0]
[ 61338]    [     0]    [  100]    [   0]    [    0]    [    0]    [    0]    [    0]
[]          []          []         []        []         []         []         []    
[]          []          []         []        []         []         []         []  
[]          []          []         []        []         []         []         []   

In this case, I want to exclude the 4th row of (:,:,1), the three last rows from (:,:,42) and all the others from these variable.

I've tried

x1(all(all(cellfun((@isempty,x1),2),:,:) = [];

But it gave me this following error:

Error: Expression or statement is incorrect--possibly unbalanced (, {, or [.

PS: I cannot use "==" because its a cell array.

Thanks in advance

Upvotes: 0

Views: 1524

Answers (3)

nhowe
nhowe

Reputation: 929

There seem to be two problems here. One is the fact that you are using a 3D cell array, and it appears that you want to delete different numbers of rows from different planes. This would give you something that does not form a proper MxNxP structure, because M won't be the same.

That said, I can tell you how to remove the rows that are all empty in a 2D cell array. Let's say val is MxN. Then

val2 = val(~all(cellfun(@numel,val)==0,2),:);

If you want to work with the 3D data you described, you'll have to store the result for each plane separately in a cell. Something like this:

val2 = cell(1,1,size(val,3));
for i = 1:size(val,3)
    valplane = val(:,:,i);
    val2{i} = valplane(~all(cellfun(@numel,valplane)==0,2),:);
end

Upvotes: 2

Oleg
Oleg

Reputation: 10676

You cannot remove different rows from a 3D array, you can remove 'floors', or layers or 'walls'. (If you imagine a building by layer I intend a vertical and perpendicular plane to your point of vision while a wall is a vertical plane along your point of vision).

You should not store numeric data in this way, i.e. one number per cell. You incur in a 112 bytes overhead per cell when a scalar double is only 8 bytes.

According to the sparsity pattern I can observe from your example, you might benefit by converting it into a sparse array which still reference against the original size of the array but without storing 0 or []. However, sparse arrays are only 2D, where the additional layers (from a 3rd dimension) are stored consecutively along the 2nd dimension.

A simplified version of your example will clarify:

val(:,:,1) = {
[20]    []    []    []
[ 0]    []    []    []
[ 0]    []    []    []
[]      []    []    []};
val(:,:,2) = {
[ 34225]    [   215]    [    0]    [   0]    
[ 85200]    [   545]    [    0]    [   0]   
[ 65074]    [   190]    [ 1000]    [   0]   
[]          []          []         []     };

% Find non-zero empty elements (0s will be discarded automatically)
[r,c] = find(~cellfun('isempty',val));

% Convert to sparse (note the coordinates are only 2D)
sp    = sparse(r,c,[val{:}]);
sp =
   (1,1)             20
   (1,5)          34225
   (2,5)          85200
   (3,5)          65074
   (1,6)            215
   (2,6)            545
   (3,6)            190
   (3,7)           1000

% Convert to full to see what happened with the 3rd dimension
full(sp)
ans =
     20      0      0      0  34225   215     0     0     
      0      0      0      0  65074   190     0     0
      0      0      0      0  85200   545  1000     0

you can see that the second layer has been concatenated horizontally (along columns). You can use reshape if you need to recover the 3D.

The advantage of val vs sp is in the reduced storage:

  Name      Size             Bytes  Class     Attributes
  sp        3x8                200  double    sparse    
  val       4x4x2             3704  cell

Upvotes: 0

Roney Michael
Roney Michael

Reputation: 3994

This should work for you for a particular row, say the first row:

i=1;    %Row number
val(~all(cellfun(@isempty,val(:,:,i)')),:,i);

For example:

>> 
val = cell(4,8,2);
val(:,:,1) = {
[20]    []    []    []    []    []    []    []
[ 0]    []    []    []    []    []    []    []
[ 0]    []    []    []    []    []    []    []
[]      []    []    []    []    []    []    []
};
>> 
i=1;    %Row number
val(~all(cellfun(@isempty,val(:,:,i)')),:,i)

The result was:

ans = 

    [20]    []    []    []    []    []    []    []
    [ 0]    []    []    []    []    []    []    []
    [ 0]    []    []    []    []    []    []    []

Upvotes: 0

Related Questions