INTERPN
Overview
The INTERPN function performs multidimensional interpolation on regular or rectilinear grids, estimating values at arbitrary points within a structured 2D data grid. This implementation wraps SciPy’s scipy.interpolate.interpn function, which internally uses the RegularGridInterpolator class.
A rectilinear grid is a rectangular grid where spacing along each axis can be uneven, but the grid points must be strictly ascending along each dimension. Given known data values at these grid points, interpolation estimates values at intermediate locations that fall between the defined grid coordinates. This is particularly useful for working with tabular data, lookup tables, or any scenario where values are known at discrete grid points but needed at arbitrary locations.
The function supports three interpolation methods: - Linear (default): Performs multilinear interpolation by computing weighted averages of the 2^n nearest grid points. For 2D data, this is equivalent to bilinear interpolation. - Nearest: Returns the value of the closest grid point, useful when data represents discrete categories or when speed is prioritized over smoothness. - Splinef2d: Uses a 2D spline approximation via RectBivariateSpline, providing smoother results but only available for 2-dimensional data.
For bilinear interpolation (linear method in 2D), the interpolated value at point (x, y) is computed as:
f(x, y) \approx \frac{1}{(x_2 - x_1)(y_2 - y_1)} \left[ f(x_1, y_1)(x_2 - x)(y_2 - y) + f(x_2, y_1)(x - x_1)(y_2 - y) + f(x_1, y_2)(x_2 - x)(y - y_1) + f(x_2, y_2)(x - x_1)(y - y_1) \right]
where (x_1, y_1), (x_2, y_1), (x_1, y_2), and (x_2, y_2) are the four surrounding grid points.
The function provides boundary handling options: bounds_error controls whether out-of-bounds queries raise an error, and fill_value specifies the value returned for out-of-bounds points when errors are disabled. For more information, see the SciPy interpolation documentation and the interpn source code on GitHub.
This example function is provided as-is without any representation of accuracy.
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 pointspoints_y(list[list], required): Column vector of y-coordinates of the grid pointsvalues(list[list], required): 2D array of data values on the gridxi(list[list], required): Points at which to interpolate data (n_points, 2)interpn_method(str, optional, default: “linear”): Interpolation methodbounds_error(bool, optional, default: true): If True, error on out-of-bounds pointsfill_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.
Examples
Example 1: Demo case 1
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:
| Result |
|---|
| 1 |
Example 2: Demo case 2
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:
| Result |
|---|
| 2 |
Example 3: Demo case 3
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:
| Result |
|---|
| -999 |
Example 4: Demo case 4
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.
"""
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"Invalid input: {name} must be a 2D list."
if not all(isinstance(row, list) for row in arr):
return f"Invalid input: {name} must be a 2D list."
flat = flatten(arr)
if not flat:
return f"Invalid input: {name} must not be empty."
for val in flat:
if not isinstance(val, (int, float)):
return f"Invalid input: {name} must contain only numeric values."
if math.isnan(val) or math.isinf(val):
return f"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"Invalid input: interpn_method must be one of {valid_methods}."
# Validate bounds_error
if not isinstance(bounds_error, bool):
return "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 "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 "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 "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 "Invalid input: points_y must be strictly increasing."
# Validate values dimensions
if len(values) != len(points_x_flat):
return f"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"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 "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"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"scipy.interpolate.interpn error: {exc}"
# Convert result to 2D list (column vector)
if not isinstance(result, np.ndarray):
return "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 "scipy.interpolate.interpn error: non-numeric result."
# Allow NaN if fill_value is NaN, but not inf
if math.isinf(val):
return "scipy.interpolate.interpn error: result contains infinite values."
return result_list