我正在寻找一种方法将不规则网格数据重新定位到常规网格上,但没有插值(所以不是matplotlib.mlab.griddata
。最好是,我喜欢平均或中位一个单元格内的点数,或甚至应用我自己的函数。
网格是2D,但由于我预见到具有不同尺寸的未来情况,因此N维解决方案甚至更好。
例如,请考虑以下数据,x
和y
坐标:
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并不关心x
和y
是网格索引),我觉得这可能不是最佳解决方案:拥有一个解决方案知道输入和输出已经在(2D)网格上似乎更有效。但是,我找不到一个; np.digitize
最接近,但这只是1维,并且仍需要Python中的循环来访问索引以及数据的平均值或中位数。
有谁知道上述一个更好的解决方案?
答案 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
参数来支持用户定义的统计信息。