Jawaban lainnya adalah pendekatan yang baik. Namun, ada beberapa opsi lain di R yang belum disebutkan, termasuk lowess
danapprox
, yang mungkin memberikan kesesuaian yang lebih baik atau kinerja yang lebih cepat.
Keuntungannya lebih mudah ditunjukkan dengan kumpulan data alternatif:
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)))
Berikut adalah data yang dihamparkan dengan kurva sigmoid yang menghasilkannya:
Jenis data ini biasa terjadi saat melihat perilaku biner di antara suatu populasi. Misalnya, ini mungkin plot tentang apakah pelanggan membeli sesuatu (biner 1/0 pada sumbu y) versus jumlah waktu yang mereka habiskan di situs (sumbu x).
Sejumlah besar poin digunakan untuk mendemonstrasikan perbedaan kinerja fungsi-fungsi ini dengan lebih baik.
Smooth
,, spline
dansmooth.spline
semuanya menghasilkan omong kosong pada kumpulan data seperti ini dengan kumpulan parameter apa pun yang telah saya coba, mungkin karena kecenderungannya untuk memetakan ke setiap titik, yang tidak berfungsi untuk data yang berisik.
Fungsi loess
,, lowess
dan approx
semuanya menghasilkan hasil yang dapat digunakan, meskipun hanya untuk approx
. Ini adalah kode untuk masing-masing menggunakan parameter yang dioptimalkan ringan:
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))
Dan hasilnya:
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"))
Seperti yang Anda lihat, lowess
menghasilkan kesesuaian yang hampir sempurna dengan kurva pembangkit asli. Loess
dekat, tetapi mengalami penyimpangan yang aneh di kedua ekor.
Meskipun kumpulan data Anda akan sangat berbeda, saya menemukan bahwa kumpulan data lain memiliki kinerja yang sama, dengan keduanya loess
dan lowess
mampu memberikan hasil yang baik. Perbedaan menjadi lebih signifikan saat Anda melihat tolok ukur:
> 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
sangat lambat, memakan waktu 100x lebih lama approx
. Lowess
menghasilkan hasil yang lebih baik daripada approx
, sambil tetap berlari dengan cukup cepat (15x lebih cepat dari loess).
Loess
juga menjadi semakin macet karena jumlah poin meningkat, menjadi tidak dapat digunakan sekitar 50.000.
EDIT: Penelitian tambahan menunjukkan bahwa loess
lebih cocok untuk set data tertentu. Jika Anda berurusan dengan set data kecil atau kinerja tidak menjadi pertimbangan, coba kedua fungsi dan bandingkan hasilnya.