这是我的问题,假设我有一个像这样的向量:
import numpy as np
idxx = np.array([0. , 0.07665982, 0.24366872, 0.49555099, 0.74743326,
1.07871321, 1.58247775, 2.24503765, 2.58179329, 3.16221766,
3.74811773, 4.1615332 , 4.58042437, 5.33059548])
我感兴趣的是仅过滤掉0.25
,0.5
和1.0
的大约倍数的那些值。让我们从0.25
开始,说明我正在寻找要返回的过滤器:
np.array([0.24366872, 0.49555099, 0.74743326,
1.07871321, 1.58247775, 2.24503765, 2.58179329,
3.74811773, 4.58042437, 5.33059548])
这里仅保留大约0.25
倍数的值。实际上,我还需要保留第一个条目0.0
,但在此演示中已将其删除。
如果我正在使用0.5
,则结果将如下所示:
np.array([0.49555099, 1.07871321, 1.58247775, 2.58179329, 4.58042437])
我最初的尝试是:
import math
for i in idxx:
g = 0.25
k = i % g
if math.isclose(k, g, rel_tol=0.5):
print('This is reasonably close: ', i, '\n\t for modulus k == ', k, '\n')
仍然需要我做很多调优(而且我仍然无法过滤掉我想要的东西),所以我想知道是否有人有更好的方法来正确地做到这一点?
从本质上讲,我想选择那些不规则点(例如0.24366872)到“规则”间隔的网格(例如0.25间距)上,但是规则间隔的网格上的每个点都具有一定的容差,例如。 +/- 0.05,以适应实际数据中的不规则性。因此,我可以找到那些在此公差范围内的规则间隔的点。
答案 0 :(得分:1)
您可能会稍微向后退。与其试图找到一个可行的公差(1.07871321
确实会丢掉东西,不是吗),而是找到最靠近网格点的点。
这是一种非循环方法,会浪费内存,因为它会创建完整的idxx.size
乘n
数组,其中n
是网格的大小:>
def grid_filter(idxx, spacing):
# use idxx[0] instead of idxx.min() if idxx is sorted
g0 = np.floor(idxx.min() / spacing) * spacing
# use idxx[-1] instead of idxx.max() if idxx is sorted
g1 = np.ceil(idxx.max() / spacing) * spacing
# turn the grid into a column vector for broadcasting
n = np.round((g1 - g0) / spacing) + 1
grid = np.linspace(g0, g1, n).reshape(-1, 1)
# compute the absolute distance to each point and
# get the index of the point nearest each grid point:
# rows are grid points, columns data points
indices = np.abs(grid - idxx).argmin(axis=1)
# post-process to ensure that a data point only matches one grid point
indices = np.unique(indices)
# apply the result
return idxx[indices]
浪费的数组是grid - idxx
。这可能不会成为问题。 grid_filter(idxx, 0.25)
的结果是:
[ 0. 0.24366872 0.49555099 0.74743326 1.07871321 1.58247775 2.24503765 2.58179329 3.16221766 3.74811773 4.1615332 4.58042437 5.33059548]
如果您不满意3.16
和4.16
并使其成为结果,则可以使容差为spacing
的1/3或类似的值,然后使用:
def tolerance_filter(idxx, spacing, tolerance):
deltas = (idxx % spacing)
deltas = np.minimum(deltas, spacing - deltas)
candidates = deltas < tolerance * spacing
return idxx[candidates]
此解决方案实际上可以满足您的要求,并且已完全矢量化。 tolerance_filter(idxx, 0.25, 0.33)
返回
[ 0. 0.07665982 0.24366872 0.49555099 0.74743326 1.07871321 1.58247775 2.24503765 2.58179329 3.74811773 4.58042437 5.33059548]
要进一步摆脱0.07665982
,我建议结合以下方法:首先过滤以获取最接近每个网格点的元素,然后过滤绝对公差:
tolerance_filter(grid_filter(idxx, 0.25), 0.25, 0.33)
这时您可以做得更好:首先将每个数组元素附加到最近的网格点,如第一部分所示。然后做一些自适应的事情。例如,获取残差的标准偏差,并丢弃高于标称值3σ的任何内容:
def sigma_filter(idxx, spacing, nsigma):
deltas = (idxx % spacing)
deltas[deltas > 0.5 * spacing] -= spacing
sigma = np.std(deltas)
candidates = (np.abs(deltas) <= nsigma * sigma)
return idxx[candidates]
答案 1 :(得分:0)
您需要正确管理+/-
。一种简单的方法:
error=minimum(-idxx%.25,idxx%.25)
res= idxx[error<.05]
# [ 0., 0.24366872, 0.49555099, 0.74743326, 2.24503765, 3.74811773]