Googleスプレッドシートで範囲内のデータを補間する方法


9

私はデータを持つ配列を持っています:

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

データは完全に非線形です。Xはソートされることが保証されています。

ここで、任意の値について、数値間を線形補間したいとします(たとえば、3 => 50、4 => 55、5 => 60)。双一次補間の方が優れていますが、私は期待を低く抑えています。

回答:


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スプレッドシートアプリとWebアプリのモバイルバージョンはスクリプトをサポートしていません)。しかし、機能は間違いなくよりクリーンでエレガントです。だから私はあなたの答えを選んでいます。
EboMike 14

@EboMikeコードを確認したところ、エラーが発生しました。コードを修正し、モバイルアプリで使用できるように数式を作成しました。
Jacob Jan Tuinstra、2014

2
そして、これが残念なことです。答えを2回以上投票することができないのは残念です:)ジェイコブに感謝します。
EboMike 14

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))

詳細に:

FORECASTは線形補間を行いますが、直線を想定しています。したがって、探している値を囲む2つの値を見つける必要があります。

したがって、MATCHを使用して、探しているもの以上の最初の数値を見つけます。

FORECASTはデータ範囲を想定しているため、OFFSETを使用してデータ範囲への参照を作成します。MATCHは1インデックスなので、最初に1を引く必要があります。1つの幅と2つの高さの範囲を作成します。この値には、検索値$ C $ 1が含まれることが保証されています。


+1; 素敵な式!! を選択x=20すると、になり#DIV/0ます。
Jacob Jan Tuinstra 2014

1

これはJacob Jan Tuinstraのスクリプトを少し変更したものであり、配列または値を3番目の引数として取ることができるため、補間された関数を一度に多くの場所で計算できます。唯一の違いは、最初に追加された数行です。これは、ほとんどすべてのカスタム関数を、配列を受け入れるカスタム関数にすばやく変換する方法です。

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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.