【问题标题】:How to automatically create variables which are column extracts from a matrix如何自动创建从矩阵中提取列的变量
【发布时间】:2017-08-15 15:39:14
【问题描述】:

我有一个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]

【问题讨论】:

  • 将现有矩阵的子集放入不同的变量中是一种非常低效的处理方式,并且会导致代码更长、更混乱。为什么你不想使用A(:, 1:3) 语法(甚至使用变量A(:, c:c+2))?创建完这些变量后,您打算如何处理它们?
  • 我假设 A2 应该开始 4 5 6...?

标签: matlab matrix vector octave


【解决方案1】:

你真的不应该这样拆分 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

【讨论】:

  • 这是迄今为止最好的一个,但需要注意的是,这不允许分配给变量AAc() 并且不反映匿名后对A 所做的更改函数已创建。
  • 我在我的回答中提出了解决第二个问题的方法
【解决方案2】:

你可以使用:

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

它将您的矩阵拆分为子单元格。

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

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

【讨论】:

    【解决方案3】:

    总结

    你有几个选择

    • 使用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 中是非常糟糕的做法

    请阅读 Mathworks 在 avoiding eval 上发布的这篇文章。没有理由以这种方式设置变量优于 any 其他方法。

    • 你不会知道你做了多少变量
    • 你不会知道你生成的所有变量名
    • 您在内存中复制了“大量数据”
    • 当事情(不可避免地)出错时,eval 更难调试!

    【讨论】:

      【解决方案4】:

      不要创建动态变量。如果确实需要,将reshapeA 转换成3D 数组,如下所示:

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

      【讨论】:

        猜你喜欢
        • 2015-02-04
        • 2023-02-02
        • 1970-01-01
        • 2021-04-28
        • 2012-07-10
        • 1970-01-01
        • 1970-01-01
        • 2014-05-11
        • 2020-07-01
        相关资源
        最近更新 更多