363

I have a number, for example 1.128347132904321674821 that I would like to show as only two decimal places when output to screen (or written to a file). How does one do that?

x <- 1.128347132904321674821

EDIT:

The use of:

options(digits=2)

Has been suggested as a possible answer. Is there a way to specify this within a script for one-time use? When I add it to my script it doesn't seem to do anything different and I'm not interested in a lot of re-typing to format each number (I'm automating a very large report).

--

Answer: round(x, digits=2)

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
Brandon Bertelsen
  • 43,807
  • 34
  • 160
  • 255
  • 2
    Related question: http://stackoverflow.com/questions/2287616/controlling-digits-in-r-language – Shane Aug 09 '10 at 20:03
  • If one uses options(digits=4), that doesn't limit the calculations to 4 digits, does it? In that case it would make programs far less accurate. It ONLY affects the number when it is printed, correct? – MikeZ Aug 02 '12 at 17:20
  • `controls the number of digits to print when printing numeric values. It is a suggestion only. Valid values are 1...22 with default 7. See the note in print.default about values greater than 15.` from ?options it only effects output. – Brandon Bertelsen Aug 02 '12 at 21:22
  • 2
    Note that `round(23, digits=2)` will print `23` and not `23.00`. If you want the latter, try http://stackoverflow.com/a/12135122/180892 – Jeromy Anglim Dec 07 '12 at 05:02
  • 8
    @PaulHurleyuk, I think it's good practice in programming to use the minimal number of libraries as possible. Someone who uses a different library for each trivial need usually ends up with a mess, big files, portability issues, etc. – Rodrigo Aug 05 '13 at 14:49
  • https://stackoverflow.com/questions/11228403/setting-default-number-of-decimal-places-for-printing – M-- Jun 09 '17 at 22:00

15 Answers15

520

Background: Some answers suggested on this page (e.g., signif, options(digits=...)) do not guarantee that a certain number of decimals are displayed for an arbitrary number. I presume this is a design feature in R whereby good scientific practice involves showing a certain number of digits based on principles of "significant figures". However, in many domains (e.g., APA style, business reports) formatting requirements dictate that a certain number of decimal places are displayed. This is often done for consistency and standardisation purposes rather than being concerned with significant figures.

Solution:

The following code shows exactly two decimal places for the number x.

format(round(x, 2), nsmall = 2)

For example:

format(round(1.20, 2), nsmall = 2)
# [1] "1.20"
format(round(1, 2), nsmall = 2)
# [1] "1.00"
format(round(1.1234, 2), nsmall = 2)
# [1] "1.12"

A more general function is as follows where x is the number and k is the number of decimals to show. trimws removes any leading white space which can be useful if you have a vector of numbers.

specify_decimal <- function(x, k) trimws(format(round(x, k), nsmall=k))

E.g.,

specify_decimal(1234, 5)
# [1] "1234.00000"
specify_decimal(0.1234, 5)
# [1] "0.12340"

Discussion of alternatives:

The formatC answers and sprintf answers work fairly well. But they will show negative zeros in some cases which may be unwanted. I.e.,

formatC(c(-0.001), digits = 2, format = "f")
# [1] "-0.00"
sprintf(-0.001, fmt = '%#.2f')
# [1] "-0.00"

One possible workaround to this is as follows:

formatC(as.numeric(as.character(round(-.001, 2))), digits = 2, format = "f")
# [1] "0.00" 
Jeromy Anglim
  • 33,939
  • 30
  • 115
  • 173
  • 10
    +1 Only answer that worked for me, correctly prints `0.0001` as `0.00` – ThomasH Dec 06 '12 at 17:42
  • 17
    It's always bothered me how functions like `format()` and `prettyNum()` transform numerics into characters. How would you address this? – Waldir Leoncio Mar 06 '15 at 14:19
  • What's with the quotes that appear? – F.Webber May 31 '17 at 16:14
  • @F.Webber the variable becomes type "character" rather "numeric". – Jeromy Anglim May 31 '17 at 23:25
  • What about `format(round(98082706897709.000098754390, 2), nsmall=2)`? – Simon Knapp Sep 11 '17 at 19:11
  • @JeromyAnglim - How to round `8.1999999999999993` to `8.2`? – Chetan Arvind Patil Oct 18 '18 at 21:15
  • 2
    @JeromyAnglim I note that the solution above has a possible edge-case disadvantage of fixing the number of characters in front of the decimal, e.g. `format(c(10, 1), nsmall=1)` yields `"10.0" " 1.0"` (note the leading space in front of the 1.0. Whereas, the `sprintf()` function seems to guarantee nicer formatting on both sides of the decimal, e.g. `sprintf(c(10,1), fmt = '%#.1f')` gets rid of that pesky leading space and returns `"10.0" "1.0"`. – Nicholas G Reich Oct 31 '18 at 15:42
  • any of you guys could help on this one? https://stackoverflow.com/q/53279593/5224236 – gaut Nov 13 '18 at 20:49
  • 4
    The leading spaces are a feature designed to align the decimal point when the result of `format` is used in a column. – Inhabitant May 25 '19 at 15:29
  • format(round(0.9995, 2), nsmall = 2) gives "1.00" however substr(0.9995, 1, 3) gives "0.99" . You could use substr(number, 1, 2+desire decimals) – Frish Vanmol Nov 12 '20 at 02:50
  • This answer is incorrect .It does not always work. Try this: options(digits=22); format(round(1.1111111111111, 2), nsmall = 2) – Feng Jiang Apr 24 '21 at 14:23
  • @FedericoMolinaMagne 0.9995 rounds to 1.00. That is correct rounding behaviour. – Jeromy Anglim Dec 14 '21 at 00:44
  • 1
    @FengJiang This is not an issue with the function. Rather you should perhaps avoid setting the digits option too high. See warning in [print.default help](https://astrostatistics.psu.edu/su07/R/html/base/html/print.default.html). It warns that setting digits >=16 can cause print issues. – Jeromy Anglim Dec 14 '21 at 00:45
  • As of R `base` 4.3.1 (maybe prior), there is no need to use `round` and setting `digits` parameter on `format` is enough. _e.g._: `format(pi, digits = 2, nsmall = 2)` returns `"3.14"`, `format(-0, ...)` returns `"0.00"` or `format(2.199, ...)` returns `"2.20"`. It's important to note that `digits = 0` is *not* allowed, `sprintf("%.0f", )` is the best option for that case. – Adrià Jul 12 '23 at 17:22
53

You can format a number, say x, up to decimal places as you wish. Here x is a number with many decimal places. Suppose we wish to show up to 8 decimal places of this number:

x = 1111111234.6547389758965789345
y = formatC(x, digits = 8, format = "f")
# [1] "1111111234.65473890"

Here format="f" gives floating numbers in the usual decimal places say, xxx.xxx, and digits specifies the number of digits. By contrast, if you wanted to get an integer to display you would use format="d" (much like sprintf).

MichaelChirico
  • 33,841
  • 14
  • 113
  • 198
Sorif Hossain
  • 1,231
  • 1
  • 11
  • 18
  • 2
    While I'm unclear on exactly what the OP was asking, judging by the highest rated answer, I couldn't help but observe that `formatC` is almost exclusively what I use for this purpose. I think this answer is good and is in base R per the OP's request. – AdamO Dec 27 '17 at 20:42
  • This answer works better than the selected answer. formatC is not impacted by options(digits) – Feng Jiang Apr 24 '21 at 14:25
37

You can try my package formattable.

> # devtools::install_github("renkun-ken/formattable")
> library(formattable)
> x <- formattable(1.128347132904321674821, digits = 2, format = "f")
> x
[1] 1.13

The good thing is, x is still a numeric vector and you can do more calculations with the same formatting.

> x + 1
[1] 2.13

Even better, the digits are not lost, you can reformat with more digits any time :)

> formattable(x, digits = 6, format = "f")
[1] 1.128347
Kun Ren
  • 4,715
  • 3
  • 35
  • 50
  • Such a tiny little prick bugging me whole morning. For some reason R would round up the display for some column only. I needed this fix as I had to perform calculations on those columns as well. This works. Thanks ! – thethakuri Oct 07 '16 at 07:24
  • 2
    I like formattable than any baseR functions. The biggest advantage it retains the variable as numeric. – Lazarus Thurston Oct 16 '19 at 14:54
33

for 2 decimal places assuming that you want to keep trailing zeros

sprintf(5.5, fmt = '%#.2f')

which gives

[1] "5.50"

As @mpag mentions below, it seems R can sometimes give unexpected values with this and the round method e.g. sprintf(5.5550, fmt='%#.2f') gives 5.55, not 5.56

Mark Adamson
  • 878
  • 10
  • 17
  • 1
    however, although sprintf rounds, sprintf(5.5550, fmt='%#.2f') gives a slightly unexpected result: 5.55. sprintf(5.555000000001, fmt='%#.2f') gives 5.56. This appears to be a general "issue" with rounding in R, as the round, nsmall method gives the same. – mpag Mar 23 '18 at 18:22
  • Thanks @mpag, I had no idea that R struggled with rounding on boundaries, I've just tried it with 5.565 which does round up, while 5.545 rounds down. I guess it is the way they are handling floating point inprecision. I don't think I've seen this behaviour in other languages which I guess means they have a built-in workaround – Mark Adamson Mar 24 '18 at 21:32
  • I think rather that they're intentionally treating the values as limited in the degree of precision. They are figuring that a value that is 5.555 is really just as likely to have resulted from a "real" value of 5.5546 as 5.5554. However, if you continue that sort of rounding game, 5.444445 might (untested) end up as "6" if you do it one digit at a time. But you might be right that it might be a matter of the binary representation being a bit under or over 5.55. – mpag Mar 25 '18 at 21:06
  • Yeah, I think if it was intentional it would also be consistent between 5.565 and 5.545. The' randomness' suggests to me it's a floating point representation thing. – Mark Adamson Apr 05 '18 at 11:48
12

Something like that :

options(digits=2)

Definition of digits option :

digits: controls the number of digits to print when printing numeric values.
Xavier V.
  • 6,068
  • 6
  • 30
  • 35
  • Is there any way to set this dynamically when running a script? – Brandon Bertelsen Aug 09 '10 at 20:23
  • This works for outputting within the R console, but doesn't work within my script (they still come out with .1289273982) – Brandon Bertelsen Aug 09 '10 at 20:48
  • 2
    I get a weird behavior, the `digits` option doesn't seem to set the number of digits after decimal. E.g., when I set options(digits = 2), then printing 7.25 results in the output of 7.2, 1234.25 becomes 1234, and 0.25 remains 0.25. Is there another option interacting with this? – Maxim.K Sep 22 '14 at 08:20
  • This is something you definitely should NOT do, if you just need one time use. Change options will impact everything. – Feng Jiang Apr 24 '21 at 14:26
12

If you prefer significant digits to fixed digits then, the signif command might be useful:

> signif(1.12345, digits = 3)
[1] 1.12
> signif(12.12345, digits = 3)
[1] 12.1
> signif(12345.12345, digits = 3)
[1] 12300
Andreas
  • 6,447
  • 2
  • 34
  • 46
PaulHurleyuk
  • 8,009
  • 15
  • 54
  • 78
  • 1
    Thanks Paul. These two weren't exactly what I was looking for, but signif led me to round() which is exactly what I needed. Cheers, – Brandon Bertelsen Aug 09 '10 at 21:17
  • 34
    `Error: could not find function "fixed"` – ThomasH Dec 06 '12 at 17:40
  • 1
    `signif` works for the specific number provided, but I presume the common applied problem is when you need to show exactly two decimal places but you don't know what the number is ahead of time. In that case, `signif` will give different numbers of decimals depending on the actual number. – Jeromy Anglim Dec 07 '12 at 04:57
  • 3
    fixed is not found anywhere. Please fix it, otherwise this misleading answer should be deleted. – ABCD Apr 24 '16 at 12:33
  • @JeromyAnglim how do we fix that when we want 3sf? sometimes it gives me 3sf, other times 4sf, etc. how do we fix this? – christouandr7 Mar 28 '20 at 12:06
10

Check functions prettyNum, format

to have trialling zeros (123.1240 for example) use sprintf(x, fmt='%#.4g')

ilya
  • 3,124
  • 2
  • 26
  • 26
6

The function formatC() can be used to format a number to two decimal places. Two decimal places are given by this function even when the resulting values include trailing zeros.

Chernoff
  • 2,494
  • 2
  • 20
  • 24
4

I'm using this variant for force print K decimal places:

# format numeric value to K decimal places
formatDecimal <- function(x, k) format(round(x, k), trim=T, nsmall=k)
Eldar Agalarov
  • 4,849
  • 4
  • 30
  • 38
3

Note that numeric objects in R are stored with double precision, which gives you (roughly) 16 decimal digits of precision - the rest will be noise. I grant that the number shown above is probably just for an example, but it is 22 digits long.

nullglob
  • 6,903
  • 1
  • 29
  • 31
2

Looks to me like to would be something like

library(tutoR)
format(1.128347132904321674821, 2)

Per a little online help.

Jeromy Anglim
  • 33,939
  • 30
  • 115
  • 173
Tim Meers
  • 928
  • 1
  • 14
  • 24
  • I found this, but it requires a package, I'm looking for something within the base package. – Brandon Bertelsen Aug 09 '10 at 20:19
  • 2
    @brandon, format() is part of base. Open up R and type ?format ... no packages needed. – JD Long Aug 09 '10 at 20:38
  • Hrmmm, did you look at what this outputs? [1] "1.128347" otherwise, you're quite right about it being in the base package, my bad. – Brandon Bertelsen Aug 10 '10 at 01:24
  • 1
    Perhaps try `format.default(x, digits = 2)` just a shot in the dark though based on the link provided. That info is some what lacking from what I normally read for documentation, I expected to see the printed outputs as well. – Tim Meers Aug 10 '10 at 14:08
  • Just noticed that your link points to tutoR documentation, which is not part of the base. – Brandon Bertelsen Aug 10 '10 at 17:09
  • It's just amazing how many times "format" turns out to be the right answer. It has a large number of methods, as I suspect you know, but others should try `methods(format)`. – IRTFM Aug 27 '12 at 01:10
  • `format(0.0002, 2)` will output `0` instead of `0.00`, which I assume is the intended. – ThomasH Dec 06 '12 at 17:41
2

if you just want to round a number or a list, simply use

round(data, 2)

Then, data will be round to 2 decimal place.

jared
  • 522
  • 4
  • 11
2
library(dplyr)
# round the numbers
df <- df %>%
  mutate(across(where(is.numeric), .fns = function(x) {format(round(x, 2), nsmall = 2)}))

Here I am changing all numeric values to have only 2 decimal places. If you need to change it to more decimal places

# round the numbers for k decimal places
df <- df %>%
  mutate(across(where(is.numeric), .fns = function(x) {format(round(x, k), nsmall = k)}))

Replace the k with the desired number of decimal places

1

I wrote this function that could be improve but looks like works well in corner cases. For example, in the case of 0.9995 the vote correct answer gives us 1.00 which is incorrect. I use that solution in the case that the number has no decimals.

round_correct <- function(x, digits, chars = TRUE) {
  if(grepl(x = x, pattern = "\\.")) {
    y <- as.character(x)
    pos <- grep(unlist(strsplit(x = y, split = "")), pattern = "\\.", value = FALSE)
    if(chars) {
      return(substr(x = x, start = 1, stop = pos + digits))
    }
    return(
      as.numeric(substr(x = x, start = 1, stop = pos + digits))
    )
  } else {
    return(
      format(round(x, 2), nsmall = 2)
    )
  }
}

Example:

round_correct(10.59648, digits = 2)
[1] "10.59"
round_correct(0.9995, digits = 2)
[1] "0.99"
round_correct(10, digits = 2)
[1] "10.00"
Frish Vanmol
  • 314
  • 2
  • 6
0

here's my approach from units to millions. digits parameter let me adjust the minimum number of significant values (integer + decimals). You could adjust decimal rounding inside first.

number <-function(number){
  result <- if_else(
    abs(number) < 1000000,
    format(
      number, digits = 3,
      big.mark = ".",
      decimal.mark = ","
    ),
    paste0(
      format(
        number/1000000,
        digits = 3,
        drop0trailing = TRUE,
        big.mark = ".",
        decimal.mark = ","
      ),
      "MM"
    )
  )
  # result <- paste0("$", result)
  return(result)
}
Captain Tyler
  • 500
  • 7
  • 19