Aybars
Aybars

Reputation: 385

Extracting every n-th column from matrix

I need to extract every n-th column from my matrix.

For example I have a matrix:

A =
     1    23    34    53    67    45    67    45
    12    34    45    56    67    87    98    12
     1     2     3    45    56    76    87    56

And I want to extract each group of three columns, i.e. deleting every fourth. My data should be like:

X =
     1    23    34    67    45    67
    12    34    45    67    87    98
     1     2     3    56    76    87

So I would skip the 4th column, then the 8th column and so on. I know how to extract every n-th column and row but I couldn't figure out how to use that to get what I need.

Upvotes: 2

Views: 983

Answers (4)

Nicky Mattsson
Nicky Mattsson

Reputation: 3052

If you want to "save" every fourth column, then the syntax would be:

toKeep = 4:4:8;
A = rand(3,8) % Insert your matrix
B = A(:,toKeep);

i.e. you assign those values to a new matrix. In your case, you want to remove them, thus you can simply assign an empty matrix to those places, which practically deletes them.

toRemove = 4:4:8; %Every fourth column
A = rand(3,8) % Insert your matrix
A(:,toRemove) = [];

EDIT 1

As Wolfie correctly notes in the comments, you can improve this a bit by writing toRemove together with A(:,toRemove) and using the end keyword such that you have:

A = rand(3,8) % Insert your matrix
A(:,4:4:end) = [];

In this case, you do not have to worry about the size of the matrix.

EDIT 2:

This approach will of course also work, for general cases without a period. The variable toRemove will just have to contain the indexes of the columns to remove, e.g.

toRemove = randperm(8,randi(5)); %Select up to 5 random columns to remove
A = rand(3,8) % Insert your matrix
A(:,toRemove) = [];

PS. If you want to keep the original matrix, A you can just assign it to B=A; first and then perform the operation on B instead.

Upvotes: 4

Adriaan
Adriaan

Reputation: 18177

A = rand(3,8) % Insert your matrix
n = 4; % Index of column to skip
idx = 1:size(A,2) % create indexing array
B = A(:,mod(idx,n)~=0) % logically index
A =
    0.7094    0.6797    0.1190    0.3404    0.7513    0.6991    0.5472    0.2575
    0.7547    0.6551    0.4984    0.5853    0.2551    0.8909    0.1386    0.8407
    0.2760    0.1626    0.9597    0.2238    0.5060    0.9593    0.1493    0.2543
idx =
     1     2     3     4     5     6     7     8
B =
    0.7094    0.6797    0.1190    0.7513    0.6991    0.5472
    0.7547    0.6551    0.4984    0.2551    0.8909    0.1386
    0.2760    0.1626    0.9597    0.5060    0.9593    0.1493

The idea here is that you create an index array idx, then check where division of idx by the desired n equals zero. Whenever it does, you want to skip that column. Breaking it down:

mod(idx,n) % 0 whenever idx is entirely divisible by n
mod(idx,n)==0 % finds where the zeros are
~(mod(idx,n)==0) % finds wherever the non-zeros are, i.e. the columns we want

then we can use the last one as logical index on the columns in A generating the desired output.

One-liner, because we can:

B = A(:,mod(1:size(A,2),n)~=0)

Upvotes: 2

Dev-iL
Dev-iL

Reputation: 24159

This is a slightly more general solution, for cases when a clear periodicity doesn't exist within the IDs of the columns to be excluded; added for completeness.


Suppose you have matrix A with N columns, and you want to exclude the columns whose IDs are in vector E, you can use the setdiff function as demonstrated below:

N = randi([30 50]);        % Generate data size
A = randi(N^2,N,N);        % Generate data
E = randperm(N,randi(10)); % Define column ids to exclude
X = A(:,setdiff(1:N,E));   % Create output

Applied to your example it would look like this:

S = size(A,2);
X = A(:, setdiff(1:S,4:4:S) ); % No need for the intermediate variable E

Upvotes: 0

Bentoy13
Bentoy13

Reputation: 4956

Building the vector of column indexes is easy, you can do it by several ways. For example, if you want to skip every n-th column and there are N columns in your matrix:

I = (1:n-1).'+(0:n:N-1);

Note that the + operates along all dimensions; in older versions of Matlab, you should use bsxfun instead.

In your case, n=4 and N=8, so I is:

1    5
2    6
3    7

Then you get your matrix only with indexing:

X = A(:,I);

Upvotes: 0

Related Questions