Stückweise Funktion in Python anpassen

Ich versuche, eine stückweise definierte Funktion an einen Datensatz in Python anzupassen. Ich habe schon eine Weile gesucht, aber ich habe keine Antwort gefunden, ob es möglich ist oder nicht.

Um einen Eindruck davon zu bekommen, was ich versuche, sehen Sie sich das folgende Beispiel an (das bei mir nicht funktioniert). Hier versuche ich, eine verschobene Absolutwertfunktion (f (x) = | x-p |) an einen Datensatz mit p als Anpassungsparameter anzupassen.

import scipy.optimize as so
import numpy as np

def fitfunc(x,p):
   if x>p:
      return x-p
   else:
      return -(x-p)

fitfunc = np.vectorize(fitfunc) #vectorize so you can use func with array

x=np.arange(1,10)
y=fitfunc(x,6)+0.1*np.random.randn(len(x))

popt, pcov = so.curve_fit(fitfunc, x, y) #fitting routine that gives error

Gibt es eine Möglichkeit, dies in Python zu erreichen?

Ein Weg dies in R zu tun ist:

# Fit of a absolute value function f(x)=|x-p|

f.lr <- function(x,p) {
    ifelse(x>p, x-p,-(x-p))
}
x <- seq(0,10)  #
y <- f.lr(x,6) + rnorm (length(x),0,2)
plot(y ~ x)
fit.lr <- nls(y ~ f.lr(x,p), start = list(p = 0), trace = T, control = list(warnOnly = T,minFactor = 1/2048))
summary(fit.lr)
coefficients(fit.lr)
p.fit <- coefficients(fit.lr)["p"]
x_fine <- seq(0,10,length.out=1000)
lines(x_fine,f.lr(x_fine,p.fit),type='l',col='red')
lines(x,f.lr(x,6),type='l',col='blue')

Nach noch mehr Nachforschungen habe ich einen Weg gefunden, dies zu tun. In dieser Lösung gefällt mir nicht, dass ich die Fehlerfunktion selbst definieren muss. Außerdem bin ich mir nicht sicher, warum es in diesem Lambda-Stil sein muss. Daher sind Anregungen und weiterentwickelte Lösungen jederzeit willkommen.

import scipy.optimize as so
import numpy as np
import matplotlib.pyplot as plt

def fitfunc(p,x): return x - p if x > p else p - x 

def array_fitfunc(p,x):
    y = np.zeros(x.shape)
    for i in range(len(y)):
        y[i]=fitfunc(x[i],p)
    return y

errfunc = lambda p, x, y: array_fitfunc(p, x) - y # Distance to the target function

x=np.arange(1,10)
x_fine=np.arange(1,10,0.1)
y=array_fitfunc(6,x)+1*np.random.randn(len(x)) #data with noise

p1, success = so.leastsq(errfunc, -100, args=(x, y), epsfcn=1.) # -100 is the initial value for p; epsfcn sets the step width

plt.plot(x,y,'o') # fit data
plt.plot(x_fine,array_fitfunc(6,x_fine),'r-') #original function
plt.plot(x_fine,array_fitfunc(p1[0],x_fine),'b-') #fitted version
plt.show()

Antworten auf die Frage(2)

Ihre Antwort auf die Frage