sapply()定义的小数向量作为参数,seq()作为参数给出不同的结果

时间:2018-03-23 05:20:22

标签: r sapply seq

我正在尝试获取数据帧中列中某个阈值超过某个阈值的值,其中十进制值范围为0到1.为此,我使用sapply迭代阈值列表。当我提供一个定义的阈值向量时,sapply工作正常但是当我使用seq()来定义阈值时,我得到奇怪的结果(重复)并且结果不匹配。这只发生在小数而不是整数。

t <- data.frame(replicate(10,sample((0:10)/10,1000,rep=TRUE)))

l <- c()
l <- sapply(c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9), function(x){
    nrow(t[t[,"X1"]>=x,]);
});

l2 <- c()
l2 <- sapply(seq(0, 0.9, 0.1), function(x){
    nrow(t[t[,"X1"]>=x,]);
});

print(l)
print(l2)

输出:

> print(l)
 [1] 1000  909  811  723  626  530  443  365  275  187
> print(l2)
 [1] 1000  909  811  626  626  530  365  275  275  187

当使用整数和整数阈值执行相同的代码时,l和l2完全匹配。

整数代码:

t <- data.frame(replicate(10,sample(0:10,1000,rep=TRUE)))

l <- c()
l <- sapply(c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), function(x){
    nrow(t[t[,"X1"]>=x,]);
});

l2 <- c()
l2 <- sapply(seq(0, 9, 1), function(x){
    nrow(t[t[,"X1"]>=x,]);
});

print(l)
print(l2)

输出:

> print(l)
 [1] 1000  915  816  729  643  555  468  367  270  188
> print(l2)
 [1] 1000  915  816  729  643  555  468  367  270  188

我不确定我是否遗漏了一些非常基本或错误的东西。

谢谢。

2 个答案:

答案 0 :(得分:2)

这是因为seq()并不能准确生成您期望的十进制值:

> seq(0, 0.9, 0.1)[4] == 0.3
[1] FALSE

使用all.equal从精确小数中计算微小偏差(浮点错误)可以恢复“相等”

> all.equal(seq(0, 0.9, 0.1)[4], 0.3)
[1] TRUE

整数版本不会受到相同的浮点错误的影响,因此您会看到两种方法的一致行为。

这是R FAQ 7.31

的一个实例

答案 1 :(得分:1)

解决此问题:

grt_or_near <- function (x, y, tol = .Machine$double.eps^0.5) 
{
  (x > y) | (abs(x - y) < tol)
}

t <- data.frame(replicate(10,sample((0:10)/10,1000,rep=TRUE)))
l <- sapply(c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9), function(x){
  nrow(t[grt_or_near(t[,"X1"],x),])
})


l2 <- sapply(seq(0, 0.9, 0.1), function(x){
  nrow(t[grt_or_near(t[,"X1"],x),])
})
l
# [1] 1000  924  830  759  664  570  480  374  290  186
l2
# [1] 1000  924  830  759  664  570  480  374  290  186