如何在两个不规则数据集之间插值?(涉及IT技术)

10

很抱歉标题有点让人困惑,但我不确定如何更清晰地概括这个问题。

我有两组X,Y数据,每组对应一个整体的值。它们从原始数据中进行了相当密集的采样。我正在寻找一种方法,可以为我已经有的两组数值之间的任何给定Y值找到插值的X值。

以下的图表可以更清楚地说明:

A graph of points

在这个例子中,红线是对应于100的集合,黄线是对应于50的集合。

换句话说,假设这些集合对应于一系列的值(尽管它们明显是由离散的X、Y测量值构成的),我想知道如何找到这样一个值:如果Y等于500,对应于一个值为75的集合,那么此时的X值是多少?

在这个例子中,我期望我的目标点大约在这里:

A graph of points with an interpolated point

我并不需要这个函数过于复杂——它可以是简单的线性插值数据点。我只是在思考这个问题时有些困难。

需要注意的是,两组数据点中的X和Y坐标并不完全重叠。然而,“找到这两组共享的最近的X点”或“找到这两组共享的最近的Y点”却是相当简单的。

我已经尝试过使用已知值之间的简单插值(例如找到集合“50”和“100”的相应Y值,然后取平均得到“75”),但结果看起来像这样:

Not very good interpolation

很明显我在这里做错了什么。显然,在所有Y高于“最低”集的最大Y的情况下,X都正确地返回为0。事情一开始很顺利,但在接近最低集的最大Y时,它开始失控。

很容易看出我的做法有何问题。以下是另一种解决问题的方法:

Illustration

在“正确”的版本中,X应该大约是250。相反,我正在将400和0平均,所以X是200。如何在这种情况下求解X?我想双线性插值可能有答案,但我找到的所有信息似乎都结构不同,没有清晰地说明我该如何解决这类问题。

感谢您的帮助。请注意,虽然我显然已经在R中绘制了上述数据,以便更容易看出我在说什么,但最终的工作是在Javascript和PHP中完成的。我不需要重型工具;简单就好。


这似乎更像是一个数学问题而不是编程问题,因此最好适合于http://math.stackexchange.com或http://stats.stackexchange.com。 - Oliver Charlesworth
1
我正在寻找一种实用的解决方案,与理论性的解决方案相对。我在这类论坛上的经验是,他们喜欢回复一个优雅的方程式,而我不知道如何将其实现为代码。(另外,我对目前数学或统计前几页的问题一无所知,这并不鼓舞人心...)(一个例子就是:http://math.stackexchange.com/questions/177491/how-to-perform-simple-linear-interpolation-on-a-data-set) - nucleon
问题是你可能没有在红线和/或黄线上的点吗?如果是这样,你可以分别对红线和黄线进行插值,然后取平均值..? - thebjorn
这个答案看起来很有前途。基本上的想法是在两条线之间进行变形(例如在两张脸之间进行变形)。也许这会指引你朝着正确的方向前进?其他更简单的想法:一个非常简单的想法是线性插值,但在两个轴上都要进行。只需将两个插值平均在一起,甚至可以加权。另一个想法是找到每个点和每组的另一条线上最接近的点。你需要这样做两次(每条线各一次),因为结果不对称。然后以某种方式将它们平均。 - jmiserez
所以我得出结论,这实际上是一个有趣而困难的问题。对于任何给定点来说,正确的中点实际上更加复杂:想象一条从0,0到外部集合上的点x1,y1的线段AB。x2,y2是与之相交的内部集合上的点。因此,AB由于适当插值的X点与所需的Y点相交而被定义。但如何编写代码呢... - nucleon
显示剩余2条评论
1个回答

11

天啊,我终于明白了。这就是最终的结果:

最终成果

太棒了!但是这需要很多工作。

我的代码太过零散,也太过特定于我的项目,对别人用处不大。但是这里有基本的逻辑。

你需要两组数据进行插值。我称之为“外部”曲线和“内部”曲线。“外部”曲线被认为完全包围并且不与“内部”曲线相交。这些曲线实际上只是X、Y数据集,并且对应于一个定义为Z的一组值。在这个例子中,“外部”曲线对应于Z=50,“内部”曲线对应于Z=100。

目标,就是再已知数据点的某个区间内,当Z代表某个数字时,查找给定Y的X。

  1. 首先确定未知Z在两组曲线之间的比例。例如,在我们的例子中,如果Z=75,则这个比例为0.5。如果Z=60,则为0.2。如果Z=90,则为0.8。将这个比例记为P。

  2. 选择“外部”曲线上Y等于所需Y的数据点。设想一条线段连接该点和0,0,并将其定义为AB。

  3. 我们希望找到AB与“内部”曲线相交的位置。为此,我们遍历每个内部曲线上的点。将所选点和点+1之间的线段定义为CD。检查AB和CD是否相交。如果没有,则继续迭代直到它们相交。

  4. 当我们发现一个AB-CD交点时,我们会看这个交点与第二步中“外部”曲线上原始点形成的线段。这条线段是内部和外部曲线之间的一条线,在图表向下延伸时,它的斜率将与0,0相交。将这个新的线段定义为EF。
    在EF的长度的P百分比位置(来自第一步),找到位置P。检查Y值。它是我们想要的Y值吗?如果是(不太可能),则返回该点的X。如果不是,则查看Y是否小于目标Y。如果是,请将该点的位置存储在一个变量中,我称其为lowY。然后再次回到第2步,处理外部曲线上的下一个点。如果它大于目标Y,则查看lowY是否有值。如果有,就在两个值之间进行插值,并返回插值X。(换句话说,我们已经“框定”了我们想要的坐标。)
    以上过程效果很好。但当Y=0时会失败,但可以通过特定的两个点进行插值解决。在样本数量较少的地方,结果可能会出现粗糙,但我认为这是可以预料的(这些是Z = 5000,6000,7000,8000,9000,10000,只有5000和10000是已知点,每个点只有20个数据点 - 其余是插值)。
    我并不打算将其作为一个优化的解决方案,但在我的电脑上对于大量数据点的求解几乎是瞬时的,所以我认为对于现代机器来说,它不会太费劲,至少对于我手头的总点数(每个曲线有30-50个数据点)。感谢大家的帮助;通过沟通,我意识到我真正想要的并不是简单的线性插值,而是一种沿着曲线的“径向”插值。

3
干得好,伙计。我也有同样的问题,不过是用 Matlab。如果你需要,这里有答案 =) https://dev59.com/Jn_aa4cB1Zd3GeqP22kO - Nikko
你的回答是我接下来几天需要做的事情。我会尝试一下,看看能否解决它。只是想说谢谢! - la femme cosmique
如果你还有一些代码遗留在身边,那么如果能看到它的话,我将不胜感激。 - la femme cosmique
非常遗憾,这个问题非常特定于该项目,并且非常复杂。 (到目前为止,我只理解了一半,因为已经很久没有看它了。)总有一天我会尝试创建一个通用版本的相同函数...但今天不行! - nucleon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接