AKIMA_INTERP

Overview

The AKIMA_INTERP function performs one-dimensional interpolation using the Akima spline method, producing “visually pleasing” smooth curves that pass through given data points. This technique is particularly useful when you need to estimate intermediate values between measured data points, such as filling gaps in time-series data or creating smooth curves through experimental measurements.

The Akima interpolation method, introduced by Hiroshi Akima in 1970, constructs a continuously differentiable (C1 smooth) piecewise cubic polynomial. Unlike traditional cubic splines, Akima’s approach uses a locally-weighted average of neighboring slopes, which helps reduce unwanted oscillations near outliers or sharp changes in the data.

The algorithm computes derivatives at each data point using weighted averages of the slopes between adjacent intervals. For each point x_i, the derivative d_i is calculated as:

d_i = \frac{w_1 \cdot \delta_{i-1} + w_2 \cdot \delta_i}{w_1 + w_2}

where \delta_i = \frac{y_{i+1} - y_i}{x_{i+1} - x_i} represents the slope of the interval [x_i, x_{i+1}), and the weights are defined as w_1 = |\delta_{i+1} - \delta_i| and w_2 = |\delta_{i-1} - \delta_{i-2}|.

This implementation uses the Akima1DInterpolator class from SciPy, a fundamental library for scientific computing in Python. The function requires at least two data points and expects unique, monotonically increasing x-values. For related interpolation methods, see SciPy’s PchipInterpolator for monotonic interpolation or CubicSpline for traditional spline interpolation.

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

Excel Usage

=AKIMA_INTERP(x, y, x_new)
  • x (list[list], required): X-coordinates of the data points (column vector)
  • y (list[list], required): Y-coordinates of the data points (column vector)
  • x_new (list[list], required): X-coordinates at which to evaluate the interpolated values

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

Examples

Example 1: Demo case 1

Inputs:

x y x_new
0 0 1.5
1 1
2 0
3 1

Excel formula:

=AKIMA_INTERP({0;1;2;3}, {0;1;0;1}, 1.5)

Expected output:

Result
0.5

Example 2: Demo case 2

Inputs:

x y x_new
0 0 0.5
1 2 1.5
2 1 2.5
3 3
4 2

Excel formula:

=AKIMA_INTERP({0;1;2;3;4}, {0;2;1;3;2}, {0.5;1.5;2.5})

Expected output:

Result
1.375
1.5
2

Example 3: Demo case 3

Inputs:

x y x_new
0 0 1.5
1 1 2.5
2 4
3 9
4 16

Excel formula:

=AKIMA_INTERP({0;1;2;3;4}, {0;1;4;9;16}, {1.5;2.5})

Expected output:

Result
2.25
6.25

Example 4: Demo case 4

Inputs:

x y x_new
0 0 0.3927
0.7854 0.7071 1.1781
1.5708 1
2.3562 0.7071
3.1416 0

Excel formula:

=AKIMA_INTERP({0;0.7854;1.5708;2.3562;3.1416}, {0;0.7071;1;0.7071;0}, {0.3927;1.1781})

Expected output:

Result
0.4009
0.9205

Python Code

import math
from scipy.interpolate import Akima1DInterpolator as scipy_Akima1DInterpolator

def akima_interp(x, y, x_new):
    """
    Akima 1D interpolation.

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

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

    Args:
        x (list[list]): X-coordinates of the data points (column vector)
        y (list[list]): Y-coordinates of the data points (column vector)
        x_new (list[list]): X-coordinates at which to evaluate the interpolated values

    Returns:
        list[list]: A 2D list of interpolated values, or an error message (str) if invalid.
    """
    def to2d(val):
        """Convert scalar or list to 2D list format."""
        return [[val]] if not isinstance(val, list) else val

    def flatten(arr):
        """Flatten a 2D list to 1D."""
        return [item for sublist in arr for item in sublist]

    def validate_numeric_array(arr, name):
        """Validate that array contains only finite numeric values."""
        if not isinstance(arr, list):
            return f"Invalid input: {name} must be a 2D list."
        for row in arr:
            if not isinstance(row, list):
                return f"Invalid input: {name} must be a 2D list."
            for val in row:
                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

    try:
        # Normalize inputs to 2D lists
        x = to2d(x)
        y = to2d(y)
        x_new = to2d(x_new)

        # Validate inputs
        error = validate_numeric_array(x, "x")
        if error:
            return error
        error = validate_numeric_array(y, "y")
        if error:
            return error
        error = validate_numeric_array(x_new, "x_new")
        if error:
            return error

        # Flatten arrays
        x_flat = flatten(x)
        y_flat = flatten(y)
        x_new_flat = flatten(x_new)

        # Check that x and y have the same length
        if len(x_flat) != len(y_flat):
            return "Invalid input: x and y must have the same length."

        # Check minimum number of points
        if len(x_flat) < 2:
            return "Invalid input: at least 2 data points are required."

        # Check for empty arrays before processing
        if len(x_flat) == 0 or len(y_flat) == 0:
            return "Invalid input: x and y cannot be empty."

        # Sort by x
        combined = sorted(zip(x_flat, y_flat), key=lambda pair: pair[0])
        x_sorted, y_sorted = zip(*combined)
        x_sorted = list(x_sorted)
        y_sorted = list(y_sorted)

        # Check for duplicates
        for i in range(len(x_sorted) - 1):
            if x_sorted[i] == x_sorted[i+1]:
                return "Invalid input: x values must be unique."

        # Create interpolator and evaluate
        interp = scipy_Akima1DInterpolator(x_sorted, y_sorted)
        result = interp(x_new_flat)

        # Convert result to 2D list
        output = [[float(val)] for val in result]

        # Validate output
        for row in output:
            for val in row:
                if math.isnan(val) or math.isinf(val):
                    return "Interpolation error: result contains non-finite values."

        return output

    except ValueError as e:
        return f"Invalid input: {e}"
    except Exception as e:
        return f"scipy.interpolate.Akima1DInterpolator error: {e}"

Online Calculator