通过条件简化对相似命名列的选择

时间:2018-09-03 13:23:10

标签: r

下面的示例代码可以正常工作,但是我的问题是如何用更少的代码和更优雅的方式编写代码?

重点是我有相似名称的列。在此示例中,我想选择所有以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 个答案:

答案 0 :(得分:3)

在基数R中,我们可以选择以“ B”开头的列,然后使用rowSums选择总和等于0的行。

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]

答案 1 :(得分:1)

使用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 :(得分:1)

一种快速的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]

答案 3 :(得分:1)

我会这样:

您的数据:

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

答案 4 :(得分:1)

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