2013-03-09 101 views
2

我想将一个numpy数组重新加入一个新的网格。在这个特定的情况下,我试图将一个功率谱重新映射到一个对数网格上,以便数据以对数方式均匀间隔以用于绘图目的。Numpy:通过平均值的regrid?

使用np.interp进行直插插值会导致一些原始数据被完全忽略。使用digitize得到我想要的结果,但我已经使用了一些丑陋的循环,以得到它的工作:

xfreq = np.fft.fftfreq(100)[1:50] # only positive, nonzero freqs 
psw = np.arange(xfreq.size) # dummy array for MWE 

# new logarithmic grid 
logfreq = np.logspace(np.log10(np.min(xfreq)), np.log10(np.max(xfreq)), 100) 

inds = np.digitize(xfreq,logfreq) 

# interpolation: ignores data *but* populates all points 
logpsw = np.interp(logfreq, xfreq, psw) 
# so average down where available... 
logpsw[np.unique(inds)] = [psw[inds==i].mean() for i in np.unique(inds)] 

# the new plot 
loglog(logfreq, logpsw, linewidth=0.5, color='k') 

是否有numpy的做到这一点一个更好的办法吗?我只会满足于更换内联循环步骤。

回答

1

您可以使用bincount()两次来计算每个仓的平均值:

logpsw2 = np.interp(logfreq, xfreq, psw) 
counts = np.bincount(inds) 
mask = counts != 0 
logpsw2[mask] = np.bincount(inds, psw)[mask]/counts[mask] 

或使用unique(inds, return_inverse=True)bincount()两次:

logpsw4 = np.interp(logfreq, xfreq, psw) 
uinds, inv_index = np.unique(inds, return_inverse=True) 
logpsw4[uinds] = np.bincount(inv_index, psw)/np.bincount(inv_index) 

或者,如果您使用熊猫:

import pandas as pd 
logpsw4 = np.interp(logfreq, xfreq, psw) 
s = pd.groupby(pd.Series(psw), inds).mean() 
logpsw4[s.index] = s.values 
+0

很酷。 'pandas'对于这个用途会有点沉重,所以我喜欢'bincount'方法。我不认为这个解决方案可以用于中位数,但是 - 你能想出一种方法来做中位数/百分位数吗? – keflavich 2013-03-10 16:01:15