Нахождение двух значений 'y', соответствующих значению 1 'x' в python - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть следующая кривая:

curve with 2 y values for one x

Я пытаюсь получить два значения y, которые соответствуют одному значению x (здесь 0).

Я пробовал interp1d из scipy, но это работает только с монотонно возрастающей или убывающей кривой.В данном случае он находит два ближайших значения и выполняет линейную интерполяцию между ними, и в результате получается только одно значение, расположенное в районе 3.9.

Вот фрагмент кода для воспроизведения примера:

from scipy import interpolate
import numpy as np

testdata = np.linspace(0,2*np.pi,100)
testy = np.cos(testdata)

fig, ax = plt.subplots()
ax.plot(testy, testdata)
ax.axvline(0, c = 'r')
f = interpolate.interp1d(testy, testdata)

print(f(0))

Что может быть хорошим способом получить эти значения?Я также пытался получить наиболее близкое значение, но это недостаточно точно для того, для чего я планирую его использовать.

Спасибо за вашу помощь

Редактировать:

Следующее решение работает, но есть ли лучший способ сделать это?

testdata = np.linspace(0,2*np.pi,100)
testy = np.cos(testdata)

gradx = np.gradient(testy)
asign = np.sign(gradx)
signchange = ((np.roll(asign, 1) - asign) != 0).astype(int)
splitloc = [i for i, e in enumerate(signchange) if e != 0]
newdata = np.split(testy,splitloc)
newx = np.split(testdata,splitloc)

fig, ax = plt.subplots()

for i in range(len(splitloc)):
    ax.plot(newdata[i+1], newx[i+1])
    f = interpolate.interp1d(newdata[i+1], newx[i+1])
    print(f(0))

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019

Поскольку данные, которые вы пытаетесь интерполировать, не являются функцией, я думаю, что будет сложно решить вашу проблему путем интерполяции.Но вы можете видеть, что если вы умножаете последовательные значения на x, знак всех значений будет (+), за исключением ближайших точек, где x = 0, будет изменение знака (-).Используя:

vals=[testdata[j] for j in range(len(testy)-1) if np.sign(testy[j]*testy[j+1])==-1]

, я получаю [1.5231964381041423, 4.696522350821105].Вы можете использовать либо j, либо j+1 над testdata[j], так как сетка одинакова, в обоих приближениях будет одинаковое количество ошибок.Надеюсь, поможет.

0 голосов
/ 27 февраля 2019

Один из способов, который вы можете попробовать, состоит в том, чтобы разбить входные данные на куски, которые находятся рядом с вашим желаемым значением x (я переименовал ваши переменные, чтобы они были ближе к тому, что они есть на ваших графиках):

test_y = np.linspace(0,2*np.pi,100)
test_x = np.cos(test_y)
# Determine which parts are close to zero
close_to_zero = np.isclose(test_x, 0, atol=1e-1)

Теперь мы можем разбить ваш ввод на «непрерывные» порции, близкие к нулю:

chunks = []
prev_close = False
for x, y, close in zip(test_x, test_y, close_to_zero):
    if not close:
        if prev_close:
            chunks.append(chunk)
    if close:
        if not prev_close:
            chunk=[[y], [x]]
        chunk[0].append(y)
        chunk[1].append(x)
    prev_close = close
chunks

Вывод:

[[[1.5231964381041423,
   1.5231964381041423,
   1.5866629563584815,
   1.6501294746128208],
  [0.04758191582374218,
   0.04758191582374218,
   -0.01586596383480803,
   -0.07924995685678855]],
 [[4.6330558325667655,
   4.6330558325667655,
   4.696522350821105,
   4.759988869075444],
  [-0.07924995685678878,
   -0.07924995685678878,
   -0.01586596383480761,
   0.04758191582374238]]]

Теперь вы можете перебирать пары списков (y, x) вchunks и выполните линейную интерполяцию для этих пар, чтобы получить более точное значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...