2016-06-02 20 views
5

Quindi ho una matrice mensile di resi, sotto forma di 1000x300. Vorrei prendere i valori medi delle 12 colonne per ogni riga nella matrice dei resi per ottenere un rendimento annuale, che alla fine porterebbe a una matrice 1000x25.Come media ogni n colonne di ogni riga in una matrice?

Come faccio a fare questo in Matlab?

Attraverso alcune ricerche rapide, credo di poter utilizzare la funzione di risagoma in qualche modo, ma ho difficoltà a capire come implementarlo nel ciclo del mio codice.

Finora, questo è il mio tentativo.

for i = 1:25 
Strategy1.MeanReturn(:,i) = mean(Data.Return(:,i+1):Data.Return(:,i*12+1)); 
end 

Fyi, il +1 è lì perché sto ignorando la prima colonna della matrice.

Ma questo mi porta a ottenere un valore NaN singolare.

risposta

5

provare questo:

B = zeros(1000,25); 
A = rand(1000,300); 
for i = 1:25  
    B(:,i) = mean(A(:,(i-1)*12+1:i*12),2); 
end 

ho appena provato con la costruzione di una somma di quelli e ha funzionato.

+0

Grazie! Ho apportato una piccola modifica al mio esempio di dati, ma questo era perfetto! Ho provato la trasposizione della matrice e il ', 2' in uno dei miei tentativi ma devo aver incasinato il mio ciclo con i. Funziona perfettamente ora. Grazie ancora per la rapida risposta. – rahulk92

+1

@ rahulk92, ricordarsi di [preallocare la memoria] (http://stackoverflow.com/a/6217182/2338750)! –

+0

modificato ... grazie Stewie! specialmente quando si lavora con array di grandi dimensioni, la preallocazione apporta un enorme effetto. – bushmills

5

è possibile impilare le sottomatrici desiderati lungo la prima dimensione di un array 3D, poi fare la media lungo quella dimensione, e spremere la dimensione Singleton risultante:

x = rand(10,20); % example data. 1000x300 in your case 
N = 4; % group size. 12 in your case 
y = reshape(x.', N, size(x,2)/N, []); 
result = squeeze(mean(y,1)).'; 
+0

Grazie per la soluzione Luis! Ti dispiacerebbe spiegare cosa potrebbe fare la compressione? Sono ancora abbastanza nuovo e lo apprezzerei. Saluti :) – rahulk92

+0

@ rahulk92 'squeeze' rimuove le dimensioni singleton degli array con più di due dimensioni. Ad esempio, una matrice di dimensione '4'x'1'x'5' viene convertita in una matrice' 4'x'5' –

5

Loops non sono sempre lento. Infatti, prove effettuate da Mathworks ha dimostrato che la velocità di loop è migliorata del 40% a causa del nuovo e migliorato Execution Engine (JIT)

Il miglioramento medio delle prestazioni sui test era 40%. I test consistevano in un codice che utilizzava una gamma di prodotti MATLAB. Sebbene non sia tutte le applicazioni funzionino più velocemente con la riprogettazione, la maggior parte di queste applicazioni ha funzionato almeno il 10% più velocemente in R2015b che in R2015a.

e

Il beneficio delle prestazioni della compilazione JIT è maggiore quando MATLAB codice viene eseguito tempi supplementari e può riutilizzare il codice compilato. Questo accade in casi comuni come per-loop o quando le applicazioni vengono eseguite volte aggiuntive in una sessione MATLAB


Un rapido riferimento delle tre soluzioni:

%% bushmills answer, saved as bushmills.m 
function B = bushmills(A,N) 
B = zeros(size(A,1),size(A,2)/N); 
for i = 1:size(A,2)/N 
    B(:,i) = mean(A(:,(i-1)*12+1:i*12),2); 
end 
end 

A = rand(1000,300); N = 12; 

%% Luis Mendo's answer: 
lmendo = @(A,N) squeeze(mean(reshape(x.', N, size(x,2)/N, []))).'; 

%% Divakar's answer: 
divakar = @(A,N) reshape(mean(reshape(A,size(A,1),N,[]),2),size(A,1),[]); 

b = @() bushmills(A,N); 
l = @() lmendo(A,N); 
d = @() divakar(A,N); 

sprintf('Bushmill: %d\nLuis Mendo: %d\nDivakar: %d', timeit(b), timeit(l), timeit(d)) 
ans = 
Bushmill: 1.102774e-03 
Luis Mendo: 1.611329e-03 
Divakar: 1.888878e-04 

sprintf('Relative to fastest approach:\nDivakar: %0.5f\nBushmill: %0.5f\nLuis Mendo: %0.5f', 1, tb/td, tl/td) 
ans = 
Relative to fastest approach: 
Divakar: 1.00000 
Bushmill: 5.34464 
Luis Mendo: 10.73969 

L' l'approccio loop (con pre-allocazione) è circa il 40% più veloce rispetto alla soluzione squeeze(mean(reshape(...))). La soluzione di Divakar batte entrambi di un miglio.


Potrebbe essere diverso per altri valori di A e N, ma non ho ancora testato tutti.

5

Utilizzando la filosofia che reshape is virtually zero cost, ecco un approccio che utilizza fondamentalmente solo mean:

% A is the input array of shape (1000,300) 

N = 12; %// Group size 
M = size(A,1); 
out = reshape(mean(reshape(A,M,N,[]),2),M,[]); 

sarebbe interessante vedere come si svolge contro il nuovo JIT!

+0

@StewieGriffin Lovely! Dovrei darlo alla magia di costo zero di 'reshape'! :) Grazie mille per il benchmarking! – Divakar

+1

Aha, grazie per quello! Sì, sono ancora un po 'principiante in Matlab e sto solo imparando a rimodellare, è incredibile! – rahulk92