在列表中查找缺失值

时间:2014-01-15 16:14:36

标签: c# arrays list interpolation linear-interpolation

我有一个带累计值的List,point有一个日期和3个值。第一次测量为零。

我正在尝试获取每个月的第一个值。

知道点数(月/日)

1/10/2008   0.000
1/12/2008   0.201
1/2/2009    0.403
1/4/2009    0.604
1/6/2009    0.810
1/8/2009    1.023
1/10/2009   1.234
1/12/2009   1.453
1/1/2010    1.677
1/2/2010    1.892
1/4/2010    2.117
1/6/2010    2.342
1/8/2010    2.569
1/10/2010   2.798
1/12/2010   3.032
1/2/2011    3.255
1/4/2011    3.487
1/6/2011    3.720
1/8/2011    3.954
1/10/2011   4.189
1/12/2011   4.428
1/2/2012    4.661
1/4/2012    4.898
1/6/2012    5.135
1/8/2012    5.373
1/10/2012   5.612
1/12/2012   5.855
1/2/2013    6.087
1/4/2013    6.327
1/6/2013    6.568
1/8/2013    6.809
1/10/2013   7.051
1/12/2013   7.297
1/2/2014    7.531
1/4/2014    7.774
1/6/2014    8.017
1/8/2014    8.260
1/10/2014   8.504
1/12/2014   8.752
1/2/2015    8.988
1/4/2015    9.233
1/6/2015    9.478
1/8/2015    9.723
1/10/2015   9.968
1/12/2015   10.218
1/2/2016    10.460
1/4/2016    10.706
1/6/2016    10.953
1/8/2016    11.199
1/10/2016   11.446
1/12/2016   11.698
1/2/2017    11.937
1/4/2017    12.185
1/6/2017    12.433
1/8/2017    12.681
1/10/2017   12.929
1/12/2017   13.182
1/2/2018    13.422
1/4/2018    13.671
1/6/2018    13.921
1/8/2018    14.170

预期结果

10/1/2008   0
11/1/2008   0.102
12/1/2008   0.201
1/1/2009    0.302
2/1/2009    0.403
3/1/2009    0.498
4/1/2009    0.604
5/1/2009    0.705
6/1/2009    0.81
7/1/2009    0.915
8/1/2009    1.023
9/1/2009    1.131
10/1/2009   1.234
11/1/2009   1.345
12/1/2009   1.453
1/1/2010    1.565
2/1/2010    1.677
3/1/2010    1.779
4/1/2010    1.892
5/1/2010    2.003
6/1/2010    2.117
7/1/2010    2.228
8/1/2010    2.342
9/1/2010    2.458
10/1/2010   2.569
11/1/2010   2.686
12/1/2010   2.798
1/1/2011    2.915
2/1/2011    3.032
3/1/2011    3.138
4/1/2011    3.255
5/1/2011    3.369
6/1/2011    3.487
7/1/2011    3.602
8/1/2011    3.72
9/1/2011    3.839
10/1/2011   3.954
11/1/2011   4.073
12/1/2011   4.189
1/1/2012    4.308
2/1/2012    4.428
3/1/2012    4.54
4/1/2012    4.661
5/1/2012    4.777
6/1/2012    4.897
7/1/2012    5.014
8/1/2012    5.135
9/1/2012    5.256
10/1/2012   5.373
11/1/2012   5.495
12/1/2012   5.612
1/1/2013    5.734
2/1/2013    5.855
3/1/2013    5.965
4/1/2013    6.087
5/1/2013    6.205
6/1/2013    6.327
7/1/2013    6.446
8/1/2013    6.568
9/1/2013    6.691
10/1/2013   6.809
11/1/2013   6.932
12/1/2013   7.051
1/1/2014    7.174
2/1/2014    7.297
3/1/2014    7.408
4/1/2014    7.531
5/1/2014    7.65
6/1/2014    7.774
7/1/2014    7.893
8/1/2014    8.017
9/1/2014    8.14
10/1/2014   8.26
11/1/2014   8.384
12/1/2014   8.504
1/1/2015    8.628
2/1/2015    8.752
3/1/2015    8.864
4/1/2015    8.988
5/1/2015    9.108
6/1/2015    9.233
7/1/2015    9.353
8/1/2015    9.478
9/1/2015    9.602
10/1/2015   9.723
11/1/2015   9.848
12/1/2015   9.968
1/1/2016    10.093
2/1/2016    10.218
3/1/2016    10.335
4/1/2016    10.46
5/1/2016    10.581
6/1/2016    10.706
7/1/2016    10.827
8/1/2016    10.953
9/1/2016    11.078
10/1/2016   11.199
11/1/2016   11.325
12/1/2016   11.446
1/1/2017    11.572
2/1/2017    11.698
3/1/2017    11.811
4/1/2017    11.937
5/1/2017    12.059
6/1/2017    12.185
7/1/2017    12.307
8/1/2017    12.433
9/1/2017    12.559
10/1/2017   12.681
11/1/2017   12.807
12/1/2017   12.929
1/1/2018    13.055
2/1/2018    13.182
3/1/2018    13.296
4/1/2018    13.422
5/1/2018    13.545
6/1/2018    13.671
7/1/2018    13.794
8/1/2018    13.92
9/1/2018    14.047
10/1/2018   14.17

