Selecting a range of rows at a time

14 vues (au cours des 30 derniers jours)
Diana
Diana le 14 Avr 2017
Commenté : Stephen23 le 14 Avr 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!

Réponse acceptée

Stephen23
Stephen23 le 14 Avr 2017
Modifié(e) : Stephen23 le 14 Avr 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 commentaires
Diana
Diana le 14 Avr 2017
Thank you. I used the loop - modified a bit, but the original also worked really well.
Stephen23
Stephen23 le 14 Avr 2017
@Diana: I hope that it helped. Make sure that you always preallocate the output array (as my example showed):

Connectez-vous pour commenter.

Plus de réponses (2)

Jos (10584)
Jos (10584) le 14 Avr 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 le 14 Avr 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

Catégories

En savoir plus sur Loops and Conditional Statements dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by