【问题标题】:Function for mean and sem in Sweave/knitr implementationSweave/knitr 实现中均值和 sem 的函数
【发布时间】:2013-01-03 19:25:43
【问题描述】:

我正在集思广益,为 Sweave/knitr 编写一个均值和 sem 函数。就我有限的知识而言,它看起来像这样

m.se <- function (x, na.rm = TRUE) {
    if (na.rm) 
        x <- x[!is.na(x)]
    n <- length(x)
    if (n == 0) 
        return(c(mean = NA, sem = NA))
     xbar <- sum(x)/n
     se <- sqrt(sum((x - xbar)^2)/(n - 1))/sqrt(n)
     c(mean = xbar, sem = se)
     return(paste(xbar,"\\pm",se))
}

它确实做了一些工作,它给出的输出如下:

43.9303846153846 \pm 3.34823050767781

问题是它不尊重我在主环境中定义的option()(在knitr 中设置块)。 我该如何解决这个问题。

【问题讨论】:

    标签: r function latex sweave knitr


    【解决方案1】:

    您的均值和标准差代码不是最优的。正如 Dieter Menne 提到的,如果您不是出于锻炼目的,可以简单地使用内置的 mean()sd()

    knitr 包为更好地打印数字做了很多努力,我建议您使用这些工具而不是发明自己的格式规则。我的解决方案见下文(\Sexpr{} 将尊重options('digits')):

    \documentclass{article}
    \begin{document}
    
    <<mean-sem>>=
    options(digits = 3)
    m.se <- function (x, ...) {
      n <- length(x)
      if (n == 0) return(c(mean = NA, sem = NA))
      se <- sd(x, ...)/sqrt(n)
      c(mean = mean(x, ...), sem = se)
    }
    res <- m.se(rnorm(100))
    @
    
    What you want is $\Sexpr{res['mean']} \pm \Sexpr{res['sem']}$.
    
    \end{document}
    

    更重要的是,这是一个可移植的解决方案——如果你想要一个 HTML 版本,你只需写 &lt;!--rinline res['mean']--&gt; ± &lt;!--rinline res['sem']--&gt;,你不必重新定义你的 R 函数。

    【讨论】:

    • 感谢一辉,这是另一种解决方案。但当一个翻腾又长又复杂的文件时,必须保持编码部分整洁,否则就是安静混乱。但我确实找到了解决方案,至少它对我有用。代码是 m.se &lt;- function (x, na.rm = TRUE) { if (na.rm) x &lt;- x[!is.na(x)] n &lt;- length(x) if (n == 0) return(c(mean = NA, sem = NA)) xbar &lt;- sum(x)/n se &lt;- sqrt(sum((x - xbar)^2)/(n - 1))/sqrt(n) c(mean = xbar, sem = se) return(paste(format(xbar),"$\\pm$",format(se))) } 。 @dieter-menne 的代码更优雅,但对我不起作用。谢谢。
    • @Yihui:两者都是有效的方法,但是当你经常写 $\Sexpr{res['mean']} \pm \Sexpr{res['sem']}$ 时,有一个简写将 \pm 放入 Sexpr 是有帮助的,所以我倾向于同意 Rafik。在过去,只有乳胶,这很容易,但现在我尝试让打印类知道乳胶/HTML 处理上下文以输出正确的分隔符。
    • @DieterMenne 这是有道理的。另一个小问题是我宁愿在format() 而不是print() 上定义S3 方法。
    【解决方案2】:

    我认为format 函数可以解决问题:

    R> 1.1111111
    [1] 1.111
    R> paste(1.1111111)
    [1] "1.1111111"
    R> paste(format(1.1111111))
    [1] "1.111"
    

    所以在你的情况下,

    paste(format(xbar), "\\pm", format(se))
    

    【讨论】:

      【解决方案3】:

      正如@csgilliespie 所指出的,格式声明将完成这项工作,但这还不能解决您可能希望格式化为option(digit=3) 服务的问题。最好分两步执行此操作,将数字与视图分开。参见例如print.lm(不带 ())。

      m.se <- function (x, na.rm = TRUE) {
        if (na.rm) 
          x <- x[!is.na(x)]
        n <- length(x)
        if (n == 0) 
          return(c(mean = NA, sem = NA))
        xbar <- sum(x)/n
        se <- sqrt(sum((x - xbar)^2)/(n - 1))/sqrt(n)
        ret = c(mean = xbar, sem = se)
        class(ret) ="m.se"
        ret
      }
      
      print.m.se = function(x, digits = max(3, getOption("digits") - 3),...){
        print(paste(format(x["mean"],digits=digits), "//pm",format(x["sem"],digits=digits)))
        invisible(x)
      }
      
      m.se(rnorm(10))
      

      【讨论】:

      • 这似乎是正确的方法。在大多数情况下,我使用option(digits=2),在这种情况下,我每次都必须更改代码设置最大值和-3。最初,我希望代码尊重.GlobalEnv 选项数字。在那种情况下,我会写digits=getOption("digits")。我可以确认它确实对我有用。非常感谢。
      • 如果您将此函数用作编写 R 代码的练习,那很好。但是,对于严肃的工作,我建议使用内置函数来解决数值问题,它可以更好地优化数值问题。
      • 嗨@dieter-menne,我仍然在为这段代码感到困惑。当我在 R 中执行此操作时,它会给出不想要的“平均 \\pm sem”输出。但是在 RStudio 中使用 knitr 进行编译时,它会像“mean, sem”一样出现,并且没有来自 \pm 的痕迹。如何修复此代码?
      • 使用所谓的 Dalgaard 规则:如果您认为自己使用了正确数量的反斜杠,请将其加倍。四个反斜杠可能是对的,我记得一个 8 的情况...
      • Dalgaard 规则的正确版本:markmail.org/message/5rry23dw5gxoapgf:反斜杠的通用规则是您需要的数量是您想象的两倍。
      猜你喜欢
      • 2013-09-28
      • 1970-01-01
      • 1970-01-01
      • 2018-01-05
      • 2023-03-08
      • 2012-01-16
      • 2012-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多