【问题标题】:interpolate missing values 2d python插入缺失值 2d python
【发布时间】:2016-10-06 08:12:06
【问题描述】:

我有一个二维数组(或矩阵,如果你愿意的话),其中一些缺失值表示为 NaN。缺失值通常沿一个轴呈一条带状,例如:

1   2   3 NaN   5
2   3   4 Nan   6
3   4 Nan Nan   7
4   5 Nan Nan   8
5   6   7   8   9

我想用一些合理的数字替换NaN

我查看了 delaunay 三角测量,但发现的文档很少。

我尝试使用astropy's convolve,因为它支持使用二维数组,而且非常简单。 这样做的问题是卷积不是插值,它会将所有值移向平均值(可以通过使用窄内核来缓解)。

这个问题应该是this post 的自然二维扩展。有没有办法在二维数组中插入NaN/缺失值?

【问题讨论】:

  • 有很多方法可以插入这个。一个困难是您的数据不再是矩形的,许多简单的 2d 插值算法都需要这样做,但它仍然是可能的。您对插值有什么特殊要求吗?
  • 例如,这个docs.scipy.org/doc/scipy-0.14.0/reference/generated/… 可能满足您的需求。只需传入不是 NaN 的数据点,然后在构建插值后在 NaN 处重新采样。
  • 另外,这个问题:stackoverflow.com/questions/5146025/… 似乎本质上是一样的。
  • @JeremyWest 非常感谢您提供的链接,我认为 griddata 与我所寻找的很接近。

标签: python numpy interpolation


【解决方案1】:

我实际上是逐行手动遍历这个矩阵,每当您开始遇到一个 Nans 列表时,请跟踪紧接在 Nans 之前和之后的数字,以及您在返回之前看到的 Nans 的数量普通数字。一旦找到这些数字,就可以自己用插值覆盖 Nans。

【讨论】:

    【解决方案2】:

    是的,您可以使用scipy.interpolate.griddata 和掩码数组,您可以使用参数method 通常选择您喜欢的插值类型'cubic' 做得很好:

    import numpy as np
    from scipy import interpolate
    
    
    #Let's create some random  data
    array = np.random.random_integers(0,10,(10,10)).astype(float)
    #values grater then 7 goes to np.nan
    array[array>7] = np.nan
    

    使用plt.imshow(array,interpolation='nearest') 看起来像这样 :

    x = np.arange(0, array.shape[1])
    y = np.arange(0, array.shape[0])
    #mask invalid values
    array = np.ma.masked_invalid(array)
    xx, yy = np.meshgrid(x, y)
    #get only the valid values
    x1 = xx[~array.mask]
    y1 = yy[~array.mask]
    newarr = array[~array.mask]
    
    GD1 = interpolate.griddata((x1, y1), newarr.ravel(),
                              (xx, yy),
                                 method='cubic')
    

    这是最终结果:

    如果 nan 值位于边缘并且被 nan 值包围,则无法插值并保留 nan。您可以使用 fill_value 参数更改它。

    如果有一个 3x3 区域的 NaN 值,这将如何工作,你会得到中间点的合理数据吗?

    这取决于您的数据类型,您必须执行一些测试。例如,您可以故意屏蔽一些好的数据,尝试不同类型的插值,例如三次、线性等等。使用带有掩码值的数组,计算插值与您之前掩码的原始值之间的差异,看看哪种方法会返回微小的差异。

    你可以这样使用:

    reference = array[3:6,3:6].copy()
    array[3:6,3:6] = np.nan
    method = ['linear', 'nearest', 'cubic']
    
    for i in method:
        GD1 = interpolate.griddata((x1, y1), newarr.ravel(),
                                  (xx, yy),
                                     method=i)
        meandifference = np.mean(np.abs(reference - GD1[3:6,3:6]))
        print ' %s interpolation difference: %s' %(i,meandifference )
    

    这给出了这样的结果:

       linear interpolation difference: 4.88888888889
       nearest interpolation difference: 4.11111111111
       cubic interpolation difference: 5.99400137377
    

    当然,这是针对随机数的,因此结果可能会有很大差异是正常的。因此,最好的办法是对数据集的“故意屏蔽”部分进行测试,看看会发生什么。

    【讨论】:

    • 如果有一个 3x3 的 NaN 值区域,这将如何工作,你会得到中间点的合理数据吗?
    • @M.T 你好,我已经编辑了答案,来回答这个问题。
    【解决方案3】:

    为方便起见,这里有一个实现G M's answer的函数。

    from scipy import interpolate
    import numpy as np
    
    def interpolate_missing_pixels(
            image: np.ndarray,
            mask: np.ndarray,
            method: str = 'nearest',
            fill_value: int = 0
    ):
        """
        :param image: a 2D image
        :param mask: a 2D boolean image, True indicates missing values
        :param method: interpolation method, one of
            'nearest', 'linear', 'cubic'.
        :param fill_value: which value to use for filling up data outside the
            convex hull of known pixel values.
            Default is 0, Has no effect for 'nearest'.
        :return: the image with missing values interpolated
        """
        from scipy import interpolate
    
        h, w = image.shape[:2]
        xx, yy = np.meshgrid(np.arange(w), np.arange(h))
    
        known_x = xx[~mask]
        known_y = yy[~mask]
        known_v = image[~mask]
        missing_x = xx[mask]
        missing_y = yy[mask]
    
        interp_values = interpolate.griddata(
            (known_x, known_y), known_v, (missing_x, missing_y),
            method=method, fill_value=fill_value
        )
    
        interp_image = image.copy()
        interp_image[missing_y, missing_x] = interp_values
    
        return interp_image
    

    【讨论】:

      猜你喜欢
      • 2013-07-31
      • 2018-05-21
      • 1970-01-01
      • 2020-01-15
      • 1970-01-01
      • 2020-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多