我正在尝试进行线性插值,但值不匹配。也许我做错了什么。

你能帮忙找到我错过的东西吗?

这是我的代码

   public List<Cum> Interpolate() {

        List<Cum> result = new List<Cum>();
        Cum firstCum = this.Cums.First();
        Cum lastCum = this.Cums.Last();

        //warn if first date is nonzero
        if (firstCum.O > 0) Msg.alert("Warning! Starting rates are nonzero");

        //0. add data point at the end of known points if last kp is not beginning of month. i.e. 11/7/2018 -> 12/01/2018
        DateTime nextLastDate = lastCum.T.AddMonths(1);
        if (lastCum.T.Day > 1) this.Cums.Add(new Cum(new DateTime(nextLastDate.Year, nextLastDate.Month, 1), lastCum.O));

        //1. Add missing data points 
        int knownPoints = this.Cums.Count - 1;
        DateTime firstDate = this.Cums.First().T;
        DateTime nextMonthDate = new DateTime(firstDate.Year, firstDate.AddMonths(1).Month, 1);
        for (int i = 0; i <= knownPoints; i++) {

            DateTime aDate = new DateTime(this.Cums[i].T.Year, this.Cums[i].T.Month, 1);

            //if date is not missing, do not interpolate
            if (aDate < nextMonthDate) {

                //remove duplicate from results (this is first of month, so it's a good one)
                if (this.Cums[i].T.Day == 1) result.Remove(result.Last());

                result.Add(this.Cums[i]);

                //if first of month is missing, add new data point and interpolate
            } else {

                //before and after datapoints
                int p1 = i - 1 < 0 ? 0 : i - 1;
                int p2 = i + 1 > knownPoints ? i : i + 1;

                float x0 = this.Cums[p1].T.Year + this.Cums[p1].T.DayOfYear;
                float x1 = this.Cums[p2].T.Year + this.Cums[p2].T.DayOfYear;
                float y0 = this.Cums[p1].O;
                float y1 = this.Cums[p2].O;

                //Linear Interpolation
                //DateTime T = new DateTime(this.Cums[i].T.Year, this.Cums[i].T.Month, 1);
                float x = nextMonthDate.Year + nextMonthDate.DayOfYear;
                //float x = T.Year + this.Cums[p1].T.DayOfYear;
                float O = (float)linear(x, x0, x1, y0, y1);


                //first date should have zero cummulative;
                if (i == 0) O = G = W = 0;

                result.Add(new Cum(new DateTime(nextMonthDate.Year, nextMonthDate.Month, 1), O));
                nextMonthDate = nextMonthDate.AddMonths(1);
                i--;
            }
        }
        return result;


    }


    static public double linear(double x, double x0, double x1, double y0, double y1) {
        if ((x1 - x0) == 0) {
            return (y0 + y1) / 2;
        }
        return y0 + (x - x0) * (y1 - y0) / (x1 - x0);
    }

0 个答案:

没有答案