在Python中将不规则间隔的数据重新采样为规则网格
Posted
技术标签:
【中文标题】在Python中将不规则间隔的数据重新采样为规则网格【英文标题】:Resampling irregularly spaced data to a regular grid in Python 【发布时间】:2011-04-21 08:43:13 【问题描述】:我需要将 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)是二维数据的形状,我已经安装了mpl_toolkits.natgrid。
我的问题是我得到了一个掩码数组,其中大多数条目是 nan,而不是一个主要由常规条目组成且边界处只有 nan 的数组。
有人能指出我做错了什么吗?
谢谢!
【问题讨论】:
作为第一步,我只是尝试运行您的示例代码,但它不起作用。我收到了ValueError: x,y must be equal length 1-D arrays
。我正在从 Enthought 发行版运行 matplotlib v0.99.3。你能修复这个例子,让它重现 NaN,并包含更多关于你的计算所需的输入/输出的信息,如果可能的话,也许用图表?
我认为您必须安装 mpl_toolkits 中的 natgrid 才能使示例工作。
【参考方案1】:
将您的代码示例与您的问题标题进行比较,我认为您有点困惑...
在您的示例代码中,您正在创建定期网格化随机数据,然后将其重新采样到另一个常规网格。您的示例中的任何地方都没有不规则数据...
(此外,代码不会按原样运行,您应该查看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()
然后您可以像以前一样插入数据...(继续上面的代码 sn-p...)
# 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()
希望对您有所帮助,无论如何...抱歉回答太长了!
【讨论】:
感谢您的广泛回答,乔!事实证明,我可能不应该将原始答案标记为具有不规则网格,但我会检查轴的标准化是否有帮助! 我只是想说谢谢你的回答。对于确实需要处理不规则网格数据的人来说,这非常有用。一个问题,不过。您能否指出任何可以帮助我更好地了解一些可用插值方法的参考资料,以便我可以选择最好的一种? 真正优秀的解释。远远超过mlab.griddata
documentation,相比之下几乎是神秘的。
这是一个很好的答案,知道如何使用 Java 做到这一点吗?
@JoeKington 感谢您的回答,这确实对我帮助很大(即使在 4 年后...)!以上是关于在Python中将不规则间隔的数据重新采样为规则网格的主要内容,如果未能解决你的问题,请参考以下文章
Pandas 使用其他不规则时间列表重新采样和插值不规则时间序列
pandas DataFrame 从不规则时间序列索引中重新采样