Các câu trả lời khác đều là cách tiếp cận tốt. Tuy nhiên, có một số tùy chọn khác trong R chưa được đề cập, bao gồm lowessvà approx, có thể mang lại hiệu suất phù hợp hơn hoặc nhanh hơn.
Các lợi thế được chứng minh dễ dàng hơn với một tập dữ liệu thay thế:
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)))
Đây là dữ liệu được phủ bằng đường cong sigmoid đã tạo ra nó:

Loại dữ liệu này phổ biến khi xem xét hành vi nhị phân giữa một tập hợp. Ví dụ: đây có thể là biểu đồ về việc khách hàng có mua thứ gì đó hay không (nhị phân 1/0 trên trục y) so với lượng thời gian họ đã dành trên trang web (trục x).
Một số lượng lớn các điểm được sử dụng để chứng minh rõ hơn sự khác biệt về hiệu suất của các chức năng này.
Smooth, splinevà smooth.splinetất cả đều tạo ra những thứ vô nghĩa trên một tập dữ liệu như thế này với bất kỳ tập hợp thông số nào tôi đã thử, có lẽ do xu hướng ánh xạ đến mọi điểm của chúng, điều này không hoạt động đối với dữ liệu nhiễu.
Tất cả loess, lowessvà các approxchức năng đều tạo ra kết quả có thể sử dụng được, mặc dù chỉ cho approx. Đây là mã cho mỗi thông số sử dụng các thông số được tối ưu hóa nhẹ:
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))
Và kết quả:
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"))

Như bạn có thể thấy, lowesstạo ra sự phù hợp gần như hoàn hảo với đường cong tạo ban đầu. Loesslà gần nhau, nhưng trải qua một độ lệch kỳ lạ ở cả hai đuôi.
Mặc dù tập dữ liệu của bạn sẽ rất khác, nhưng tôi nhận thấy rằng các tập dữ liệu khác hoạt động tương tự, với cả hai loessvà lowesscó khả năng tạo ra kết quả tốt. Sự khác biệt trở nên đáng kể hơn khi bạn nhìn vào điểm chuẩn:
> 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
Loesscực kỳ chậm, lâu nhất là 100 lần approx. Lowesstạo ra kết quả tốt hơn approx, trong khi vẫn chạy khá nhanh (nhanh hơn 15 lần so với hoàng thổ).
Loess cũng ngày càng sa lầy khi số điểm tăng lên, trở nên không sử dụng được khoảng 50.000.
CHỈNH SỬA: Nghiên cứu bổ sung cho thấy loessphù hợp hơn với một số bộ dữ liệu nhất định. Nếu bạn đang xử lý một tập dữ liệu nhỏ hoặc hiệu suất không phải là điều đáng cân nhắc, hãy thử cả hai hàm và so sánh kết quả.