Как усреднить каждые n столбцов каждой строки в матрице?


Таким образом, у меня есть ежемесячная матрица доходности, в виде 1000x300. Я хотел бы взять средние значения каждых 12 столбцов для каждой строки в матрице доходности, чтобы получить годовую доходность, которая в конечном итоге приведет к матрице 1000x25.

Как бы я сделал это в Matlab?

С помощью быстрого поиска я полагаю, что могу каким-то образом использовать функцию reshape, но мне трудно понять, как реализовать ее в цикле моего кода.

Пока что это мой попытка.

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

К вашему сведению, +1 существует, потому что я игнорирую первый столбец матрицы.

Но это приводит меня к получению сингулярного значения NaN.
4 5

4 ответа:

Попробуйте это:

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

Я только что протестировал его с построением суммы единиц, и это сработало.

Петли не всегда медленные. Фактически, тесты, проведенные Mathworks, показали, что скорость петель улучшилась на 40% в результате нового и улучшенного механизма выполнения (JIT)

Среднее улучшение производительности по всем тестам составило 40%. Тесты состоял из кода, который использовал ряд продуктов MATLAB. Хотя нет все приложения работали быстрее с редизайном, большинство из них приложения выполнялись по крайней мере на 10% быстрее в R2015b, чем в R2015a.

И

Преимущество производительности JIT-компиляции является наибольшим, когда MATLAB код выполняется дополнительное время и может повторно использовать скомпилированный код. Это происходит в обычных случаях, таких как for-loops или когда приложения выполняются дополнительные разы в сеансе MATLAB


Быстрый бенчмарк из трех решений:

%% 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

Циклический подход (с предварительным распределением) примерно на 40% быстрее, чем Решение squeeze(mean(reshape(...))). Решение дивакара превосходит оба на милю.


Это может быть по-другому для других значений A и N, но я не проверил все.

Используя философию, которая reshape является практически нулевой стоимостью , вот подход, который в основном просто использует 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,[]);
Было бы интересно посмотреть, как он работает против нового JIT!

Вы можете сложить нужные подматрицы вдоль первого измерения трехмерного массива, затем выполнить усреднение вдоль этого измерения и выдавить результирующее синглетное измерение:

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)).';