其他答案都是好的方法。但是,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)))
以下是生成该数据的S型曲线所覆盖的数据:
当查看总体中的二进制行为时,此类数据很常见。例如,这可能是客户是否购买了某些商品(y轴为二进制1/0)与他们在网站上花费的时间(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
非常慢,需要100倍的时间approx
。 Lowess
产生比以下更好的结果approx
,同时仍保持相当快的运行速度(比黄土快15倍)。
Loess
随着点数的增加,也变得越来越陷入困境,在50,000左右无法使用。
编辑:其他研究表明,loess
它可以更好地拟合某些数据集。如果要处理的数据集较小或不考虑性能,请尝试使用两个函数并比较结果。