Rounding numbers in R to specified number of digits
For fine control over formatting of numbers, try formatC()
res <- structure(c(9.50863385275955e-05, 4.05702267762077e-06),
.Names = c("CC/CC", "TT/CC"))
formatC(res, format="f", digits=8)
`round()` to many digits in R
Actually, round
IS working correctly:
a <- round(x = 234234.3456789, digits = 7)
paste(a)
[1] "234234.3456789"
In your example, print.default
, which is what happens when you ask R to print
something is cutting the number of digits.
print.default(a, digits = 15)
[1] 234234.3456789
You can control the behavoiour via options
options(digits = 15)
round(pi, digits = 15)
[1] 3.14159265358979
Different rounding rule based on number of digits before the decimal
It is not clear whether the question is about pretty printing (result is character) or rounding (result is numeric).
If the question is about conversion to character for pretty printing, the sprintf()
function can be used.
The sprintf()
function understands the conversion specifier g
where the number of significant digits can be specified. However, it does not cover the whole range of values. Therefore, different conversion specifiers have to be used depending on the size of y
:
y <- c(0.0111, 0.111, 1.11, 11.1, 111.1, 1111, 11111)
sprintf(c("%3.2f", "%3.3g", "%3.0f")[cut(y, c(0, 1, 1000, Inf))], y)
[1] "0.01" "0.11" "1.11" "11.1" "111" "1111" "11111"
If the question is about rounding numeric values:
round(y, c(2, 1, 0)[cut(y, c(0, 10, 100, Inf))])
[1] 0.01 0.11 1.11 11.10 111.00 1111.00 11111.00
Explanation
c("%3.2f", "%3.3g", "%3.0f")[cut(y, c(0, 1, 1000, Inf))]
is a replacement for nested ifelse()
in order to pick the right conversion specifier for each y
:
[1] "%3.2f" "%3.2f" "%3.3g" "%3.3g" "%3.3g" "%3.0f" "%3.0f"
cut()
converts from numeric to factor. It divides the range of y
into intervals and codes the values in y
according to which interval they fall. The leftmost interval corresponds to level one, the next leftmost to level two and so on. (from help("cut")
).
Then, the level number is used to subset the vector of conversion specifiers to pick the appropriate specifier according to the value of y
.
While writing the explanation, there is a slightly different approach. Instead of using the level numbers to subset the vector of conversion specifiers, we can use the labels of the levels directly:
sprintf(as.character(cut(y, c(0, 1, 1000, Inf), labels = c("%3.2f", "%3.3g", "%3.0f"))), y)
[1] "0.01" "0.11" "1.11" "11.1" "111" "1111" "11111"
How to round to specific decimal numbers in R
In R there are two usefull operator for this %%
and %/%
which can be used to get the integer part and the decimal part of a divition. If you have this, and you divide by 1 yo can do it easy.
set.seed(123)
x <- rnorm(10, mean = 300)
ifelse(x %% 1 > 0.5,
x %/%1 + 0.75,
x %/%1 + 0.25)
the vector went from this
[1] 299.4395 299.7698 301.5587 300.0705 300.1293 301.7151 300.4609 298.7349 299.3131 299.5543
to this
[1] 299.25 299.75 301.75 300.25 300.25 301.75 300.25 298.75 299.25 299.75
Formatting Decimal places in R
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"
Always round down to specified number of significant digits in R
Here's a custom function to do it
down_signif <- function(x, digits = 0) {
m <- 10^(ceiling(log(x, 10)) - digits)
(x %/% m)*m
}
down_signif(3599, digits = 2)
#> [1] 3500
down_signif(7890349, digits = 2)
#> [1] 7800000
Round depending on number of decimal places
You can just count the digits after the dot and round to that value-1, i.e.
x <- c(4.5, 2.12, 3, 5.245)
i1 <- nchar(sub('.*\\.', '', x))
round(x, (i1-1))
#[1] 4.00 2.10 3.00 5.25
Related Topics
How to Determine If Date Is a Weekend or Not (Not Using Lubridate)
Deploying R Shiny App as a Standalone Application
Lme4::Lmer Reports "Fixed-Effect Model Matrix Is Rank Deficient", Do I Need a Fix and How To
Multiple Ggplots of Different Sizes
Align Multiple Plots in Ggplot2 When Some Have Legends and Others Don'T
Choropleth Map in Ggplot with Polygons That Have Holes
Exporting Non-S3-Methods with Dots in the Name Using Roxygen2 V4
Extreme Numerical Values in Floating-Point Precision in R
Subset Xts Object by Time of Day
Reading Multiple Files into Multiple Data Frames
How to Separate Comma Separated Values in R in a New Row
Get Column Index from Label in a Data Frame
How to Change Xts to Data.Frame and Keep Index
Superscript and Subscript Axis Labels in Ggplot2
How to Programmatically Extract/Unzip a .7Z (7-Zip) File with R
Dt: Dynamically Change Column Values Based on Selectinput from Another Column in R Shiny App