Coincidencias superpuestas en R

He buscado y pude encontrar esta discusión en el foro para lograr el efecto de coincidencias superpuestas.

También encontré la siguiente pregunta SO hablando de encontrar índices para realizar esta tarea, pero no pude encontrar nada conciso sobre el uso de coincidencias superpuestas en el lenguaje R.

Puedo realizar esta tarea en la mayoría de los idiomas que admiten ( PCRE ) mediante el uso de una afirmación de Posicionamiento anticipado al implementar un grupo de captura dentro de la búsqueda anticipada para capturar las coincidencias superpuestas.

Pero, aunque realicé esto de la misma manera que lo haría en otros idiomas, usando perl=T en R, no hay resultados.

 > x  regmatches(x, gregexpr('(?=([AC]C))', x, perl=T))[[1]] [1] "" "" "" "" "" "" "" 

Lo mismo ocurre con el uso del paquete stringi y stringr .

 > library(stringi) > library(stringr) > stri_extract_all_regex(x, '(?=([AC]C))')[[1]] [1] "" "" "" "" "" "" "" > str_extract_all(x, perl('(?=([AC]C))'))[[1]] [1] "" "" "" "" "" "" "" 

Los resultados correctos que se deben devolver al ejecutar esto son:

 [1] "AC" "CC" "AC" "CC" "AC" "CC" "AC" 

Editar

  1. Soy consciente de que los regmatches no funcionan bien con las coincidencias capturadas, pero ¿ qué causa exactamente este comportamiento en los registros y por qué no se devuelven los resultados? Estoy buscando una respuesta algo detallada .

  2. ¿ stringr paquete stringi y stringr no es capaz de realizar esto por sobre regmatches ?

  3. Por favor, siéntase libre de agregar a mi respuesta o encontrar una solución diferente a la que he encontrado.

Los regmatches estándar no funcionan bien con las coincidencias capturadas (específicamente múltiples coincidencias capturadas en la misma cadena). Y en este caso, dado que estás “haciendo coincidir” una mirada hacia adelante (ignorando la captura), el partido en sí es de longitud cero. También hay una función de regmatches()<- que puede ilustrar esto. Obseerve

 x <- 'ACCACCACCAC' m <- gregexpr('(?=([AC]C))', x, perl=T) regmatches(x, m) <- "~" x # [1] "~A~CC~A~CC~A~CC~AC" 

Observe cómo se conservan todas las letras, simplemente hemos reemplazado las ubicaciones de las coincidencias de longitud cero con algo que podemos observar.

Creé una función regcapturedmatches () que a menudo uso para tales tareas. Por ejemplo

 x <- 'ACCACCACCAC' regcapturedmatches(x, gregexpr('(?=([AC]C))', x, perl=T))[[1]] # [,1] [,2] [,3] [,4] [,5] [,6] [,7] # [1,] "AC" "CC" "AC" "CC" "AC" "CC" "AC" 

El gregexpr está tomando todos los datos muy bien para que pueda extraerlo de ese objeto de todos modos si prefiere no usar esta función de ayuda.

En cuanto a una solución alternativa, esto es lo que se me ocurrió para extraer las coincidencias superpuestas.

 > x <- 'ACCACCACCAC' > m <- gregexpr('(?=([AC]C))', x, perl=T) > mapply(function(X) substr(x, X, X+1), m[[1]]) [1] "AC" "CC" "AC" "CC" "AC" "CC" "AC" 

Por favor, siéntase libre de agregar o comentar sobre una mejor manera de realizar esta tarea.

Otra forma indirecta de extraer la misma información que he hecho en el pasado es reemplazar "match.length" con "capture.length" :

 x <- c("ACCACCACCAC","ACCACCACCAC") m <- gregexpr('(?=([AC]C))', x, perl=TRUE) m <- lapply(m, function(i) { attr(i,"match.length") <- attr(i,"capture.length") i }) regmatches(x,m) #[[1]] #[1] "AC" "CC" "AC" "CC" "AC" "CC" "AC" # #[[2]] #[1] "AC" "CC" "AC" "CC" "AC" "CC" "AC" 

No es una solución de expresiones regulares, y realmente no responde a ninguna de sus preguntas más importantes, pero también puede obtener el resultado deseado al utilizar las subcadenas de dos caracteres a la vez y luego eliminar los elementos de CA no deseados.

 x <- 'ACCACCACCAC' y <- substring(x, 1:(nchar(x)-1), 2:nchar(x)) y[y != "CA"] # [1] "AC" "CC" "AC" "CC" "AC" "CC" "AC" 

Una solución de stringi utilizando un grupo de captura en la parte de anticipación:

 > stri_match_all_regex('ACCACCACCAC', '(?=([AC]C))')[[1]][,2] ## [1] "AC" "CC" "AC" "CC" "AC" "CC" "AC" 

Esto no funciona con stringr ya que str_match_all no admite expresiones regulares PCRE.

Una respuesta adicional, basada en la propia respuesta de @hwnd (el original no permitía regiones capturadas de longitud variable), utilizando solo las funciones R incorporadas:

 > x <- 'ACCACCACCAC' > m <- gregexpr('(?=([AC]C))', x, perl=T)[[1]] > start <- attr(m,"capture.start") > end <- attr(m,"capture.start") + attr(m,"capture.length") - 1 > sapply(seq_along(m), function(i) substr(x, start[i], end[i])) [1] "AC" "CC" "AC" "CC" "AC" "CC" "AC" 

Bastante feo, por eso existen los paquetes de stringr etc.

Intereting Posts