以前在工作中遇到了一个数据错误的问题,顺便写下 用 Math.Net 解决的思路。

1. 错误的数据

上图是同一组探测器在同一天采集到的 19 次数据,总体来说重复性不错,但很明显最后 8 个探测器出了问题,导致采集到的数据在最后八个点一片混乱。即使把其中看起来最好的一组数据拿出来使用多项式拟合,也可以看出最后几个点没有落在拟合曲线上(只拟合最后 14 个点):

虽然我知道这是硬件问题,但是遇到事情不能坐以待毙,软件方面也许可以做些什么。既然我从上图中得知出了最后几个点之外,其它数据都在拟合曲线上,那我可以使用前面几个点的拟合结果预测后面几个点并替换掉出错的数据,从而得到一组看起来正常的数据。

2. 曲线拟合与数据预测

曲线拟合(curve fitting)是指选择适当的曲线类型来拟合观测数据,以便观察两组数据之间的内在联系,了解数据之间的变化趋势。

在数据分析时,我们有时需要通过已有数据来预测未来数据。在一些复杂的数据模型中,数据维度很多,数据之间的关系很复杂,我们可能会用到深度学习的算法。但是在一些简单的数据模型中,数据之间有很明显的相关性,那我们就可以使用简单的曲线拟合来预测未来的数据。

这些工作都可以使用 Excel 完成,先来尝试一下。把某组数据最后14个点(只选取峰值右边的14个点是因为容易计算)放进Excel中,插入一个散点图,右键点击其中的蓝色散点,选择添加趋势线

然后在右侧出现的设置趋势线格式中选择多项式,阶数为 3,勾选显示公式

可以看到,曲线图中出现了一条虚线的曲线,并显示了对应的公式为 y = 6E-07x3 + 0.0002x2 - 0.0072x + 0.0637

如果需要预测数据,可以修改前推数字以得到后面几个周期的数据。

3. 使用 Math.Net 进行曲线拟合

当然我不可能对每一条数据都扔进 Excel 里进行拟合。在 C# 中我们可以使用 Math.Net 进行非线性拟合。

Math.Net 是一个开源项目,旨在构建和维护涵盖基础数学的工具箱,以满足 .Net 开发人员的高级需求和日常需求。其中 Math.NET Numerics 旨在为科学、工程和日常使用中的数值计算提供方法和算法。涵盖的主题包括特殊函数,线性代数,概率模型,随机数,插值,积分变换等等。

要使用 Math.NET Numerics,首先安装它的 Nuget 包:

Install-Package MathNet.Numerics

Math.NET Numerics 提供了 Fit.Polynomial 函数用作多项式拟合,如以下代码所示,其中 X 是 X 轴的数组, Y 是 Y 轴的数组, 函数的第三个参数是多项式的阶数,这里用 2 作为阶数。

double[] X = Enumerable.Range(1, 6).Select(r => (double)r).ToArray();
double[] Y = values.ToArray();
double[] parameters = Fit.Polynomial(X, Y, 2);

返回的结果是最佳拟合参数的数组 [p0,p1,p2,…,pk],将其带入公式 p0 + p1×x + p2×x2 + ... + pk×xk 即可算出对应的拟合数据。完整的代码如下,在这个示例里,我只需要用倒数第9到14个数据,通过 Fit.Polynomial 获得一个多项式的方程 ( f(x) = p0 + p1×x + p2×x2 ),然后用这个方程计算出后面 8 个点的数据替换原本出错的数据:

double[] X = Enumerable.Range(1, 6).Select(r => (double)r).ToArray();
double[] Y = values.ToArray();
double[] parameters = Fit.Polynomial(X, Y, 2); List<double> result = new List<double>();
for (int i = 1; i < 15; i++)
{
result.Add(parameters[0] + parameters[1] * i + parameters[2] * i * i );
} for (int i = 0; i < 8; i++)
{
data[data.Count - 1 - i] = result[result.Count - 1 - i];
}

替换后的结果如上所示,整体符合前面数据的趋势,使用这组数据进行运算也能得到很好的结果。

4. 最后

Math.Net 是一个强大的项目,这篇文章只介绍了它所有功能的冰山一角。想了解更多可以参考官方文档,或参考博客园上的文章,例如:

【目录】开源Math.NET基础数学类库使用总目录 - 数据之巅 - 博客园

5. 参考

Math.NET Numerics

Curve Fitting Linear Regression

【目录】开源Math.NET基础数学类库使用总目录 - 数据之巅 - 博客园

数据预测与曲线拟合 - 知乎

6. 源码

https://github.com/DinoChan/SimpleDataPrediction

