我正在尝试计算矩阵的多列上的移动平均值。在stackoverflow上读了一些答案,即this之后,似乎filter
函数就是这样的。但是,它不会忽略NaN
元素,我想在函数NaN
的精神中忽略nanmean
元素。下面是示例代码:
X = rand(100,100); %generate sample matrix
X(sort(randi([1 100],1,10)),sort(randi([1 100],1,10))) = NaN; %put some random NaNs
windowlenght = 7;
MeanMA = filter(ones(1, windowlenght) / windowlenght, 1, X);
答案 0 :(得分:1)
>> A = [1 2 3 4 5; 2 nan nan nan 6; 3 nan nan nan 7; 4 nan nan nan 8; 5 6 7 8 9]
A =
1 2 3 4 5
2 NaN NaN NaN 6
3 NaN NaN NaN 7
4 NaN NaN NaN 8
5 6 7 8 9
>> colfilt(A, [3,3], 'sliding', @nanmean)
ans =
0.6250 1.1429 1.5000 2.5714 1.8750
1.1429 2.2000 3.0000 5.0000 3.1429
1.5000 3.0000 NaN 7.0000 3.5000
2.5714 5.0000 7.0000 7.8000 4.5714
1.8750 3.1429 3.5000 4.5714 3.1250
(如果您只关心'完整'块,请适当选择内部行/列)
或者,您也可以使用nlfilter,但是您需要明确(通过匿名函数句柄)关于您将对块执行的操作;特别是,与nanmean一起使用它会产生整个块的标量输出,你需要在匿名函数中调用nanmean之前将每个块转换为列向量:
>> nlfilter(A, [3,3], @(x) nanmean(x(:)))
ans =
0.6250 1.1429 1.5000 2.5714 1.8750
1.1429 2.2000 3.0000 5.0000 3.1429
1.5000 3.0000 NaN 7.0000 3.5000
2.5714 5.0000 7.0000 7.8000 4.5714
1.8750 3.1429 3.5000 4.5714 3.1250
但是,对于记录,matlab声称colfilt通常会更快,所以通常nlfilter更好地保留用于在处理每个块时将输入转换为列没有意义的情况。
另请参阅matlab关于sliding operations in general的手册页/章节。
答案 1 :(得分:0)
尝试
MeanMA = filter(ones(1, windowlenght) / windowlenght, 1, X(find(~isnan(X)));
这将从X中提取非纳米值。
问题是......你还有一个有效的过滤处理吗?如果迭代地填充X,每个时间步长一个元素,则“NaN消除”将产生较短的向量,其值不再与原始时间向量对齐。
<强> 修改 强>
要仍然有一个有效的平均值计算,必须根据非NaN值的数量更新过滤器参数。
values = X(find(~isnan(X));
templength = length(values);
MeanMA = filter(ones(1, templength ) / templength , 1, values );
答案 2 :(得分:0)
如果您使用的是R2016a或更高版本,则可以the movmean
function使用'omitnan'
选项。