代码之家  ›  专栏  ›  技术社区  ›  dassouki

numpy数组上的scipy插值

  •  10
  • dassouki  · 技术社区  · 15 年前

    我有一个查找表,定义如下:

           | <1    2    3    4    5+
    -------|----------------------------
    <10000 | 3.6   6.5  9.1  11.5 13.8
    20000  | 3.9   7.3  10.0 13.1 15.9
    20000+ | 4.5   9.2  12.2 14.8 18.2
    
    
    TR_ua1 = np.array([ [3.6, 6.5, 9.1, 11.5, 13.8],
                        [3.9, 7.3, 10.0, 13.1, 15.9],
                        [4.5, 9.2, 12.2, 14.8, 18.2] ])
    
    • 标题行元素是(hh)<1、2、3、4、5+
    • 头列(inc)元素为<10000、20000、20001+

    用户将输入一个值示例(1.3,25000),(0.2,50000),依此类推。 scipy.interpolate() 应插入以确定正确的值。

    目前,我唯一能做的就是 if / elifs 如下文所示。我很肯定有更好更有效的方法

    以下是我目前为止的情况:

    import numpy as np
    from scipy import interpolate
    
    if (ua == 1):
        if (inc <= low_inc):  # low_inc = 10,000
          if (hh <= 1):
            return TR_ua1[0][0]
          elif (hh >= 1 & hh < 2):
            return interpolate( (1, 2), (TR_ua1[0][1], TR_ua1[0][2]) )
    
    1 回复  |  直到 9 年前
        1
  •  8
  •   Joe Kington    15 年前

    编辑:更新的事情,以反映你的澄清上述。你的问题现在更清楚了,谢谢!

    基本上,你只是想在任意点插入一个二维数组。

    scipy.ndimage.map_coordinates 是你想要的……

    我理解您的问题,您有一个二维数组,其中“z”值的范围从一些xmin到xmax,以及每个方向的ymin到ymax。

    在这些边界坐标之外的任何内容,都要从数组的边返回值。

    地图坐标有几个选项可以处理网格边界以外的点,但它们都不能完全满足您的需要。相反,我们可以在边界之外设置任何东西,使其位于边缘,并像往常一样使用地图坐标。

    因此,要使用地图坐标,您需要转动实际坐标:

           | <1    2    3    4    5+
    -------|----------------------------
    <10000 | 3.6   6.5  9.1  11.5 13.8
    20000  | 3.9   7.3  10.0 13.1 15.9
    20000+ | 4.5   9.2  12.2 14.8 18.2
    

    索引坐标:

           |  0     1    2    3    4
    -------|----------------------------
       0   | 3.6   6.5  9.1  11.5 13.8
       1   | 3.9   7.3  10.0 13.1 15.9
       2   | 4.5   9.2  12.2 14.8 18.2
    

    请注意,您的边界在每个方向上的行为都不同…在x方向上,事情表现得很平稳,但在y方向上,你要求一个“硬”休息,其中y=20000-->3.9,但y=20000.000001-->4.5。

    举个例子:

    import numpy as np
    from scipy.ndimage import map_coordinates
    
    #-- Setup ---------------------------
    z = np.array([ [3.6, 6.5, 9.1, 11.5, 13.8],
                   [3.9, 7.3, 10.0, 13.1, 15.9],
                   [4.5, 9.2, 12.2, 14.8, 18.2] ])
    ny, nx = z.shape
    xmin, xmax = 1, 5
    ymin, ymax = 10000, 20000
    
    # Points we want to interpolate at
    x1, y1 = 1.3, 25000
    x2, y2 = 0.2, 50000
    x3, y3 = 2.5, 15000
    
    # To make our lives easier down the road, let's 
    # turn these into arrays of x & y coords
    xi = np.array([x1, x2, x3], dtype=np.float)
    yi = np.array([y1, y2, y3], dtype=np.float)
    
    # Now, we'll set points outside the boundaries to lie along an edge
    xi[xi > xmax] = xmax
    xi[xi < xmin] = xmin
    
    # To deal with the "hard" break, we'll have to treat y differently, 
    # so we're ust setting the min here...
    yi[yi < ymin] = ymin
    
    # We need to convert these to (float) indicies
    #   (xi should range from 0 to (nx - 1), etc)
    xi = (nx - 1) * (xi - xmin) / (xmax - xmin)
    
    # Deal with the "hard" break in the y-direction
    yi = (ny - 2) * (yi - ymin) / (ymax - ymin)
    yi[yi > 1] = 2.0
    
    # Now we actually interpolate
    # map_coordinates does cubic interpolation by default, 
    # use "order=1" to preform bilinear interpolation instead...
    z1, z2, z3 = map_coordinates(z, [yi, xi])
    
    # Display the results
    for X, Y, Z in zip((x1, x2, x3), (y1, y2, y3), (z1, z2, z3)):
        print X, ',', Y, '-->', Z
    

    这就产生了:

    1.3 , 25000 --> 5.1807375
    0.2 , 50000 --> 4.5
    2.5 , 15000 --> 8.12252371652
    

    希望这有助于…