используя stringr::str_detect, чтобы определить, появляется ли строка после того, как символ появился 4 раза

Не уверен, что я так хорошо сформулировал свой вопрос, но, по сути, это то, что я пытаюсь сделать.

Пример данных:

Data <- c("NELIG_Q1_1_C1_A", "NELIG_N1_1_EG1_B", "NELIG_V2_1_NTH_C", "NELIG_Q2_1_C5_Q",
"NELIG_N1_1_C1_RA", "NELIG_Q1_1_EG1_QR", "NELIG_V2_1_NTH_PQ", "NELIG_N2_1_C5_PRQ")

Я хочу фильтровать, используя str_detect в последнем наборе комбинаций букв. Перед строкой/шаблоном, который я ищу, всегда будет четыре _, но после четвертого _ может быть много разных комбинаций букв. В приведенном выше примере я пытаюсь обнаружить только букву Q.

Если я сделаю простое Data2 <- Data %>% filter(str_detect(column, "Q")), я получу все строки, содержащие Q в любом месте строки. Как я могу сказать, чтобы он сосредоточился только на последнем разделе?


person Checht    schedule 02.11.2020    source источник


Ответы (3)


Если цель состоит в том, чтобы обнаружить/сопоставить те строки, которые содержат Q в «разделе» после последнего _, тогда это работает:

grep("_[A-Z]*Q[A-Z]*$", Data, value = T, perl = T)
[1] "NELIG_Q2_1_C5_Q"   "NELIG_Q1_1_EG1_QR" "NELIG_V2_1_NTH_PQ" "NELIG_N2_1_C5_PRQ"

или, с str_detect:

library(stringr)
str_detect(Data, "_[A-Z]*Q[A-Z]*$")
[1] FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE  TRUE

Данные:

Data <- c("NELIG_Q1_1_C1_A", "NELIG_N1_1_EG1_B", "NELIG_V2_1_NTH_C", "NELIG_Q2_1_C5_Q",
          "NELIG_N1_1_C1_RA", "NELIG_Q1_1_EG1_QR", "NELIG_V2_1_NTH_PQ", "NELIG_N2_1_C5_PRQ")
person Chris Ruehlemann    schedule 10.11.2020
comment
Это, вероятно, мой любимый ответ, так как он является наиболее «строгим» в использовании решений типа tidyverse. Я просто хочу понять, как/где в _[az]*Q[az]*$ он говорит ему искать только последний раздел? Я понимаю, что мы говорим об обнаружении строки в DATA, поиске строки, которая начинается с _ (имеет символ) **не уверен, что делает *Q**(за которым следует символ)** не уверен, что делает *$) - person Checht; 11.11.2020
comment
_[a-z]*Q[a-z]*$ ловит последний «раздел», как вы говорите, из-за якоря $. Это метасимвол нулевой ширины, привязывающий шаблон к позиции в строке, а именно к ее концу! (Противоположный якорь — ^, который привязывает шаблон к самому началу строки.) - person Chris Ruehlemann; 11.11.2020
comment
Благодарю вас! В этом есть смысл. - person Checht; 12.11.2020

Если вы хотите использовать tidyverse:

library(magrittr)

data <- tibble::tibble(Col =  c("NELIG_Q1_1_C1_A", "NELIG_N1_1_EG1_B", 
                                "NELIG_V2_1_NTH_C", "NELIG_Q2_1_C5_Q",
                                "NELIG_N1_1_C1_RA", "NELIG_Q1_1_EG1_QR", 
                                "NELIG_V2_1_NTH_PQ", "NELIG_N2_1_C5_PRQ"))

data %>% 
  dplyr::mutate(Col = purrr::map_lgl(Col,
                                     ~ stringr::str_detect(
                                       unlist(
                                         stringr::str_split(.x, 
                                                            "_"))[5], 
                                       "Q")))
#> # A tibble: 8 x 1
#>   Col  
#>   <lgl>
#> 1 FALSE
#> 2 FALSE
#> 3 FALSE
#> 4 TRUE 
#> 5 FALSE
#> 6 TRUE 
#> 7 TRUE 
#> 8 TRUE

Создана 05.11.2020 с помощью пакета reprex (v0.3.0)

person Florian    schedule 05.11.2020

Если я правильно понял ваш вопрос, то вы можете сделать что-то вроде этого:

library(stringr)
str_detect(Data, ".*_.*_.*_.*_.*Q.*$")
#R> [1] FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE  TRUE

Это обнаружит, есть ли какой-либо Q после четвертого _.

Глядя на заголовок:

обнаружение строки после 4 постоянных символов

то вы можете сделать общую функцию, которая делает это следующим образом:

# returns TRUE if a certain character occurs after a character has been 
# there four times.
# 
# Args: 
#   x characters to check.
#   what character to occur at the end. 
#   after character to occur four times.
detect_after_four_times <- function(x, what, after){
  reg <- sprintf(".*%s.*%s.*%s.*%s.*%s.*$", after, after, after, after, 
                 what)
  str_detect(x, reg)
}

detect_after_four_times(Data, "Q", "_")
#R> [1] FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE  TRUE
detect_after_four_times(Data, "R", "_") # look for R instead
#R> [1] FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE  TRUE

# also works if there are only three times of "after"
detect_after_four_times("only_three_dashes_Q", "Q", "_")
#R> [1] FALSE
person Benjamin Christoffersen    schedule 05.11.2020