3

我正在集思广益,为 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中设置块)。我怎么解决这个问题。

4

3 回答 3

2

您的均值和标准差代码不是最优的。正如 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 版本,您只需编写<!--rinline res['mean']--> ± <!--rinline res['sem']-->,而不必重新定义您的 R 函数。

于 2013-01-04T19:21:03.583 回答
1

我认为该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))
于 2013-01-03T19:51:11.270 回答
1

正如@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))
于 2013-01-03T20:21:47.450 回答