6

我有一个正在用 R 分析的大型数据集,并且我对一列或一列信息感兴趣。这个向量中的每个条目都有不同数量的有效数字(范围从 1-5),我想对这个向量进行子集化,所以我看不到只有一个有效数字的数据。我可以使用什么样的测试或函数来让 R 报告每个条目的有效数字的数量?我已经研究了 signif() 函数,但这更多的是用于将数据四舍五入到指定数量的有效数字,而不是查询那里有多少 sig figs。

示例:假设我有这个向量:
4
28.382
120
82.3
100
30.0003

我想删除只有一位有效数字的条目。这将是条目 1(值为 4)和条目 5(值为 100)。我知道如何在 R 中对数据进行子集化,但我不知道如何告诉 R “找到”只有一个有效数字的所有值。

4

2 回答 2

7
x <- c(4, 28.382, 120, 82.3, 100, 30.0003)
#compare the values with result of signif
#you need to consider floating point precision
keep <- abs(signif(x, 1) - x) > .Machine$double.eps
x[keep]
#[1]  28.3820 120.0000  82.3000  30.0003
于 2015-01-04T16:57:34.150 回答
2

我认为这应该等同于 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
于 2017-03-10T15:09:39.900 回答