delete dimension based on user input
Mostrar comentarios más antiguos
Dear Matlab users,
I have a 4D array and I want to delete a dimension based on user input. I have written the below code for this but it uses eval statements (which I have seen people warn against) and feels like this could be done in a more optimum manner. Any suggestions would be much appreciated.
%find input file and take user input (time dimension)
vtc = xff('73_zk18w7_036.RUN1_RS_undist_SCCTBL_3DMCTS_THPGLMF2c_IDENTITY_ALIGNED.vtc');
disp(['VTC dimensions are: ' num2str(size(vtc.VTCData))]);
timeDim = input('What dimension is time? ');
%delete user input time dimension
switch timeDim
case 1
index = '(1,:,:,:)';
case 2
index = '(:,1,:,:)';
eval(['vtc.VTCData=vtc.VTCData' index])
case 3
index = '(:,:,1,:)';
case 4
index = '(:,:,:,1)';
otherwise
disp('Input a dimension between 1 and 4');
end
eval(['vtc.VTCData=vtc.VTCData' index]);
vtc.VTCData = squeeze(vtc.VTCData);
Best,
Joe
Respuestas (2)
This should work.
a = rand(4,3,2,5); % random 4D matrix
dim = 3; % let's remove 3rd dimension
numDims = 1:length(size(a)); % [1 2 3 4]
[~,permInd] = sort(dim == numDims); % [1 2 4 3]
b = permute(a,permInd); % rearranges a
b = b(:,:,:,1); % only takes first value of last dimension
We can test it:
c = squeeze(a(:,:,1,:));
isequal(b,c)
% ans = 1
5 comentarios
Adam Danz
el 22 de Oct. de 2019
What if the size of each dimension is the same (or contains at least 1 duplicate)?
Example: a= rand(4,4,4,4)
Daniel M
el 22 de Oct. de 2019
I believe the solution still works. My test case still passes (isequal(b,c)), but maybe it is insufficient. Can you think of a more robust test case?
Adam Danz
el 22 de Oct. de 2019
Ah, right. I misread the sort() line.
Joe_Z
el 23 de Oct. de 2019
% Set up default index
S.type = '()';
S.subs = {':',':',':',':'};
% Choose dimension and replace that value with 1
timeDim = 3
S.subs{timeDim } = 1;
% Do indexing
vtc.VTCData = subsref(vtc.VTCData,S)
vtc.VTCData = squeeze(vtc.VTCData);
If you'd rather use the switch-case method, just do the indexing within the cases.
switch timeDim
case 1
vtc.VTCData = vtc.VTCData(1,:,:,:);
case 2
vtc.VTCData = vtc.VTCData(:,1,:,:);
case 3
vtc.VTCData = vtc.VTCData(:,:,1,:);
case 4
vtc.VTCData =vtc.VTCData(:,:,:,1);
otherwise
disp('Input a dimension between 1 and 4');
end
vtc.VTCData = squeeze(vtc.VTCData);
4 comentarios
Joe_Z
el 23 de Oct. de 2019
Daniel M
el 23 de Oct. de 2019
Note that the use of squeeze will remove ALL singleton dimensions, not just the one you indicated.
Say the variable A = rand(1,3,2,5), and you want to remove only the 3rd dimension. In my solution above, the output will be [1x3x5], whereas any solution that uses squeeze will be [3x5].
Adam Danz
el 23 de Oct. de 2019
Good point. I'd personally avoid using squeeze here and let the singlton dimensions be. I only added it because the OP included it in his code at the end. But it's good you're bringing that to his attention.
Categorías
Más información sobre Logical en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!