Невозможно сделать кусочек с 3 сегментами

У меня есть следующие данные x, y

x = np.array([-1.280199006, -1.136209343, -1.048070216, -0.9616764178, -0.8752826199, -0.7871434926, -0.6981317008, -0.6108652382, -0.5235987756, -0.4372049776,
 -0.3490658504, -0.2644173817, -0.1762782545,
-0.0907571211, 0, 0.09250245036, 0.1762782545, 0.2661627109, 0.3516838443, 0.4345869837, 0.529707428, 0.6108652382, 0.7007496947, 0.7880161573, 0.872664626,
0.9616764178, 1.055051533, 1.160643953, 1.274090354, 1.413716694])

y = np.array([-0.05860218717, -0.05275174988, -0.04961805822, -0.02860635697, -0.04150466841, -0.02672933264, -0.02422597285, -0.03056176732, -0.02885180089, -0.02085851636, 
-0.02873319291, -0.02374542821, -0.02132671806,
-0.02088924602, -0.0216617248, -0.01835553738, -0.01369531698, -0.01331112368, -0.01156455074, -0.009163690404, -0.003542622659, -0.003515924976, -0.003828831726, -0.002622163805, -0.001622083468,
-0.00297346133, -0.001845415856, -0.001913228234, -0.001495496086, -0.001454621173])

и хотел бы соединить его с кусочками по крайней мере с 3 отрезками

Я пробовал это

def piecewise_linear(x, x0, x1, y0, y1, k1, k2, k3):
    conds = [x<x0, (x>=x0) & (x<x1),x>=x1]
    funcs = [lambda x:k1*(x-x0) + y0, lambda x:k2*(x-x0) + y0, lambda x:k2*(x1-x0) + y0 + k3*(x-x1)]
    return np.piecewise(x, conds, funcs)
p , e = curve_fit(piecewise_linear, x, y)
xd = np.linspace(-1.3, 1.5, 100)
plt.plot(x, y, "o")
plt.plot(xd, piecewise_linear(xd, *p))

но это устанавливает

x1= +0,266162745743

а также

х0= +0,323723668069

то есть х0> х1. В итоге получается 2-сегментная посадка.

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

1 ответ

Решение

Проблема в том, что piecewise вернуть массив вместо функции. Следовательно y1 не является независимым параметром. Способ определения функции - использовать логическое значение в арифметическом контексте (True=1, False=0):

def f(x,x0,y0,x1,k1,k2,k3):
    # x0,y0 : first breakpoint
    # x1 : second breakpoint
    # k1,k2,k3 : 3 slopes.

    y1=y0+ k2*(x1-x0) # for continuity
    return (
    (x<x0)              *   (y0 + k1*(x-x0))      +
    ((x>=x0) & (x<x1))  *   (y0 + k2*(x-x0))      +
    (x>=x1)             *   (y1 + k3*(x-x1)))

p0=(-.7,-0.03,.5,0.03,0.02,0.01)
p , e = curve_fit(f, x, y,p0)
close()
plt.plot(x, y, "o")
plot(x,f(x,*p))
show()

Здесь подходит.

Другие вопросы по тегам