我想比较R中具有相同列名(df1和df2)的两个数据帧。根据其中一列(df2)中每列中的值,我想过滤另一列(df1)。我需要消除 df1 中大于或等于 df2 中关于每个列名的值的行。换句话说,需要产生以下 res1:
df1 <- data.frame( v1 = c(1,2,3,4), v2 = c(2, 10, 5, 11), v3=c(20, 25, 23, 2), v4=c(1,2,1,3) )
> df1
v1 v2 v3 v4
1 1 2 20 1
2 2 10 25 2
3 3 5 23 1
4 4 11 2 3
df2 <- data.frame(v1 = 4, v2 = 10, v3 =30, v4 = 3)
> df2
v1 v2 v3 v4
1 4 10 30 3
因此,通过基于列名将 df1 中的每一行与 df2 进行比较并消除 df1 中大于或等于 df2 中定义的特定列阈值的行,可以生成所需的输出 res1:
> res1
v1 v2 v3 v4
1 1 2 20 1
2 3 5 23 1
我们可以使用带有<
符号的mapply
来比较两个数据框,并使用rowSums
来索引子集,即
df1[rowSums(mapply(`<`, df1, df2)) == ncol(df1),]
# v1 v2 v3 v4
#1 1 2 20 1
#3 3 5 23 1
此外,上述内容的完全矢量化翻译可以是(@RonakShah的补充),
df1[rowSums(df1 < df2[rep(1, nrow(df1)), ]) == ncol(df1), ]
我们可以逐行使用apply
并检查行中的所有元素是否都小于其他数据帧中的元素
df1[t(apply(df1, 1, function(x) all(x < df2[1, ]))), ]
# v1 v2 v3 v4
#1 1 2 20 1
#3 3 5 23 1
这是将Reduce
与Map
一起使用的另一个选项
df1[Reduce(`&`, Map(`<`, df1, df2)),]
# v1 v2 v3 v4
#1 1 2 20 1
#3 3 5 23 1
或使用tidyverse
library(dplyr)
library(purrr)
map2(df1, df2, `<`) %>%
reduce(`&`) %>%
df1[.,]
# v1 v2 v3 v4
#1 1 2 20 1
#3 3 5 23 1