Search code examples
rknitrxtable

Fixing rounded R values in xtable in knitr


Has anyone come up with a solution to adjust rounded R values shown in a knitr document, either as stand along \Sexpr{} or through xtable? Typing?round returns Note that for rounding off a 5, the IEC 60559 standard is expected to be used, ‘go to the even digit’.

My problem is the following scenario when showing calculated numbers from a dataframe using xtable. If the values were each shown in a separate column in a table, the reader would assume there is a calculation error:

2.5 + 3.1 = 5.6

would show up as

2 + 3 = 6

when R rounds the numbers (I have set the significant digits to 0 since the audience doesn't need more detail). This situation could potentially happen no matter how many decimal places are shown (and I would like to avoid showing any!).

I use the following for inline expressions, however I rarely insert a number into the paragraph and it usually isn't shown as a calculation. This will show 1 decimal place for numbers less than 10 and greater than -10 and should round up on even numbers ending with 0.5.

number_hook <- function(x) {
  if (is.numeric(x)) {
    if (x < 10 & x > 0 | x < 0 & x > -10) {
      y = prettyNum(x, 
                    small.mark = ".", 
                    digits = 2)
      return(y)

    } else if (sign(x) == 1) {
      y = x + 0.5
      y = trunc(y)
      y = prettyNum(y, big.mark = ",", small.mark = ".", digits = 0)
      return(y)

    } else if (sign(x) == -1) {
      y = x - 0.5
      y = trunc(y)
      y = prettyNum(y, big.mark = ",", small.mark = ".", digits = 0)
      return(y)
    }

  } else {
    x
  }
}

Any help, work-arounds, or suggestions are appreciated! Thank you!

I have also visited this similar question.


Solution

  • My original recommendation did not work correctly. First you should modify your original function.

    number_hook <- function(x) {
      ifelse(abs(x) < 10 & abs(x) > 0, prettyNum(x, small.mark = ",", digits = 2), trunc(x))
    }
    

    This should simplify the number of if statements. Then you can use:

    xtable::xtable(dplyr::mutate_if(iris, is.numeric, number_hook))
    

    To apply the function to every numeric column in your data frame.

    Try it on:

    foo <- data.frame(a = rnorm(10), b = rnorm(10, 10), c = rnorm(10, -10))
    xtable::xtable(dplyr::mutate_if(foo, is.numeric, number_hook))
    

    And you should get values that you need.