[C#] 使用 Excel 和 Math.Net 进行曲线拟合和数据预测的更多相关文章

  1. 【原创】.NET读写Excel工具Spire.Xls使用(4)对数据操作与控制

                  本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html .NET读写Excel工具Spire.Xls使用文章 ...

  2. 如何用Apache POI操作Excel文件-----如何在已有的Excel文件中插入一行新的数据?

    在POI的第一节入门中,我们提供了两个简单的例子,一个是如何用Apache POI新建一个工作薄,另外一个例子是,如果用Apache POI新建一个工作表.那么在这个章节里面,我将会给大家演示一下,如 ...

  3. 如何使用python在保留原excel格式的前提下插入/修改数据

    一.需求分析: 统计的报表中需要每日查询当天数据并追加到原有的excel后面. 因为原始excel格式已经设定好,如果使用xlwt,仅仅指定设定我们要插入的单元格的格式,原始数据的格式会被初始化. 所 ...

  4. Java读取Excel并与SqlServer库中的数据比较

    先说说需求.在SQL server数据库中的表里存在一些数据,现在整理的Excel文档中也存在一些数据,现在需要通过根据比较某个字段值(唯一)来判断出,在库中有但excel中没有的数据. 大概的思路就 ...

  5. 使用Apache POI操作Excel文件---在已有的Excel文件中插入一行新的数据

    package org.test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundEx ...

  6. C# 使用Epplus导出Excel [3]:合并列连续相同数据

    C# 使用Epplus导出Excel [1]:导出固定列数据 C# 使用Epplus导出Excel [2]:导出动态列数据 C# 使用Epplus导出Excel [3]:合并列连续相同数据 C# 使用 ...

  7. [办公自动化]如何让excel图表标签中显示最新值数据

    同事做了一张excel图表,希望最新的数据显示数据标签,其他都不显示.并且当单元格的数据新增加时,这个标签要能自动更新. 这里需要用到公式,获取到这个最新值.在b2输入公式=lookup(9e+307 ...

  8. 第三课 创建函数 - 从EXCEL读取 - 导出到EXCEL - 异常值 - Lambda函数 - 切片和骰子数据

    第 3 课   获取数据 - 我们的数据集将包含一个Excel文件,其中包含每天的客户数量.我们将学习如何对 excel 文件进​​行处理.准备数据 - 数据是有重复日期的不规则时间序列.我们将挑战数 ...

  9. 如何使用Java创建Excel(.xls 和 .xlsx)文件 并写入数据

    1,需要依赖的jar包, <!-- POI(operate excel) start --> <!-- the version of the following POI packag ...

随机推荐

  1. HTTP接口传输数据常用的方式

    Get方式是从服务器上获取数据,在数据查询时,建议用Get方式:如商品信息接口.搜索接口等 Post方式是向服务器传送数据,做数据添加.修改或删除时,建议用Post方式,如登录注册接口等. 1.GET ...

  2. element ui的el-radio踩坑

    1.html 1 <div class="listPeopleDetail"> 2 <div class="item" v-for=" ...

  3. js数组去重方法集合

    //第一种方法,新建一个空数组,将原来的数组循环逐个与新数组的成员做比较,如果新数组没有该元素就push进来 var arr = ['a', 1, 1, 1, 2, 4, 4, 'b', 'c', ' ...

  4. OI学习过程记录

    这帖子本来是教练为了给低年级学生分享经验而让我写的学习经历,不过等我退役之后可能就变成回忆录了. 初三 WC 前:上了正睿的线上课程,练了一些模拟赛,同时也正在学文化课. 然后,莫名奇妙1膜考了全校前 ...

  5. 题解-CF1437F Emotional Fishermen

    题面 CF1437F Emotional Fishermen 给 \(n\) 个数的序列 \(a_i\),求有多少种 \(n\) 个数的排列 \(p_i\),使得 \[\frac{a_{p_i}}{\ ...

  6. Codeforces Edu Round 66 A-E

    A. From Hero to Zero 通过取余快速运行第一步即可.由于\(a \% b (a >= b) <= \frac{a}{2}\).所以总复杂度不超过\(O(log_2n)\) ...

  7. Python 中的哈希表

    Python 中的哈希表:对字典的理解   有没有想过,Python中的字典为什么这么高效稳定.原因是他是建立在hash表上.了解Python中的hash表有助于更好的理解Python,因为Pytho ...

  8. SSM框架中常用的注解及含义

    @Controller---使用它标记在一个类上,dispatcher会扫描使用该注解类的方法,并检测该方法是否使用了@RequestMapping注解,加上RequestMapping注解的方法才是 ...

  9. C 与 C++ 中 指向二维数组的指针进行指针运算

    二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有"缝隙".以下面的二维数组 nums 为例: 从概念上理解,nums 的分布像一个矩阵,但在 ...

  10. Mongdb优化

    1.索引1)基础索引--为集合colt1的x列创建升序基础索引# cd /usr/local/mongodb4.2.2/bin# ./mongo -uroot -p> use db_test&g ...