INTERPN

This function interpolates values on a regular or rectilinear 2D grid and evaluates the interpolant at specified query points. It supports linear, nearest-neighbor, and spline-based 2D interpolation modes supported by the underlying library.

If grid axes are x_i and y_j with tabulated values f(x_i, y_j), the function estimates \hat{f}(x, y) for each query coordinate pair (x, y) using the selected interpolation method.

Excel Usage

=INTERPN(points_x, points_y, values, xi, interpn_method, bounds_error, fill_value)
  • points_x (list[list], required): Column vector of x-coordinates of the grid points
  • points_y (list[list], required): Column vector of y-coordinates of the grid points
  • values (list[list], required): 2D array of data values on the grid
  • xi (list[list], required): Points at which to interpolate data (n_points, 2)
  • interpn_method (str, optional, default: “linear”): Interpolation method
  • bounds_error (bool, optional, default: true): If True, error on out-of-bounds points
  • fill_value (float, optional, default: null): Value for out-of-bounds points if bounds_error is False

Returns (list[list]): 2D list (column vector) of interpolated values, or error message (str) if invalid.

Example 1: Linear interpolation at grid center

Inputs:

points_x points_y values xi
0 0 0 1 0.5 0.5
1 1 1 2

Excel formula:

=INTERPN({0;1}, {0;1}, {0,1;1,2}, {0.5,0.5})

Expected output:

1

Example 2: Nearest-neighbor on 3x3 grid

Inputs:

points_x points_y values xi interpn_method
0 0 1 2 3 0.4 0.6 nearest
1 1 4 5 6
2 2 7 8 9

Excel formula:

=INTERPN({0;1;2}, {0;1;2}, {1,2,3;4,5,6;7,8,9}, {0.4,0.6}, "nearest")

Expected output:

2

Example 3: Out-of-bounds query with custom fill value

Inputs:

points_x points_y values xi interpn_method bounds_error fill_value
0 0 1 2 1.5 1.5 linear false -999
1 1 3 4

Excel formula:

=INTERPN({0;1}, {0;1}, {1,2;3,4}, {1.5,1.5}, "linear", FALSE, -999)

Expected output:

-999

Example 4: Linear interpolation at multiple query points

Inputs:

points_x points_y values xi interpn_method bounds_error
0 0 1 2 3 0.5 0.5 linear true
1 1 2 3 4 1.5 1
2 2 3 4 5 2 1.5
3 4 5 6

Excel formula:

=INTERPN({0;1;2;3}, {0;1;2}, {1,2,3;2,3,4;3,4,5;4,5,6}, {0.5,0.5;1.5,1;2,1.5}, "linear", TRUE)

Expected output:

Result
2
3.5
4.5

Python Code

import math
import numpy as np
from scipy.interpolate import interpn as scipy_interpn

