查找包含另一个数据帧行的所有元素的数据帧中的行

时间:2021-01-19 09:21:40

标签: r dataframe

我有一个包含三列的数据框,第二个包含两列。

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'))

问题:

  1. 如何在 df1 中找到包含 df2 行的所有元素的行?即 df1 的第 1:3 行包含 ABdf2 的第一行)。我希望删除包含 df1 行的两个元素的任何 df2 行。因此,在示例中,我想删除 df1 的第 1、2、3、4 和 6 行,因为它们包括 AB OR A 和 {{1 }}。
  2. 有没有一种快速计算 D 的每一行的行数而不循环的方法?即 df2 第 1 行的计数为 3,第 2 行的计数为 3。

3 个答案:

答案 0 :(得分:2)

这是使用 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 生成来自 df1df2 的所有行组合
  • intersect 给出两个数据框中行的相交元素
  • subset 选择公共元素少于一个的行

答案 1 :(得分:1)

使用应用

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

答案 2 :(得分:0)

你需要以某种方式循环。以下是使用 dplyrpurrr 执行此操作的一种方法:

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)