以编程方式选择包含字符串的列名

4

假设有这样的数据框:

df <- data.frame(z_a = 1:2,
                 z_b = 1:2,
                 y_a = 3:4,
                 y_b = 3:4)

我可以使用以下方式选择包含字符的列名:

library(dplyr)
df %>% select(contains("a"), contains("b"))

  z_a y_a z_b y_b
1   1   3   1   3
2   2   4   2   4

注意:列的顺序已更改。包含a的列先于包含b的列。

我想要选择包含向量中字符的列名并重新排序这些列。

searchfor <- letters[1:2]

使用searchfor,我想制作以下表达式,并在select语句中使用:
E <- quote(contains(searchfor[1]), contains(searchfor[2]))
df %>% select_(E) 

1
这是一个略微不同于 https://dev59.com/nl4b5IYBdhLWcg3whB-V 的问题。但是它有相同的解决方案。 - wibeasley
1
这里是更直接的比较:https://dev59.com/C18e5IYBdhLWcg3wRIpQ#25923466 - wibeasley
@wibeasley 根据我原帖的澄清,以下答案更贴近我的问题。谢谢! - CPak
4个回答

4
我们可以做。
df %>% 
   select_at(vars(matches(paste(searchfor, collapse="|")))) %>%
   select(order(sub(".*_", "", names(.))))

不是我想要的行为。df %>% select(contains("a"), contains("b")) 改变了列的顺序,这正是我想要的输出。我会在我的帖子中明确说明。 - CPak
谢谢。现在我需要弄清楚你做了什么。 - CPak
@ChiPak 在第一个 select 中,我使用了正则表达式来提取那些列,然后删除子字符串,基于此排序并选择列。感谢您的注意。 - akrun
第二个只有在我想要按字母顺序排序时才有效,是这样吗?如果我想要任意顺序(由“searchfor”的顺序确定),那么它在那种情况下就不起作用了? - CPak
@ChiPak 你可以为一般情况下添加具有级别的factor(因子)。 - akrun
只是想确保我理解正在发生的事情...谢谢 - CPak

2

purrr 解决方案:

library(purrr)
ind_lgl <- map(letters[1:2], ~ grepl(.x, names(df), fixed = TRUE)) %>%
  pmap_lgl(`|`)

df[ind_lgl]

使用管道符:

df %>%
  `[`(map(letters[1:2], ~ grepl(.x, names(df), fixed = TRUE)) %>%
        pmap_lgl(`|`))

如果你需要获得正确的顺序:
rank <- map(letters[1:2], ~ grepl(.x, names(df), fixed = TRUE)) %>%
  pmap(c) %>%
  map(which)


ind_chr <- data_frame(colnames = names(df), rank) %>%
  mutate(l = lengths(rank)) %>%
  filter(l > 0) %>%
  mutate(rank = unlist(map(rank, ~ .x[[1]]))) %>%
  arrange(rank) %>%
  pull(colnames)


df[ind_chr]

但这并不美观...


不是我想要的行为。df %>% select(contains("a"), contains("b")) 改变了列的顺序,这正是我想要的输出。我在帖子中应该更清楚地表达。 - CPak
不太美观,但对我来说很有用。你赢得了我的点赞... - CPak

1

我不明白确切的要求,但这是解决方案。

select(df, matches("a|b"))

关闭...我想要的两件事。首先,在select中使用字符元素向量searchfor作为contains的参数。您没有在语句中使用searchfor。其次,语句应根据匹配重新排序列,以便searchfor的顺序确定输出的列顺序。 - CPak

0

自我回答 - 这里有一个使用 select_ 并仍然使用 contains 的解决方案 - 以防其他人感兴趣:

library(iterators)
library(dplyr)
s <- paste0("c(", paste0(sapply(iter(searchfor), function(x) paste0("contains(\"", x, "\")")), collapse=","), ")")
df %>% select_(., s)

  z_a y_a z_b y_b
1   1   3   1   3
2   2   4   2   4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接