Cara menginterpolasi data dalam rentang di Google Sheets

9

Saya memiliki array dengan data:

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

Data sepenuhnya non-linear. X dijamin akan disortir.

Sekarang untuk setiap nilai yang diberikan, saya ingin memiliki interpolasi linier antara angka-angka (jadi misalnya, 3 => 50, 4 => 55, 5 => 60). Interpolasi bilinear bahkan akan lebih bagus, tapi saya menjaga harapan saya rendah.

EboMike
sumber

Jawaban:

9

Script ini akan melakukan hal yang sama (ditambah sedikit lagi).

Kode

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;
}

Dijelaskan

Di awal skrip, ada sedikit penanganan kesalahan. Setelah itu akan menemukan entri terendah pertama dibandingkan dengan nilai input. Setelah ditemukan, ia akan menghitung dan menyajikan hasilnya.

Catatan

Jika nilai yang dipilih sama dengan 20, skrip mengembalikan 150 sebagai tempat rumus menghasilkan #DIV/0.

Tangkapan layar

masukkan deskripsi gambar di sini

Rumus

Gunakan rumus berikut untuk memperhitungkan semua nilai akun

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

Contoh

Tambahkan skrip di bawah Alat> Editor skrip dan tekan tombol simpan (tidak diperlukan otentikasi).

Saya telah membuat contoh file untuk Anda: Cara menginterpolasi data dalam rentang di Google Sheets

Jacob Jan Tuinstra
sumber
2
Yakub terima kasih! Sejujurnya, saya hampir menyukai versi saya lebih baik karena berfungsi di perangkat seluler juga (aplikasi Android Sheets asli dan versi seluler dari aplikasi web tidak memiliki dukungan skrip afaict), tetapi fungsi Anda jelas lebih bersih dan lebih elegan . Jadi saya memilih jawaban Anda.
EboMike
@ EboMike Saya melihat kode saya dan melihat ada kesalahan. Saya merevisi kode dan menghasilkan rumus, sehingga Anda dapat menggunakannya di aplikasi seluler Anda.
Jacob Jan Tuinstra
2
Dan inilah mengapa sangat disayangkan Anda tidak dapat memilih jawaban lebih dari satu kali :) Terima kasih Jacob.
EboMike
10

Saya menemukan cara untuk melakukannya - mungkin ada cara yang lebih baik, tetapi inilah yang saya temukan:

Dengan asumsi data dalam A1: B10 dan $ C $ 1 berisi kunci untuk mencari:

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

Secara terperinci:

PRAKIRAAN melakukan interpolasi linier, tetapi mengasumsikan garis lurus. Jadi kita perlu menemukan dua nilai yang menyertakan nilai yang kita cari.

Jadi kami menggunakan MATCH untuk menemukan angka pertama yang sama atau lebih tinggi dari yang kami cari.

FORECAST mengharapkan rentang data, jadi kami menggunakan OFFSET untuk membuat referensi ke rentang data. MATCH adalah satu-diindeks, jadi kita harus kurangi dulu. Kami membuat rentang satu lebar dan dua tinggi. Nilai ini dijamin untuk menyertakan $ C $ 1, nilai pencarian kami.

EboMike
sumber
+1; formula yang bagus !! Memilih x=20akan menghasilkan #DIV/0.
Jacob Jan Tuinstra
1

Ini adalah modifikasi kecil dari skrip Jacob Jan Tuinstra , memungkinkannya untuk mengambil array atau nilai sebagai argumen ketiga, sehingga fungsi yang diinterpolasi dapat dihitung di banyak tempat sekaligus. Satu-satunya perbedaan adalah beberapa baris ditambahkan di awal; ini adalah cara cepat untuk mengubah hampir semua fungsi kustom menjadi fungsi kustom yang menerima array.

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;
}
pengguna135384
sumber