Función para mean y sem en la implementación de Sweave/knitr

Estoy haciendo una lluvia de ideas para escribir una función media y sem para el uso de Sweave/knitr. Y para mi conocimiento limitado se ve así

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))
}

Realmente hace un trabajo y da resultados como:

43.9303846153846 \pm 3.34823050767781

El problema es que no respeta option() que defino en el entorno principal (trozo de configuración en knitr). Como puedó resolver esté problema.

preguntado el 03 de enero de 13 a las 19:01

3 Respuestas

Su código para la media y la desviación estándar no es óptimo. Como mencionó Dieter Menne, simplemente puede usar el mean() y sd() si no está haciendo esto con fines de ejercicio.

La knitr El paquete se ha esforzado mucho para imprimir mejor los números, y le recomiendo que use estas funciones en lugar de inventar sus propias reglas de formato. Vea a continuación mi solución (\Sexpr{} respetará 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}

Más importante aún, esta es una solución portátil: si desea una versión HTML, simplemente escriba <!--rinline res['mean']--> ± <!--rinline res['sem']-->, y no tiene que redefinir su función R.

Respondido el 04 de enero de 13 a las 19:01

Gracias Yihui, esta es otra solución. Pero cuando uno se retuerce en un documento largo y complejo, debe mantener ordenada la parte de codificación, de lo contrario es bastante confuso. Pero encontré la solución, al menos a mí me funciona. Y el código es 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(format(xbar),"$\\pm$",format(se))) } . El código de @dieter-menne es más elegante pero no funcionó para mí. Gracias. - Rafik Margaryan

@Yihui: Ambos son enfoques válidos, pero cuando escribe $\Sexpr{res['mean']} \pm \Sexpr{res['sem']}$ con mucha frecuencia, tiene una abreviatura que pone \pm en Sexpr es útil, así que tiendo a estar de acuerdo con Rafik. En los viejos tiempos, solo con látex, eso era fácil, pero hoy en día trato de hacer que las clases de impresión sean conscientes del contexto de procesamiento de látex/HTML para generar los separadores correctos. - Dieter Menne

@DieterMenne Eso tiene sentido. Otro problema menor es que preferiría definir el método S3 en format() en lugar de print(). - Yihui Xie

Pienso que el format la función hará el truco:

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

Entonces en tu caso,

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

Respondido el 03 de enero de 13 a las 19:01

Como señaló @csgilliespie, la declaración de formato hará el trabajo, pero esto aún no resuelve el problema que probablemente desee que solucione el formato. option(digit=3). Es mejor hacer esto en un enfoque de dos pasos, separando los números de la vista. Ver por ejemplo print.lm (sin el ()).

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))

Respondido el 03 de enero de 13 a las 20:01

Este parece el camino correcto a seguir. En la mayoría de los casos uso option(digits=2), en ese caso, cada vez que debo cambiar el valor máximo de configuración del código y -3. Originalmente, me gustaría que el código respetara .GlobalEnv dígitos de opción. En ese caso escribiría digits=getOption("digits"). Y puedo confirmar que realmente funcionó para mí. Muchas gracias. - Rafik Margaryan

Si está utilizando esta función como un ejercicio para escribir código R, está bien. Sin embargo, para un trabajo serio, recomiendo usar las funciones incorporadas para la varianza, que está mejor optimizada contra problemas numéricos. - Dieter Menne

Hola, @dieter-menne, todavía estoy luchando con este fragmento de código. Cuando lo hago en R, da la salida "media \\pm sem" como se deseaba. Pero al compilar con knitr en RStudio, sale como "mean, sem" y no hay rastro de \pm. ¿Cómo puedo arreglar este código? - Rafik Margaryan

Use la llamada regla de Dalgaard: si cree que ha estado usando el número correcto de barras invertidas, duplíquelo. Cuatro con barra invertida podría ser correcto, recuerdo un caso de 8... - Dieter Menne

La versión correcta de la regla de Dalgaard: markmail.org/message/5rry23dw5gxoapgf : La regla genérica para las barras invertidas es que necesita el doble de lo que pensaba. - Dieter Menne

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.