使用Scippy的ndimage.map_coordinates进行插值时出现意外结果

时间:2013-08-13 16:40:17

标签: python numpy scipy interpolation

我想在以下数据上插入(x, y)的多个用户输入:

            | >=0 1    2   3    4   5    >=6
   -------------------------------------------
   >=09 <10 | 6.4 5.60 4.8 4.15 3.5 2.85 2.2
   >=10 <11 | 5.3 4.50 3.7 3.05 2.4 1.75 1.1
   >=11 <12 | 4.7 3.85 3.0 2.35 1.7 1.05 0.4
       >=12 | 4.2 3.40 2.6 1.95 1.3 0.65 0.0

如果用户输入x = 2.5y = 9,则模型应返回4.475。另一方面,如果用户输入x = 2.5y = 9.5,则模型应返回3.925

我使用map_coordinates,因为它提供了将坐标映射到x,y范围

的功能

这是我到目前为止所做的事情:

import numpy as np
from scipy.ndimage import map_coordinates

# define array
z = np.array([[6.4, 5.60, 4.8, 4.15, 3.5, 2.85, 2.2],
              [5.3, 4.50, 3.7, 3.05, 2.4, 1.75, 1.1],
              [4.7, 3.85, 3.0, 2.35, 1.7, 1.05, 0.4],
              [4.2, 3.40, 2.6, 1.95, 1.3, 0.65, 0.0]])

# function to interpolate
def twoD_interpolate(arr, xmin, xmax, ymin, ymax, x1, y1):
    """
    interpolate in two dimensions with "hard edges"
    """
    nx, ny = arr.shape
    x1 = np.array([x1], dtype=np.float)
    y1 = np.array([y1], dtype=np.float)

    # if x1 is out of bounds set its value to its closest point, so that we're always
    # interpolating within the range
    x1[x1 > xmax] = xmax
    x1[x1 < xmin] = xmin

    # if y1 is out of bounds set its value to its closest point, so that we're always
    # interpolating within the range
    y1[y1 > ymax] = ymax
    y1[y1 < ymin] = ymin

    # convert x1 and y1 to indices so we can map over them
    x1 = (nx - 1) * (x1 - xmin) / (xmax - xmin)
    y1 = (ny - 2) * (y1 - ymin) / (ymax - ymin)
    y1[y1 > 1] = 2.0

    return map_coordinates(arr, [y1, x1])

# function to get the value
def test_val(x, y, arr):
    return twoD_interpolate(arr, 0, 6, 9, 12, x, y)

测试代码

print test_val(4, 11, z) --> 3.00
print test_val(2, 10, z) --> 3.85

这些结果不正确,因为它们应分别返回1.73.7

关于我做错了什么想法或想法?

1 个答案:

答案 0 :(得分:2)

使用您的功能:

def twoD_interpolate(arr, xmin, xmax, ymin, ymax, x1, y1):
    """
    interpolate in two dimensions with "hard edges"
    """
    ny, nx = arr.shape  # Note the order of ny and xy

    x1 = np.atleast_1d(x1)
    y1 = np.atleast_1d(y1)

    # Change coordinates to match your array.
    x1 = (x1 - xmin) * (nx - 1) / float(xmax - xmin)
    y1 = (y1 - ymin) * (ny - 1) / float(ymax - ymin)

    # order=1 is required to return your examples.
    # mode='nearest' prevents the need for clip
    return map_coordinates(arr, np.vstack((y1, x1)), order=1, mode='nearest')

# function to get the value
def test_val(x, y, arr):
    return twoD_interpolate(arr, 0, 6, 9, 12, x, y)

现在让我们进行一些测试:

print test_val(4, 11, z)
[ 1.7]

print test_val(2, 10, z)
[ 3.7]

print test_val(2.5, 9, z)
[ 4.475]

print test_val(2.5, 9.5, z)
[ 3.925]

#Can even use 1D numpy arrays now
print test_val(np.arange(4),np.arange(4)+9,z)
[ 6.4   4.5   3.    1.95]

解释:

np.atleast_1d是一个确保您的数组至少为1维的函数。如果np.array([x1])是一个numpy数组,x1将返回一个2D数组。这是不可取的。

>>> np.atleast_1d(5)
array([5])
>>> np.atleast_1d(np.arange(5))
array([0, 1, 2, 3, 4])

设置order=1是指样条插值顺序。在上面你展示了线性插值1,如果你想考虑更多的值,你可以增加它以达到预期的效果。

np.vstack用于正确定位xy索引。在这个术语中,map_coordinates希望数据为:

coords=[[y1,y2,y3,...
        [x1,y2,y3,...]]

ycoords,xcoords=['y1','y2','y3'],['x1','x2','x3']
>>> np.vstack((xcoords,ycoords))
array([['y1', 'y2','y3'],
       ['x1', 'x2','x3']],
      dtype='|S2')