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 lowess
và 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
, spline
và smooth.spline
tấ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
, lowess
và các approx
chứ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, lowess
tạo ra sự phù hợp gần như hoàn hảo với đường cong tạo ban đầu. Loess
là 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 loess
và lowess
có 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
Loess
cực kỳ chậm, lâu nhất là 100 lần approx
. Lowess
tạ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 loess
phù 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ả.