【问题标题】:Not able to create a smoother curve fit plot无法创建更平滑的曲线拟合图
【发布时间】:2017-08-02 15:56:43
【问题描述】:

如何平滑拟合曲线?

XY <- data.frame(cbind(Values = c(91.8, 95.3,   99.8,   123.3,  202.9,  619.8,  1214.2, 1519.1, 1509.2, 1523.3, 1595.2, 1625.1),
            Concn = c(1000, 300,    100,    30, 10, 3,  1,  0.3,    0.1,    0.03,   0.01,   0)))
nls.fit <- nls(Values ~ (ymax* Concn / (ec50 + Concn)) + Ns*XY$Concn + ymin, data=XY,
                   start=list(ymax=max(XY$Values), ymin = min(XY$Values), ec50 = 3, Ns = 0.2045514))
plot(XY$Values ~ XY$Concn , data = XY, col = 4, main = "XY Std curve", log = "x")
lines(XY$Concn, predict(nls.fit))

当我尝试以下脚本时,我收到错误消息。

SmoothX <- seq(min(XY$Values), max(XY$Values), length = 100)
lines(SmoothX, predict(nls.fit,SmoothX), col='red', lwd=2)

错误(函数(公式,数据 = NULL,子集 = NULL,na.action = na.fail,: 可变长度不同(为“SmoothX”找到)

如何修复错误?

【问题讨论】:

    标签: r


    【解决方案1】:

    首先,我认为您在预测中使用的新数据应该使用浓度而不是值:

    SmoothX <- seq(min(XY$Concn), max(XY$Concn), length = 100)
    

    另外,看看 SmoothX 和 predict(nls.fit,SmoothX) 的长度不同:

    str(SmoothX)
    

    num [1:100] 91.8 107.3 122.8 138.3 153.8 ...

    str(predict(nls.fit,SmoothX))
    

    num [1:12] 109.5 49 52.3 120.6 298.6 ...

    但是,如果您包含list(Concn=SmoothX),您将获得一个包含 100 个值的向量,因为您的新数据向量长度是。

     str(predict(nls.fit,list(Concn=SmoothX)))
    

    num [1:100] 1714 324.7 175.5 119.6 91.8 ...

    这效果更好,但它仍然会发出警告消息和难看的红线:c。

    lines(SmoothX, predict(nls.fit,list(Concn=SmoothX)), col='red', lwd=2)
    

    警告信息: 在 (ymax * Concn/(ec50 + Concn)) + Ns * XY$Concn 中: 较长的对象长度不是较短对象长度的倍数

    【讨论】:

    • 感谢您一步一步地教您如何获取 100 个值的向量进行绘图。这对像我这样的许多人来说非常有用..
    【解决方案2】:

    首先,您需要在nls() 中使用一个公式,其中没有XY$

    nls.fit <- nls(Values ~ (ymax* Concn / (ec50 + Concn)) + 
                             Ns*Concn + ymin,
                   data=XY,
                   start=list(ymax=max(XY$Values), ymin = min(XY$Values),
                              ec50 = 3, Ns = 0.2045514))
    

    剧情:

    plot(Values ~ Concn , data = XY, col = 4, main = "XY Std curve",
         log = "x")
    

    如果您要在 log-X 尺度上绘图,这将有助于在 log 尺度上均匀分布您的预测值。您还需要将预测数据作为与模型中的预测变量具有相同变量名称 (Conc) 的数据框:

    SmoothX <- with(XY,
          data.frame(Concn=10^seq(min(log10(Concn[Concn>0])),
                                  max(log10(Concn)), length = 100)))
    pp <- predict(nls.fit,SmoothX)
    lines(SmoothX$Concn, pp, col='red', lwd=2)
    
    
     plot(Values ~ Concn , data = XY, col = 4, main = "XY Std curve",
         log = "x")
    SmoothX <- with(XY,
          data.frame(Concn=10^seq(min(log10(Concn[Concn>0])),
                                  max(log10(Concn)), length = 100)))
    pp <- predict(nls.fit,SmoothX)
    lines(SmoothX$Concn, pp, col='red', lwd=2)
    

    【讨论】:

    • 谢谢!我非常感谢您的指导。我同样喜欢您的回答以及 G. Grothendieck 的回答。由于 G. Grothendieck 的答案是第一个答案,所以我选择了它。对不起!
    【解决方案3】:

    首先确保XY按Concn的升序排序,以确保当我们使用lines时,每个点都连接到下一个排序点,而不是连接到其他点。还要确保从公式中删除XY,因为它已经在data 参数中指定,如果存在会导致问题。使用plotlines 参数subsetplotlines 中使用的数据中排除0,因为它们指定了对数刻度。

    o <- order(XY$Concn)
    XY <- XY[o, ]
    
    fo <- Values ~ (ymax* Concn / (ec50 + Concn)) + Ns * Concn + ymin
    st <- list(ymax=max(XY$Values), ymin = min(XY$Values), ec50 = 3, Ns = 0.2045514)
    nls.fit <- nls(fo, data = XY, start = st)
    
    plot(Values ~ Concn, XY, subset = Concn > 0, col = 4, log = "x")
    title(main = "XY Std curve")
    lines(predict(nls.fit, new = list(Concn = Concn)) ~ Concn, XY, subset = Concn > 0) ##
    

    或者,可以通过以下 3 行代码替换 lines 语句(上面标记为 ##)来提供更多的对数刻度上等距的点,从而使其更加平滑。请注意,我们在取对数之前删除了 0 点。

    logRange <- with(XY, log(range(Concn[Concn > 0])))
    x <- exp(seq(logRange[1], logRange[2], length = 100))
    lines(x, predict(nls.fit, new = list(Concn = x)))
    

    省略标记 ## 的行,然后运行上面的所有其余代码,包括我们得到的最后 3 行:

    【讨论】:

    • 谢谢!非常感谢您的指导。
    猜你喜欢
    • 2017-01-02
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 2020-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多