I have an n*n
matrix and I want to extract every 3 columns and keep the result in different variables.
I know that it is possible to do it in this way:
You really shouldn't split A this way. If you really want to adress A in 3 column block then use something like
A = (1:9).*((1:9).');
%% create anonymous function which can be called as Ac(1), Ac(2) and so on
Ac = @(n) A(:,(n-1)*3+1:n*3)
octave:2> Ac(1)
ans =
1 2 3
2 4 6
3 6 9
4 8 12
5 10 15
6 12 18
7 14 21
8 16 24
9 18 27
octave:3> Ac(2)
ans =
4 5 6
8 10 12
12 15 18
16 20 24
20 25 30
24 30 36
28 35 42
32 40 48
36 45 54
Don't create dynamic variables. If really needed, reshape A
into a 3D array as follows:
A = reshape(A,size(A,1),3,[]);
%where 3 is the number of columns you want to extract at a time
You have a few options
eval
. Don't do this, it's bad practise. However, it does directly answer your question in case you were curious how to do it. Because you shouldn't use this, I've included it last!As suggested by Mathworks in the above linked blog, you could store the partitions in a cell array...
myCellArray = cell(size(A,2)/3,1)
for n = 1:3:size(A,2)
myCellArray{1+(n-1)/3} = A(:,n:n+2)
end
% For accessing:
myCellArray{1} % = A1
or use a 3D matrix
% option 1
my3DArray = reshape(A,9,3,[]);
% option 2 (same structure as above cell example)
my3DArray = zeros(size(A,1), 3, size(A,2)/3);
for n = 1:3:size(A,2)
my3DArray(:,:,1+(n-1)/3) = A(:,n:n+2);
end
% For accessing:
my3DArray(:,:,1); % = A1
The best option is not to duplicate A
in memory and just index it as needed, either directly or using a helper function as shown above.
You can create a function which just essentially lets you write in short hand if this is a common indexing operation. Inline functions written with the @()
notation are called anonymous functions.
% Create A
A = repmat(1:9, 9, 1);
% Create helper function
An = @(n) A(:,(n-1)*3+1:n*3);
% For accessing:
An(1); % An(1) = [1 2 3; 1 2 3; ...]
However, you cannot assign using this.
An(1) = [11 12 13; 11 12 13; ...] % wont work
And you may be surprised if you change A
then try and use it.
% Change A
A = repmat(11:19, 9, 1); % A = [11 12 13 14 15 16 17 18 19; 11 12 ...]
% indexing
An(1); % An(1) = [1 2 3; 1 2 3; ...] not the new values!!
To get around this second point, we could also pass A
into the helper function:
An = @(M,n) M(:,(n-1)*3+1:n*3);
A = repmat(1:9, 9, 1);
An(A,1); % An(1) = [1 2 3; 1 2 3; ...];
A = repmat(11:19, 9, 1);
An(A,1); % An(1) = [11 12 13; 11 12 13; ...]; as desired!
eval
You can easily assign the variables like so
% Create some 9x9 matrix A
A = repmat(1:9, 9, 1);
% Loop through A, create A1, A2, ...
for n = 1:3:size(A,2)
eval(['A', num2str(1+(n-1)/3), ' = A(:,n:n+2)']);
end
% Gives the result
% A1 = [1 2 3; 1 2 3; ...], A2 = [4 5 6; 4 5 6; ...], ...
Please read this post by Mathworks on avoiding eval. There is no reason why setting up variables in this way is better than any other method.
eval
is harder to debug when things (inevitably) go wrong!You can use:
C = mat2cell(A,size(A,1),ones(size(A,2)/3,1)*3);
It will split your matrix into subcells.
You can access the information contained by those cells with:
C{1}
C{2} %and so on