كيفية تناسب منحنى سلس إلى البيانات الخاصة بي في "ص" ؟
-
28-09-2019 - |
سؤال
أحاول رسم منحنى سلس في R
.لدي لعبة بسيطة البيانات:
> x
[1] 1 2 3 4 5 6 7 8 9 10
> y
[1] 2 4 6 8 7 12 14 16 18 20
الآن عندما مؤامرة مع معيار الأمر يبدو وعرة و منفعل ، بالطبع:
> plot(x,y, type='l', lwd=2, col='red')
كيف يمكنني جعل منحنى سلس بحيث 3 حواف مدورة باستخدام يقدر القيم ؟ أعرف أن هناك العديد من الأساليب لتناسب منحنى سلس ولكن لست متأكد أي واحد من شأنها أن تكون أكثر ملاءمة لهذا النوع من منحنى كيف يمكنك أن تكتب في R
.
المحلول
انا يعجبني loess()
الكثير لتنعيم:
x <- 1:10
y <- c(2,4,6,8,7,12,14,16,18,20)
lo <- loess(y~x)
plot(x,y)
lines(predict(lo), col='red', lwd=2)
يحتوي كتاب Venables and Ripley's Mass على قسم كامل عن التنعيم الذي يغطي أيضًا الحشرات والحيوية - ولكن loess()
هو مجرد مفضل للجميع.
نصائح أخرى
ربما smooth.spline هو خيار ، يمكنك تعيين معلمة تجانس (عادة بين 0 و 1) هنا
smoothingSpline = smooth.spline(x, y, spar=0.35)
plot(x,y)
lines(smoothingSpline)
يمكنك أيضًا استخدام التنبؤ على كائنات smooth.spline. تأتي الوظيفة مع قاعدة R ، انظر؟ Smooth.spline للحصول على التفاصيل.
من أجل الحصول عليها حقا smoooth ...
x <- 1:10
y <- c(2,4,6,8,7,8,14,16,18,20)
lo <- loess(y~x)
plot(x,y)
xl <- seq(min(x),max(x), (max(x) - min(x))/1000)
lines(xl, predict(lo,xl), col='red', lwd=2)
يستفيد هذا النمط من الكثير من النقاط الإضافية ويحصل على منحنى سلس للغاية. يبدو أيضًا أن النهج الذي يتطلبه GgPlot. إذا كان المستوى القياسي للنعومة جيدًا ، فيمكنك استخدامه فقط.
scatter.smooth(x, y)
ال qplot () الوظيفة في حزمة GGPLOT2 بسيطة للغاية للاستخدام وتوفر حلًا أنيقًا يتضمن نطاقات الثقة. على سبيل المثال،
qplot(x,y, geom='smooth', span =0.5)
ينتج عنه
لوس هو نهج جيد للغاية ، كما قال ديرك.
خيار آخر هو استخدام Bezier Splines ، والتي قد تعمل في بعض الحالات بشكل أفضل من LOESS إذا لم يكن لديك العديد من نقاط البيانات.
هنا ستجد مثالاً: http://rosettacode.org/wiki/cubic_bezier_curves#r
# x, y: the x and y coordinates of the hull points
# n: the number of points in the curve.
bezierCurve <- function(x, y, n=10)
{
outx <- NULL
outy <- NULL
i <- 1
for (t in seq(0, 1, length.out=n))
{
b <- bez(x, y, t)
outx[i] <- b$x
outy[i] <- b$y
i <- i+1
}
return (list(x=outx, y=outy))
}
bez <- function(x, y, t)
{
outx <- 0
outy <- 0
n <- length(x)-1
for (i in 0:n)
{
outx <- outx + choose(n, i)*((1-t)^(n-i))*t^i*x[i+1]
outy <- outy + choose(n, i)*((1-t)^(n-i))*t^i*y[i+1]
}
return (list(x=outx, y=outy))
}
# Example usage
x <- c(4,6,4,5,6,7)
y <- 1:6
plot(x, y, "o", pch=20)
points(bezierCurve(x,y,20), type="l", col="red")
إجابات أخرى كلها جيدة النهج.ومع ذلك ، هناك عدد قليل من الخيارات الأخرى في R التي لم يتم ذكرها ، بما في ذلك lowess
و approx
, التي قد تعطي أفضل يناسب أو أداء أسرع.
مزايا أكثر أظهرت بسهولة مع بديل dataset:
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-axis).
عدد كبير من النقاط تستخدم لإظهار أفضل أداء الاختلافات من هذه الوظائف.
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
يعطي أفضل يناسب بعض البيانات.إذا كنت تتعامل مع مجموعة صغيرة من البيانات أو الأداء لا اعتبار حاول كل الوظائف و مقارنة النتائج.
لم أر هذه الطريقة معروضة ، لذا إذا كان شخص آخر يتطلع إلى القيام بذلك ، فقد وجدت أن وثائق GGPLOT تقترح تقنية لاستخدام gam
الطريقة التي أنتجت نتائج مماثلة ل loess
عند العمل مع مجموعات البيانات الصغيرة.
library(ggplot2)
x <- 1:10
y <- c(2,4,6,8,7,8,14,16,18,20)
df <- data.frame(x,y)
r <- ggplot(df, aes(x = x, y = y)) + geom_smooth(method = "gam", formula = y ~ s(x, bs = "cs"))+geom_point()
r
أولاً مع طريقة LOESS وصيغة السيارات الثانية مع طريقة GAM مع الصيغة المقترحة