差异 scipy interpolate vs mpl griddata

Posted

技术标签:

【中文标题】差异 scipy interpolate vs mpl griddata【英文标题】:differences scipy interpolate vs mpl griddata 【发布时间】:2021-12-31 22:15:36 【问题描述】:

我差点把头发扯下来,真的希望有人能在这里帮助我。

我需要将一个脚本从 python 2 转换为 python 3,它是一个简单的脚本,它接受坐标点xy,以及这些点的值z

z 在网格上插值,然后绘制。 python 2脚本中的插值目前正在使用from matplotlib.mlab import griddata

但是,python 3 中不存在 mlab griddata。所以我认为我们应该使用 scipy.interpolate 作为替代品。

问题是,它给了我非常奇怪的结果。

最近邻比较

Mpl griddata With interp='nn' 给我:

scipy interpolate using method='nearest' 给了我

这是最重要的,因为这是我需要的结果,但结果却如此不同!

我尝试了其他参数看看是否仍然存在

线性比较

带有interp='linear'的mpl griddata给了我

scipy interpolate with method='linear' 给了我

线性显示相同的结果,但我不在乎线性。

三次比较

mpl griddata 没有三次,但是使用 scipy interpolate 的结果非常奇怪。

数据

import numpy as np
# points
x = np.array([31132.71118116, 10763.66383076, 29340.62119857,  4025.2544491 ,
       19158.87683925, 36584.96725821, 17335.28090098, 27279.80878719,
        5893.32833709, 36392.22873482, 22350.16973122, 40235.86525991,
       19844.57893466, 11245.50791534, 17103.62528354, 29944.77964486,
       34021.92540595, 44485.36307614,  8797.36817447, 24733.44616607,
       30628.62812172, 27227.91858716, 26221.60497488, 27987.74985745,
       14366.37775758, 32035.24328142, 29779.84095199, 42821.14608703,
       42229.95963477, 22592.94483609, 26362.45107434, 22161.13844494,
       21562.53974235, 40784.42626907, 14195.87932099, 25628.56490406,
       19212.62065784, 28354.69294259, 34299.91259166, 28276.85653059,
       13291.49360218, 64014.88912569,     0.        , 64014.88912569,
           0.        ])
    
y = np.array([1.61640041e+04, 1.18226221e+04, 1.66496799e+04, 1.60268291e+04,
       1.47533260e+04, 1.72743862e+04, 2.58461610e+04, 1.11997818e+04,
       1.94747705e+04, 2.81559903e+04, 2.85786579e+04, 2.16418047e+04,
       2.58684064e+04, 2.17474690e+04, 3.21398453e+04, 2.13563269e+04,
       2.12339790e+04, 2.42537633e+04, 1.89242092e+04, 2.45410984e+04,
       1.90984612e+04, 2.45058762e+04, 1.76859142e+04, 2.13655953e+04,
       2.62595562e+04, 1.44826845e+04, 2.55328718e+04, 2.97076285e+04,
       1.81975446e+04, 3.27182416e+04, 1.88407910e+04, 1.58599943e+04,
       2.02514897e+04, 2.42723003e+04, 1.76265941e+04, 1.60045845e+04,
       2.03274941e+04, 1.67609034e+04, 1.74986867e+04, 1.78898244e+04,
       3.21546756e+04, 9.55042196e-08, 9.55042196e-08, 4.04414440e+04,
       4.04414440e+04])
    
z = np.array([0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0.6, 0. , 0. , 0. , 0. ,
       0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ,
       0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ,
       0. , 0. , 0. , 0. , 0. , 0. ])
    
min_grid_val_x = 0
max_grid_val_x = 64014.88912569069

min_grid_val_y = 9.550421964377165e-08
max_grid_val_y = 40441.443993242734
    
# set up a square grid with the same extents as our measured data
numcols, numrows = 1000, 1000
xi = np.linspace(min_grid_val_x, max_grid_val_x, numcols)
yi = np.linspace(min_grid_val_y, max_grid_val_y, numrows)
xi, yi = np.meshgrid(xi, yi)

其他代码


import numpy as np
import pandas as pd
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import matplotlib.colors as mc
import matplotlib.patches as mpatches
from matplotlib.colors import ListedColormap
from matplotlib.colors import Normalize
import math

