Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knitr hook to separate 000's, but not for years

Tags:

r

knitr

I define a hook at the top of my rnw to separate '000s with commas:

knit_hooks$set(inline = function(x) {
      prettyNum(x, big.mark=",")
    })

However, there are some numbers that I don't want to format like this, such as years. Is there a better way to write the hook, or a way to override the hook when I print \Sexpr{nocomma} in the example below?

\documentclass{article}

\begin{document}

<<setup>>=
  library(knitr)
  options(scipen=999) # turn off scientific notation for numbers
  opts_chunk$set(echo=FALSE, warning=FALSE, message=FALSE)
  knit_hooks$set(inline = function(x) {
      prettyNum(x, big.mark=",")
    })
  wantcomma <- 1234*5
  nocomma <- "September 1, 2014"
@

The hook will separate \Sexpr{wantcomma} and \Sexpr{nocomma}, but I don't want to separate years.

\end{document}

Output:

The hook will separate 6,170 and September 1, 2,014, but I don’t want to separate years.

like image 225
Eric Green Avatar asked Oct 15 '14 12:10

Eric Green


1 Answers

If the only things your don't want comma-separated are strings that have years in, use:

  knit_hooks$set(inline = function(x) {
      if(is.numeric(x)){
          return(prettyNum(x, big.mark=","))
      }else{
          return(x)
       }
   })

That works for your calendar string. But suppose you want to just print a year number on its own? Well, how about using the above hook and converting to character:

What about \Sexpr{2014}?   % gets commad
What about \Sexpr{as.character(2014)}?   % not commad

or possibly (untested):

What about \Sexpr{paste(2014)}?   % not commad

which converts the scalar to character and saves a bit of typing. We're not playing code golf here though...

Alternatively a class-based method:

  comma <- function(x){structure(x,class="comma")}
  nocomma <- function(x){structure(x,class="nocomma")}

  options(scipen=999) # turn off scientific notation for numbers
  opts_chunk$set(echo=FALSE, warning=FALSE, message=FALSE)
  knit_hooks$set(inline = function(x) {
      if(inherits(x,"comma")) return(prettyNum(x, big.mark=","))
      if(inherits(x,"nocomma")) return(x)
      return(x) # default
    })
  wantcomma <- 1234*5
  nocomma1 <- "September 1, 2014"  # note name change here to not clash with function

Then just wrap your Sexpr in either comma or nocomma like:

 The hook will separate \Sexpr{comma(wantcomma)} and \Sexpr{nocomma(nocomma1)}, but I don't want to separate years.

If you want the default to commaify then change the line commented "# default" to use prettyNum. Although I'm thinking I've overcomplicated this and the comma and nocomma functions could just compute the string format themselves and then you wouldn't need a hook at all.

Without knowing exactly your cases I don't think we can write a function that infers the comma-sep scheme - for example it would have to know that "1342 cases in 2013" needs its first number commad and not its second...

like image 97
Spacedman Avatar answered Oct 12 '22 22:10

Spacedman