Как усреднить каждые 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 ответа:
Попробуйте это:
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)).';