MODE == 'mpl'
if MODE == 'mpl':
    from matplotlib.mlab import griddata
    zi = griddata(x, y, z, xi, yi, interp='nn')
else:
    from scipy.interpolate import griddata
    points = np.array([[x[i],y[i]] for i in range(len(x))])
    zi = griddata(points, z, (xi, yi), method='cubic',fill_value=0)
    
min_val = math.floor(z.min())
max_val = math.ceil(z.max())
resolutions = [0.1, 0.2, 0.5, 1, 1.5, 2, 3, 5, 10, 
               15, 20, 30, 40, 50, 60, 70, 80]
    
max_of_Z = z.max()
if (max_of_Z==0):
    levels = np.arange(min, min + (0.1 * 12), 0.1)
else:
    hit = False
    for res in resolutions:
        condition = res*12
        if condition > z.max():
            print("Using ".format(res))
            levels = np.arange(min_val, max_val + condition, res)
            hit = True
            break
    if not hit:
        res = 90
        print("Using ".format(res))
        condition = res*12
        levels = np.arange(min_val, max_val + condition, res)
    
norm = mc.BoundaryNorm(levels, len(levels)-1)

cmapV=ListedColormap([[0.73,0.90,0.97],
[0.66,0.87,0.97],
[0.57,0.82,0.95],
[0.49,0.76,0.91],
[0.40,0.69,0.87],
[0.32,0.62,0.83],
[0.26,0.53,0.77],
[0.20,0.44,0.71],
[0.14,0.34,0.64],
[0.13,0.29,0.56],
[0.12,0.23,0.47],
[0.11,0.17,0.38]])

# define map extent
lllat=1.1497
urlat=1.5133
lllon=103.5822
urlon=104.1579
# set up plot
plt.clf()
fig = plt.figure(figsize=(13, 6))
ax = fig.add_subplot(111, facecolor='w', frame_on=False)

# Set up Basemap instance
m = Basemap(
    projection = 'merc',
    llcrnrlon = lllon, llcrnrlat = lllat, urcrnrlon = urlon, urcrnrlat = urlat,
    resolution='h')

# contour plot
con = m.contourf(xi, yi, zi, zorder=1, alpha=None, cmap=cmapV, levels=levels, norm=norm)

【问题讨论】:

【参考方案1】:

根据STOQS 的问题Github 页面上的this discussion,最接近旧Matplotlib 的griddata 默认算法,即自然邻居,是使用scipy.interpolate.griddata 获得的与method='cubic'rescale=True

也就是说,如果您发布的数据代表了您的实际问题,那么您的图表都没有洞察力,因为您不应该从单个数据点 (x=5893.32833709, y=19474.7705, z=0.6) 进行推断,而所有其他数据点都有一个 z纵坐标全等于零。

【讨论】:

嘿,感谢您的回复!我以前看过那个帖子,它对我也不起作用。尝试griddata(points, z, (xi, yi), method='cubic',fill_value=0, rescale=True) 给了我与问题中最后一个情节几乎完全相同的情节。如果它只给出左上角的区域(即大多数点为 0),我会接受这个图。是的,这是真实数据,将是一种常见情况。这种情况下的预期结果是理想情况下的第一个图 (NN) @Wboy ①如果你在Q中提到你已经看过那个问题,我可能不会浪费时间回答②当你的数据有结构时,插值结果是明智的,尽管有算法;相反…… 抱歉浪费您的时间。我正在寻找一种在 python 3 中复制 mpl 的旧 griddata 自然邻居插值的方法。

以上是关于差异 scipy interpolate vs mpl griddata的主要内容,如果未能解决你的问题,请参考以下文章

scipy 0.11.0 到 0.12.0 更改了线性 scipy.interpolate.interp1d,破坏了我不断更新的插值器

如何使 scipy.interpolate 给出超出输入范围的推断结果?

使用scipy.interpolate.CubicSpline添加或乘以三次样条曲线

Python scipy.interpolate插值

使用 scipy interpolate griddata 方法重新网格化数据时出现意外的内存错误

测试scipy.interpolate.interp2d对于低分辨率图像插值处理结果