如何在ggplot中添加对数非线性拟合?

时间:2015-09-17 21:07:30

标签: r ggplot2 nls

我想使用nls在我的数据中拟合对数曲线。

library(dplyr)
library(ggplot2)
a <- 3
b <- 2
Y <- data_frame(x = c(0.2, 0.5, 1, 2, 5, 10),
                y = a + b*log(x))

Y %>%
  ggplot(aes(x = x, y = y)) +
  geom_point(shape = 19, size = 2) +
  geom_smooth(method = "nls",
              formula = y ~ p1 + p2*log(x),
              start = list(a = a, b = b),
              se = FALSE,
              control = list(maxiter = 100))

这给了我一个错误:

  

方法错误(公式,数据=数据,权重=权重,...):     迭代次数超过最大值100

出了什么问题?

1 个答案:

答案 0 :(得分:4)

以下是我在执行?nls之后复制并粘贴的一些文字:

  

警告

     

不要在人工“零残留”数据上使用nls。

     

nls函数使用相对偏移收敛标准,将当前参数估计值的数值不精确度与残差平方和进行比较。这对表格

的数据表现良好      

y = f(x,θ)+ eps

     

(var(eps)> 0)。它无法表明表格数据的收敛性

     

y = f(x,θ)

     

因为该标准相当于比较舍入误差的两个分量。如果您希望在人工数据上测试nls,请添加噪声分量,如下例所示。

这激发了我尝试这个:

> library(dplyr)
> library(ggplot2)
> a <- 3
> b <- 2
> Y <- data_frame(x = c(0.2, 0.5, 1, 2, 5, 10),
+                 y = a + b*log(x)*(1 + rnorm(length(x), sd=0.001)))
> Y %>%
+   ggplot(aes(x = x, y = y)) +
+   geom_point(shape = 19, size = 2) +
+   geom_smooth(method = "nls",
+               formula = y ~ p1 + p2*log(x),
+               start = list(p1 = a, p2 = b),
+               se = FALSE,
+               control = list(maxiter = 100))

注意:您的代码有start = list(a=a, b=b),这是一个错字,因为您的公式中未定义ab。除此之外,添加*(1 + rnorm(length(x), sd=0.001))是我唯一做的事情。

结果图表看起来一切正常。

Plot of results

我通常建议单独进行拟合,然后用predict绘制它。这样你就可以在绘图之前检查合适的质量,看它是否有效。

> fit <- nls(data=Y, formula = y ~ p1 + p2*log(x), start = list(p1 = a, p2 = b))
> summary(fit)

Formula: y ~ p1 + p2 * log(x)

Parameters:
   Estimate Std. Error t value Pr(>|t|)    
p1 3.001926   0.001538    1952 4.14e-13 ***
p2 1.999604   0.001114    1795 5.78e-13 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.003619 on 4 degrees of freedom

Number of iterations to convergence: 1 
Achieved convergence tolerance: 1.623e-08

> new_x = data.frame(x=seq(from=0.2, to=10, length.out=100))
> ggplot(data=Y, aes(x=x, y=y)) + 
       geom_point() + 
       geom_line(data=new_x, 
                 aes(x=new_x, y=predict(fit, newdata=new_x)), 
                 color='blue')