如何检查数字和字符串转换为数字之间的相等性(向量化)

时间:2015-09-23 17:50:34

标签: r vectorization precision outliers

我想查找grubbs.test包的outliers函数发现的异常值的索引(我从另一个SO回复here改编了它)

where = function(x) which(x==as.numeric(strsplit(grubbs.test(x)$alternative," ")[[1]][3]))

它的工作原理是检索grubbs结果显示的文本中的数字。这是一种黑客攻击,但它可以很好地用于数字:

df=c(0, 3, rnorm(10))
where(df) #[1] 2

当达到十进制数字时,文本与实际数字的数字不匹配:

df=c(0, sqrt(10), rnorm(10))
where(df) # integer(0)

有人有想法解决这个问题吗?或者另一种方法来查找grubbs测试最大异常值的索引?我试图在循环中使用它。

1 个答案:

答案 0 :(得分:1)

问题是因为strsplit返回stings而不是数字。在你的第二个例子中,我得到了:

[1] "highest"          "value"            "3.16227766016838" "is"               "an"               "outlier"   

但第三个元素实际上不是数字3.16227766016838的字符版本。实际上,从grubbs.test返回的实数可能会有更多的小数位,这就是为什么==运算符不会“捕获”它作为相等的原因。这可以在这里清楚地看到:

a<-sqrt(10)
> a == as.numeric(as.character(a))
[1] FALSE

有解决方法吗?

有。

为了解决这个问题,只需使用almost.equal函数,我就可以从this R-help帖子中复制:

almost.equal <- function (x, y, tolerance=.Machine$double.eps^0.5,
                          na.value=TRUE)
{
  answer <- rep(na.value, length(x))
  test <- !is.na(x)
  answer[test] <- abs(x[test] - y) < tolerance
  answer
}

上述函数是all.equal函数的矢量化形式,它检查“近似”的相等性,以便捕获像你这样的案例。

让我们将您的功能转换为:

where = function(x) {
  which(almost.equal(x, as.numeric(strsplit(grubbs.test(x)$alternative," ")[[1]][3])))
}

让我们现在检查一下:

> df=c(0, 3, rnorm(10))
> where(df)
[1] 2

> df=c(0, sqrt(10), rnorm(10))
> where(df)
[1] 2

你有一个适用于十进制数的解决方案!!