def interpn(points_x, points_y, values, xi, interpn_method='linear', bounds_error=True, fill_value=None):
    """
    Multidimensional interpolation on regular grids (2D).

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interpn.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        points_x (list[list]): Column vector of x-coordinates of the grid points
        points_y (list[list]): Column vector of y-coordinates of the grid points
        values (list[list]): 2D array of data values on the grid
        xi (list[list]): Points at which to interpolate data (n_points, 2)
        interpn_method (str, optional): Interpolation method Valid options: Linear, Nearest, Spline 2D. Default is 'linear'.
        bounds_error (bool, optional): If True, error on out-of-bounds points Default is True.
        fill_value (float, optional): Value for out-of-bounds points if bounds_error is False Default is None.

    Returns:
        list[list]: 2D list (column vector) of interpolated values, or error message (str) if invalid.
    """
    try:
        def to2d(x):
            return [[x]] if not isinstance(x, list) else x

        def flatten(arr):
            return [item for sublist in arr for item in sublist]

        def validate_numeric_2d(arr, name):
            if not isinstance(arr, list):
                return f"Error: Invalid input: {name} must be a 2D list."
            if not all(isinstance(row, list) for row in arr):
                return f"Error: Invalid input: {name} must be a 2D list."
            flat = flatten(arr)
            if not flat:
                return f"Error: Invalid input: {name} must not be empty."
            for val in flat:
                if not isinstance(val, (int, float)):
                    return f"Error: Invalid input: {name} must contain only numeric values."
                if math.isnan(val) or math.isinf(val):
                    return f"Error: Invalid input: {name} must contain only finite values."
            return None

        # Normalize inputs
        points_x = to2d(points_x)
        points_y = to2d(points_y)
        values = to2d(values)
        xi = to2d(xi)

        # Validate inputs
        err = validate_numeric_2d(points_x, "points_x")
        if err:
            return err
        err = validate_numeric_2d(points_y, "points_y")
        if err:
            return err
        err = validate_numeric_2d(values, "values")
        if err:
            return err
        err = validate_numeric_2d(xi, "xi")
        if err:
            return err

        # Validate interpn_method
        valid_methods = ['linear', 'nearest', 'splinef2d']
        if not isinstance(interpn_method, str) or interpn_method not in valid_methods:
            return f"Error: Invalid input: interpn_method must be one of {valid_methods}."

        # Validate bounds_error
        if not isinstance(bounds_error, bool):
            return "Error: Invalid input: bounds_error must be a boolean."

        # Validate and set fill_value
        if fill_value is None:
            fill_value = float('nan')
        else:
            if not isinstance(fill_value, (int, float)):
                return "Error: Invalid input: fill_value must be a number."
            fill_value = float(fill_value)

        # Flatten grid coordinates
        points_x_flat = flatten(points_x)
        points_y_flat = flatten(points_y)

        # Check grid monotonicity
        if len(points_x_flat) < 2 or len(points_y_flat) < 2:
            return "Error: Invalid input: grid coordinates must have at least 2 points."

        for i in range(len(points_x_flat) - 1):
            if points_x_flat[i] >= points_x_flat[i + 1]:
                return "Error: Invalid input: points_x must be strictly increasing."

        for i in range(len(points_y_flat) - 1):
            if points_y_flat[i] >= points_y_flat[i + 1]:
                return "Error: Invalid input: points_y must be strictly increasing."

        # Validate values dimensions
        if len(values) != len(points_x_flat):
            return f"Error: Invalid input: values must have {len(points_x_flat)} rows to match points_x."

        for row in values:
            if len(row) != len(points_y_flat):
                return f"Error: Invalid input: each row in values must have {len(points_y_flat)} columns to match points_y."

        # Validate xi dimensions
        for row in xi:
            if len(row) != 2:
                return "Error: Invalid input: each row in xi must have exactly 2 columns [x, y]."

        # Convert to numpy arrays
        try:
            values_arr = np.array(values, dtype=float)
            xi_arr = np.array(xi, dtype=float)
            points = (np.array(points_x_flat, dtype=float), np.array(points_y_flat, dtype=float))
        except Exception as exc:
            return f"Error: Invalid input: unable to convert inputs to arrays: {exc}"

        # Perform interpolation
        try:
            result = scipy_interpn(
                points,
                values_arr,
                xi_arr,
                method=interpn_method,
                bounds_error=bounds_error,
                fill_value=fill_value,
            )
        except Exception as exc:
            return f"Error: scipy.interpolate.interpn error: {exc}"

        # Convert result to 2D list (column vector)
        if not isinstance(result, np.ndarray):
            return "Error: scipy.interpolate.interpn error: unexpected result type."

        result_list = [[float(val)] for val in result.flatten()]

        # Validate result
        for row in result_list:
            for val in row:
                if not isinstance(val, float):
                    return "Error: scipy.interpolate.interpn error: non-numeric result."
                # Allow NaN if fill_value is NaN, but not inf
                if math.isinf(val):
                    return "Error: scipy.interpolate.interpn error: result contains infinite values."

        return result_list
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

Column vector of x-coordinates of the grid points
Column vector of y-coordinates of the grid points
2D array of data values on the grid
Points at which to interpolate data (n_points, 2)
Interpolation method
If True, error on out-of-bounds points
Value for out-of-bounds points if bounds_error is False