captcoma
captcoma

Reputation: 1898

Round depending on number of decimal places

What I would like to to

I would like to round all numeric values of a large data set depending on their actual decimal place.

E.g. for the df below, I would like to round all numbers, numbers with one decimal place to a full number and numbers with two decimal places to one decimal place.

Update In the original post, I used iris as data set. Since iris does only have 1 decimal place, I added a new data set:

   df <- tibble(one=round(runif(100,0,10), 1),
                 two=round(runif(100,0,10), 2),
                 characters=rep("thanks",100))

Upvotes: 1

Views: 388

Answers (2)

Chris Ruehlemann
Chris Ruehlemann

Reputation: 21400

DATA:

 v1 <- c(1.1, 1.2, 2.91, 5.9)

SOLUTION for vector:

Key here is the identification of numbers with 2 decimals via regular expression using grepl; to make the regex work, the data need to be converted to character using as.character. Then you can simply set up an ifelse clause determining that if the condition evaluates to TRUE, round to 1 decimal, else round to 0 decimals:

ifelse(grepl(".\\d{2}$", as.character(v1)), round(v1,1), round(v1,0))

RESULT:

[1] 1.0 1.0 2.9 6.0

SOLUTION for dataframe:

The same principle can be applied to transforming several vectors in a dataframe in one go:

dt <- data.frame(
  v1 = c(1.11, 2.2, 3.9, 5.55),
  v2 = c(6.99, 7.07, 8.5, 9.01))

The above sketched out solution just needs to be made part of a function inside an apply statement:

apply(dt, 2, function(x) ifelse(grepl(".\\d{2}$", as.character(x)), round(x,1), round(x,0)))
      v1  v2
[1,] 1.1 7.0
[2,] 2.0 7.1
[3,] 4.0 8.0
[4,] 5.5 9.0

Upvotes: 1

Sotos
Sotos

Reputation: 51592

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

Upvotes: 5

Related Questions