Extracting from vector to multidimensional array using indices provided
2 views (last 30 days)
Show older comments
Andris Cerins
on 14 Apr 2020
Commented: Andris Cerins
on 18 Apr 2020
Can this extraction be performed better without loops?
% data vector
data = [1 1 1 1 1 4 4 4 4 4 7 7 7 7 7 2 2 2 2 2 5 5 5 5 5 8 8 8 8 8 3 3 3 3 3 6 6 6 6 6 6 9 9 9 9 9]
% Desired output
data3d(:,:,1)
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
data3d(:,:,2)
4 4 4 4 4
5 5 5 5 5
6 6 6 6 6
data3d(:,:,3)
7 7 7 7 7
8 8 8 8 8
9 9 9 9 9
% indices for starts and ends of trials, rows are channels
dstart = [1 16 31; 6 21 36; 11 26 42]
dend = [5 20 35; 10 25 41; 15 30 46]
% note the annoying extra 6 in data
% can truncate now, dend_tr = dstart+4, or just use dstart:dstart+4
% or if target matrix pads then truncate later?
[numchannels,numsweeps] = size(dstart) %in case it is useful
% Here is how I think it would work using loops
% For all channels in that file
for ich = 1:numchannels
data_sweeps = [];
% For all sweeps in that file
for isw = 1:numsweeps
sweepdata = [];
% Get that sweep, truncate it to 5 samples (because some have extras)
sweepdata = data(dstart(ich,isw):dstart(ich,isw)+4);
% Make sweeps x samples matrix
data_sweeps(isw,:) = sweepdata;
end
% Adds each channel as a page in a 3d matrix
data3d(:,:,ich) = data_sweeps
end
0 Comments
Accepted Answer
Stephen23
on 17 Apr 2020
Edited: Stephen23
on 17 Apr 2020
In three lines (could be just one), no loops, and yes that extra 6 is taken into account!
>> D = [1,1,1,1,1,4,4,4,4,4,7,7,7,7,7,2,2,2,2,2,5,5,5,5,5,8,8,8,8,8,3,3,3,3,3,6,6,6,6,6,6,9,9,9,9,9];
>> S = [1,16,31;6,21,36;11,26,42];
>> E = [5,20,35;10,25,41;15,30,46];
>> F = @(s)reshape(s:s+4,[],1);
>> X = cell2mat(arrayfun(F,sort(S(:)),'uniformoutput',false));
>> A = permute(reshape(D(X),[5,3,3]),[3,1,2])
A(:,:,1) =
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
A(:,:,2) =
4 4 4 4 4
5 5 5 5 5
6 6 6 6 6
A(:,:,3) =
7 7 7 7 7
8 8 8 8 8
9 9 9 9 9
More Answers (1)
Guru Mohanty
on 17 Apr 2020
I understand you are trying to extract data from a vector to multidimensional array without for loops.
It can be possible using MATLAB Array indexing. Here is a sample code for it.
% data vector
tic;
data = [1 1 1 1 1 ...
4 4 4 4 4 ...
7 7 7 7 7 ...
2 2 2 2 2 ...
5 5 5 5 5 ...
8 8 8 8 8 ...
3 3 3 3 3 ...
6 6 6 6 6 ...
9 9 9 9 9];
data=reshape(data,5,9);
dstart = [1 4 7;
2 5 8;
3 6 9];
data3d(:,:,1) = [data(:,dstart(1,1))';data(:,dstart(1,2))';data(:,dstart(1,3))'];
data3d(:,:,2) = [data(:,dstart(2,1))';data(:,dstart(2,2))';data(:,dstart(2,3))'];
data3d(:,:,3) = [data(:,dstart(3,1))';data(:,dstart(3,2))';data(:,dstart(3,3))'];
toc;
1 Comment
Stephen23
on 17 Apr 2020
Edited: Stephen23
on 17 Apr 2020
@Guru Mohanty: your data vector is missing a 6 (as the original question points out, there are more of them). So your data vector should actually be defined as:
data = [1 1 1 1 1 ...
4 4 4 4 4 ...
7 7 7 7 7 ...
2 2 2 2 2 ...
5 5 5 5 5 ...
8 8 8 8 8 ...
3 3 3 3 3 ...
6 6 6 6 6 6 ... <- "note the annoying extra 6 in data"
9 9 9 9 9];
and then reshape fails with an error.
Using MATLAB permute instead of copy-and-pasting the same code nine times will improve your Code performance.
See Also
Categories
Find more on Structures in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!