Come interpolare i dati in un intervallo in Fogli Google


9

Ho un array con dati:

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

I dati sono interamente non lineari. X è garantito per essere ordinato.

Ora per ogni dato valore, vorrei avere un'interpolazione lineare tra i numeri (quindi, ad esempio, 3 => 50, 4 => 55, 5 => 60). Un'interpolazione bilineare sarebbe ancora più bella, ma sto mantenendo basse le mie aspettative.

Risposte:


9

Questo script farà lo stesso (più un po 'di più).

Codice

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

spiegato

All'inizio dello script, c'è un piccolo errore nella gestione. Successivamente troverà la prima voce più bassa rispetto al valore di input. Una volta trovato, farà un po 'di matematica e presenterà il risultato.

Nota

Se il valore selezionato è uguale a 20, lo script restituisce 150 come dove viene resa la formula #DIV/0.

Immagine dello schermo

inserisci qui la descrizione dell'immagine

Formula

Utilizzare la seguente formula per tenere conto di tutti i valori

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

Esempio

Aggiungi lo script in Strumenti> Editor di script e premi il pulsante Salva (non è necessaria l'autenticazione).

Ho creato un file di esempio per te: come interpolare i dati in un intervallo in Fogli Google


2
Grazie Jacob! Ad essere sincero, mi piace quasi di più la mia versione perché funziona anche su dispositivi mobili (l'app Android Sheets nativa e la versione mobile dell'app Web non hanno il supporto per gli script afaict), ma la tua funzione è decisamente più pulita ed elegante . Quindi sto scegliendo la tua risposta.
EboMike

@EboMike Ho guardato il mio codice e ho notato un errore. Ho rivisto il codice e mi è venuta in mente una formula, in modo che tu possa usarlo sulla tua app mobile.
Jacob Jan Tuinstra,

2
Ed è per questo che è un peccato non poter votare una risposta più di una volta :) Grazie Jacob.
EboMike,

10

Ho trovato un modo per farlo - potrebbe esserci un modo migliore, ma questo è quello che mi è venuto in mente:

Supponendo che i dati siano in A1: B10 e $ C $ 1 contiene la chiave da cercare:

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

In dettaglio:

PREVISIONE esegue un'interpolazione lineare, ma assume una linea retta. Quindi dobbiamo trovare i due valori che racchiudono il valore che stiamo cercando.

Quindi usiamo MATCH per trovare il primo numero uguale o superiore a quello che stiamo cercando.

PREVISIONE prevede un intervallo di dati, quindi utilizziamo OFFSET per creare un riferimento a un intervallo di dati. MATCH è un indice, quindi dobbiamo sottrarre prima uno. Creiamo un intervallo che è uno largo e due alti. Questo valore è garantito per racchiudere $ C $ 1, il nostro valore di ricerca.


+1; bella formula !! La scelta x=20comporterà #DIV/0.
Jacob Jan Tuinstra,

1

Questa è una piccola modifica della sceneggiatura di Jacob Jan Tuinstra , che consente di prendere una matrice o un valore come terzo argomento, in modo che la funzione interpolata possa essere calcolata in più punti contemporaneamente. L'unica differenza sono alcune righe aggiunte all'inizio; questo è un modo rapido per trasformare praticamente qualsiasi funzione personalizzata in una funzione personalizzata che accetta un 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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.