如何在numpy中找到x给定y或反之?

时间:2012-07-13 09:22:57

标签: search numpy numerical-methods

例如,我有以下数组:

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)

此问题的情况

我可以使用封闭的分析函数绘制yx,只需调用foo_function(x)即可。但是,我正在运行数值模拟,其数据图没有封闭的分析解决方案。

尝试解决方案

我之前已经解决过类似的问题并且大致以这种方式接近他们:

what_is_y_when_x_is(some_x)

  1. 在数组x中搜索some_x
  2. 获取其索引i
  3. 选择y[i]
  4. 问题

    有更好的方法吗?也许是内置的numpy函数或更好的算法?

6 个答案:

答案 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)]