我希望你能帮助我找到解决方案,因为我的结果真的很意外......
我使用函数expand.grid()
从所提供的矢量的所有组合创建数据帧。
vector1=seq(from=0.8,to=1.6,by=0.2)
vector2=c(seq(from=0.8,to=1.8,by=0.2),2.6)
vector3=seq(from=0.6,to=1.2,by=0.2)
data=expand.grid(F1= vector1,F2= vector2,F3= vector3)
data
F1 F2 F3
1 0.8 0.8 0.6
2 1.0 0.8 0.6
3 1.2 0.8 0.6
4 1.4 0.8 0.6
5 1.6 1.0 0.6
6 0.8 1.0 0.6
7 1.0 1.0 0.6
… … … …
现在我想通过逻辑比较删除一些行。
data_remove=which(data[,1]-data[,2]>0.2)
data_remove
[1] 3 4 5 8 … 110 113 114 115 120
让我们看一下第113行,因为这是错误的 - 也可能是data_remove
中的其他一些条目。
data
F1 F2 F3
… … … …
113 1.2 1.0 1.2
… … … …
data[113,1]- data[113,2]
[1] 0.2
(data[113,1]- data[113,2])>0.2
[1] TRUE
这个结果让我感到困惑,因为
0.2>0.2
[1] FALSE
和
mode(data[113,1])
[1] “numeric”
mode(data[113,2])
[1] “numeric”
你能解释一下我的错误吗?
非常感谢提前!
答案 0 :(得分:1)
正如RHertel在他的评论中提到的,这与浮点算术有关,你可以在this question的答案中阅读更多关于它的信息。你会在那里找到你需要的一切,我不会进一步讨论,因为我没有什么有意义的补充。
您的具体示例可以通过使用整数来解决,并且只能转换为您最终想要的数字。此方法也有其局限性,我最终会回过头来。
所以,我基本上从定义三个向量和网格开始如下:
vector1 <- seq(from = 8, to = 16, by = 2)
vector2 <- c(seq(from = 8, to = 18, by = 2), 26)
vector3 <- seq(from = 6, to = 12, by = 2)
data <- expand.grid(F1 = vector1, F2 = vector2, F3 = vector3)
通过这种方式,我得到的数值比你定义的数值大10倍。但是最后只需要除以10就可以很容易地纠正。优点是对于整数,比较按预期工作:
data_remove = which(data[,1] - data[,2] > 2)
head(data[data_remove, ])
## F1 F2 F3
## 3 12 8 6
## 4 14 8 6
## 5 16 8 6
## 9 14 10 6
## 10 16 10 6
## 15 16 12 6
您可以看到在所有情况下都满足条件。特别是,此次不会删除您在问题中提到的第113行。要获得您真正想要的数据,您只需要除以10:
data_new <- data[-data_remove, ]/10
head(data_new)
## F1 F2 F3
## 1 0.8 0.8 0.6
## 2 1.0 0.8 0.6
## 6 0.8 1.0 0.6
## 7 1.0 1.0 0.6
## 8 1.2 1.0 0.6
我答应回到这种方法的局限性。从数学的角度来看,它总是有效的,只要你只使用有理数。例如,
seq(1/3, 5, by = 1/4)
可以用整数重写
seq(4, 60, by = 3)/12
因子12的出现是因为12是3和4的least common multiple。然而,由于其中的无理数,这个序列不能用整数重写:
seq(sqrt(2), 7*sqrt(3), by = pi/5)
没有因素q
,q * sqrt(2)
和q * pi/5
都是整数。但你仍然可以通过舍入数字来解决问题。在逗号后面舍入到两位数,以整数表示的序列是
seq(141, 1212, by = 63)/100
非常大的数字可能会出现另一个限制。如果您有许多相关数字,因此需要将序列乘以非常大的数字,则比较将再次失败:
(1e18 + 1) > 1e18
## [1] FALSE
答案 1 :(得分:0)
除了Stibus详细解答(非常感谢)......
我的回答是由于RHertel的暗示 - 两种解决方案。
让我们看一下vector data_remove并指定错误的条目(8,43,78,113)。
data_remove
[1] 3 4 5 8 9 10 15 38 39 40 43 44 45 50 73 74 75 78 79 80 85 108 109 110 113 114 115 120
length(data_remove)
[1] 28
我的第一个解决方案是使用round
- 函数。在这里你必须定义digits-argument。
data_remove1=which(round(data[,1]-data[,2],4)>0.2)
data_remove1
[1] 3 4 5 9 10 15 38 39 40 44 45 50 73 74 75 79 80 85 108 109 110 114 115 120
length(data_remove1)
[1] 24
当您将digits-argument增加到16或更高时,向量中会再次出现四个错误的条目。
data_remove1=which(round(data[,1]-data[,2],16)>0.2)
data_remove1
[1] 3 4 5 8 9 10 15 38 39 40 43 44 45 50 73 74 75 78 79 80 85 108 109 110 113 114 115 120
length(data_remove1)
[1] 28
data_remove1=which(round(data[,1]-data[,2],22)>0.2)
data_remove1
[1] 3 4 5 8 9 10 15 38 39 40 43 44 45 50 73 74 75 78 79 80 85 108 109 110 113 114 115 120
length(data_remove1)
[1] 28
我的第二个解决方案使用函数all.equal
的矢量化。在这里,也可以根据需要改变容差。
data_critical是一个带条目的向量,其中数据[,1]和数据[,2]的减法几乎精确为0.2。
elementwise.all.equal=Vectorize(function(x,y,z) {isTRUE(all.equal(x,y,z))})
data_critical=which(elementwise.all.equal(data[,1]-data[,2],rep(0.2,length.out=length(data[,1])),1e-15)==TRUE)
data_critical
[1] 2 8 14 20 37 43 49 55 72 78 84 90 107 113 119 125
data_remove_correct=match(data_critical,data_remove)
data_remove_correct
[1] NA 4 NA NA NA 11 NA NA NA 18 NA NA NA 25 NA NA
data_remove_correct=data_remove_correct[!is.na(data_remove_correct)]
data_remove_correct
[1] 4 11 18 25
data_remove_perfect=data_remove[-data_remove_correct]
data_remove_perfect
[1] 3 4 5 9 10 15 38 39 40 44 45 50 73 74 75 79 80 85 108 109 110 114 115 120
length(data_remove_perfect)
[1] 24
为什么不在data_remove中表示所有data_critical?观察减法的结果 - 只有正数结果出现在向量data_remove中。
data[2,1]-data[2,2]-0.2
[1] -5.551115e-17
data[8,1]-data[8,2]-0.2
[1] 1.665335e-16