移动平均线忽略NaN

时间:2017-06-28 12:51:07

标签: matlab nan moving-average

我正在尝试计算矩阵的多列上的移动平均值。在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);

3 个答案:

答案 0 :(得分:1)

colfilt使用nanmean

>> 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'选项。