How to Return Number of Decimal Places in R

how to return number of decimal places in R

You could write a small function for the task with ease, e.g.:

decimalplaces <- function(x) {
if ((x %% 1) != 0) {
nchar(strsplit(sub('0+$', '', as.character(x)), ".", fixed=TRUE)[[1]][[2]])
} else {
return(0)
}
}

And run:

> decimalplaces(23.43234525)
[1] 8
> decimalplaces(334.3410000000000000)
[1] 3
> decimalplaces(2.000)
[1] 0

Update (Apr 3, 2018) to address @owen88's report on error due to rounding double precision floating point numbers -- replacing the x %% 1 check:

decimalplaces <- function(x) {
if (abs(x - round(x)) > .Machine$double.eps^0.5) {
nchar(strsplit(sub('0+$', '', as.character(x)), ".", fixed = TRUE)[[1]][[2]])
} else {
return(0)
}
}

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"

How to count the number of decimal places in dplyr for multiple variables

dpylr solution, untested due to lack of MRE:

library(dplyr)
library(tidyr)

data %>%
pivot_longer(starts_with("value"), names_to = "variable", values_to = "value") %>%
mutate(N_digits = nchar(gsub(".*\\.", "", as.character(value)))) %>%
group_by(variable) %>%
summarise(max_N_digits = max(N_digits)) %>%
pivot_wider(names_from = variable, values_from = max_N_digits)

Edit

This should also work for numbers without decimal point (i.e. give 0):

data1 <- data.frame(value1 = c(1.11, 1.121,1.1212),
value2 = c(6666, 5,5),
value3 = c(1.1111, 1.121,1.12111))
library(dplyr)
library(tidyr)
data1 %>%
pivot_longer(starts_with("value"), names_to = "variable", values_to = "value") %>%
mutate(N_digits = nchar(gsub(".*\\.|^[^.]+$", "", as.character(value)))) %>%
group_by(variable) %>%
summarise(max_N_digits = max(N_digits)) %>%
pivot_wider(names_from = variable, values_from = max_N_digits)

Returns:

  value1 value2 value3
<int> <int> <int>
1 4 0 5

Extracting the complete decimal part of the number in R

There are multiple ways to solve and extract the decimal part some are:
lets store the result in dec

  1. dec <- my_num - floor(my_num)
  2. dec <- my_num%%1
  3. dec <- my_num - as.integer(my_num)
  4. dec <- my_num - trunc(my_num)

all these will result the same.

Force R to always round up to two decimal places

If your numbers are in a numeric vector :

format(round(a,digits=2),nsmall=2)

which gives a character vector. The format function is there so that 1 is displayed as 1.00 and not 1 for example. If you don't care about that, omit it.


If you want 2.3421 to be rounded to 2.35 (not standard rounding but ceiling at 2 decimals), use

format(ceiling(a*100)/100,nsmall=2)

or more legible with pipes:

a %>% multiply_by(100) %>% ceiling %>% divide_by(100) %>% format(2)

Without format: ceiling(a*100)/100 which gives you a numeric.

Controlling number of decimal digits in print output in R

The reason it is only a suggestion is that you could quite easily write a print function that ignored the options value. The built-in printing and formatting functions do use the options value as a default.

As to the second question, since R uses finite precision arithmetic, your answers aren't accurate beyond 15 or 16 decimal places, so in general, more aren't required. The gmp and rcdd packages deal with multiple precision arithmetic (via an interace to the gmp library), but this is mostly related to big integers rather than more decimal places for your doubles.

Mathematica or Maple will allow you to give as many decimal places as your heart desires.

EDIT:

It might be useful to think about the difference between decimal places and significant figures. If you are doing statistical tests that rely on differences beyond the 15th significant figure, then your analysis is almost certainly junk.

On the other hand, if you are just dealing with very small numbers, that is less of a problem, since R can handle number as small as .Machine$double.xmin (usually 2e-308).

Compare these two analyses.

x1 <- rnorm(50, 1, 1e-15)
y1 <- rnorm(50, 1 + 1e-15, 1e-15)
t.test(x1, y1) #Should throw an error

x2 <- rnorm(50, 0, 1e-15)
y2 <- rnorm(50, 1e-15, 1e-15)
t.test(x2, y2) #ok

In the first case, differences between numbers only occur after many significant figures, so the data are "nearly constant". In the second case, Although the size of the differences between numbers are the same, compared to the magnitude of the numbers themselves they are large.


As mentioned by e3bo, you can use multiple-precision floating point numbers using the Rmpfr package.

mpfr("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825")

These are slower and more memory intensive to use than regular (double precision) numeric vectors, but can be useful if you have a poorly conditioned problem or unstable algorithm.

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

Adjust number of decimal places in a dataset


Test %>%
mutate(sum = rowSums(across(3:last_col()), na.rm = TRUE),
across(where(is.numeric), ~sprintf("US $%.2f", .x)))

date2 Category coef1 coef2 sum
1 2021-06-30 FDE US $445.23 US $8.32 US $453.56
2 2021-06-30 ABC US $1.31 US $3.34 US $4.66
3 2021-07-01 FDE US $6.32 US $1.32 US $7.65
4 2021-07-02 ABC US $1.23 US $6.32 US $7.56

Limit decimal places in variable in R

You can use round() option or digit.
The following code shows exactly two decimal places for the number using round()

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"

You can format a number, say x, up to decimal places as your wish. Here x is a number with big decimal places , you can format decimal places as your wish. Such that we wish to take up to 8 decimal places of this number.

x<-c(1111111234.6547389758965789345) 
y<-formatC(x,digits=8,format="f")

[1] "1111111234.65473890"


Related Topics



Leave a reply



Submit