使用均值/中值将不规则网格数据重新排列到Python中的常规(2D)网格

时间:2014-11-17 11:18:07

标签: python numpy

我正在寻找一种方法将不规则网格数据重新定位到常规网格上,但没有插值(所以不是matplotlib.mlab.griddata。最好是,我喜欢平均或中位一个单元格内的点数,或甚至应用我自己的函数。

网格是2D,但由于我预见到具有不同尺寸的未来情况,因此N维解决方案甚至更好。

例如,请考虑以下数据,xy坐标:

data = np.arange(6)
x = np.array([0.4, 0.6, 0.8, 1.5, 1.8, 2.2])
y = np.array([0.4, 0.8, 2.3, 2.5, 2.7, 2.9])

,当分箱到常规3x3网格并使用平均值时,应该导致:

[[ 0.5  nan  2. ]
 [ nan  nan  3.5]
 [ nan  nan  5. ]]

(NaN' s是可选的,但比0更清晰,因为后者的值可以是实际的平均值;这当然也很容易变成掩码数组。)

到目前为止,我已经能够使用Pandas来解决这个问题:

xindices = np.digitize(x, np.arange(NX))
yindices = np.digitize(y, np.arange(NY))
df = pd.DataFrame({
    'x': xindices,
    'y': yindices,
    'z': data
})
grouped = df.groupby(['y', 'x'])
result = grouped.aggregate(np.mean).reset_index()
grid = np.empty((NX, NY)) * np.NaN
grid[result['x']-1, result['y']-1] = result['z']

允许我选择我喜欢的任何聚合函数。

然而,由于Pandas相当普遍(Pandas并不关心xy是网格索引),我觉得这可能不是最佳解决方案:拥有一个解决方案知道输入和输出已经在(2D)网格上似乎更有效。但是,我找不到一个; np.digitize最接近,但这只是1维,并且仍需要Python中的循环来访问索引以及数据的平均值或中位数。

有谁知道上述一个更好的解决方案?

1 个答案:

答案 0 :(得分:5)

您可以使用scipy.stats.binned_statistic_2d

import numpy as np
import scipy.stats as stats

data = np.arange(6)
x = np.array([0.4, 0.6, 0.8, 1.5, 1.8, 2.2])
y = np.array([0.4, 0.8, 2.3, 2.5, 2.7, 2.9])

NX, NY = 4, 4
statistic, xedges, yedges, binnumber = stats.binned_statistic_2d(
    x, y, values=data, statistic='mean', 
    bins=[np.arange(NX), np.arange(NY)])
print(statistic)

产生

[[ 0.5  nan  2. ]
 [ nan  nan  3.5]
 [ nan  nan  5. ]]

还有binned_statistic_dd用于更高维度的分级。 这些函数中的每一个都通过将callable传递给statistic参数来支持用户定义的统计信息。