Программирование R / Sweave для правильного вывода \ Sexpr - PullRequest
7 голосов
/ 21 марта 2010

У меня небольшая проблема в программировании R для Sweave, и здесь часто упоминается твиттер-группа #rstats, поэтому я решил задать этот вопрос SO-толпе. Я аналитик, а не программист, так что будьте спокойны с моим первым постом.

Вот проблема: я пишу отчет об опросе в Sweave с использованием R и хотел бы сообщить о предельной прибыли в строке, используя \Sexpr{}. Например, вместо того, чтобы сказать:

Только 14% респондентов сказали «Х».

Я хочу написать отчет так:

Только \ Sexpr {p.mean (переменная)} $ \% $ респондентов ответили 'X'.

Проблема в том, что Sweave преобразует результаты выражения в \Sexpr{} в символьную строку, что означает, что выходные данные из выражения в R и выходные данные, которые появляются в моем документе, отличаются. Например, выше я использую функцию 'p.mean':

p.mean<- function (x) {options(digits=1)  
mmm<-weighted.mean(x, weight=weight, na.rm=T)  
print(100*mmm)  
}

В R вывод выглядит так:

p.mean(variable)
>14

но когда я использую \Sexpr{p.mean(variable)}, я получаю необоснованную строку символов (в данном случае: 13.5857142857143) в моем документе. Я попытался ограничить вывод своей функции digits=1 в глобальной среде, в самой функции и в различных командах. Кажется, он содержит только то, что печатает R, а не преобразование символов, которое является результатом выражения и которое в конечном итоге печатается в файле LaTeX.

as.character(p.mean(variable))  
>[1] 14  
>[1] "13.5857142857143"  

Кто-нибудь знает, что я могу сделать, чтобы ограничить цифры, напечатанные в файле LaTeX, либо перепрограммировав функцию R, либо установив значение в Sweave или \Sexpr{}?

Ответы [ 5 ]

4 голосов
/ 21 марта 2010

@ Кенни ТМ понял. @ Давид, вам следует избегать options(digits = 1), поскольку это повлияет на все ваши расчеты (впоследствии оно будет подавлять десятичные дроби в каждом выводе). Так что используйте функцию round() после применения weighted.mean(). Примерно так:

\Sexpr{round(p.mean(x))}

И не используют print(), но return(). И вот почему:

> set.seed(1234)
> x <- rnorm(100)
> foo <- function(x) {
   res <- mean(x) + 5
   print(res)
}
> foo(x)
[1] 5
> foo(x) + 10
[1] 5
[1] 15

Используйте return() или просто введите результирующую переменную в последней строке:

> bar <- function(x) {
   res <- mean(x) + 5
   return(res)
}
> bar(x) + 10
[1] 15

Итак, перепишите свою функцию и обязательно используйте as.character() ... у вас есть все биты, теперь просто сложите все вместе.

приписка

Я не уверен, как работает ваша функция ... Я никогда не использовал взвешенное среднее в моем анализе. Больше всего меня удивляет weight=weight. Разве не было бы лучше поместить еще один аргумент в функцию? Честно говоря, я все еще поражен тем фактом, что ваша функция дает правильный результат ... возможно, потому что у вас есть переменная weight, определенная до определения функции. [РЕДАКТИРОВАТЬ] Вы не получите средневзвешенное значение с вашей функцией, если у вас нет предопределенной функции weight, а "обычное" среднее значение!

Надеюсь, этот тебе помог!

С уважением, Александар

3 голосов
/ 21 марта 2010

Попробуйте 'format':

options(digits=1)

и затем:

\Sexpr{format(p.mean(variable))}

Вы также можете использовать аргумент 'nsmall':

options(digits=3)
...
\Sexpr{format(sqrt(2)-0.41,nsmall=2)}

И вы также можете попробовать 'sprintf', если вы знакомы с C.

2 голосов
/ 21 марта 2010
as.character(round(p.mean(variable)))

?

1 голос
/ 25 марта 2010

функция sprintf () отлично подходит для форматирования числового вывода.

0 голосов
/ 31 декабря 2017

Пакет siunitx также можно использовать для форматирования чисел в Sweave.

Код для Sweave

Следующий скрипт показывает, как использовать его для форматирования чисел, синтаксис для Sweave . В преамбуле вы можете установить форматирование по умолчанию, например

\sisetup{
round-mode = figures,
round-precision = 3
}

и затем переопределить его в командах \Sexpr{num(pi,round_precision=2)}

\documentclass[a4paper]{article}
\usepackage{siunitx}
\usepackage{Sweave}
\title{siunitx}

\sisetup{
round-mode = figures,
round-precision = 3
}
\begin{document}

\maketitle
<<sanitize_number,echo=FALSE>>=
num <- function(x,round_precision=NULL)
{
  if (is.null(round_precision)) {
    return(sprintf("\\\\num{%s}", x))
  } else {
    return(sprintf("\\\\num[round-precision=%s]{%s}",round_precision, x))
  }
}
@
Examples :\\
round\_precision= 2 gives : \Sexpr{num(pi,round_precision=2)} \\
round\_precision= 4 gives : \Sexpr{num(pi,round_precision=4)}\\
Default formatting gives : \Sexpr{num(pi)}
\end{document}

enter image description here

Код для knitr

В knitr по умолчанию числа в \ Sexpr округляются, если установлена ​​опция options(digits = 2). Но если вам нужно различное округление в разных местах, следующий код работает, его необходимо адаптировать, так как нет необходимости удваивать двойные экранирования в \ Sexpr в knitr.

num <- function(x,round_precision=NULL)
{
  if (is.null(round_precision)) {
    return(sprintf("\\num{%s}", x))
  } else {
    return(sprintf("\\num[round-precision=%s]{%s}",round_precision, x))
  }
}
...