How to automatically create variables which are column extracts from a matrix

前端 未结 4 519
被撕碎了的回忆
被撕碎了的回忆 2021-01-20 11:34

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:

相关标签:
4条回答
  • 2021-01-20 11:58

    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
    
    0 讨论(0)
  • 2021-01-20 12:03

    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
    
    0 讨论(0)
  • 2021-01-20 12:04

    Summary

    You have a few options

    • Using 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!
    • Using cell arrays or matrices. This is how I would do it, although if your data set is very large you may get memory issues. It does make indexing very simple, and allows you to over-write sections of the array.
    • Using an anonymous function as shorthand for your indexing. This is a read-only way to quickly access your data, and has no memory footprint.

    Using cell arrays and 3D matrices

    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.


    Using an anonymous function

    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!
    

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

    This is very bad practise in MATLAB

    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.

    • You won't know how many variables you're making
    • You won't know all the variable names you've generated
    • You've duplicated your "big amount of data" in memory
    • eval is harder to debug when things (inevitably) go wrong!
    0 讨论(0)
  • 2021-01-20 12:10

    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
    
    0 讨论(0)
提交回复
热议问题