如何在Google表格中对数据进行插值


9

我有一个数据数组:

   X      Y
   3     50
   5     60
   9    120
  11    130
  18     90
  20    150

数据完全是非线性的。X保证可以排序。

现在,对于任何给定的值,我想在数字之间进行线性插值(例如3 => 50、4 => 55、5 => 60)。双线性插值会更好,但是我的期望值偏低。

Answers:


9

该脚本将执行相同的操作(还有更多)。

function myInterpolation(x, y, value) {
  if(value > Math.max.apply(Math, x) || value < Math.min.apply(Math, x)) {
    throw "value can't be interpolated !!";
    return;
  }

  var check = 0, index;
  for(var i = 0, iLen = x.length; i < iLen; i++) {
    if(x[i][0] == value) {
      return y[i][0];
    } else {      
      if(x[i][0] < value && ((x[i][0] - check) < (value - check))) {
        check = x[i][0];
        index = i;
      }
    }
  }

  var xValue, yValue, xDiff, yDiff, xInt;
  yValue = y[index][0];
  xDiff = x[index+1][0] - check;
  yDiff = y[index+1][0] - yValue;
  xInt = value - check; 

  return (xInt * (yDiff / xDiff)) + yValue;
}

讲解

在脚本的开头,有一个小的错误处理。之后,它将找到与输入值相比第一最低的条目。一旦找到,它将进行一些数学运算并给出结果。

注意

如果所选值等于20,则脚本将在公式产生的地方返回150 #DIV/0

屏幕截图

在此处输入图片说明

使用以下公式考虑所有值

=IF(
   ISNA(
     MATCH(C2,A2:A7,0)),
   FORECAST(
     $C$2,
     OFFSET(B$2,MATCH($C$2,A$2:A$7,1)-1,0,2,1),
     OFFSET(A$2,MATCH($C$2,A$2:A$7,1)-1,0,2,1)), 
   INDEX(
     B2:B7,
     MATCH(C2,A2:A7,0)
     ,0)
 )

 copy / paste
 =IF(ISNA(MATCH(C2, A2:A7, 0)), FORECAST($C$2,OFFSET(B$2,MATCH($C$2,A$2:A$7,1)-1,0,2,1),OFFSET(A$2,MATCH($C$2,A$2:A$7,1)-1,0,2,1)), INDEX(B2:B7, MATCH(C2, A2:A7, 0), 0))

在“工具”>“脚本编辑器”下添加脚本,然后按“保存”按钮(无需身份验证)。

我为您创建了一个示例文件:如何在Google表格中的某个区域内插数据


2
谢谢雅各!老实说,我几乎更喜欢我的版本,因为它也可以在移动设备上运行(本机Android Sheets应用程序和Web应用程序的移动版本没有脚本支持aafict),但是您的功能肯定更简洁,更优雅。所以我在选你的答案。
EboMike

@EboMike我查看了我的代码,发现一个错误。我修改了代码并提出了一个公式,以便您可以在移动应用程序上使用它。
Jacob Jan Tuinstra 2014年

2
这就是为什么不幸的是您不能多次回答一个问题:)谢谢Jacob。
EboMike

10

我找到了一种方法-可能有更好的方法,但这就是我想出的方法:

假设数据在A1:B10中,并且$ C $ 1包含要查找的键:

=FORECAST($C$1,
    OFFSET(B$1,MATCH($C$1,A$1:A$10,1)-1,0,2,1),
    OFFSET(A$1,MATCH($C$1,A$1:A$10,1)-1,0,2,1))

详细:

预测进行线性插值,但假定为直线。因此,我们需要找到两个值来包围我们想要的值。

因此,我们使用MATCH查找等于或大于所要查找的第一个数字。

FORECAST需要一个数据范围,因此我们使用OFFSET创建对数据范围的引用。MATCH是单索引的,因此我们需要先减去一个。我们创建一个范围为一宽两高的范围。确保该值包含我们的搜索值$ C $ 1。


+1; 漂亮的公式!选择x=20将导致#DIV/0
Jacob Jan Tuinstra 2014年

1

这是对Jacob Jan Tuinstra脚本的一个小修改,使它可以将数组或值作为第三个参数,以便可以在许多地方一次计算内插函数。唯一的区别是在开头添加了几行;这是将几乎所有自定义函数转换为接受数组的自定义函数的快速方法。

function myInterpolation(x, y, value) {
  if (value.map) {
    return value.map(function(v) {
      return myInterpolation(x, y, v);
    });
  }
  //  the rest stays the same

  if (value > Math.max.apply(Math, x) || value < Math.min.apply(Math, x)) {
    throw "value can't be interpolated !!";
    return;
  }

  var check = 0, index;
  for(var i = 0, iLen = x.length; i < iLen; i++) {
    if(x[i][0] == value) {
      return y[i][0];
    } else {      
      if(x[i][0] < value && ((x[i][0] - check) < (value - check))) {
        check = x[i][0];
        index = i;
      }
    }
  }

  var xValue, yValue, xDiff, yDiff, xInt;
  yValue = y[index][0];
  xDiff = x[index+1][0] - check;
  yDiff = y[index+1][0] - yValue;
  xInt = value - check; 

  return (xInt * (yDiff / xDiff)) + yValue;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.