在numpy数组中,需要最接近给定常量的所有值的索引。
背景是数字信号处理。该阵列保持滤波器(np.abs(np.fft.rfft(h))
)的幅度函数,并搜索某些频率(=索引),其幅度为例如0.5或在另一种情况下0。
大多数情况下,有问题的值并未完全包含在序列中。闭合值的索引应该在此中找到。
到目前为止,我想出了以下方法,其中我看到了序列和常量之间差异的符号变化。然而,这仅适用于在所讨论的点处单调增加或减少的序列。它有时也会减1。
def findvalue(seq, value):
diffseq = seq - value
signseq = np.sign(diffseq)
signseq[signseq == 0] = 1
return np.where(np.diff(signseq))[0]
我想知道是否有更好的解决方案。它仅适用于1D实数浮点数组,在我的情况下,计算效率的要求并不高。
作为数值示例,以下代码应返回[8, 41]
。为了简单起见,我用半波替换了滤波器幅度响应。
f=np.sin(np.linspace(0, np.pi))
findvalue(f, 0.5)
我发现的类似问题如下,但它们只返回第一个或第二个索引:
Find the second closest index to value
Find nearest value in numpy array
答案 0 :(得分:1)
以下函数将返回一个小数索引,显示大约何时超过该值:
def FindValueIndex(seq, val):
r = np.where(np.diff(np.sign(seq - val)) != 0)
idx = r + (val - seq[r]) / (seq[r + np.ones_like(r)] - seq[r])
idx = np.append(idx, np.where(seq == val))
idx = np.sort(idx)
return idx
逻辑:查找seq-val符号的变化。取转换和插值下方和上方的一个索引值。添加到此索引,其中值实际上等于该值。
如果你想要一个整数索引,只需使用np.round。您也可以选择np.floor或np.ceil将索引四舍五入为您的首选项。
def FindValueIndex(seq, val):
r = np.where(np.diff(np.sign(seq - val)) != 0)
idx = r + (val - seq[r]) / (seq[r + np.ones_like(r)] - seq[r])
idx = np.append(idx, np.where(seq == val))
idx = np.sort(idx)
return np.round(idx)
答案 1 :(得分:1)
def findvalue(seq, value):
diffseq = seq - value
signseq = np.sign(diffseq)
zero_crossings = signseq[0:-2] != signseq[1:-1]
indices = np.where(zero_crossings)[0]
for i, v in enumerate(indices):
if abs(seq[v + 1] - value) < abs(seq[v] - value):
indices[i] = v + 1
return indices
更多解释
def print_vec(v):
for i, f in enumerate(v):
print("[{}]{:.2f} ".format(i,f), end='')
print('')
def findvalue_loud(seq, value):
diffseq = seq - value
signseq = np.sign(diffseq)
print_vec(signseq)
zero_crossings = signseq[0:-2] != signseq[1:-1]
print(zero_crossings)
indices = np.where(zero_crossings)[0]
# indices contains the index in the original vector
# just before the seq crosses the value [8 40]
# this may be good enough for you
print(indices)
for i, v in enumerate(indices):
if abs(seq[v + 1] - value) < abs(seq[v] - value):
indices[i] = v + 1
# now indices contains the closest [8 41]
print(indices)
return indices
答案 2 :(得分:1)
我认为你有两个选择。一种是对形状做出一些假设,并寻找seq
和val
之间差异的过零点(@ColonelFazackerley中的their answer)。另一个是要说明你想要考虑哪个相对容差值足够接近。
在后一种情况下,您可以使用numpy.isclose
:
import numpy as np
def findvalue(seq, val, rtol=0.05): # value that works for your example
return np.where(np.isclose(seq, val, rtol=rtol))[0]
示例:
x = np.sin(np.linspace(0, np.pi))
print(findvalue(x, 0.5))
# array([ 8, 41])
这样做的缺点在于它取决于rtol
的值。将它设置得太大(本例中为0.1
),你会得到靠近交叉点的多个值,将它设置得太低而且你没有得到任何值。
答案 3 :(得分:0)
这可能远不是最好的方法(我还在学习numpy),但我希望它能帮助你找到一个。
min_distance = np.abs(your_array - your_constant).min()
# These two tuples contain number closest to your constant from each side.
np.where(bar == val - min_distance) # Closest, < your_constant
np.where(bar == val + min_distance) # Closest, > your_constant