使用nls和ggplot2将对数曲线拟合到数据中

时间:2017-09-01 10:28:52

标签: r modeling ggplot2 nls

我使用R来拟合对数曲线上的数据,方程式为:

y = a * log(b * x)

我的数据如下:

#Creating example data
pre <- c(946116, 1243227, 1259646, 1434124, 1575268, 2192526, 3252832, 6076519)  
post <- c(907355, 1553586, 1684253, 2592938, 1919173, 1702644,3173743, 3654198)  
data <- data.frame(pre,post)

#Plotting data
  ggplot(data, aes(x=pre, y=post))+
  geom_point()

Example plot

但是当我尝试使用geom_smooth来拟合对数曲线时,我得到一个错误。

# Fitting logarithmic curve
ggplot(data, aes(x=pre, y=post))+
  geom_point()+
  geom_smooth(method="nls", se=FALSE,
              method.args=list(formula=y~a*log(b*x),
                               start=c(a=100, b=2)))

警告讯息:

1: In log(b * x) : NaNs produced
2: Computation failed in `stat_smooth()`:
Missing value or an infinity produced when evaluating the model 

当我尝试在nls中创建对数模型时,我遇到类似的问题,而不使用ggplot

model <- nls(data=data, 
             formula=y~a*log(b*x),
             start=list(a=100, b=2))

警告讯息:

Error in numericDeriv(form[[3L]], names(ind), env) : 
  Missing value or an infinity produced when evaluating the model
In addition: Warning messages:
1: In min(x) : no non-missing arguments to min; returning Inf
2: In max(x) : no non-missing arguments to max; returning -Inf
3: In log(b * x) : NaNs produced

作为R的新手,我不太清楚错误消息试图告诉我的内容。我知道我需要改变我指定开始条件的方式,但我不知道如何。

2 个答案:

答案 0 :(得分:3)

试试这个:

ggplot(data, aes(x=pre, y=post))+
  geom_point()+
  geom_smooth(method="nls", se=FALSE, formula=y~a*log(x)+k,
              method.args=list(start=c(a=1, k=1)))

enter image description here

请注意,它基本上是相同的公式,但现在k = a * log(b)

a * log(b * x) = a * {log(b) + log(x)} = a * log(x) + a * log(b) = a * log(x) + k

答案 1 :(得分:0)

我在 nls 电话中看到了一些问题。 1)当这些变量不存在时,您正在使用变量 x y 。它们应该 pre post 。 2)数字的大小给出 nls 麻烦。如果你将它们除以1,000,000就会有所帮助。

pre <- c(946116, 1243227, 1259646, 1434124, 1575268, 2192526, 3252832, 6076519)  
post <- c(907355, 1553586, 1684253, 2592938, 1919173, 1702644,3173743, 3654198)

pre = pre/1000000
post = post/1000000

data <- data.frame(pre,post)

model <- nls(data=data, 
             formula=post~a*log(b*pre),
             start=list(a=1, b=1))

summary(model)

但如前面的答案所示,改变等式的形式将有助于无需改变数据的规模。

pre <- c(946116, 1243227, 1259646, 1434124, 1575268, 2192526, 3252832, 6076519)  
post <- c(907355, 1553586, 1684253, 2592938, 1919173, 1702644,3173743, 3654198)

data <- data.frame(pre,post)

model <- nls(data=data, 
             formula=post~a*log(pre)+b,
             start=list(a=1, b=0))

summary(model)