我认为这应该等同于 Rolands 解决方案。
x <- c(4, 4.0, 4.00, 28.382, 120,
82.3, 100, 100.0, 30.0003)
x
ifelse(x == signif(x, 1), NA, x)
ifelse(x == signif(x, 2), NA, x)
ifelse(x == signif(x, 3), NA, x)
无论如何,对于像“4.00”和“100.0”这样的情况,给出不正确的有效数字位数至少有同样的问题。
如上所述,解决方案部分是将数字视为字符串。仅仅将数字转换为字符是不够的,它们必须照此读取,这需要一点小心。colClasses
函数read.table
组中的参数可以派上用场。
xc <- c("4", "4.0", "4.00", "28.382", "120",
"82.3", "100", "100.0", "30.0003")
xc
# "4" "4.0" "4.00" "28.382" "120" "82.3" "100" "100.0" "30.0003"
ifelse(xc == signif(as.numeric(xc), 1), NA, xc)
# "NA" "4.0" "4.00" "28.382" "120" "82.3" "NA" "100.0" "30.0003"
仅删除“4”和“100”。这看起来很有希望,但如果我们走得更远,我们会发现并非一切都像它应该的那样。
ifelse(xc == signif(as.numeric(xc), 2), NA, xc)
# "NA" "4.0" "4.00" "28.382" "120" "82.3" "NA" "100.0" "30.0003"
ifelse(xc == signif(as.numeric(xc), 3), NA, xc)
# "NA" "4.0" "4.00" "28.382" "120" "82.3" "NA" "100.0" "30.0003"
原因可以这样证明
2 == "2"
# TRUE – only what's between the quotes is compared
2.0 == "2"; 02 == "2"
# TRUE
# TRUE – R removes what's considered numerically empty characters
2 == "2.0"
# FALSE – strings aren't modified.
2 == as.numeric("2.0")
# TRUE – that is, unless you explicitly request it.
还值得记住的是,字符串的比较是基于字母数字顺序的,即使字符串很容易被解释为数字。
2 < "2.0"
# TRUE
2 > "2.0"
# FALSE
"2.0" < "2.00"
# TRUE
sort(xc)
# "100" "100.0" "120" "28.382" "30.0003" "4" "4.0" "4.00" "82.3"
到目前为止,我为这个问题找到的唯一完整的解决方法是有点 hacky。它包括分离出包含小数点分隔符(“.”)的字符串,并将这些字符串的最后一个字符替换为“1”(或任何非零数字)。从而将“4.0”变成“4.1”,但保持“100”不变。然后将这个新向量用作比较的基础。
xc.1 <- xc
decimal <- grep(".", xc, fixed=TRUE)
xc.1[decimal] <- gsub(".$", "1", xc[decimal])
xc.1 <- as.numeric(xc.1)
xc
# "4" "4.0" "4.00" "28.382" "120" "82.3" "100" "100.0" "30.0003"
ifelse(xc.1 == signif(xc.1, 1), NA, xc)
# "NA" "4.0" "4.00" "28.382" "120" "82.3" "NA" "100.0" "30.0003"
ifelse(xc.1 == signif(xc.1, 2), NA, xc)
# "NA" "NA" "4.00" "28.382" "NA" "82.3" "NA" "100.0" "30.0003"
ifelse(xc.1 == signif(xc.1, 3), NA, xc)
# "NA" "NA" "NA" "28.382" "NA" "NA" "NA" "100.0" "30.0003"
如果您想实际计算有效数字的数量,可以通过一个小循环来完成。
n <- 7
# true counts
xc.count <- vector(length=length(xc.1))
for (i in n:1) xc.count[xc.1 == signif(xc.1, i)] <- i
xc.count
# 1 2 3 5 2 3 1 4 6
# simple counts
x.count <- vector(length=length(x))
for (i in n:1) x.count[x == signif(x, i)] <- i
x.count
# 1 1 1 5 2 3 1 1 6