【发布时间】:2014-04-13 19:38:06
【问题描述】:
假设我有一个 1 x n 的矩阵 1a1,我想找到 a 的每个元素与其相邻元素之间的平均值。
这样做的聪明方法是什么?
前:
如果
a=[0 1 2 1 0 1];
那么“平均值矩阵”就是:
b=[0.5 1 1.33 1 0.5];
b 的第一个条目是:
b(1) = (0+1)/2 = 0.5
b(2) = (0+1+2)/3 = 1
等等
【问题讨论】:
假设我有一个 1 x n 的矩阵 1a1,我想找到 a 的每个元素与其相邻元素之间的平均值。
这样做的聪明方法是什么?
前:
如果
a=[0 1 2 1 0 1];
那么“平均值矩阵”就是:
b=[0.5 1 1.33 1 0.5];
b 的第一个条目是:
b(1) = (0+1)/2 = 0.5
b(2) = (0+1+2)/3 = 1
等等
【问题讨论】:
我建议将中间作为向量运算并将边缘条件作为标量处理。
b=zeros(size(a));
b(2:end-1)=(a(1:end-2)+a(2:end-1)+a(3:end))/3;
b(1)=(a(1)+a(2))/2;
b(end)=(a(end-1)+a(end))/2;
如果你得到更大的平均值......
% scale and sum elements with a sliding window 3 long.
b=conv(a,[1,1,1]/3)
%
% remove the tails
b=b(2:end-1)
%
% and rescale the edge cases.
b(1)=b(1)*3/2
b(end)=b(end)*3/2
我比较了上面第一种方法(向量),卷积方法和RDizzl3建议的hankel方法。 (对不起,Luis,我没有 Statistics 包,虽然我预计 nanmean 方法会由于条件检查的数量而变慢。)比较是使用 10000 长度的随机向量,以使时间显着。在这些计时完成之前,b 被初始化为正确大小的零矩阵。正确大小的汉克尔矩阵(h)也在这些计时之前被预先计算。
% hankle method
tic; b(1)=mean(a([1,2])); b(2:(n-1))=mean(a(h),2); b(2)=mean(a([n-1,n])); toc
Elapsed time is 0.001698 seconds.
% convolution method
tic; c=conv(a,[1,1,1]/3) ; b=c(2:(2+n-1)); b(1)=b(1)*3/2; b(n)=b(n)*3/2; toc;
Elapsed time is 0.000339 seconds.
% vector method
tic; b(1)=mean(a([1,2])) ; b(2:(n-1))=(a(1:(n-2))+a(2:(n-1))+a(3:n))/3;b(2)=mean(a([n-1,n])); toc
Elapsed time is 0.000914 seconds.
上面我又重复了3次,对结果进行了排序,
hankel convolution vector
9.2500e-04 3.3900e-04 7.2600e-04
1.3820e-03 5.2600e-04 8.7100e-04
1.6980e-03 5.5200e-04 9.1400e-04
2.1570e-03 5.5300e-04 2.6390e-03
我有点惊讶,我没想到卷积方法的效率直到更大的窗口尺寸才会出现。但它一直在这里做得最好。
请注意,如果您使用较小的数据集,这些时间可能不合适。如果感兴趣的是大量较短长度的向量,如果 hankel 方法效果更好,我一点也不感到惊讶。
【讨论】:
你可以用这个:
a=[0 1 2 1 0 1];
n = numel(a);
h = hankel(1:(n-2),(n-2):n);
b(1) = mean(a([1 2]))
b(2:(n-1)) = mean(a(h),2);
b(n) = mean(a([n-1 n]))
这将返回向量:
b = [0.5000 1.0000 1.3333 1.0000 0.6667 0.5000]
这会从向量 a 中获取元素并为其邻居求平均值,因此:
b(1) = (0+1)/2 = 0.5
b(2) = (0+1+2)/3 = 1
b(3) = (1+2+1)/3 = 1.3333
b(4) = (2+1+0)/3 = 1
b(5) = (1+0+1)/3 = 0.6667
b(6) = (0+1)/2 = 0.5 % last element
【讨论】:
a = [0 1 2 1 0 1]; %// data
n = 1; %// how many neighbours to consider on each side
a2 = [NaN(1,n) a NaN(1,n)]; %// pad with NaN's (which will be ignored by nanmean)
b = arrayfun(@(k) nanmean(a2(k-n:k+n)), n+1:n+numel(a)); %// apply a
%// sliding-window mean ignoring NaN's
【讨论】:
使用平滑过滤器的最简单方法
output=smooth(A,3,'moving');
其中 3 是窗口大小(应该是奇数值)
检查文档以获得平滑功能
【讨论】: