使用dplyr或Base R按行和筛选数据框返回空行的技术问题
解决行和筛选数据框无结果的问题
嘿,我来帮你搞定这个困扰!你遇到的问题核心原因其实是浮点数的精度误差,咱们一步步拆解来看:
问题根源
你用seq(-1, 1, 0.2)生成的是浮点数,虽然看起来是规整的0.2、0.4这类数值,但计算机存储浮点数时会有微小的精度偏差(比如0.2在二进制里是无限循环的)。当你计算rowSums(df)时,这些偏差会累积,导致soma列的数值看起来和预期一致,但实际底层存储的是带有微小误差的数值,直接用==比较就会匹配失败。而你用整数筛选时,整数的存储是精确的,所以不会有这个问题。
解决方案
1. 使用dplyr的near()函数(推荐)
dplyr专门提供了near()函数来处理浮点数的近似比较,它会允许一个极小的误差范围,避免精度问题:
library(dplyr) x <- seq(-1, 1, 0.2) df <- data.frame(V1 = x, V2 = x, V3 = x, V4 = x, V5 = x) df <- df %>% mutate(soma = rowSums(df)) # 用near()替代==进行浮点数比较,比如筛选行和为1的行 df %>% filter(near(soma, 1))
2. 对数值进行四舍五入处理
如果你的业务场景允许,可以把行和以及要比较的数值都四舍五入到指定小数位,消除精度偏差:
df <- df %>% mutate(soma = round(rowSums(df), 1)) df %>% filter(soma == 1.0)
3. Base R中的解决方法
在Base R里,你可以用all.equal()函数来进行近似比较(需要结合Vectorize()处理向量),或者同样用round():
x <- seq(-1, 1, 0.2) df <- data.frame(V1 = x, V2 = x, V3 = x, V4 = x, V5 = x) df$soma <- rowSums(df) # 方法1:用Vectorize(all.equal)实现向量级近似比较 df[Vectorize(function(a, b) isTRUE(all.equal(a, b)))(df$soma, 1), ] # 方法2:四舍五入后精确匹配 df$soma <- round(df$soma, 1) df[df$soma == 1.0, ]
验证偏差
你可以打印出soma列的真实数值,就能看到隐藏的精度偏差:
print(df$soma, digits = 15)
会看到类似1.000000000000001或者0.999999999999999这样的数值,这就是直接用==匹配不到的原因!
内容的提问来源于stack exchange,提问作者Rodrigo Remedio
相关产品推荐
相关产品推荐

