Reputation: 385
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
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
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
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
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