dplyr / tidy 方法来过滤基于子字符串的向量?

use*_*745 5 r dplyr

我们可以看到一些关于如何基于子字符串过滤 data.frame 的好例子;有没有一种整洁的方法来为向量做这件事?(即不使用grepl()或类似)

例子

我尝试了对 data.frame 有效的方法

# Leave only words that don't begin with 'cat'

vec <- c("cat", "catamaran", "dog", "mouse", "catacombs")

vec %>% filter(substr(1, 3) != "cat") # %>% ... etc
Run Code Online (Sandbox Code Playgroud)

Error in UseMethod("filter_") : 
  no applicable method for 'filter_' applied to an object of class "character"
Run Code Online (Sandbox Code Playgroud)

笔记

我们可以使用类似的东西vec %>% { .[!grepl("cat", .)] },或者更准确地说vec %>% { .[substr(., 1, 3) != "cat"]},但我会尝试找到一些东西......

  1. 对初学者更友好,具有更多的口头描述功能(例如,一个完整的新手可能会猜到“过滤器”的作用,但可能不会猜到“grepl”)
  2. 少挑剔的语法(尽可能少{}尽可能)
  3. 更优雅的管道(例如vec %>% filter(...) %>% next operations
  4. 包含尽可能少的重复,注意该grepl方式使用原始向量(由 表示.)两次(而不是一次,这是理想的)

Ron*_*hah 8

我认为tidyverse更适合数据帧/列表而不是向量。如果您想执行多个操作,则需要管道,但在这里您可以使用单个函数 ( grep)获得预期结果,而无需任何管道。

grep('^cat', vec, value = TRUE, invert = TRUE)
#[1] "dog"   "mouse"
Run Code Online (Sandbox Code Playgroud)

或者可能将向量转换为数据帧,然后使用

library(dplyr)
library(tibble)

vec %>% enframe() %>% filter(!startsWith(value, 'cat'))
Run Code Online (Sandbox Code Playgroud)

或者

vec %>% enframe() %>% filter_at(vars(value), any_vars(!startsWith(., 'cat')))
Run Code Online (Sandbox Code Playgroud)


bga*_*ber 5

如果您不介意使用不同的包,则可以使用包中的stri_detect_fixed函数stringi

install.packages('stringi')
library(stringi)

vec <- c("cat", "catamaran", "dog", "mouse", "catacombs")
vec[stri_detect_fixed(vec, 'cat')]
Run Code Online (Sandbox Code Playgroud)

输出:

[1] "cat"       "catamaran" "catacombs"
Run Code Online (Sandbox Code Playgroud)

然后,您应该能够将其传递给您想要的任何命令。


Wal*_*ltS 5

使用purrr工作与向量

library(purrr)
library(stringr)

vec <- c("cat", "catamaran", "dog", "mouse", "catacombs")
vec %>% discard(.p=str_detect, pattern = "^cat")
Run Code Online (Sandbox Code Playgroud)