16

I am just starting to write some documents with Sweave/R and I like the \sexpr{} command that lets one tow write numbers directly within text.

If I have a number like mus=0.0002433121, well I can say round it to a number of decimal places e.g.

\Sexpr{round(mus,7)}

How to write it in the scientific notation i.e. as LaTeX would be outputting

2.43 \times 10^{-4} 

and can we control the number of significant digits to be outputted like 3 in this example?

I note that a number like sigma = 2000000 is written automatically to 2e + 06 if I specify

\Sexpr{round(sigma,2)}. 

I would prefer that it would be written as

2 \times 10^6 

same as we would get in LaTeX notation and perhaps giving us the possibility to control the number of significant digits as well.

How to achieve this?

yCalleecharan
  • 4,656
  • 11
  • 56
  • 86

2 Answers2

15

I think this function should work:

sn <- function(x,digits)
{
  if (x==0) return("0")
  ord <- floor(log(abs(x),10))
  x <- x / 10^ord
  if (!missing(digits)) x <- format(x,digits=digits)
  if (ord==0) return(as.character(x))
  return(paste(x,"\\\\times 10^{",ord,"}",sep=""))
}

Some tests:

> sn(2000000)
[1] "2\\\\times 10^{6}"
> sn(0.001)
[1] "1\\\\times 10^{-3}"
> sn(0.00005)
[1] "5\\\\times 10^{-5}"
> sn(10.1203)
[1] "1.01203\\\\times 10^{1}"
> sn(-0.00013)
[1] "-1.3\\\\times 10^{-4}"
> sn(0)
[1] "0"

If you want the result in math mode you could enter $ signs in the paste() call.

Edit:

Here is a Sweave example:

\documentclass{article}

\begin{document}
<<echo=FALSE>>= 
sn <- function(x,digits)
{
  if (x==0) return("0")
  ord <- floor(log(abs(x),10))
  x <- x / 10^ord
  if (!missing(digits)) x <- format(x,digits=digits)
  if (ord==0) return(as.character(x))
  return(paste(x,"\\\\times 10^{",ord,"}",sep=""))
}
@

Blablabla this is a pretty formatted number $\Sexpr{sn(0.00134,2)}$.

\end{document}
Sacha Epskamp
  • 46,463
  • 20
  • 113
  • 131
  • Changed the function to also include 0 and negative cases. – Sacha Epskamp Dec 03 '11 at 11:46
  • @Sacha Epskamp I have decided to take away my "accept answer" as you didn't explicitly show how to use with \Sexpr{}. Yes you code does work fine in R but I couldn't make it work with \Sexpr{} in Sweave. Thanks. – yCalleecharan Dec 05 '11 at 06:36
  • @Sacha Epskamp. Thanks for your patience. Now I am getting 1.34times10-3 (the power being well represented). How to insert $ $ properly so that the number 1.34 also is between $ and $ and the \times appears as x. Thanks. – yCalleecharan Dec 05 '11 at 10:44
  • Ah I hadn't actually tested it in Sweave and apearently I had to use four backslashes instead of two:) This should work. – Sacha Epskamp Dec 05 '11 at 12:24
  • @Sacha Epskamp Thanks. This is very helpful and it works. If you can consider adding a possibility to specify the number of significant digits as I mention in my post e,g. in your example I can just want to output 1.3 x 10 -3 instead of 1.34 x 10-3. Setting options(digits=1) or similar won't work. – yCalleecharan Dec 05 '11 at 12:43
  • @Sacha Epskamp Great. If you try say $\Sexpr{sn(-2.00134,4)}$, then you get -2.001 x 10^0. The 10^0 is not pretty as it is just 1 but I am accepting your answer as you gave a good answer. – yCalleecharan Dec 05 '11 at 13:06
  • @RomanLuštrik Enclosing in the \[.. \] makes the number to be written on a new line (as expected with LaTeX) – yCalleecharan Dec 05 '11 at 13:08
  • Didn't thought of the exception with order 0, nice find. I will probably add this function to my 'swst' package too. – Sacha Epskamp Dec 05 '11 at 13:14
  • @Sacha Epskam Is "swst" a package that you are developing? – yCalleecharan Dec 06 '11 at 11:56
2

An example using siunitx link to pdf. In the preamble you can define your default options which you may override later in the document.

For numeric output :

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

For scientific output :

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

siunitx example

Here is a full reproducible .Rnw script (to be used with knitr ... for sweave use four antislashes in the functions instead of two see this SO post.)

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

\sisetup{
round-mode = figures,
round-precision = 3,
group-separator = \text{~}
}
\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))
  }
}

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

@
Examples :\\
$num$ for number formatting :

\begin{itemize}
\item \textbf{num(pi, round\_precision=2)} $\Rightarrow$
\num[round-precision=2]{3.14159265358979} 
\item \textbf{num(pi, round\_precision=4)}  $\Rightarrow$
\num[round-precision=4]{3.14159265358979}
\item The default formatting (here round-precision=3) is taken from
\textbf{\textbackslash sisetup} 
\textbf{num(pi)}  $\Rightarrow$ \num{3.14159265358979}\\
\end{itemize}

\noindent $sci$ for scientific notation :

\begin{itemize}
\item \textbf{sci(12.5687e4)}  $\Rightarrow$ \num[scientific-notation =
true]{125687}
\item \textbf{sci(125687.11111)}  $\Rightarrow$
\num[scientific-notation = true]{125687.11111}
\item \textbf{sci(125687.11111, round\_precision=4)} $\Rightarrow$
 \Sexpr{sci(125687.11111, round_precision=4)}
\end{itemize}

\end{document}
Cedric
  • 2,412
  • 17
  • 31