LucaS
LucaS

Reputation: 1231

Set number of decimal places to show in output

I am wanting to get more into using R markdown to perform analyses and generate output. Maybe I'm missing something simple, but I just want to be able to set the number of decimal places to show either 2 or 3 digits, depending on the output (e.g. t-statistic vs p-value).

I have previously used r options(digits=2), which works until the last digit you want to include is 0. I have gotten around this with the sprintf function, but having to specify for each number.

Is there a way to set a 'global' sprintf option so that for all numbers following, the same number of decimal places are shown?

Thank you,

Paul

Upvotes: 6

Views: 16623

Answers (3)

Zawir Amin
Zawir Amin

Reputation: 129

As found in the tutorial here by Yihui, this is how I've successfully implemented it in my Rmd file.

{r setup, include=FALSE, cache=FALSE}
options(scipen = 1, digits = 2) #set to two decimal 

Upvotes: 1

RLesur
RLesur

Reputation: 5910

Defining a format for inline code output is feasible with a knitr inline hook (hooks are the hidden gems of knitr).

Example #1
With this Rmd file, the number of decimals is controlled without using sprintf() in all inline codes:

---
title: "Use an inline hook"
---
```{r setup, include=FALSE}
# Register an inline hook:
knitr::knit_hooks$set(inline = function(x) {
  x <- sprintf("%1.2f", x)
  paste(x, collapse = ", ")
})
```
Now, get 3.14 with just writing `r pi`.

Example #2
Want to change the inline output format in some part of the report?
This Rmd file does the job:

---
title: "Use a closure and an inline hook"
---
```{r setup, include=FALSE}
# Register an inline hook
knitr::knit_hooks$set(inline = function(x) {
  paste(custom_print(x), collapse = ", ")
})
# Define a function factory (from @eipi10 answer)
op <- function(d = 2) {
  function(x) sprintf(paste0("%1.", d, "f"), x)
}
# Use a closure
custom_print <- op()
```
Now, get 3.14 with `r pi`...
```{r three-decimals, include=FALSE}
custom_print <- op(d = 3)
```
...and now 3.142 with `r pi`.
```{r more-decimals, include=FALSE}
custom_print <- op(d = 10)
```
Finally, get 3.1415926536 with `r pi`.

Example #3
Want to display different formats for t-statistic and p-value?
One can use S3 objects and an inline hook as in this Rmd file:

---
title: "Use S3 methods and an inline hook"
---
```{r setup, include=FALSE}
# Register an inline hook
knitr::knit_hooks$set(inline = function(x) {
  paste(custom_print(x), collapse = ", ")
})
# Define a generic
custom_print <- function(x, ...) {
  UseMethod("custom_print", x)
}
# Define a method for p-values
custom_print.p.value <- function(x, ...) paste(sprintf("%1.2f", x), collapse = ", ")
# Define a method for t-statistics
custom_print.t.stat <- function(x, ...) paste(sprintf("%1.1f", x), collapse = ", ")
```
Estimate models...
```{r fake-results, include=FALSE}
t <- c(2.581, -1.897)
class(t) <- "t.stat"
p <- c(0.025, 0.745)
class(p) <- "p.value"
```
Want to show T-stats: `r t` (get 2.6, -1.9).  
And p-values: `r p` (get 0.03, 0.74).

Who said knitr is a wonderful package?

Upvotes: 8

eipi10
eipi10

Reputation: 93761

I don't know of a way to set a global option (though there may be one). But you can write a convenience output function to reduce the amount of typing. For example, put this function at the beginning of your document:

op = function(x, d=2) sprintf(paste0("%1.",d,"f"), x) 

Then, later in your document, when you want to output numbers, you can, for example, do:

op(mtcars$mpg)

Or if you want 3 digits instead of the default 2, you can do:

op(mtcars$mpg, 3)

Upvotes: 5

Related Questions