我有一个包含三列的数据框,第二个包含两列的数据框。
df1 <- data.frame(X1 = c('A', 'A', 'A', 'A', 'A', 'A', 'B'),
X2 = c('B', 'B', 'B', 'C', 'C', 'D', 'C'),
X3 = c('C', 'D', 'E', 'D', 'E', 'E', 'D'))
df2 <- data.frame(X1 = c('A', 'A'),
X2 = c('B', 'D'))
问题:
- 我如何找到
df1
中包含df2
一行的所有元素的行?即df1
的第1:3行同时包含A
和B
(df2
的第一行)。我希望删除df1
的任何行,其中包含df2
行的两个元素。因此,在示例中,我想删除df1
的第1,2,3,4和6行,因为这些行包括A
和B
或A
和D
。 - 是否有一种快速的方法来计算
df2
的每一行的行数而不循环?即df2
第1行计数为3,第2行计数为3。
这是使用outer
+intersect
的基础R选项
mat <- lengths(
outer(
asplit(df1, 1),
asplit(df2, 1),
Vectorize(intersect)
)
) >= ncol(df2)
得到
> subset(df1, !rowSums(mat))
X1 X2 X3
5 A C E
7 B C D
> within(df2, cnt <- colSums(mat))
X1 X2 cnt
1 A B 3
2 A D 3
asplit
按行拆分数据帧outer
生成df1
和df2
的所有行组合intersect
给出了来自两个数据帧的行相交元素subset
选择少于一个公共元素的行
Usingapply:
df1[ !apply(df1, 1, function(i) any(apply(df2, 1, function(j) all(j %in% i)))), ]
# X1 X2 X3
# 5 A C E
# 7 B C D
对df2匹配计数执行类似的循环:
cbind(df2,
cnt = apply(df2, 1, function(i) sum(apply(df1, 1, function(j) all(i %in% j)))))
# X1 X2 cnt
# 1 A B 3
# 2 A D 3
你需要以某种方式循环。下面是使用dplyr
和purrr
的一种方法:
1。
for(iRow in seq_len(nrow(df2))){
df1 <- df1 %>%
rowwise() %>%
filter(!all(as.character(df2[iRow,]) %in% c_across(everything())))
}
2。
df2 %>%
rowwise() %>%
mutate(n = sum(map_int(transpose(df1), ~all(c_across(everything()) %in% .x))))
请确保在第一部分之前执行第二部分,因为第一部分会删除行。此外,您还可以首先检测要为df2
的每一行删除哪些行。这样你就可以计数它们,然后再删除它们。
df2 <- df2 %>%
rowwise() %>%
mutate(
indices = list(which(map_lgl(transpose(df1), ~all(c_across(everything()) %in% .x))))
) %>%
ungroup() %>%
mutate(n = map_int(indices, length))
df1 <- df2[["indices"]] %>%
unlist() %>%
unique() %>%
"*"(-1) %>%
df1[.,]
df2 <- df2 %>% select(-indices)