如何自动创建从矩阵中提取列的变量

时间:2017-08-15 15:39:14

标签: matlab matrix vector octave

我有一个n*n矩阵,我想提取每3列并将结果保存在不同的变量中。

我知道可以这样做:

A1 = A(:,1:3); 
A2 = A(:,4:6); 
A3 = A(:,7:9);

但我希望简化并自动化这个以管理大量数据!

A =

[1     2     3     4     5     6     7     8     9
 2     4     6     8    10    12    14    16    18
 3     6     9    12    15    18    21    24    27
 4     8    12    16    20    24    28    32    36
 5    10    15    20    25    30    35    40    45
 6    12    18    24    30    36    42    48    54
 7    14    21    28    35    42    49    56    63
 8    16    24    32    40    48    56    64    72
 9    18    27    36    45    54    63    72    81]

预期结果:

A1 =               
[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]

A2 =
[4  5   7 
 8  10  12
 12 15  18
 16 20  24 
 20 25  30
 24 30  36
 28 35  42 
 32 40  48
 36 45  54]

A3 =
[7  8   9 
 14 16  18
 21 24  27
 28 32  36 
 35 40  45
 42 48  54
 49 56  63  
 56 64  72 
 63 72  81]

4 个答案:

答案 0 :(得分:6)

你真的不应该这样分裂A.如果您真的想要在3列块中添加A,请使用类似

的内容
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

答案 1 :(得分:4)

您可以使用:

C = mat2cell(A,size(A,1),ones(size(A,2)/3,1)*3);

它会将矩阵分割成子单元格。

您可以通过以下方式访问这些单元格所包含的信息:

C{1}
C{2}  %and so on

答案 2 :(得分:4)

摘要

您有几个选择

  • 使用eval。不要这样做,这是不好的做法。但是,它会直接回答您的问题,以防您好奇如何这样做。因为你不应该使用它,我已经把它包括在内了!
  • 使用单元格数组或矩阵。我就是这样做的,尽管如果你的数据集非常大,你可能会遇到内存问题。它确实使索引变得非常简单,并允许您覆盖数组的各个部分。
  • 使用匿名函数作为索引的简写。这是一种快速访问数据的只读方式,并且没有内存占用。

使用单元格数组和3D矩阵

正如Mathworks在上面链接的博客中所建议的那样,您可以将分区存储在单元格数组中......

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

或使用3D矩阵

% 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

最好的选择是不要在内存中复制A,只需直接或使用如上所示的辅助函数对其进行索引。

使用匿名函数

如果这是一个常见的索引操作,您可以创建一个基本上允许您用简写的函数。使用@()表示法编写的内联函数称为匿名函数。

% 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; ...]

但是,您无法使用此功能进行分配。

An(1) = [11 12 13; 11 12 13; ...] % wont work

如果您更改A然后尝试使用它,您可能会感到惊讶。

% 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!!

为了解决第二点,我们还可以将A传递给辅助函数:

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

您可以轻松分配变量

% 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; ...], ...

这在MATLAB

中是非常糟糕的做法

请在avoiding eval 上阅读Mathworks的这篇文章。没有理由以这种方式设置变量比任何其他方法更好。

  • 您不知道自己制作了多少变量
  • 您不会知道您生成的所有变量名称
  • 您已经复制了大量数据"在记忆中
  • 当事情(不可避免地)出错时,
  • eval更难调试!

答案 3 :(得分:3)

不要创建动态变量。如果真的需要,reshape A进入3D数组,如下所示:

A = reshape(A,size(A,1),3,[]); 
%where 3 is the number of columns you want to extract at a time