使用expand.grid()生成的数据框中的逻辑比较

时间:2017-01-26 08:25:08

标签: r logical-operators

我希望你能帮助我找到解决方案,因为我的结果真的很意外......

我使用函数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”

你能解释一下我的错误吗?

非常感谢提前!

2 个答案:

答案 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)

没有因素qq * 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