【问题标题】:Filtering rows based on dynamic column count & column name in R根据 R 中的动态列数和列名过滤行
【发布时间】:2021-04-16 06:54:01
【问题描述】:

我有一个名为 inputDf 的数据框,它在除 Rating 列之外的所有列中都有二进制值。

inputDf <- structure(list(Q1 = c(0L, 1L, 1L, 1L, 1L, 0L, 0L, 1L), Q2 = c(1L, 
1L, 1L, 1L, 1L, 0L, 1L, 0L), Q3 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L), Q4 = c(1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L), Q5 = c(1L, 1L, 1L, 
1L, 1L, 0L, 0L, 1L), Q6 = c(1L, 1L, 1L, 1L, 1L, 1L, 0L, 1L), 
Q7 = c(1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L), Q8 = c(1L, 1L, 1L, 
1L, 1L, 1L, 0L, 0L), Q9 = c(1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L
), Q10 = c(0L, 1L, 0L, 1L, 1L, 0L, 0L, 0L), Q11 = c(1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L), Q12 = c(1L, 1L, 1L, 1L, 1L, 1L, 
0L, 1L), Rating = c(7L, 7L, 6L, 5L, 6L, 6L, 7L, 5L), RatingBinary = c(1L, 
1L, 1L, 0L, 1L, 1L, 1L, 0L)), row.names = c(13L, 17L, 26L, 
71L, 72L, 55L, 56L, 69L), class = "data.frame")

我有另一个类似的数据框,名为 combinationDf

combinationDf <- structure(list(Q1 = c(0L, 0L), Q2 = c(0L, 0L), Q3 = 1:0, Q4 = c(1L, 
1L), Q5 = c(0L, 0L), Q6 = c(0L, 0L), Q7 = c(0L, 0L), Q8 = c(0L, 
0L), Q9 = c(0L, 0L), Q10 = c(0L, 0L), Q11 = c(1L, 1L), Q12 = 0:1), row.names = 1:2, class = 
"data.frame")

问题陈述是针对combinationDf 中每一行中1 的每个组合,我需要从inputDf 中过滤行

我通过硬编码要考虑过滤数据的列数来实现逻辑。

    finalDf <- data.frame() 
    for(i in 1:nrow(combinationDf)){
      ind <- which(combinationDf[i,] == 1)
      ind <- paste("Q",ind, sep = "")
      sample <- inputDf %>%
        dplyr::filter(eval(parse(text=ind[1])) == 1 & eval(parse(text=ind[2])) == 1 & eval(parse(text=ind[3])) == 1) %>%
        as.data.frame()
      finalDf <<- rbind(finalDf,sample)
    }

但是,我正在寻找使用 N # 列过滤掉数据的通用代码。即,上面的代码适用于使用 3 列进行过滤。如果我需要基于 4 列进行过滤,我需要添加一个条件。为了克服这个问题,我使用了下面的代码,

  sample <- inputDf %>%
    dplyr::filter(as.logical(paste(paste0("eval(parse(text = ind[", 1:length(ind), "])) == 1"), collapse = " & "))) %>%
    as.data.frame()

此 sn-p 不会按预期过滤行。谁能指出我在上面的代码中犯的错误?或者可以提供实现相同目标的最佳方法?

【问题讨论】:

    标签: r filter dplyr


    【解决方案1】:

    对子集进行子集化然后进行半连接以进行过滤可能是有意义的

    finalDf <- data.frame() 
    for(i in 1:nrow(combinationDf)){
      sample <- inputDf %>%
        semi_join(combinationDf %>% slice(i) %>% select(where(~.x==1)))
      finalDf2 <- rbind(finalDf ,sample)
    }
    

    在每次循环迭代中,我们选择所有为 1 的列,然后连接以从 inputDf 中提取匹配值。这将适用于任意数量的列。在dplyr 中没有循环的另一种表达方式是

    combinationDf %>% 
      group_by(id=1:n()) %>% 
      group_map(~.x %>% 
        select(where(~.x==1)) %>% 
        semi_join(inputDf, .)
      ) %>% 
      bind_rows()
    

    这可能更具可读性。

    【讨论】:

      【解决方案2】:

      基础 R 方法:

      • 以逐行方式使用apply 遍历combinationDf 中的每一行。
      • 获取连续值为1的列名。
      • inputDf 中的这些列进行子集化,然后选择所有值为 1 的行。
      • 将数据帧列表合并为一个数据帧。
      result <- do.call(rbind, apply(combinationDf, 1, function(x) 
                 inputDf[rowSums(inputDf[names(x)[x == 1]] != 1) == 0, ]))
      rownames(result) <- NULL
      result
      
      #   Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q10 Q11 Q12 Rating RatingBinary
      #1   0  1  1  1  1  1  1  1  1   0   1   1      7            1
      #2   1  1  1  1  1  1  1  1  1   1   1   1      7            1
      #3   1  1  1  1  1  1  1  1  1   0   1   1      6            1
      #4   1  1  1  1  1  1  1  1  1   1   1   1      5            0
      #5   1  1  1  1  1  1  1  1  1   1   1   1      6            1
      #6   0  1  1  1  1  1  1  1  1   0   1   1      7            1
      #7   1  1  1  1  1  1  1  1  1   1   1   1      7            1
      #8   1  1  1  1  1  1  1  1  1   0   1   1      6            1
      #9   1  1  1  1  1  1  1  1  1   1   1   1      5            0
      #10  1  1  1  1  1  1  1  1  1   1   1   1      6            1
      

      【讨论】:

        【解决方案3】:
        combinationDf %>% 
          apply(1, function(x) paste0(names(inputDf)[x == 1], "==1", collapse = "&")) %>%
          lapply(function(x) filter(inputDf, eval(parse(text = x)))) %>%
          Reduce(rbind, .)
        

        【讨论】:

          猜你喜欢
          • 2018-11-21
          • 1970-01-01
          • 2021-08-16
          • 1970-01-01
          • 1970-01-01
          • 2016-10-05
          • 1970-01-01
          • 1970-01-01
          • 2021-06-25
          相关资源
          最近更新 更多