Reputation: 71
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!
Upvotes: 1
Views: 125
Reputation: 112659
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
Upvotes: 5