我需要将2D数据重新采样到常规网格。
这就是我的代码:
import matplotlib.mlab as ml
import numpy as np
y = np.zeros((512,115))
x = np.zeros((512,115))
# Just random data for this test:
data = np.random.randn(512,115)
# filling the grid coordinates:
for i in range(512):
y[i,:]=np.arange(380,380+4*115,4)
for i in range(115):
x[:,i] = np.linspace(-8,8,512)
y[:,i] -= np.linspace(-0.1,0.2,512)
# Defining the regular grid
y_i = np.arange(380,380+4*115,4)
x_i = np.linspace(-8,8,512)
resampled_data = ml.griddata(x,y,data,x_i,y_i)
(512,115)是2D数据的形状,我已经安装了mpl_toolkits.natgrid。
我的问题是我找回了一个蒙面数组,其中大部分条目都是nan,而不是一个主要由常规条目组成的数组,而且只是边界处的nan。
有人能指出我做错了吗?
谢谢!
答案 0 :(得分:65)
将您的代码示例与您的问题标题进行比较,我认为您有点困惑......
在您的示例代码中,您正在创建定期网格化随机数据,然后将其重新采样到另一个常规网格。您的示例中的任何地方都没有不规则数据......
(此外,代码不会按原样运行,您应该查看meshgrid
而不是循环以生成x& y网格。)
如果您想重新采样已经定期采样的网格,就像您在示例中所做的那样,有比griddata或我将在下面描述的任何内容更有效的方法。 (scipy.ndimage.map_coordinates
非常适合您的问题,就是这种情况。)
但是,根据您的问题,您可能会想要在常规网格上插入不规则间隔的数据。
在这种情况下,您可能会有以下几点:
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
# Bounds and number of the randomly generated data points
ndata = 20
xmin, xmax = -8, 8
ymin, ymax = 380, 2428
# Generate random data
x = np.random.randint(xmin, xmax, ndata)
y = np.random.randint(ymin, ymax, ndata)
z = np.random.random(ndata)
# Plot the random data points
plt.scatter(x,y,c=z)
plt.axis([xmin, xmax, ymin, ymax])
plt.colorbar()
plt.show()
然后您可以像以前一样插入数据...(续上面的代码片段......)
# Size of regular grid
ny, nx = 512, 115
# Generate a regular grid to interpolate the data.
xi = np.linspace(xmin, xmax, nx)
yi = np.linspace(ymin, ymax, ny)
xi, yi = np.meshgrid(xi, yi)
# Interpolate using delaunay triangularization
zi = mlab.griddata(x,y,z,xi,yi)
# Plot the results
plt.figure()
plt.pcolormesh(xi,yi,zi)
plt.scatter(x,y,c=z)
plt.colorbar()
plt.axis([xmin, xmax, ymin, ymax])
plt.show()
但是,您会注意到网格中存在大量文物。这是因为你的x坐标范围从-8到8,而y坐标范围从~300到~2500。插值算法试图使各向同性,而您可能需要高度各向异性插值(以便在绘制网格时它看起来是各向同性的。)
要纠正这个问题,你需要创建一个新的坐标系来进行插值。没有一种正确的方法可以做到这一点。我在下面使用的内容可行,但“最佳”方式在很大程度上取决于您的数据实际代表的内容。
(换句话说,使用您对数据所测量的系统的了解来决定如何操作。使用插值总是为真!除非,否则不应插值知道结果应该是什么样的 ,并且熟悉插值算法以使用先验信息对您有利!!还有比Delaunay三角测量更灵活的插值算法griddata默认使用,但是对于一个简单的例子来说这很好......)
无论如何,一种方法是重新缩放x和y坐标,使它们的范围大致相同。在这种情况下。我们将它们从0重新缩放到1 ...(原谅意大利面条字符串代码......我只是想以此为例......)
# (Continued from examples above...)
# Normalize coordinate system
def normalize_x(data):
data = data.astype(np.float)
return (data - xmin) / (xmax - xmin)
def normalize_y(data):
data = data.astype(np.float)
return (data - ymin) / (ymax - ymin)
x_new, xi_new = normalize_x(x), normalize_x(xi)
y_new, yi_new = normalize_y(y), normalize_y(yi)
# Interpolate using delaunay triangularization
zi = mlab.griddata(x_new, y_new, z, xi_new, yi_new)
# Plot the results
plt.figure()
plt.pcolormesh(xi,yi,zi)
plt.scatter(x,y,c=z)
plt.colorbar()
plt.axis([xmin, xmax, ymin, ymax])
plt.show()
希望无论如何都有帮助...对不起答案的长度!