我想在具有非常不同比例的数字向量中找到有效数字的数量。
例如,数字 1000 有 1 位数字;数字 100 也有 1。数字 1300 有 2。
不要将此与小数点后的位数混淆,在这两种情况下都等于 0。
此函数会将向量中的每个值转换为字符值,删除所有前导零、尾随零和小数位,并计算剩余的字符数。它的性能似乎与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)
注意事项:
此函数返回既不是前导零也不是尾随零的位数。 这与有效位数不完全相同。虽然前导零从不重要,但尾随零可能重要,也可能不重要 - 确定它们是否重要需要一些关于测量精度的知识。 我建议阅读维基百科关于"重要数字"的文章以获取更多详细信息。
我认为这可以工作。如果你有像 100000 这样的数字,你需要通过设置选项(scipen = 999(来防止 R 使用像 1e5 这样的科学记数法。另外,在这里你发布你不关心小数点后的数字。在这里,我假设你没有带小数点的数字,但如果你有,你可以先做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
我稍微调整了本文中的函数以使其再次工作。所有功劳归文章作者所有。该功能可能可以改进。
法典:
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)
}
你可以试试
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