Die anderen Antworten sind alle gute Ansätze. Es gibt jedoch einige andere Optionen in R, die nicht erwähnt wurden, einschließlich lowess
und approx
, die möglicherweise eine bessere Passform oder eine schnellere Leistung ergeben.
Die Vorteile lassen sich mit einem alternativen Datensatz leichter demonstrieren:
sigmoid <- function(x)
{
y<-1/(1+exp(-.15*(x-100)))
return(y)
}
dat<-data.frame(x=rnorm(5000)*30+100)
dat$y<-as.numeric(as.logical(round(sigmoid(dat$x)+rnorm(5000)*.3,0)))
Hier sind die Daten, die mit der Sigmoidkurve überlagert sind, die sie generiert hat:
Diese Art von Daten ist häufig, wenn ein binäres Verhalten in einer Population betrachtet wird. Dies kann beispielsweise ein Diagramm darüber sein, ob ein Kunde etwas gekauft hat (ein binäres 1/0 auf der y-Achse) oder nicht, und wie viel Zeit er auf der Site verbracht hat (x-Achse).
Eine große Anzahl von Punkten wird verwendet, um die Leistungsunterschiede dieser Funktionen besser zu demonstrieren.
Smooth
, spline
Undsmooth.spline
alle Produkte Kauderwelsch auf einem Datensatz , wie dies mit jedem Satz von Parametern habe ich versucht, vielleicht aufgrund ihrer Neigung zu jedem Punkt auf der Karte, die für verrauschte Daten nicht funktioniert.
Die loess
, lowess
und approx
Funktionen alle Produkte brauchbare Ergebnisse, wenn auch nur knapp für approx
. Dies ist der Code für jeden, der leicht optimierte Parameter verwendet:
loessFit <- loess(y~x, dat, span = 0.6)
loessFit <- data.frame(x=loessFit$x,y=loessFit$fitted)
loessFit <- loessFit[order(loessFit$x),]
approxFit <- approx(dat,n = 15)
lowessFit <-data.frame(lowess(dat,f = .6,iter=1))
Und die Ergebnisse:
plot(dat,col='gray')
curve(sigmoid,0,200,add=TRUE,col='blue',)
lines(lowessFit,col='red')
lines(loessFit,col='green')
lines(approxFit,col='purple')
legend(150,.6,
legend=c("Sigmoid","Loess","Lowess",'Approx'),
lty=c(1,1),
lwd=c(2.5,2.5),col=c("blue","green","red","purple"))
Wie Sie sehen können, lowess
ergibt sich eine nahezu perfekte Anpassung an die ursprüngliche Erzeugungskurve. Loess
ist nah, erfährt aber eine merkwürdige Abweichung an beiden Schwänzen.
Obwohl Ihr Datensatz sehr unterschiedlich sein wird, habe ich festgestellt, dass andere Datensätze ähnlich funktionieren, mit beiden loess
und lowess
in der Lage sind, gute Ergebnisse zu erzielen. Die Unterschiede werden bedeutender, wenn Sie sich Benchmarks ansehen:
> microbenchmark::microbenchmark(loess(y~x, dat, span = 0.6),approx(dat,n = 20),lowess(dat,f = .6,iter=1),times=20)
Unit: milliseconds
expr min lq mean median uq max neval cld
loess(y ~ x, dat, span = 0.6) 153.034810 154.450750 156.794257 156.004357 159.23183 163.117746 20 c
approx(dat, n = 20) 1.297685 1.346773 1.689133 1.441823 1.86018 4.281735 20 a
lowess(dat, f = 0.6, iter = 1) 9.637583 10.085613 11.270911 11.350722 12.33046 12.495343 20 b
Loess
ist extrem langsam und dauert 100x so lange wie approx
. Lowess
liefert bessere Ergebnisse als approx
, läuft aber immer noch ziemlich schnell (15x schneller als Löss).
Loess
Mit zunehmender Anzahl von Punkten bleibt es auch zunehmend stecken und wird um 50.000 unbrauchbar.
BEARBEITEN: Zusätzliche Untersuchungen zeigen, dass loess
bestimmte Datensätze besser passen. Wenn Sie mit einem kleinen Datensatz arbeiten oder die Leistung keine Rolle spielt, probieren Sie beide Funktionen aus und vergleichen Sie die Ergebnisse.