在 r 中找到有效数字与小数点后的数字

finding the number of significant digits versus digits after decimal in r

我想在一个具有不同标度的数字向量中找出有效数字的个数。

例如,数字1000有1个数字; 数字100也有1。数字1300有2.

不要将这与小数点后的位数混淆,后者在这两种情况下都等于 0。

我认为这可行。如果你有像 100000 这样的数字,你需要通过设置选项 (scipen = 999) 来阻止 R 使用像 1e5 这样的科学记数法。另外,在这里你 post 你不关心小数点后的数字。在这里我假设你没有带小数点的数字,但如果你有,你可以先做 floor(x)。

x <- c(1000,100,1300, 1234,54334,324,1,1,546,12140465,0,100000,10203,20003,20,102030405060,20)

options(scipen = 999)

sapply(x, function(x) {sum(as.numeric(substring(x, 1: nchar(x), 1:nchar(x))) %in% c(1:9))})

这给出了: [1] 1 1 2 4 5 3 1 1 3 7 0 1 3 2 1 6 1

你可以试试

library(tidyverse)
library(stringr)
a <- c(1000,100,1300, 1234,1,0,12140465,1003.02,1003.20,1003.22,0.00001)
tibble(a) %>% 
  mutate(b=format(a, scientific = FALSE)) %>% 
  separate(b, into = c("b1", "b2"), sep = "[.]", remove = F) %>% 
  mutate(b1 = case_when(str_sub(b1, str_length(b1),str_length(b1)) == "0" ~ str_count(b1, "[1-9]"),
                      TRUE ~ str_count(b1, "[0-9]"))) %>% 
  mutate(b2 = str_count(b2, "[1-9]")) %>% 
  mutate(res=b1+b2)
# A tibble: 11 x 5
         a b                   b1    b2   res
     <dbl> <chr>            <int> <int> <int>
 1 1.00e+3 "    1000.00000"     1     0     1
 2 1.00e+2 "     100.00000"     1     0     1
 3 1.30e+3 "    1300.00000"     2     0     2
 4 1.23e+3 "    1234.00000"     4     0     4
 5 1.00e+0 "       1.00000"     1     0     1
 6 0.      "       0.00000"     0     0     0
 7 1.21e+7 12140465.00000       8     0     8
 8 1.00e+3 "    1003.02000"     4     1     5
 9 1.00e+3 "    1003.20000"     4     1     5
10 1.00e+3 "    1003.22000"     4     2     6
11 1.00e-5 "       0.00001"     0     1     1

我已经稍微调整了 this article 中的功能,使其再次运行。所有学分归文章作者所有。该功能可能会得到改进。

代码:

x <- c(1000,100,1300, 1200.1, 12345.67, 12345.670)
sapply(x, FUN = sigdigs)
[1] 1 1 2 5 7 7

函数:

sigdigs <- function(n) {
  i <- 0
  # Check for decimal point is present
  if(length(grep("\.", as.character(n))) > 0) { # real number
    # Separate integer and fractional parts
    intfrac <- unlist(strsplit(as.character(n), "\."))
    digstring <- paste(intfrac[1], intfrac[2], sep = "")
    numfigs <- nchar(digstring)
    while(i < numfigs) {
      # Find index of 1st non-zero digit from LEFT
      if(substr(digstring,i+1,i+1) == "0") {
        i <- i + 1
        next
      } else {
        sigfigs <- numfigs - i
        break
      }
    }   
  } else {  # must be an integer      
    digstring <- n
    numfigs <- nchar(digstring)
    while(i < numfigs) {
      # Find index of 1st non-zero digit from RIGHT
      if(substr(digstring, numfigs-i, numfigs-i) == "0") {
        i <- i + 1
        next
      } else {
        sigfigs <- numfigs - i
        break
      }
    }   
  }   
  return(sigfigs)
}

此函数会将向量中的每个值转换为字符值,删除所有前导零、尾随零和小数位,并计算剩余的字符数。它的性能似乎与 phiver 的答案相当。

sigfigs <- function(x){
  orig_scipen <- getOption("scipen")
  options(scipen = 999)
  on.exit(options(scipen = orig_scipen))

  x <- as.character(x)
  x <- sub("\.", "", x)
  x <- gsub("(^0+|0+$)", "", x)
  nchar(x)
}

x <- c(1000,100,1300, 1200.1, 12345.67, 12345.670)

sigfigs(x)

注意事项:

此函数returns既不是前导零也不是尾随零的数字的数量。这与有效数字的数量不完全相同。虽然前导零从不重要,但尾随零可能重要也可能不重要——决定它们是否重要需要一些关于测量精度的知识。我建议阅读有关 "Significant Figures" 的维基百科文章以获取更多详细信息。