Інші відповіді - це хороші підходи. Однак є кілька інших варіантів у R, про які не згадувалось, включаючи lowess
таapprox
, які можуть забезпечити кращі підходи або швидшу продуктивність.
Переваги легше продемонструвати за допомогою альтернативного набору даних:
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)))
Ось дані, накладені на сигмоподібну криву, яка їх породила:
Цей тип даних є загальним при розгляді бінарної поведінки серед населення. Наприклад, це може бути графік того, чи купував клієнт щось (двійковий файл 1/0 на осі y) проти кількості часу, проведеного ним на сайті (вісь x).
Велика кількість балів використовується для кращого демонстрування відмінностей у виконанні цих функцій.
Smooth
, spline
Іsmooth.spline
всі продукти тарабарщина на наборі даних , як це з будь-яким набором параметрів я пробував, можливо , з - за їх схильність до карти в будь-яку точку, що не робить роботу для зашумлених даних.
В loess
, lowess
і approx
функції все одно виконують потрібні результати, хоча навряд за approx
. Це код для кожного з використанням злегка оптимізованих параметрів:
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))
І результати:
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"))
Як бачите, lowess
забезпечує майже ідеальне припасування до вихідної генеруючої кривої. Loess
близько, але відчуває дивне відхилення в обох хвостах.
Незважаючи на те, що ваш набір даних буде сильно відрізнятися, я виявив, що інші набори даних працюють однаково, і те, loess
і інше і lowess
може дати хороші результати. Різниці стають більш суттєвими, якщо поглянути на еталони:
> 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
надзвичайно повільний, приймаючи 100x стільки, скільки approx
. Lowess
приносить кращі результати, ніж approx
, хоча при цьому працює досить швидко (в 15 разів швидше, ніж лесс).
Loess
також стає все більш заглибленим, оскільки кількість очок збільшується, стаючи непридатною близько 50 000.
РЕДАКТУВАТИ: Додаткове дослідження показує, що loess
краще підходить для певних наборів даних. Якщо ви маєте справу з невеликим набором даних або продуктивність не є проблемою, спробуйте обидві функції та порівняйте результати.