代码之家  ›  专栏  ›  技术社区  ›  buhtz

按条件简化相似命名列的选择

r
  •  1
  • buhtz  · 技术社区  · 7 年前

    下面的示例代码是有效的,但我的问题是如何用更少的代码和更优雅的代码来编写它?

    关键是我有相似名称的列。在本例中,我希望选择以开头的所有列 B FALSE .

    set.seed(0)
    
    df <- data.frame(A = sample(c(T, F), 100, replace=T),
                     B1 = sample(c(T, F), 100, replace=T),
                     B2 = sample(c(T, F), 100, replace=T),
                     B3 = sample(c(T, F), 100, replace=T))
    
    n <- names(df)[startsWith(names(df), 'B')]
    
    result <- df[df$B1 == FALSE & df$B2 == FALSE & df$B3 == FALSE, n]
    
    print(result)
    

    结果是

          B1    B2    B3
    1  FALSE FALSE FALSE
    26 FALSE FALSE FALSE
    31 FALSE FALSE FALSE
    35 FALSE FALSE FALSE
    51 FALSE FALSE FALSE
    66 FALSE FALSE FALSE
    70 FALSE FALSE FALSE
    84 FALSE FALSE FALSE
    

    我尝试过的结果出乎意料

    df[df[,n] == FALSE, n]
    
    5 回复  |  直到 7 年前
        1
  •  1
  •   Nicolas2    7 年前

    带tidyverse:

    df %>% select(matches("^B")) %>% filter_all(all_vars(.==FALSE))
    

    df %>% mutate(id=row_number()) %>%                  # copy row number to new variable 
      select(id,matches("^B")) %>%                      # keeps id and variables beginning with B
      filter_at(vars(matches("^B")),                    # for variables beginning with B
                all_vars(.==FALSE))                     # keep rows where all are FALSE
    #  id    B1    B2    B3
    #1  1 FALSE FALSE FALSE
    #2 26 FALSE FALSE FALSE
    #3 31 FALSE FALSE FALSE
    #4 35 FALSE FALSE FALSE
    #5 51 FALSE FALSE FALSE
    #6 66 FALSE FALSE FALSE
    #7 70 FALSE FALSE FALSE
    #8 84 FALSE FALSE FALSE
    
        2
  •  3
  •   Ronak Shah    7 年前

    在baser中,我们可以选择以“B”开头的列,然后使用 rowSums .

    inds <- grepl("^B", names(df))
    df[rowSums(df[inds]) == 0, inds]
    
    #      B1    B2    B3
    #1  FALSE FALSE FALSE
    #26 FALSE FALSE FALSE
    #31 FALSE FALSE FALSE
    #35 FALSE FALSE FALSE
    #51 FALSE FALSE FALSE
    #66 FALSE FALSE FALSE
    #70 FALSE FALSE FALSE
    #84 FALSE FALSE FALSE
    

    或者正如@snoram提到的,为了使它更简洁,我们可以

    df[!rowSums(df[inds]), inds]
    
        3
  •  1
  •   s_baldur    7 年前

    快速base-R替代方案:

    df[!do.call(pmax, df[n]), n]
    
           B1    B2    B3
    1  FALSE FALSE FALSE
    26 FALSE FALSE FALSE
    31 FALSE FALSE FALSE
    35 FALSE FALSE FALSE
    51 FALSE FALSE FALSE
    66 FALSE FALSE FALSE
    70 FALSE FALSE FALSE
    84 FALSE FALSE FALSE
    

    编辑

    保持接近最初的尝试,你可以做到:

    df[apply(df[n] == FALSE, 1, all), n] 
    # or
    df[apply(!df[n], 1, all), n]
    
        4
  •  1
  •   Andre Elrico    7 年前

    我会这样做:

    您的数据:

    df <- data.frame(A = sample(c(T, F), 100, replace=T),
                     B1 = sample(c(T, F), 100, replace=T),
                     B2 = sample(c(T, F), 100, replace=T),
                     B3 = sample(c(T, F), 100, replace=T))
    

    代码:

    df<- as.data.frame(!df[,grepl("^B",names(df))])
    
    !df[apply(df,1,all),]
    

    #      B1    B2    B3
    #1  FALSE FALSE FALSE
    #26 FALSE FALSE FALSE
    #31 FALSE FALSE FALSE
    #35 FALSE FALSE FALSE
    #51 FALSE FALSE FALSE
    #66 FALSE FALSE FALSE
    #70 FALSE FALSE FALSE
    #84 FALSE FALSE FALSE
    
        5
  •  1
  •   akrun    7 年前

    base R ,我们能做到

    df[!Reduce(`|`, df[grep("^B", names(df))]),]
    #       A    B1    B2    B3
    #1  FALSE FALSE FALSE FALSE
    #26  TRUE FALSE FALSE FALSE
    #31  TRUE FALSE FALSE FALSE
    #35  TRUE FALSE FALSE FALSE
    #51 FALSE FALSE FALSE FALSE
    #66 FALSE FALSE FALSE FALSE
    #70  TRUE FALSE FALSE FALSE
    #84  TRUE FALSE FALSE FALSE