例如,我有以下数组:
x = [0, 1, 2, 3, 4.5, 5]
y = [2, 8, 3, 7, 8, 1]
我希望能够在x
给出以下内容:
>>> what_is_y_when_x_is(2)
(2, 3)
>>> what_is_y_when_x_is(3.1) # Perhaps set rules to round to nearest (or up or down)
(3, 7)
另一方面,当给出y
时:
>>> what_is_x_when_y_is(2)
(0, 2)
>>> what_is_x_when_y_is(max(y))
([1, 4.5], 8)
我可以使用封闭的分析函数绘制y
与x
,只需调用foo_function(x)
即可。但是,我正在运行数值模拟,其数据图没有封闭的分析解决方案。
我之前已经解决过类似的问题并且大致以这种方式接近他们:
what_is_y_when_x_is(some_x)
x
中搜索some_x
。i
。y[i]
。有更好的方法吗?也许是内置的numpy
函数或更好的算法?
答案 0 :(得分:3)
你应该看看numpy.searchsorted和numpy.interp。这两个看起来都可能成功。这是一个例子:
import numpy as np
x = np.array([0, 1, 2, 3, 4.5, 5])
y = np.array([2, 8, 3, 7, 8, 1])
# y should be sorted for both of these methods
order = y.argsort()
y = y[order]
x = x[order]
def what_is_x_when_y_is(input, x, y):
return x[y.searchsorted(input, 'left')]
def interp_x_from_y(input, x, y):
return np.interp(input, y, x)
print what_is_x_when_y_is(7, x, y)
# 3
print interp_x_from_y(1.5, x, y)
# 2.5
答案 1 :(得分:1)
您可以使用bisect模块。这是纯粹的python - 这里没有numpy:
>>> x = [0, 1, 2, 3, 4.5, 5]
>>> y = [2, 8, 3, 7, 8, 1]
>>> x_lookup = sorted(zip(x, y))
>>> y_lookup = sorted(map(tuple, map(reversed, zip(x, y))))
>>>
>>> import bisect
>>> def pair_from_x(x):
... return x_lookup[min(bisect.bisect_left(x_lookup, (x,)), len(x_lookup)-1)]
...
>>> def pair_from_y(y):
... return tuple(reversed(y_lookup[min(bisect.bisect_left(y_lookup, (y,)), len(y_lookup)-1)]))
...
使用它的一些例子:
>>> pair_from_x(0)
(0, 2)
>>> pair_from_x(-2)
(0, 2)
>>> pair_from_x(2)
(2, 3)
>>> pair_from_x(3)
(3, 7)
>>> pair_from_x(7)
(5, 1)
>>>
>>> pair_from_y(0)
(5, 1)
>>> pair_from_y(1)
(5, 1)
>>> pair_from_y(3)
(2, 3)
>>> pair_from_y(4)
(3, 7)
>>> pair_from_y(8)
(1, 8)
答案 2 :(得分:0)
就我所说,你描述的方式是一种好方法。我不确定你是不是,但我认为你可以在你的阵列上使用.index(...)方法:
>>> li
['I', 'hope', 'this', 'answer', 'helps', 'you']
>>> li.index("hope")
1
除此之外,您可能想要考虑一个具有x和y的数组op“Points”,但我当然不确定这是否可行。这样你就不必保持两个数组同步(相同数量的元素)。
答案 3 :(得分:0)
我发现您的管道没有任何问题。您可以在numpy.where上编写一个代码段,以便有效地实现它。请注意,您必须首先将列表作为numpy数组传递(这可以包含在函数中)。
下面是一个执行该作业的函数示例,其中包含一个舍入目标的选项(我已经包含了一个which array
参数,所以一切都可以在一个函数中完成,无论你想在x中搜索什么或者y)。请注意,其中一个输出将是一个numpy数组,因此修改它以将其转换为您想要的任何内容(liste,tuple等等)。
import numpy as np
def pick(x_array, y_array, target, which_array='x', round=True):
# ensure that x and y are numpy arrays
x_array, y_array = np.array(x_array), np.array(y_array)
# optional: round to the nearest. True by default
if round==True:
target = np.round(target)
if which_array == 'x': # look for the target in x_array
return target, y_array[np.where(x_array == target)[0]]
if which_array == 'y': # look for the target in y_array
return x_array[np.where(y_array == target)[0]], target
您的示例给出的结果:
# >>> what_is_y_when_x_is(2)
pick(x, y, 2, 'x')
(2, array([3]))
# >>> what_is_y_when_x_is(3.1)
pick(x, y, 3.1, 'x')
3.0, array([7]))
# >>> what_is_y_when_x_is(2)
pick(x, y, 2, 'y')
(array([ 0.]), 2)
# >>> what_is_x_when_y_is(max(y))
pick(x, y, max(y), 'y')
(array([ 1. , 4.5]), 8)
答案 4 :(得分:0)
以下是@ Bi Rico提供的修订版代码:
import numpy as np
x = np.array([0, 1, 2, 3, 4.5, 5])
y = np.array([2, 8, 3, 7, 8, 1])
# y should be sorted for both of these methods
order = np.argsort(y)
y = y[order]
x = x[order]
def what_is_x_when_y_is(input, x, y):
return x[y.searchsorted(input, 'left')]
print(what_is_x_when_y_is(7, x, y))
# 3
答案 5 :(得分:0)
这对我有用:
def what_is_y_when_x_is(value, x, y, tolerance=1e-3):
return [(xi, yi) for (xi, yi) in zip(x, y) if abs(xi - value) <= tolerance]
请注意,上述代码不是比较相等,而是执行“足够接近”的相等测试。 默认容差设置为0.001(您可以使用任何其他值)。以下是一些使用示例:
>>> x = [0, 1, 2, 3, 4.5, 5]
>>> y = [2, 8, 3, 7, 8, 1]
>>> what_is_y_when_x_is(0, x, y)
[(0, 2)]
>>> what_is_y_when_x_is(1, x, y, tolerance=.1)
[(1, 8)]
>>> what_is_y_when_x_is(2, x, y, tolerance=1)
[(1, 8), (2, 3), (3, 7)]
>>> what_is_y_when_x_is(4, x, y, tolerance=.5)
[(4.5, 8)]