R语言 按行值但使用容差过滤数据框

mefy6pfw  于 2022-12-20  发布在  其他
关注(0)|答案(3)|浏览(158)
df <- data.frame(x = c(6.00001, 6.00000, 5.99999, 5, 2), y = c(1, 2, 3, 4, 5))

        x y
1 6.00001 1
2 6.00000 2
3 5.99999 3
4 5.00000 4
5 2.00000 5

我可以使用df[df$x == 6,]快速返回包含x == 6的行,

x y
2 6 2

但是如果我想在这里有一个公差呢?all.equal在这里似乎不适用:

df[all.equal(df$x, 6, 0.0001), ]
    x  y
NA NA NA

如果我想找到x6非常接近的行,有什么捷径吗?预期输出:

x y
1 6.00001 1
2 6.00000 2
3 5.99999 3
8ehkhllq

8ehkhllq1#

您可以使用near(),它是abs(x - y) < tol的 Package 器:

library(dplyr)

df %>%
  filter(near(x, 6, tol = 1e-04))

        x y
1 6.00001 1
2 6.00000 2
3 5.99999 3
0md85ypi

0md85ypi2#

使用 round

df[ round(df$x, 4) == 6, ]
#         x y
# 1 6.00001 1
# 2 6.00000 2
# 3 5.99999 3
qvk1mo1f

qvk1mo1f3#

df[all.equal(df$x, 6, 0.0001), ]产生NA输出的原因有两个。
首先,all.equal()比较整个对象,而不是循环使用较短的向量并进行元素级比较。
看看这个例子:

all.equal(
    target = c(1, 1), 
    current = 1,
    tolerance = 1e-7
)
# [1] "Numeric: lengths (2, 1) differ"

其次,它是它产生的输出。正如你所看到的,输出是一个字符向量。你不能用这个子集化一个数据框。
这样做的原因是在文档中,其中说返回值是:
TRUE(对于attr.all.equal为NULL)或描述目标和当前之间差异的“字符”模式向量。
您也可以在all.equal.numeric()源代码中看到这一点,其逻辑是它尝试构建一个消息(msg)来解释currenttarget之间的区别,如果存在这样的消息,则返回该消息,否则返回TRUE

if(is.null(msg)) TRUE else msg

因此,如果你想使用all.equal()(我可以理解你为什么要这么做),你可以使用sapply()来做元素之间的比较,测试你是否得到了一个逻辑值和在此基础上的子集:

target  <- 6
tol  <- 1e-3
df[
    sapply(
        df$x, 
        \(current) is.logical(all.equal(target, current, tol))
        ),
]

#         x y
# 1 6.00001 1
# 2 6.00000 2
# 3 5.99999 3

相关问题