将`starts_with()`和排除性`ends_with()`与`intersect()`结合使用,是否无法正常工作?

7z5jn7bk  于 2023-05-20  发布在  其他
关注(0)|答案(2)|浏览(84)

参考上一个问题和答案-How to use both starts_with and ends_with at the same time in one select statement?
我正在尝试下面的代码(使用tidyverse / dplyr)。作为参考,我的实际数据集要大得多。这是一个调查,我想只从某个部分选择问题,用字母表示,但排除有文本答案的问题-因为我试图将数据转换为长格式。

df <- data.frame(D.1 = c(1,1,0,1,1,0),
                 D.2 = c(1,1,0,0,0,0),
                 D.2_TEXT = c("Don't know", NA, "Something else", NA, NA, NA),
                 F.1 = c(0,1,0,0,1,1))

以下两个选择分别正常工作:

> select(df, starts_with("D"))

    D.1 D.2       D.2_TEXT
    1   1   1     Don't know
    2   1   1           <NA>
    3   0   0 Something else
    4   1   0           <NA>
    5   1   0           <NA>
    6   0   0           <NA>
> select(df, !ends_with("_TEXT"))

      D.1 D.2 F.1
    1   1   1   0
    2   1   1   1
    3   0   0   0
    4   1   0   0
    5   1   0   1
    6   0   0   1

但当我把它们结合起来:

> select(df, intersect(starts_with("D"), !ends_with("_TEXT")))

    data frame with 0 columns and 6 rows

我知道我可以分两步来做:

> df %>% 
+  select(starts_with("D")) %>% 
+  select(!ends_with("_TEXT"))

      D.1 D.2
    1   1   1
    2   1   1
    3   0   0
    4   1   0
    5   1   0
    6   0   0

但我感到困惑/好奇的是,为什么这不会工作类似的问题/回答上面指出?任何建议/想法?

b1zrtrql

b1zrtrql1#

您的情况与链接略有不同。
您需要选择以D开头而不是以_Text结尾的列。因此,setdiff()可能是您想要的。

df <- data.frame(D.1 = c(1,1,0,1,1,0),
                 D.2 = c(1,1,0,0,0,0),
                 D.2_TEXT = c("Don't know", NA, "Something else", NA, NA, NA),
                 F.1 = c(0,1,0,0,1,1))

df |> 
  select(setdiff(starts_with("D"), ends_with("_TEXT")))

输出

D.1 D.2
1   1   1
2   1   1
3   0   0
4   1   0
5   1   0
6   0   0
tyu7yeag

tyu7yeag2#

您可以使用dplyr::matches()来使用更灵活的正则表达式:

df %>%
  select(matches("^D.*$(?<!_TEXT)", perl = TRUE))

解释模式:

  • ^D以“D”开头;
  • .*后面有任意个(包括0个)其它字符;
  • 并且R不能(!)在字符串($)的结尾(<)之前找到“_TEXT”。(?...)是lookaround sintax

相关问题