所以,我有三个numpy数组,它们在网格上存储纬度,经度和一些属性值 - 也就是说,我有LAT(y,x),LON(y,x),并说温度T( y,x),对于x和y的某些限制。网格不一定是规则的 - 事实上,它是三极的。
然后我想将这些属性(温度)值插值到一堆不同的纬度/经度点(存储为lat1(t),lon1(t),大约10,000吨...),这些点不会落在实际网格点。我已经尝试了matplotlib.mlab.griddata,但这需要太长时间(毕竟它并不是为我正在做的事情设计的)。我也尝试过scipy.interpolate.interp2d,但是我得到了一个MemoryError(我的网格大约是400x400)。
有没有任何光滑的,最好快速的方法吗?我不禁想到答案显而易见......谢谢!!
答案 0 :(得分:9)
尝试反距离加权和组合 scipy.spatial.KDTree 在SO中描述 inverse-distance-weighted-idw-interpolation-with-python。 Kd-trees 在2d 3d中很好地工作...,反距离加权是平滑的和局部的, 并且k =最近邻居的数量可以改变以折衷速度/准确度。
答案 1 :(得分:4)
有一个nice inverse distance example by Roger Veciana i Rovira以及一些使用GDAL写入geotiff的代码,如果你进入那个。
这对于常规网格来说是粗略的,但假设您首先将数据投影到具有pyproj或其他内容的像素网格,同时要小心使用哪些投影用于数据。
他的算法副本:
from math import pow
from math import sqrt
import numpy as np
import matplotlib.pyplot as plt
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)
# Plotting the result
n = plt.normalize(0.0, 100.0)
plt.subplot(1, 1, 1)
plt.pcolor(XI, YI, ZI)
plt.scatter(xv, yv, 100, values)
plt.title('Inv dist interpolation - power: ' + str(power) + ' smoothing: ' + str(smoothing))
plt.xlim(0, 100)
plt.ylim(0, 100)
plt.colorbar()
plt.show()
答案 2 :(得分:1)
这里有很多选项,哪一个最好取决于你的数据...... 但是,我不知道为您提供开箱即用的解决方案
您说您的输入数据来自三极数据。关于如何构建这些数据有三个主要案例。
最简单的是2.不是在LAT LON空间内插,而是“只是”将你的点转换回源空间并插入那里。
适用于1和2的另一个选项是搜索从三极空间映射的单元格以覆盖您的采样点。 (您可以使用BSP或网格类型结构来加速此搜索)选择其中一个单元格,然后在其中进行插值。
最后有一堆非结构化的插值选项..但它们往往很慢。 我个人最喜欢的是使用最近N个点的线性插值,再次使用网格或BSP来找到那些N个点。另一个不错的选择是Delauney对非结构化点进行三角测量并在得到的三角形网格上进行插值。
就个人而言,如果我的网格是案例1,我会使用非结构化策略,因为我担心必须处理搜索重叠投影的单元格。选择“正确”的细胞将很困难。
答案 3 :(得分:0)
我建议你看看GRASS(一个开源GIS软件包)插值功能(http://grass.ibiblio.org/gdp/html_grass62/v.surf.bspline.html)。它不在python中,但你可以重新实现它或与C代码接口。
答案 4 :(得分:0)
我是否认为您的数据网格看起来像这样(红色是旧数据,蓝色是新的插值数据)?
alt text http://www.geekops.co.uk/photos/0000-00-02%20%28Forum%20images%29/DataSeparation.png
这可能是一种略显强力的方法,但是如何将现有数据渲染为位图(opengl将为您配置简单的颜色插值,并配置正确的选项,您可以将数据渲染为三角形,应该是相当快。然后,您可以在新点的位置处对像素进行采样。
或者,您可以在空间上对第一组点进行排序,然后找到新点周围最近的旧点,并根据到这些点的距离进行插值。
答案 5 :(得分:0)
有一个名为BIVAR的FORTRAN库,它非常适合这个问题。通过一些修改,您可以使用f2py在python中使用它。
来自说明:
BIVAR是一个FORTRAN90库,由Hiroshi Akima插入分散的双变量数据。
BIVAR接受一组散布在2D中的(X,Y)数据点,具有相关的Z数据值,并且能够构造一个平滑的插值函数Z(X,Y),它与给定的数据一致,并且可以在飞机的其他点进行评估。