Comment interpoler des données dans une plage dans Google Sheets

9

J'ai un tableau avec des données:

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

Les données sont entièrement non linéaires. X est garanti pour être trié.

Maintenant, pour une valeur donnée, je voudrais avoir une interpolation linéaire entre les nombres (donc par exemple, 3 => 50, 4 => 55, 5 => 60). Une interpolation bilinéaire serait encore plus agréable, mais je garde mes attentes basses.

EboMike
la source

Réponses:

9

Ce script fera de même (plus un peu plus).

Code

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

Expliqué

Au début du script, il y a une petite gestion des erreurs. Après cela, il trouvera la première entrée la plus basse par rapport à la valeur d'entrée. Une fois trouvé, il fera quelques calculs et présentera le résultat.

Remarque

Si la valeur sélectionnée est égale à 20, le script renvoie 150 comme où la formule donne #DIV/0.

Capture d'écran

entrez la description de l'image ici

Formule

Utilisez la formule suivante pour prendre en compte toutes les valeurs

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

Exemple

Ajoutez le script sous Outils> Editeur de script et appuyez sur le bouton Enregistrer (aucune authentification requise).

J'ai créé un exemple de fichier pour vous: comment interpoler des données dans une plage dans Google Sheets

Jacob Jan Tuinstra
la source
2
Merci Jacob! Pour être honnête, je préfère presque ma version car elle fonctionne également sur les appareils mobiles (l'application native Android Sheets et la version mobile de l'application Web ne prennent pas en charge les scripts), mais votre fonction est définitivement plus propre et plus élégante . Je choisis donc votre réponse.
EboMike
@EboMike J'ai regardé mon code et j'ai remarqué une erreur. J'ai révisé le code et trouvé une formule pour que vous puissiez l'utiliser sur votre application mobile.
Jacob Jan Tuinstra
2
Et c'est pourquoi il est malheureux que vous ne puissiez pas voter plus d'une fois :) Merci Jacob.
EboMike
10

J'ai trouvé un moyen de le faire - il y a peut-être un meilleur moyen, mais voici ce que j'ai trouvé:

En supposant que les données sont en A1: B10 et $ C $ 1 contient la clé à rechercher:

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

En détail:

FORECAST effectue une interpolation linéaire, mais il suppose une ligne droite. Nous devons donc trouver les deux valeurs qui entourent la valeur que nous recherchons.

Nous utilisons donc MATCH pour trouver le premier nombre égal ou supérieur à ce que nous recherchons.

FORECAST attend une plage de données, nous utilisons donc OFFSET pour créer une référence à une plage de données. MATCH est un indexé, nous devons donc soustraire un premier. Nous créons une gamme qui est un large et deux haut. Cette valeur est garantie d'inclure $ C $ 1, notre valeur de recherche.

EboMike
la source
+1; belle formule !! Le choix x=20se traduira par #DIV/0.
Jacob Jan Tuinstra
1

Il s'agit d'une petite modification du script de Jacob Jan Tuinstra , lui permettant de prendre un tableau ou une valeur comme troisième argument, de sorte que la fonction interpolée puisse être calculée à plusieurs endroits à la fois. La seule différence est quelques lignes ajoutées au début; c'est un moyen rapide de transformer à peu près n'importe quelle fonction personnalisée en une fonction personnalisée qui accepte un tableau.

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;
}
user135384
la source