【问题标题】:Find rows in a dataframe which contain all elements of a row of another dataframe在数据框中查找包含另一个数据框行的所有元素的行
【发布时间】:2021-01-19 18:23:28
【问题描述】:

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

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 的第一行)。我希望删除包含df2 行的两个元素的df1 的任何行。因此,在示例中,我想删除 df1 的第 1、2、3、4 和 6 行,因为这些行包括 ABAD
  2. 有没有一种快速计算df2 每一行的行数而不循环的方法?即df2 第 1 行的计数为 3,第 2 行的计数为 3。

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    这是使用 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 选择公共元素少于一个的行

    【讨论】:

      【解决方案2】:

      使用应用

      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
      

      【讨论】:

        【解决方案3】:

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

        请务必在第 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)
        

        【讨论】:

          猜你喜欢
          • 2022-01-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-08
          • 1970-01-01
          • 2021-12-19
          • 2018-04-19
          • 2022-11-15
          相关资源
          最近更新 更多