0

I have a pretty large matrix M and I am only interested in a few of the columns. I have a boolean vector V where a value of 1 represents a column that is of interest. Example:

      -1 -1 -1  7  7 -1 -1 -1  7  7  7
M  =  -1 -1  7  7  7 -1 -1  7  7  7  7
      -1 -1  7  7  7 -1 -1 -1  7  7 -1

V  =   0  0  1  1  1  0  0  1  1  1  1

If multiple adjacent values of V are all 1, then I want the corresponding columns of M to be extracted into another matrix. Here's an example, using the matrices from before.

      -1  7  7             -1  7  7  7
M1  =  7  7  7       M2  =  7  7  7  7
       7  7  7             -1  7  7 -1

How might I do this efficiently? I would like all these portions of the matrix M to be stored in a cell array, or at least have an efficient way to generate them one after the other. Currently I'm doing this in a while loop and it is not as efficient as I'd like it to be.

(Note that my examples only include the values -1 and 7 just for clarity; this isn't the actual data I use.)

Paul Manta
  • 30,618
  • 31
  • 128
  • 208

2 Answers2

1

You can utilize the diff function for this, to break your V vector into blocks

% find where block differences exist
diffs = diff(V);
% move start index one value forward, as first value in
% diff represents diff between first and second in original vector
startPoints = find(diffs == 1) + 1;
endPoints = find(diffs == -1);

% if the first block begins with the first element diff won't have
% found start
if V(1) == 1
    startPoints = [1 startPoints];
end

% if last block lasts until the end of the array, diff won't have found end
if length(startPoints) > length(endPoints)
    endPoints(end+1) = length(V);
end

% subset original matrix into cell array with indices
results = cell(size(startPoints));
for c = 1:length(results)
    results{c} = M(:,startPoints(c):endPoints(c));
end
DMR
  • 1,479
  • 1
  • 8
  • 11
  • 1
    +1: By the way, the computation of the indices can be shortened using `strfind` in the following way: `startPoints = strfind([0 V], [0 1]); endPoints = strfind([V 0], [1 0]);`. – Eitan T Mar 27 '13 at 23:55
1

The one thing I'm not sure of is if there's a better way to find the being_indices and end_indices.

Code:

X = [1     2     3     4     5     1     2     3     4     5
     6     7     8     9    10     6     7     8     9    10
    11    12    13    14    15    11    12    13    14    15
    16    17    18    19    20    16    17    18    19    20
     1     2     3     4     5     1     2     3     4     5
     6     7     8     9    10     6     7     8     9    10
    11    12    13    14    15    11    12    13    14    15
    16    17    18    19    20    16    17    18    19    20];

V = logical([ 1     1     0     0     1     1     1     0     1    1]);

find_indices = find(V);
begin_indices = [find_indices(1)  find_indices(find(diff(find_indices) ~= 1)+1)];
end_indices = [find_indices(find(diff(find_indices) ~= 1)) find_indices(end)];

X_truncated = mat2cell(X(:,V),size(X,1),[end_indices-begin_indices]+1);
X_truncated{:}

Output:

ans =

     1     2
     6     7
    11    12
    16    17
     1     2
     6     7
    11    12
    16    17


ans =

     5     1     2
    10     6     7
    15    11    12
    20    16    17
     5     1     2
    10     6     7
    15    11    12
    20    16    17


ans =

     4     5
     9    10
    14    15
    19    20
     4     5
     9    10
    14    15
    19    20
JustinBlaber
  • 4,629
  • 2
  • 36
  • 57