我正在编写一个程序,该程序在不同的日子里平均用户的体重。我打算使用5点移动平均线(当前日期,前两天和后两天)。有时,数据点会丢失1-2天。这些情况通常如何处理?

(如果我可以使用更好的低通滤波器,我会建议)

评论

首先想到的是在使用移动平均滤波器之前对点进行插值

至少在没有更多上下文的情况下,实际上,统计问题比信号处理问题更多。但是您可以简单地跳过重新计算平均值,使用当前平均值作为替换值,或等待后续测量并尝试进行线性或其他方式的插值。

正如其他人指出的那样,这通常是基于应用程序的决策,具体取决于您对过滤后的输出的行为的考虑。大多数信号处理理论都是基于均匀间隔的样本,因此您不会得到客观上可以称为“正确答案”的东西。

@JasonR我进行过滤,以便在那一点上更合理地估算用户的体重。对数据进行统一采样(采样频率= 1 /天),但缺少某些数据点。

@Anna:是的,我知道您为什么要过滤数据。但是,由于缺少数据点,因此无法统一采样数据。因此,正如我指出的那样,您不太可能找到令人满意的理论答案。您认为对特定应用程序“有意义”的临时解决方案可能会是答案。

#1 楼

作为一般印象,回归将比自动选择的移动平均值过滤器更好地自动拟合缺失点。

如果使用AR(自动回归滤波器)或ARMA滤波器-您可以根据过去的输入获得样本输出的预测值。

$$
\ hat X [i] = \ sum {\ omega_ {k} * x [i-1-k]} + \ eta
$$

其中$ \ hat X [i] $是预测值。

具体来说,假设您知道人的体重有特定范围$ X_ {max},X_ {min} $。现在,如果您没有$ x [i-1] $的值-应用两种不同的替换-一种用Min替代,另一种用Max替代,根据可用模型,您将获得$ \ hat X [i]的两种极端情况结果$,您可以在它们之间进行选择。

还有其他多种选择-您可以保留

$$ \ hat X [i] = X [i-1] $$或
$$ \ hat X [i] = \ text {X的长期样本平均值} $$

本质上,这是一个预测该值并继续将其用作信号的游戏。当然,预测将与原始样本不同,但这不是您没有数据所要付出的代价。

评论


$ \ begingroup $
为什么您说回归将更适合拟合?谢谢
$ \ endgroup $
–太空
2012年6月25日在3:22

#2 楼

如果您要运行完整的数据,则一种简单而通用的填充缺失数据的方法是使用线性回归。
假设您连续进行了1000次运行,共5次不丢失。
设置1000 x 1的向量y和1000 x 4的矩阵X: />
y       X
wt[0]   wt[-2] wt[-1] wt[1] wt[2]
---------------------------------
68      67     70     70    68
...


用于1000行数据-不同的数据,不同的abc d。
然后使用这些abcd估计(预测,内插)
缺少wt [0] 。
(对于重量,我希望abcd大约是1/4。)

在python中,请参阅
numpy.linalg.lstsq。

(在各个层次上都有成千上万的关于回归的书籍和论文。
但是,对于与插值的联系,我不知道一个好的介绍;有人吗?)

#3 楼

如果您不了解某些数据,则最好不要完全取其平均值。用线性回归之类的方法猜测可能会有所帮助,但也可能会给数据带来额外的复杂性和意料之外的偏差。我想说的是,如果您要对这五个数据点求平均值:$ [a,b,c,?,e] $,您的答案应该是

$$ \ frac {a + b + c + e} {4} $$

#4 楼

我认为最简单的方法是使用之前的数据来“预测”时间序列中“整个”的日期。那么您可以将此时间序列用于参数估算。 (然后,您可以使用整个(完成的)时间序列中的估算参数来重新估算缺失值,并重复此过程直到它们收敛为止。而不是从完整的数据系列的长度开始。

#5 楼

我也需要这个,谢谢大家的回答。我写了一个函数,它带有一个向量(v)和一个窗口(w)。该函数将w迭代应用于v的每个元素。每次迭代都会检查两个约束。首先,缺失值的总数。其次,与缺失值相对应的权重之和(移动窗口中的元素)。如果2中的任何一个超过其阈值,则将NAN推入结果向量,并且该函数继续进行下一个迭代。相反,如果存在足够的信息来确定该值,则将得出简单的加权移动平均值。请注意,代码质量肯定可以提高,我不是程序员,并且仍在进行中。
pub fn mavg(v: &[f64], w: &[f64], max_missing_v: usize, max_missing_wpct: f64) -> Vec<f64> {
    let len_v: i32 = v.len() as i32;
    let len_w: i32 = w.len() as i32;
    assert!(
        len_w < len_v,
        "length of moving average window > length vector"
    );
    assert!(
        len_w % 2 == 1,
        "the moving average window has an even number of element, it should be odd"
    );
    let side: i32 = (len_w - 1) / 2;
    let sum_all_w: f64 = w.iter().sum();
    let max_missing_w: f64 = sum_all_w / 100. * (100. - max_missing_wpct);
    let mut vout: Vec<f64> = Vec::with_capacity(len_v as usize);
    for i in 0..len_v {
        let mut missing_v = 0;
        let mut missing_w = 0.;
        let mut sum_ve_we = 0.;
        let mut sum_we = 0.;
        let mut ve: f64;
        let vl = i - side;
        let vr = i + side + 1;
        for (j, we) in (vl..vr).zip(w.iter()) {
            if (j < 0) || (j >= len_v) {
                missing_v += 1;
                missing_w += we;
            } else {
                ve = v[j as usize];
                if ve.is_nan() {
                    missing_v += 1;
                    missing_w += we;
                } else {
                    sum_ve_we += ve * we;
                    sum_we += we;
                }
            }
            if missing_v > max_missing_v {
                sum_ve_we = f64::NAN;
                println!(
                    "setting to NAN: {} missing data, limit is {}",
                    missing_v, max_missing_v
                );
                break;
            } else if missing_w > max_missing_w {
                sum_ve_we = f64::NAN;
                println!(
                    "setting to NAN: {} missed window weight, limit is {}",
                    missing_w, max_missing_w
                );
                break;
            }
        }
        vout.push(sum_ve_we / sum_we);
    }
    vout
}