how to return number of decimal places in R

前端 未结 12 1108
走了就别回头了
走了就别回头了 2020-12-01 08:25

I am working in R. I have a series of coordinates in decimal degrees, and I would like to sort these coordinates by how many decimal places these numbers have (i.e. I will w

相关标签:
12条回答
  • 2020-12-01 08:32

    Another contribution, keeping fully as numeric representations without converting to character:

    countdecimals <- function(x) 
    {
      n <- 0
      while (!isTRUE(all.equal(floor(x),x)) & n <= 1e6) { x <- x*10; n <- n+1 }
      return (n)
    }
    
    0 讨论(0)
  • 2020-12-01 08:33

    Rollowing up on Roman's suggestion:

    num.decimals <- function(x) {
        stopifnot(class(x)=="numeric")
        x <- sub("0+$","",x)
        x <- sub("^.+[.]","",x)
        nchar(x)
    }
    x <- "5.2300000"
    num.decimals(x)
    

    If your data isn't guaranteed to be of the proper form, you should do more checking to ensure other characters aren't sneaking in.

    0 讨论(0)
  • 2020-12-01 08:36

    Not sure why this simple approach was not used above (load the pipe from tidyverse/magrittr).

    count_decimals = function(x) {
      #length zero input
      if (length(x) == 0) return(numeric())
    
      #count decimals
      x_nchr = x %>% abs() %>% as.character() %>% nchar() %>% as.numeric()
      x_int = floor(x) %>% abs() %>% nchar()
      x_nchr = x_nchr - 1 - x_int
      x_nchr[x_nchr < 0] = 0
    
      x_nchr
    }
    
    > #tests
    > c(1, 1.1, 1.12, 1.123, 1.1234, 1.1, 1.10, 1.100, 1.1000) %>% count_decimals()
    [1] 0 1 2 3 4 1 1 1 1
    > c(1.1, 12.1, 123.1, 1234.1, 1234.12, 1234.123, 1234.1234) %>% count_decimals()
    [1] 1 1 1 1 2 3 4
    > seq(0, 1000, by = 100) %>% count_decimals()
     [1] 0 0 0 0 0 0 0 0 0 0 0
    > c(100.1234, -100.1234) %>% count_decimals()
    [1] 4 4
    > c() %>% count_decimals()
    numeric(0)
    

    So R does not seem internally to distinguish between getting 1.000 and 1 initially. So if one has a vector input of various decimal numbers, one can see how many digits it initially had (at least) by taking the max value of the number of decimals.

    Edited: fixed bugs

    0 讨论(0)
  • 2020-12-01 08:37

    Vector solution based on daroczig's function (can also deal with dirty columns containing strings and numerics):

    decimalplaces_vec <- function(x) {
    
      vector <- c()
      for (i in 1:length(x)){
    
        if(!is.na(as.numeric(x[i]))){
    
          if ((as.numeric(x[i]) %% 1) != 0) {
            vector <- c(vector, nchar(strsplit(sub('0+$', '', as.character(x[i])), ".", fixed=TRUE)[[1]][[2]]))
    
    
          }else{
            vector <- c(vector, 0)
          }
        }else{
          vector <- c(vector, NA)
        }
      }
      return(max(vector))
    }
    
    0 讨论(0)
  • 2020-12-01 08:40

    Don't mean to hijack the thread, just posting it here as it might help someone to deal with the task I tried to accomplish with the proposed code.

    Unfortunately, even the updated @daroczig's solution didn't work for me to check if a number has less than 8 decimal digits.

    @daroczig's code:

    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)
        }
    }
    

    In my case produced the following results

    NUMBER / NUMBER OF DECIMAL DIGITS AS PRODUCED BY THE CODE ABOVE
    [1] "0.0000437 7"
    [1] "0.000195 6"
    [1] "0.00025 20"
    [1] "0.000193 6"
    [1] "0.000115 6"
    [1] "0.00012501 8"
    [1] "0.00012701 20"
    

    etc.

    So far was able to accomplish the required tests with the following clumsy code:

    if (abs(x*10^8 - floor(as.numeric(as.character(x*10^8)))) > .Machine$double.eps*10^8) 
       {
       print("The number has more than 8 decimal digits")
       }
    

    PS: I might be missing something in regard to not taking the root of the .Machine$double.eps so please take caution

    0 讨论(0)
  • 2020-12-01 08:44

    In [R] there is no difference between 2.30000 and 2.3, both get rounded to 2.3 so the one is not more precise than the other if that is what you want to check. On the other hand if that is not what you meant: If you really want to do this you can use 1) multiply by 10, 2) use floor() function 3) divide by 10 4) check for equality with the original. (However be aware that comparing floats for equality is bad practice, make sure this is really what you want)

    0 讨论(0)
提交回复
热议问题