2

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

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?即第 1:3 行df1同时包含AB(的第一行df2)。我正在寻找删除df1其中包含的行的两个元素的任何行df2。因此,在示例中,我想删除第 1、2、3、4 和 6 行,df1因为它们包括Aand BOR Aand D
  2. 有没有一种快速的方法来计算每行的行数df2而不循环?即df2第 1 行的计数为 3,第 2 行的计数为 3。
4

3 回答 3

2

outer这是使用+的基本 R 选项intersect

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按行拆分数据帧
  • outerdf1从和生成所有行组合df2
  • intersect给出两个数据帧中行的相交元素
  • subset选择具有少于一个公共元素的行
于 2021-01-19T10:02:56.730 回答
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
于 2021-01-19T10:10:24.437 回答
0

你需要以某种方式循环。这是使用dplyrand的一种方法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))))

请务必在第 1 部分之前执行第 2 部分,因为第 1 部分会删除行。您还可以首先检测要为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)
于 2021-01-19T09:52:25.647 回答