我有一些data(x,y,z)位于非结构化网格上,我想插入数据以用于可视化目的。
我已经尝试过scipy.interpolate.griddata
,插值假定每个地方都有相同的值。之后我尝试scipy.interpolate.Rbf
,但这会给我带来内存错误(请参阅下面的代码)。
是否有其他方法或其他选项可以改善结果?
结果 - >
我的代码
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata, Rbf
x, y, z = np.loadtxt('stackoverflow_example-data')
# griddata
points = np.reshape(np.array([x, y]),(z.size, 2))
grid_x, grid_y = np.mgrid[x.min():x.max():1000j,y.min():y.max():1000j]
counts_I_grid_1 = griddata(points, z, (grid_x, grid_y), method='nearest')
counts_I_grid_2 = griddata(points, z, (grid_x, grid_y), method='linear', fill_value=0)
counts_I_grid_3 = griddata(points, z, (grid_x, grid_y), method='cubic', fill_value=0)
# Rbf -- fails due to memory error
#rbf = Rbf(x,y,z)
#counts_I_Rbf = rbf(grid_x,grid_y)
追踪(最近一次通话): 文件“/path/code.py”,第14行,in rbf = Rbf(x,y,z) 在 init 中输入文件“/[...]/python3.4/site-packages/scipy/interpolate/rbf.py”,第198行 r = self._call_norm(self.xi,self.xi) 在_call_norm中输入文件“/[...]/python3.4/site-packages/scipy/interpolate/rbf.py”,第222行 return self.norm(x1,x2) 在_euclidean_norm中输入文件“/[...]/python3.4/site-packages/scipy/interpolate/rbf.py”,第114行 return sqrt(((x1 - x2)** 2).sum(axis = 0)) 的MemoryError
# plot the result
fig = plt.figure()
ax1 = plt.subplot(2,2,1)
plt.title('Data')
plt.gca().set_aspect((x.max() - x.min()) / (y.max() - y.min()))
plt.scatter(x, y, c=z, s=2, edgecolor='', marker=',')
plt.colorbar(ax=ax1)
plt.xlim(x.min(), x.max())
plt.ylim(y.min(), y.max())
plt.xticks([20.7,20.9,21.1,21.3])
plt.ticklabel_format(useOffset=False)
ax2 = plt.subplot(2,2,2)
plt.title('nearest')
plt.imshow(counts_I_grid_1.T, origin='lower',
extent=(x.min(), x.max(), y.min(), y.max()),
aspect=(x.max() - x.min()) / (y.max() - y.min()),
vmin=0,vmax=36)
plt.colorbar(ax=ax2)
plt.xticks([20.7,20.9,21.1,21.3])
plt.ticklabel_format(useOffset=False)
ax2 = plt.subplot(2,2,3)
plt.title('linear')
plt.imshow(counts_I_grid_2.T, origin='lower',
extent=(x.min(), x.max(), y.min(), y.max()),
aspect=(x.max() - x.min()) / (y.max() - y.min()),
vmin=0,vmax=36)
plt.colorbar(ax=ax2)
plt.xticks([20.7,20.9,21.1,21.3])
plt.ticklabel_format(useOffset=False)
ax2 = plt.subplot(2,2,4)
plt.title('cubic')
plt.imshow(counts_I_grid_3.T, origin='lower',
extent=(x.min(), x.max(), y.min(), y.max()),
aspect=(x.max() - x.min()) / (y.max() - y.min()),
vmin=0,vmax=36)
plt.colorbar(ax=ax2)
plt.xticks([20.7,20.9,21.1,21.3])
plt.ticklabel_format(useOffset=False)
plt.tight_layout()
plt.show()
答案 0 :(得分:2)
你的问题是由于一个足够危险的微妙错误,我认为值得给出完整答案。
考虑这一行:
points = np.reshape(np.array([x, y]),(z.size, 2))
由于您的输入数组是1d,因此您尝试将[x,y]
转换为形状“(某事,2)”。请注意,说
points = np.reshape(np.array([x, y]),(-1, 2))
让numpy为你推断缺失的维度,这仍然不是你想要的。构造二维数组时
np.array([x, y])
你要逐行定义一个矩阵,从而创建一个形状为“(2,something)”的数组。当你在它上面调用reshape
时,默认情况下会逐行读取元素,因为numpy以行主要顺序存储数组(如C / C ++,与fortran和MATLAB不同)。这意味着生成的双列数组将首先包含所有x
值,然后包含所有y
值,而不是每行包含(x,y)
对。
您实际要做的是交换数组的维度,而不触及其结构。这意味着您必须转置矩阵。这意味着您必须使用
points = np.array([x, y]).T
# or np.transpose([x,y])
代替。请注意,虽然它与原始版本具有相同的shape
,但它具有正确顺序的元素:
In [320]: np.reshape(np.array([x,y]),(-1,2))
Out[320]:
array([[ 20.7 , 20.702 ],
[ 20.704 , 20.706 ],
[ 20.708 , 20.71 ],
...,
[ 852.356964, 852.356964],
[ 852.356964, 852.356964],
[ 852.356964, 852.356964]])
In [321]: np.array([x,y]).T
Out[321]:
array([[ 20.7 , 852.357235],
[ 20.702 , 852.357235],
[ 20.704 , 852.357235],
...,
[ 21.296 , 852.356964],
[ 21.298 , 852.356964],
[ 21.3 , 852.356964]])
这将解决您的样本x/y
点与z
之间的不一致,并会产生预期结果。根据我的经验,reshape
- 几乎从未被要求过。通常,您需要将ndarray
展平为1d
,但最好是给定数组的ravel()
方法。
结果作为证明:左,你的原始立方插值;是的,修复了points
的版本:
请注意,作为@MaxNoe suggested,我将插值网格大小减小到200x200。正如他所暗示的那样,Rbf
的内存错误很可能源于这么多的插值点。