Selecting a range of rows at a time

151 views (last 30 days)
Diana
Diana on 14 Apr 2017
Commented: Stephen23 on 14 Apr 2017
I have a matrix A = 1201x50. I would like to select a range of 30 rows at a time to analyse it (1-30, 31-60, 61-90...).
To explain better: I would like to find the bandpower of every 30 rows in all 50 columns (end up with a 40 x 50).
The easiest but very time consuming to write would be to select every single row range:
fs = 300
freqrange = [7 11]
Aa = bandpower(A((1:30),:),fs,freqrange);
Ab = bandpower(A((31:60),:),fs,freqrange);
Ac = bandpower(A((61:90),:),fs,freqrange);
Ad = bandpower(A((91:120),:),fs,freqrange);
(....)
FPOWER_Reward_7_11 = [Aa;Ab;Ac;Ad...]
But since I'll have to run a lot of frequency ranges, I would like a faster way of running this, without having to write each range of 30 (it will be 40 lines per frequency range). Is there a way to make this row selection easier and faster?
Thank you!

Accepted Answer

Stephen23
Stephen23 on 14 Apr 2017
Edited: Stephen23 on 14 Apr 2017
Method one: use a loop and basic indexing: this is the easiest and most efficient solution:
out = NaN(40,50);
for k = 1:40;
idx = (k-1)*30+(1:30);
out(k,:) = bandpower(A(idx,:),fs,freqrange);
end
Method Two: use mat2cell and cellfun:
C = mat2cell(A,30*ones(1,40),50);
out = cell2mat(cellfun(@(m)bandpower(m,fs,freqrange),C,'uni',0));
Method Three: use accumarray:
idx = 1:size(A,1);
grp = ceil(idx(:)/30);
accumarray(grp,idx(:),[],@(r)bandpower(A(r,:),fs,freqrange));
Warning: whatever you do, do NOT try to create or access lots of variable names (e.g. Aa, Ab, etc) in a loop. Read this to know why:
  2 Comments
Diana
Diana on 14 Apr 2017
Thank you. I used the loop - modified a bit, but the original also worked really well.
Stephen23
Stephen23 on 14 Apr 2017
@Diana: I hope that it helped. Make sure that you always preallocate the output array (as my example showed):

Sign in to comment.

More Answers (2)

Jos (10584)
Jos (10584) on 14 Apr 2017
You can loop over the rows, using for-loops or arrayfun:
step = 30 ;
fh = @(x) bandpower(A(x:min(x+step-1,size(A,2)),:), fs, freqrange);
Y = arrayfun(fh, 1:30step:size(A,2), 'un', 0)
FPOWER_Reward_7_11 = cat(1, Y{:})

Rik
Rik on 14 Apr 2017
You can replace your code with the code below, although it will not be any faster than the code you describe.
fs = 300
freqrange = [7 11]
FPOWER_Reward_7_11 = zeros(40,50);
for n=1:40
FPOWER_Reward_7_11(n,:) = bandpower(A((1:30)+30*(n-1),:),fs,freqrange);
end

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!