4

たとえば、次の配列があります。

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)

  1. xの配列を検索しsome_xます。
  2. そのインデックスを取得しますi
  3. 拾うy[i]

質問

これを行うより良い方法はありますか?おそらく、組み込みnumpy関数またはより優れたアルゴリズムですか?

4

6 に答える 6

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
于 2012-07-13T22:23:08.880 に答える
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)
于 2012-07-13T10:58:22.803 に答える
0

パイプラインに問題はありません。numpy.whereにスニペット ベースを記述して、効率的に実装できます。最初にリストを numpy 配列として渡す必要があることに注意してください (これは関数に含めることができます)。

以下は、ターゲットを丸めるオプションを使用して、ジョブを実行する関数の例です (which array引数を含めたので、x または y で検索したいものは何でも、1 つの関数ですべてを実行できます)。出力の 1 つが 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)
于 2012-07-13T15:53:16.343 に答える
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)]
于 2016-04-27T20:32:32.300 に答える
0

The way you described is, as far as I'm considered, a good way. I'm not sure if you are, but I think you could use the .index(...) method on your array:

>>> li
['I', 'hope', 'this', 'answer', 'helps', 'you']
>>> li.index("hope")
1

Other than that, you might want to consider one array op "Points" which have an x and a y, though I'm not sure if this is possible of course. That way you won't have to keep two arrays in sync (same number of elements).

于 2012-07-13T09:38:32.230 に答える
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
于 2016-04-27T03:55:26.187 に答える