通过`dplyr :: contains`从分组选择中排除几列

时间:2016-04-27 14:33:45

标签: regex r dplyr

假设一个包含多组列的数据框(按其名称链接,此处为BlaD):

df = data.frame(A=1, BlaTata=2, BlaTato=3, BlaTota=4, BlaToto=5, 
                C=6, D1=7, D2=8, D3=9, D4=10)
# A BlaTata BlaTato BlaTota BlaToto C D1 D2 D3 D4
# 1       2       3       4       5 6  7  8  9 10

如何轻松删除包含Bla(即select(-contains('Bla')))的所有列,除了其中一些我会明确“保护”(de)选择程序的列?

假设我想“保护”BlaTatoBlaToto

df %>% mutate(saveBlaToto=BlaToto, saveBlaTato=BlaTato) %>% 
  select(-starts_with('Bla')) %>% 
  mutate(BlaToto=saveBlaToto, BlaTato=saveBlaTato) %>% 
  select(-contains('save')) %>%
  select(order(colnames(.)))
# A BlaTato BlaToto C D1 D2 D3 D4
# 1       3       5 6  7  8  9 10

必须有一种更简单,更优雅的方式; - )

假设按列索引等选择不方便。

select(-contains('Bla' but keep c('BlaTato','BlaToto')))这样的东西可能会保留几个列...

修改

这个问题在下面弗兰克的“新问题”中得到了解答。 原始问题,更简单,并在他的“第一个问题”中得到解答,是“如何删除包含B的所有列,除了B2在以下数据框中”

df = data.frame(A=1, B1=2, B2=3, B3, B4=5, C=6, D1=7, D2=8, D3=9, D4=10)

1 个答案:

答案 0 :(得分:3)

第一个问题。如果查看?select,您会看到可以输入正则表达式,例如

# example
df = data.frame(A=1, B1=2, B2=3, B3=4, B4=5, C=6, D1=7, D2=8, D3=9, D4=10)

# goal: drop B, protect B2
df %>% select(-matches('^B[^2]$'))

  A B2 C D1 D2 D3 D4
1 1  3 6  7  8  9 10

阅读正则表达式:

  • ^$表示字符串的开头和结尾。
  • [^x]表示除x以外的任何字符。

新问题。看起来dplyr还不支持Perl风格的正则表达式,所以......

# example
df = data.frame(A=1, BlaTata=2, BlaTato=3, BlaTota=4, BlaToto=5, 
            C=6, D1=7, D2=8, D3=9, D4=10)

# goal: drop Bla, protect BlaTato, BlaToto
df %>% select(-grep('^Bla(?!Tato|Toto)', names(.), perl=TRUE))

  A BlaTato BlaToto C D1 D2 D3 D4
1 1       3       5 6  7  8  9 10

阅读正则表达式:

  • (?!xyz)表示“请勿跟随xyz
  • x|y表示xy

有关正则表达式和使用它们的基本R函数的更多信息,请阅读?regex?grep。但实际上,你不应该像这样命名你的列。如果您发现自己处于需要解析列名的位置,那么您可能在之前就犯了错误。