Reshape potentially very large 1D-array into multidimensional matrix with variable dimensions

此生再无相见时 提交于 2019-12-11 04:32:15

问题


I have to postprocess data from a parametric analysis which has as output a 1D-array with the results. I would like to reshape this 1D array into a multidimensional matrix which has the dimensions of my investigated parameters (to be in the right order), and those dimensions may vary in number.

I could came up with a function based on for-loops, but the problem is that with very large arrays I run out of RAM. I am perfectly aware that this is not the smartest way to do this. I was wondering if there is a smarter way to manipulate such a large array and to do the same job as my function does.

function [Tensor, n_dimensions]=reshape_array(Data,ndim)

n_dimensions=length(ndim);
n_elements=prod(ndim);

reshape_string=[];
for i=n_dimensions:-1:1
    if i==1
    reshape_string=strcat(reshape_string, ' ndim(', num2str(i) , ')])'); 
    elseif i== n_dimensions
    reshape_string=strcat(reshape_string, ' [ndim(', num2str(i) , ')'); 
    else
    reshape_string=strcat(reshape_string, ' ndim(', num2str(i) , ') '); 
    end

end

invert_string=[];
for i=1:n_dimensions
    if i==1
    invert_string=strcat(invert_string, 'ndim(', num2str(i) , '),'); 
    elseif i== n_dimensions
    invert_string=strcat(invert_string, ' ndim(', num2str(i) , ')'); 
    else
    invert_string=strcat(invert_string, ' ndim(', num2str(i) , '),'); 
    end

end

reshape_statement=strcat('reshape(Data,',reshape_string);
invert_statement=strcat('zeros(',invert_string,');');

Tens1=eval(reshape_statement);
Tens2=eval(invert_statement);

nLoops=length(ndim);
str = '';
str_dim_tens='';
str_dim_indeces='';
for i=1:nLoops
    str = strcat(sprintf('%s \n for i%d=1:',str,i), sprintf('%d',ndim(i)));
    if i<nLoops
    str_dim_tens=strcat(str_dim_tens,'i',num2str(i),',');
    else
    str_dim_tens=strcat(str_dim_tens,'i',num2str(i));
    end
end

for i=nLoops:-1:1
    if i~=1
    str_dim_indeces=strcat(str_dim_indeces,'i',num2str(i),',');
    else
    str_dim_indeces=strcat(str_dim_indeces,'i',num2str(i));
    end
end

str = strcat(sprintf('%s \n Tens2(%s)=Tens1(%s);',str,str_dim_tens,str_dim_indeces));

for i=1:nLoops
    str = sprintf('%s \n end',str);
end

eval(str)

Tensor=Tens2;

end

as an example,

ndim=[2 3];
Data=1:2*3
[Tensor, n_dimensions]=reshape_array(Data,ndim);

n_dimensions =

     2

Tensor =

     1     2     3
     4     5     6

I would work with more dimensions (e.g. minimum 4) and Data arrays with millions of elements. An example could be M(10,10,10,300000) This is why I was looking for the least computationally expensive method to do the job.

Thank you for your help!


回答1:


From your code, you want to fill the elements in the reshaped array using a dimension order which is the opposite of Matlab's column-major default; that is, you start from the last dimenson, then the second last, etc.

This can be done by reshaping into an array with the dimensions in reverse order (using reshape) and the reversing the order of dimensions back (using permute).

n_dimensions = numel(ndim);
Tensor = reshape(Data, ndim(end:-1:1)); % reshape with dimensions in reverse order
Tensor = permute(Tensor, n_dimensions:-1:1); % reverse back order of dimensions


来源:https://stackoverflow.com/questions/41807207/reshape-potentially-very-large-1d-array-into-multidimensional-matrix-with-variab

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!