R中的指数曲线拟合

2024-03-08

time = 1:100  
head(y)  
0.07841589 0.07686316 0.07534116 0.07384931 0.07238699 0.07095363   
plot(time,y)  

这是一条指数曲线。

  1. 在不知道公式的情况下如何在这条曲线上拟合直线?我不能使用“nls”,因为公式未知(仅给出数据点)。

  2. 我怎样才能得到这条曲线的方程并确定方程中的常数?
    我尝试了黄土,但它没有给出截距。


You need a model to fit to the data. Without knowing the full details of your model, let's say that this is an exponential growth model https://en.wikipedia.org/wiki/Exponential_growth, which one could write as: y = a * e r*t

Where y是你的测量变量,t是测量的时间,a是 y 时的值t = 0 and r是增长常数。 我们想要估计a and r.

这是一个非线性问题,因为我们想要估计指数,r。 然而,在这种情况下,我们可以使用一些代数,通过两边取对数并求解,将其转换为线性方程(记住对数规则 https://www.chilimath.com/lessons/advanced-algebra/logarithm-rules/), 导致:log(y) = log(a) + r * t

我们可以通过一个例子来可视化这一点,通过从我们的模型生成一条曲线,假设一些值a and r:

t <- 1:100      # these are your time points
a <- 10         # assume the size at t = 0 is 10
r <- 0.1        # assume a growth constant
y <- a*exp(r*t) # generate some y observations from our exponential model

# visualise
par(mfrow = c(1, 2))
plot(t, y)      # on the original scale
plot(t, log(y)) # taking the log(y)

因此,对于这种情况,我们可以探索以下可能性:

  • 将我们的非线性模型拟合到原始数据(例如使用nls()功能)
  • 将我们的“线性化”模型拟合到对数转换数据(例如使用lm()功能)

选择哪个选项(还有更多选项),取决于我们的想法 (或假设)是我们数据背后的数据生成过程。

让我们用一些包含添加噪声的模拟来说明(采样自 正态分布),以模拟真实数据。请看这个StackExchange 帖子 https://stats.stackexchange.com/questions/61747/linear-vs-nonlinear-regression?rq=1对于这个模拟背后的推理(由阿莱霍·伯纳丁的评论 https://stackoverflow.com/questions/31851936/exponential-curve-fitting-in-r/31854405#comment81629348_31854405).

set.seed(12) # for reproducible results

# errors constant across time - additive
y_add <- a*exp(r*t) + rnorm(length(t), sd = 5000) # or: rnorm(length(t), mean = a*exp(r*t), sd = 5000)

# errors grow as y grows - multiplicative (constant on the log-scale)
y_mult <- a*exp(r*t + rnorm(length(t), sd = 1))  # or: rlnorm(length(t), mean = log(a) + r*t, sd = 1)

# visualise
par(mfrow = c(1, 2))
plot(t, y_add, main = "additive error")
lines(t, a*exp(t*r), col = "red") 
plot(t, y_mult, main = "multiplicative error")
lines(t, a*exp(t*r), col = "red")

对于加性模型,我们可以使用nls(),因为误差在整个过程中是恒定的t。使用时nls()我们需要为优化算法指定一些起始值(尝试“猜测”这些是什么,因为nls()经常难以集中于解决方案)。

add_nls <- nls(y_add ~ a*exp(r*t), 
               start = list(a = 0.5, r = 0.2))
coef(add_nls)

#           a           r 
# 11.30876845  0.09867135 

使用coef()函数我们可以得到两个参数的估计值。 这为我们提供了良好的估计,接近我们的模拟(a = 10 和 r = 0.1)。

通过绘制模型的残差,您可以看到误差方差在数据范围内相当恒定:

plot(t, resid(add_nls))
abline(h = 0, lty = 2)

对于乘法误差情况(我们的y_mult模拟值),我们应该使用lm()在对数转换的数据上,因为 相反,误差在该范围内是恒定的。

mult_lm <- lm(log(y_mult) ~ t)
coef(mult_lm)

# (Intercept)           t 
#  2.39448488  0.09837215 

为了解释这个输出,再次记住我们的线性化模型是log(y) = log(a) + r*t,相当于以下形式的线性模型Y = β0 + β1 * X, where β0是我们的截距β1我们的斜坡。

因此,在此输出中(Intercept)相当于log(a)我们的模型和t是时间变量的系数,所以相当于我们的r。 有意义地解释(Intercept)我们可以取它的指数(exp(2.39448488)),给我们~10.96,这非常接近我们的模拟值。

值得注意的是,如果我们拟合误差为乘法的数据,会发生什么 使用nls函数代替:

mult_nls <- nls(y_mult ~ a*exp(r*t), start = list(a = 0.5, r = 0.2))
coef(mult_nls)

#            a            r 
# 281.06913343   0.06955642 

现在我们高估了a并低估r (马里奥路特 https://stackoverflow.com/questions/31851936/exponential-curve-fitting-in-r/31854405#comment105713296_31854405在他的评论中强调了这一点)。我们可以想象使用错误的方法来拟合我们的模型的后果:

# get the model's coefficients
lm_coef <- coef(mult_lm)
nls_coef <- coef(mult_nls)

# make the plot
plot(t, y_mult)
lines(t, a*exp(r*t), col = "brown", lwd = 5)
lines(t, exp(lm_coef[1])*exp(lm_coef[2]*t), col = "dodgerblue", lwd = 2)
lines(t, nls_coef[1]*exp(nls_coef[2]*t), col = "orange2", lwd = 2)
legend("topleft", col = c("brown", "dodgerblue", "orange2"), 
       legend = c("known model", "nls fit", "lm fit"), lwd = 3)

我们可以看到如何lm()对数转换数据的拟合效果明显优于nls()拟合原始数据。

您可以再次绘制该模型的残差,以查看方差在数据范围内不是恒定的(我们也可以在上图中看到这一点,其中数据的分布随着t):

plot(t, resid(mult_nls))
abline(h = 0, lty = 2)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

R中的指数曲线拟合 的相关文章

  • 从 leafletProxy() 返回渲染的传单地图

    是否可以在渲染后在 Shiny 中检索传单地图 下面是一个代码示例 展示了如何生成地图leaflet 与返回的不同leafletProxy 即使它们在渲染时看起来完全相同 是否有一个功能可能不同于leafletProxy 获取实际的 htm
  • 如何在R中安装pivot_long()和pivot_wide()

    如果您想尝试这些新功能 pivot wide and pivot long 需要安装开发版tidyr devtools install github tidyverse tidyr 但我还没有实现它 我安装了一系列库 除了一个之外 vctr
  • R 中舍入到下一个数量级的算法

    如果标题不清楚 我很抱歉 但我无法简洁地解释它 给定一个浓度向量 我想将最大值四舍五入到下一个数量级 即 345 到 1000 另外 我想将最小值四舍五入到较低的数量级 即 3 2 到 1 这些浓度也可能低于 1 因此例如 0 034 需要
  • 如何从 curve_fit 获取置信区间

    我的问题涉及统计学和Python 我是两者的初学者 我正在运行模拟 对于自变量 X 的每个值 我都会为因变量 Y 生成 1000 个值 我所做的是计算每个 X 值的 Y 平均值 并使用 scipy optimize curve fit 拟合
  • 关于在 LyX 中生成和交叉引用 knitr 图的意见

    我的目标是在 LyX 中包含一个knitr图 我可以在我的文档中交叉引用 我 插入了浮动图像 添加了标题和标签 在浮动图像中插入了 ERT 而不是图像 我所做的图片如下 我在这里检查过类似的问题 但没有人做我所做的事情 所以我在这里问 有没
  • Rcpp 包不包含 Rcpp_precious_remove

    我一直在尝试创建数据库并安装 DBI 包 但仍然遇到此错误 我重新安装了 DBI 和 RSQLite 软件包 但它们似乎不起作用 library DBI con lt dbConnect RSQLite SQLite dbname memo
  • xtable 中的 Cox 回归输出 - 选择行/列并添加置信区间

    我不想将 cox 回归的输出导出到一个表中 然后将其放入我的文章中 我想最好的方法是使用 xtable library survival data pbc fit pbc lt coxph Surv time status 2 age ed
  • 如何自动替换多个文件的文本内容中的字符?

    我有一个文件夹 myfolder包含许多乳胶表 我需要替换其中每个字符 即替换任何minus sign by an en dash 只是为了确定 我们正在替换连字符INSIDE该文件夹中的所有 tex 文件 我不关心 tex 文件名 手动执
  • R 中 optim() 的优化(L-BFGS-B 需要“fn”的有限值)

    我在 R 中使用 optim 来求解涉及积分的可能性时遇到一些问题 我收到一条错误消息 optim par c 0 1 0 1 LLL method L BFGS B lower c 0 L BFGS B 需要 fn 的有限值 中的错误 下
  • 使用 ggplot 为各个图例值选择所选颜色(HSV 或 HCL 或 RGB)

    我有一个类似这样的数据集 data lt read table text Me EE PE DE TE DEE CE 1 1 1 4 5 2000 0 50 0 2547 0 69 2 1 2 2 4 3000 NA 0 5896 2 56
  • R ggplot:加权 CDF

    我想使用绘制加权 CDFggplot 一些旧的非 SO 讨论 例如this https stat ethz ch pipermail r help 2012 October 337288 html从 2012 年起 建议这是不可能的 但我想
  • R 中的 aov() 错误术语:bw Error(id) 和 Error(id/timevar) 规范有什么区别?

    两者有什么区别aov depvar timevar Error id 和aov depvar timevar Error id timevar 配方规格 这两种变体产生略有不同的结果 同样的问题曾经在这里被问过 https stats st
  • 时间序列,将月度数据改为季度

    现在我有一些每月数据 例如 1 1 90 620 2 1 90 591 3 1 90 574 4 1 90 542 5 1 90 534 6 1 90 545 etc 如果我使用 ts 函数 很容易将数据转换为时间序列结构 例如 Jan F
  • Pyspark - 一次聚合数据帧的所有列[重复]

    这个问题在这里已经有答案了 我想将数据框分组到单个列上 然后对所有列应用聚合函数 例如 我有一个包含 10 列的 df 我希望对第一列 1 进行分组 然后对所有剩余列 均为数字 应用聚合函数 sum 与此等效的 R 是 summarise
  • 将 R 中的列中的单引号替换为双引号

    我在 R 中的数据框有一个 A 列 其中有带单引号的字符串数据 Column A Hello World Hi World Good morning world 我想做的是将单引号替换为双引号并实现如下所示的输出 Column A Hell
  • 为什么我的 3D 绘图没有显示在 R Studio 绘图查看器中?

    我通常在 RStudio 版本 1 0 44 中查看绘图时没有问题 但是当我尝试查看使用 rgl 包创建的 3D 绘图时 我的 RStudio 绘图查看器中什么也没有出现 我能够毫无问题地绘制图 汽车 散点图 这是我正在使用的代码 inst
  • data.table:j中的匿名函数

    我试图让匿名函数返回多列j的论证data table 这是一个例子 sample data tmpdt lt data table a c rep a 5 rep b 5 b c rep f 3 rep r 7 c 1 10 d 21 30
  • 一起使用 R6 类和 foreach() %dopar% 的问题

    当与 foreach 一起使用时 我在 R6 类上遇到问题 可能与环境有关 我使用的是 Windows 假设有两个 R6 类 class1 和 class2 class1 中的 method1 依赖于 class2 例如 请参见下面的示例代
  • 使用 ggplot2 和 geom_area 堆叠负/正时间序列

    我正在尝试重现一个堆积的时间序列图 该图显示银行资产负债表的构成和规模如何随时间变化 它应该看起来像这样 资产位于 x 轴上方 负债位于 x 轴下方 到目前为止 我已经能够使用以下方法成功重现图表的每一半ggplot plot assets
  • Caret 和 GBM:任务 1 失败 - “参数意味着行数不同”

    我正在尝试使用以下代码运行带插入符号的 GBM library caret library doParallel detectCores registerDoParallel detectCores 1 set seed 668 in tr

随机推荐