将曲线拟合到特定数据

The*_*man 5 curve r gnuplot curve-fitting

我的论文中有以下数据:

28 45
91 14
102 11
393 5
4492 1.77
Run Code Online (Sandbox Code Playgroud)

我需要在曲线中加入曲线.如果我绘制它,那么这就是我得到的.

在此输入图像描述

我认为某种指数曲线应该适合这些数据.我正在使用GNUplot.有人能告诉我哪种曲线适合这个以及我可以使用哪些初始参数?

Ben*_*Ben 39

以防R是一个选项,这里是您可能使用的两种方法的草图.

第一种方法:评估一组候选模型的拟合优度

这可能是最好的方式,因为它利用了您可能已经知道或期望变量之间的关系.

# read in the data
dat <- read.table(text= "x y 
28 45
91 14
102 11
393 5
4492 1.77", header = TRUE)

# quick visual inspection
plot(dat); lines(dat)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

# a smattering of possible models... just made up on the spot
# with more effort some better candidates should be added
# a smattering of possible models...
models <- list(lm(y ~ x, data = dat), 
               lm(y ~ I(1 / x), data = dat),
               lm(y ~ log(x), data = dat),
               nls(y ~ I(1 / x * a) + b * x, data = dat, start = list(a = 1, b = 1)), 
               nls(y ~ (a + b * log(x)), data = dat, start = setNames(coef(lm(y ~ log(x), data = dat)), c("a", "b"))),
               nls(y ~ I(exp(1) ^ (a + b * x)), data = dat, start = list(a = 0,b = 0)),
               nls(y ~ I(1 / x * a) + b, data = dat, start = list(a = 1,b = 1))
)

# have a quick look at the visual fit of these models
library(ggplot2)
ggplot(dat, aes(x, y)) + geom_point(size = 5) +
    stat_smooth(method = lm, formula = as.formula(models[[1]]), size = 1, se = FALSE, color = "black") + 
    stat_smooth(method = lm, formula = as.formula(models[[2]]), size = 1, se = FALSE, color = "blue") + 
    stat_smooth(method = lm, formula = as.formula(models[[3]]), size = 1, se = FALSE, color = "yellow") + 
    stat_smooth(method = nls, formula = as.formula(models[[4]]), data = dat, method.args = list(start = list(a = 0,b = 0)), size = 1, se = FALSE, color = "red", linetype = 2) + 
    stat_smooth(method = nls, formula = as.formula(models[[5]]), data = dat, method.args = list(start = setNames(coef(lm(y ~ log(x), data = dat)), c("a", "b"))), size = 1, se = FALSE, color = "green", linetype = 2) +
    stat_smooth(method = nls, formula = as.formula(models[[6]]), data = dat, method.args = list(start = list(a = 0,b = 0)), size = 1, se = FALSE, color = "violet") +
    stat_smooth(method = nls, formula = as.formula(models[[7]]), data = dat, method.args = list(start = list(a = 0,b = 0)), size = 1, se = FALSE, color = "orange", linetype = 2)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

橙色曲线看起来很不错.让我们看看当我们衡量这些模型的相对适合度时它的排名是......

# calculate the AIC and AICc (for small samples) for each 
# model to see which one is best, ie has the lowest AIC
library(AICcmodavg); library(plyr); library(stringr)
ldply(models, function(mod){ data.frame(AICc = AICc(mod), AIC = AIC(mod), model = deparse(formula(mod))) })

      AICc      AIC                     model
1 70.23024 46.23024                     y ~ x
2 44.37075 20.37075                y ~ I(1/x)
3 67.00075 43.00075                y ~ log(x)
4 43.82083 19.82083    y ~ I(1/x * a) + b * x
5 67.00075 43.00075      y ~ (a + b * log(x))
6 52.75748 28.75748 y ~ I(exp(1)^(a + b * x))
7 44.37075 20.37075        y ~ I(1/x * a) + b

# y ~ I(1/x * a) + b * x is the best model of those tried here for this curve
# it fits nicely on the plot and has the best goodness of fit statistic
# no doubt with a better understanding of nls and the data a better fitting
# function could be found. Perhaps the optimisation method here might be
# useful also: http://stats.stackexchange.com/a/21098/7744
Run Code Online (Sandbox Code Playgroud)

第二种方法:使用遗传编程搜索大量模型

在黑暗的曲线拟合方法中,这似乎是一种狂野的镜头.你不必在开始时指定太多,但也许我做错了...

# symbolic regression using Genetic Programming
# http://rsymbolic.org/projects/rgp/wiki/Symbolic_Regression
library(rgp)
# this will probably take some time and throw
# a lot of warnings...
result1 <- symbolicRegression(y ~ x, 
             data=dat, functionSet=mathFunctionSet,
             stopCondition=makeStepsStopCondition(2000))
# inspect results, they'll be different every time...
(symbreg <- result1$population[[which.min(sapply(result1$population, result1$fitnessFunction))]])

function (x) 
tan((x - x + tan(x)) * x) 
# quite bizarre...

# inspect visual fit
ggplot() + geom_point(data=dat, aes(x,y), size = 3) +
  geom_line(data=data.frame(symbx=dat$x, symby=sapply(dat$x, symbreg)), aes(symbx, symby), colour = "red")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

实际上是一个非常差的视觉配合.或许需要更多努力才能从遗传编程中获得高质量的结果......

致谢:曲线拟合答案1,曲线拟合答案2G.格洛腾迪克.

  • 对于5个数据点,我不打算使用后者(!)你想评论你如何猜测`poly(1/x,3)`作为候选模型吗? (3认同)

小智 6

你知道数据应该遵守的一些分析功能吗?如果是这样,它可以帮助您选择函数的形式,以适应数据.

否则,由于数据看起来像指数衰减,请在gnuplot中尝试这样的事情,其中​​具有两个自由参数的函数适合数据:

 f(x) = exp(-x*c)*b
 fit f(x) "data.dat" u 1:2 via b,c
 plot "data.dat" w p, f(x)
Run Code Online (Sandbox Code Playgroud)

Gnuplot将改变以'via'子句命名的参数以获得最佳拟合.统计信息将打印到stdout,以及当前工作目录中名为"fit.log"的文件.

c变量将确定曲率(衰减),而b变量将线性缩放所有值以获得正确的数据量.

有关详细信息,请参阅Gnuplot文档中的 " 曲线拟合"部分.

  • +1"你知道数据应该遵循哪些分析功能?".基于应该适合数据的函数形式的先验知识选择拟合函数总是比拟合任意函数更好. (3认同)