来自给定数据源的IDW插值和具有一些NoData值的网格点

时间:2014-08-08 09:50:41

标签: python grid interpolation

我一直在寻找python脚本来插入我的数据。我找到了可以解决问题的代码。 我在修改下面的代码时有几个问题。 1)我的数据按照data.txt给出的方式进行了组织。它有lat,long和值。我希望代码从我的文本数据中读取我的数据和进程。 2)我也有lat和long网格点。我想从网格点数据进行插值,并使用提供的网格点数据附加插值。 3)我在mt给定数据中有NoData / NULL值,因此我希望代码只从仅有数据的站进行插值。

data.xtx

XV   YV   v1  v2  v2  v4  v5  v6  v7
10  10  1   2   4   3   NA      4
10  15  4   4   3   NA  NA      NA
30  35  NA  NA  1   NA  5       18
5   20  4   NA  4   3   10      NA
15  15  NA  5   4   NA  NA      5
25  10  7   8   7   5   10      NA

我的网格点数据看起来

grid.txt

 X  Y
10  10
10  15
10  20
10  25
10  30
10  35
10  40
15  10
15  15
15  20
15  25
15  30
15  35
15  40
20  10
20  15
20  20
20  25
20  30
20  35
20  40
25  10
25  15
25  20
25  25
25  30
25  35
25  40
30  10
30  15
30  20
30  25
30  30
30  35
30  40
35  10
35  15
35  20
35  25
35  30
35  35
35  40
40  10
40  15
40  20
40  25
40  30
40  35
40  40

我正在尝试的代码是

#! /usr/bin/python

 from math import pow  
 from math import sqrt  
 import numpy as np  

 def pointValue(x,y,power,smoothing,xv,yv,values):  
     nominator=0  
     denominator=0  
     for i in range(0,len(values)):  
         dist = sqrt((x-xv[i])*(x-xv[i])+(y-yv[i])*(y-yv[i])+smoothing*smoothing);  
         #If the point is really close to one of the data points, return the data point value to avoid singularities  
         if(dist<0.0000000001):  
             return values[i]  
         nominator=nominator+(values[i]/pow(dist,power))  
         denominator=denominator+(1/pow(dist,power))  
     #Return NODATA if the denominator is zero  
     if denominator > 0:  
         value = nominator/denominator  
     else:  
         value = -9999  
     return value  

 def invDist(xv,yv,values,xsize=100,ysize=100,power=2,smoothing=0):  
     valuesGrid = np.zeros((ysize,xsize))  
     for x in range(0,xsize):  
         for y in range(0,ysize):  
             valuesGrid[y][x] = pointValue(x,y,power,smoothing,xv,yv,values)  
     return valuesGrid  


 if __name__ == "__main__":  
     power=1  
     smoothing=20  

     #Creating some data, with each coodinate and the values stored in separated lists  
     xv = [10,60,40,70,10,50,20,70,30,60]  
     yv = [10,20,30,30,40,50,60,70,80,90]  
     values = [1,2,2,3,4,6,7,7,8,10]  

     #Creating the output grid (100x100, in the example)  
     ti = np.linspace(0, 100, 100)  
     XI, YI = np.meshgrid(ti, ti)  

     #Creating the interpolation function and populating the output matrix value  
     ZI = invDist(xv,yv,values,100,100,power,smoothing)  
     print ZI

1 个答案:

答案 0 :(得分:0)

您确定要IDW吗? IDW有一个讨厌的属性,当你插入一些东西时,你将不得不考虑所有的点。在很多情况下插入事物也很糟糕。因此,如果您只需要对数据进行适当的插值,请查看scipy.interpolate.griddata这可能正是您所需要的。

另一方面,如果你想通过IDW插入一个未知点列表,它可以被矢量化为相当短(但请记住,这仍然是O(m * n),其中m和n是未知和已知点的数量)。

import numpy as np

# inverse power to use
pow = 2

# some points:
known_pts = np.array([[0,0], [1,0], [3,0], [4,0],
                      [0,1], [2,1], [3,1], [4,1],
                      [1,3], [2,3], [3,3], [4,3]])
# and some data associated with them
known_values = known_pts[:,0] + known_pts[:,1]

# unknown points
unknown_pts = np.array([[2,0], [1,1],  [0,2], [1,2], [2,2], [3,2], [4,2], [0,3]])

# calculate all distances from unknown points to known points:
# (the array will have as many rows as there are unknown points and as many columns
#  as there are known points)
dist = np.sqrt((known_pts[:,0][None,:]-unknown_pts[:,0][:,None])**2 + (known_pts[:,1][None,:]-unknown_pts[:,1][:,None])**2)

# calculate the inverse distances, use a small epsilon to avoid infinities:
idist = 1. / (dist + 1e-12)**pow

# calculate the weighted average for each column with idist as the weight function
unknown_values = np.sum(known_values[None,:] * idist, axis=1) / np.sum(idist, axis=1)

当绘制此示例时(斑点区域反映值,红色是已知点,蓝色未知点),我们得到:

enter image description here