Introducción

Una expresión regular es un mecanismo que permite seleccionar una cadena de caracteres de otra cadena a través de un patrón específico.

texto <- c("Filosofía", "Antropología", "Matemáticas", "Biología")
regexpr("gía",texto)
## [1] -1 10 -1  6
## attr(,"match.length")
## [1] -1  3 -1  3

El ejemplo anterior busca la sarta gía en el vector de sartas texto. Ingresa en cada posición del vector y busca si la sarta gía es un patrón identificable en cada una de las cadenas de caracteres, si encuentra el patrón entonces indica en cuál posición comienza el patrón:

1[A] 2[n] 3[t] 4[r] 5[o] 6[p] 7[o] 8[l] 9[o] 10[g] 11[í] 12[a] 1[B] 2[i] 3[o] 4[l] 5[o] 6[g] 7[í] 7[a]

Metacaracteres

Son caracteres no alfabéticos que poseen un significado especial en las expresiones regulares.

Cuantificadores

  • ?: El caracter que precede puede aparecer como mucho una vez.
  • +: El carácter que le precede debe aparecer al menos una vez.
  • *: El carácter que le precede puede aparecer cero, una, o más veces.
  • {}. Las llaves juegan el papel de meta caracteres, para que cumplan su funcionalidad deben estar despues de la expresión regular y encierren uno o varios números.
    • {n}: Indica que coincide n veces.
    • {n,}: Indica que coincide mas n veces.
    • {,n}: Indica que coincide hasta n veces.
    • {n,m}: Indica que coincide mas n veces y menos de m veces.

Alternación

  • $: El signo de dolar representa el final de la cadena de caracteres o el final de la línea.
  • ^: El acento representa el inicio de la cadena.

Agrupación

  • (): Los parentesis son usados para la aplicación de operadores sobre mas de un caracter.
  • []: Los corchetes agrupan caracteres en grupos o clases. Son útiles cuando es necesario buscar uno de un grupo de caracteres.
    • [a-z]: Especifica un rango de caracteres.
    • [^.... ]: Lista de caracteres excluidos
  • | Una barra vertical separa las alternativas. Realiza el papel de o.
  • . El punto busca cualquier carácter sin incluir los saltos de línea.

Backslash

  • \a: Representa una “campana” o “beep” que se produce al imprimir este carácter.
  • \e: Representa la tecla “Esc” o “Escape”
  • \x: Se utiliza para representar caracteres ASCII o ANSI si conoce su código. De esta forma, si se busca el símbolo de derechos de autor y la fuente en la que se busca utiliza el conjunto de caracteres Latin-1 es posible encontrarlo utilizando 9.
  • \d: Representa un dígito del 0 al 9.
  • \w: Representa cualquier carácter alfanumérico.
  • \s: Representa un espacio en blanco.
  • \D: Representa cualquier carácter que no sea un dígito del 0 al 9.
  • \W: Representa cualquier carácter no alfanumérico.
  • \S: Representa cualquier carácter que no sea un espacio en blanco.
  • \A: Representa el inicio de la cadena. No un carácter sino una posición.
  • \Z: Representa el final de la cadena. No un carácter sino una posición.
  • \b: Marca la posición de una palabra limitada por espacios en blanco, puntuación o el inicio/final de una cadena.
  • \B: Marca la posición entre dos caracteres alfanuméricos o dos no-alfanuméricos.

Negación

  • !: El signo de admiración representa una busqueda negativa, en otras palabras que no incluya la palabra que especificamos.

Metacaracteres especiales o de control

  • \t: Representa un tabulador.
  • \r: Representa el “retorno de carro” o “regreso al inicio” o sea el lugar en que la línea vuelve a iniciar.
  • \n: Representa la “nueva línea” el carácter por medio del cual una línea da inicio.
  • \f: Representa un salto de página
  • \v: Representa un tabulador vertical
  • \e: Representa un escape.

Búsqueda y condicionales

  • (?=): Búsqueda hacia adelante.
  • (?!): Búsqueda hacia adelante negativa, la posición no sigue un patrón.
  • (?<=): Búsqeda hacia atrás.
  • (?<!): Búsqueda hacia atrás negativa, la posición no sigue un patrón.
  • ?( ): Condicional, busca lo que está entre paréntesis, si es verdadero entrega lo que esta por fuera.
  • ?( ) |: Condicional, busca lo que está entre paréntesis, si es verdadero entrega lo que esta por fuera, sino entrega lo que sigue de |.

Clases de caracteres

  • [aeiou]: Coincide las vocales minúsculas.
  • [AEIOU]: Coincide las vocales mayúsculas.
  • [0123456789]: Coincide cualquier número.
  • [0-9]: Coincide cualquier número.
  • [a-z]: Coincide cualquier letra minúscula.
  • [A-Z]: Coincide cualquier letra mayúscula.
  • [a-zA-Z0-9]: Coincide cualquier alfanúmerico.
  • [^aeiou]: Coincide todo excepto las letras definidas.
  • [^0-9]: Coincide todo excepto los números.

Clases de caracteres tipo POSIX

  • [[:lower:]]: Coincide letras minúsculas.
  • [[:upper:]]: Coincide letras mayúsculas.
  • [[:alpha:]]: Coincide letras.
  • [[:digit:]]: Coincide números.
  • [[:space:]]: Coincide caracteres de espacio.
  • [[:blank:]]: Coincide caracteres de espacio, excepto los de línea nueva.
  • [[:alnum:]]: Coincide caracteres alfanuméricos.
  • [[:cntrl:]]: Coincide caracteres de control. Estos no son visibles como \t, \n, \e, \f, etc.
  • [[:punct:]]: Coincide caracteres de puntuación.
  • [[:xdigit:]]: Coincide caracteres de digitos Hexadecimales (0 - 9 A - E)
  • [[:print:]]: Coincide caracteres imprimible ([[:alpha:]], [[:punct:]] y espacios).
  • [[:graph:]]: Coincide caracteres gráficos ([[:alpha:]] y [[:punct:]])
  • [[:word:]]: Coincide dígitos, letras y guiones bajos.

Funciones para Expresiones Regulares

a <- c("Murciélago","Un pájaro en la ventana","Su ID: adf7149q#csl&232")

grep(): Muestra la posición del vector que contiene el patrón, con el argumento value se puede extraer el texto.

grep("(a|2)",a)
## [1] 1 2 3
grep("(a|2)",a,value = T)
## [1] "Murciélago"              "Un pájaro en la ventana"
## [3] "Su ID: adf7149q#csl&232"
grep("[[:digit:]]",a,value = T)
## [1] "Su ID: adf7149q#csl&232"

grepl(): Muestra un TRUE/FALSE en la posición del vector que contiene el patrón.

grepl("(a|2)",a)
## [1] TRUE TRUE TRUE
grepl("[[:digit:]]",a)
## [1] FALSE FALSE  TRUE

regexpr(): Busca el patrón en el vector de caracteres y extrae el índice y la longitud del emparejamiento.

regexpr("(a|2)",a)
## [1] 8 7 8
## attr(,"match.length")
## [1] 1 1 1
regexpr("[[:space:]]",a)
## [1] -1  3  3
## attr(,"match.length")
## [1] -1  1  1
regexpr("[[:digit:]]",a)
## [1] -1 -1 11
## attr(,"match.length")
## [1] -1 -1  1

gregexpr(): Busca el patrón en el vector de caracteres y extrae los índices y las longitudes del emparejamiento por cada cada cadena y lo guarda en una lista.

gregexpr("[l|j]a[g|r]o",a)
## [[1]]
## [1] 7
## attr(,"match.length")
## [1] 4
## 
## [[2]]
## [1] 6
## attr(,"match.length")
## [1] 4
## 
## [[3]]
## [1] -1
## attr(,"match.length")
## [1] -1
gregexpr("[[:space:]]",a)
## [[1]]
## [1] -1
## attr(,"match.length")
## [1] -1
## 
## [[2]]
## [1]  3 10 13 16
## attr(,"match.length")
## [1] 1 1 1 1
## 
## [[3]]
## [1] 3 7
## attr(,"match.length")
## [1] 1 1
gregexpr("[[:digit:]]",a)
## [[1]]
## [1] -1
## attr(,"match.length")
## [1] -1
## 
## [[2]]
## [1] -1
## attr(,"match.length")
## [1] -1
## 
## [[3]]
## [1] 11 12 13 14 21 22 23
## attr(,"match.length")
## [1] 1 1 1 1 1 1 1

substr(): Dada una sarta extrae un fragmento del texto entre start y stop.

substr(a,3,10)
## [1] "rciélago" " pájaro " " ID: adf"
substr(a,10,20)
## [1] "o"           " en la vent" "f7149q#csl&"
substr(a,3:5,6:10)
## [1] "rcié" "pája" "D: a"

regmatches(): Es similar a substr pero recibe las salidas de regexpr para extraer el fragmento del texto.

regmatches(a,regexpr("[[:digit:]]",a))
## [1] "7"
regmatches(a,regexpr("[l|j]a[g|r]o",a))
## [1] "lago" "jaro"
regmatches(a,gregexpr("[l|j]a[g|r]o",a))
## [[1]]
## [1] "lago"
## 
## [[2]]
## [1] "jaro"
## 
## [[3]]
## character(0)

regexec(): Es similar a regexpr pero se puede implementar con metacaracteres.

regexec("[[:punct:]] | [[:alpha:]]",a)
## [[1]]
## [1] -1
## attr(,"match.length")
## [1] -1
## attr(,"useBytes")
## [1] TRUE
## 
## [[2]]
## [1] 3
## attr(,"match.length")
## [1] 2
## attr(,"useBytes")
## [1] TRUE
## 
## [[3]]
## [1] 3
## attr(,"match.length")
## [1] 2
## attr(,"useBytes")
## [1] TRUE
regexec("[a-z]{1,5}",a)
## [[1]]
## [1] 2
## attr(,"match.length")
## [1] 4
## attr(,"useBytes")
## [1] TRUE
## 
## [[2]]
## [1] 2
## attr(,"match.length")
## [1] 1
## attr(,"useBytes")
## [1] TRUE
## 
## [[3]]
## [1] 2
## attr(,"match.length")
## [1] 1
## attr(,"useBytes")
## [1] TRUE

sub(): Busca el patrón en la sarta y reemplaza el primer emparejamiento por un valor definido.

sub("[a-z]{1,5}","---",a)
## [1] "M---élago"                 "U--- pájaro en la ventana"
## [3] "S--- ID: adf7149q#csl&232"
sub("[[:alnum:]]","---",a)
## [1] "---urciélago"              "---n pájaro en la ventana"
## [3] "---u ID: adf7149q#csl&232"
sub("(é|á|+[[:punct:]])","=",a)
## [1] "Murci=lago"              "Un p=jaro en la ventana"
## [3] "Su ID= adf7149q#csl&232"

gsub(): Busca el patrón en la sarta y reemplaza todos los valores del emparejamiento por un valor definido.

gsub("[a-z]{1,5}","---",a)
## [1] "M---é---"                    "U--- ---á--- --- --- ------"
## [3] "S--- ID: ---7149---#---&232"
gsub("[[:alnum:]]","_",a)
## [1] "__________"              "__ ______ __ __ _______"
## [3] "__ __: ________#___&___"
gsub("(é|á|[[:punct:]]|[[:upper:]])","=",a)
## [1] "=urci=lago"              "=n p=jaro en la ventana"
## [3] "=u === adf7149q=csl=232"

nchar(): Cuenta el número de caracteres en una sarta o vector de sartas.

nchar(a)
## [1] 10 23 23
nchar("    ")
## [1] 4

tolower(): Convierte todas las sartas o caracteres a minúsculas.

tolower(a)
## [1] "murciélago"              "un pájaro en la ventana"
## [3] "su id: adf7149q#csl&232"
tolower("NADA ME OBLIGA")
## [1] "nada me obliga"

toupper(): Convierte todas las sartas o caracteres a mayúsculas.

toupper(a)
## [1] "MURCIÉLAGO"              "UN PÁJARO EN LA VENTANA"
## [3] "SU ID: ADF7149Q#CSL&232"
toupper("voy para arriba")
## [1] "VOY PARA ARRIBA"

chartr(): Busca el patrón en una sarta y lo reemplaza por una cadena de caracteres definido.

chartr("iéla","Hola",a)
## [1] "MurcHolago"              "Un pájaro en la ventana"
## [3] "Su ID: adf7149q#csl&232"

setdiff(): Determina la diferencia entre dos vectores.

setdiff(a,c("Mucrielago","Un pájaro en la ventana","ID: adf7149q$csl&232"))
## [1] "Murciélago"              "Su ID: adf7149q#csl&232"

setequal(): Compureba si dos vectores contiene las mismas cadenas de caracteres.

setequal(a,c("Mucrielago","Un pájaro en la ventana","ID: adf7149q$csl&232"))
## [1] FALSE
setequal(a,c("Murciélago","Un pájaro en la ventana","Su ID: adf7149q#csl&232"))
## [1] TRUE

abbreviate(): Abrevia las sartas a un número definido de caracteres.

abbreviate(a,2)
##              Murciélago Un pájaro en la ventana Su ID: adf7149q#csl&232 
##                    "Mr"                 "Upelv"                   "SIa"
abbreviate(a,6)
##              Murciélago Un pájaro en la ventana Su ID: adf7149q#csl&232 
##                "Murclg"                "Unpelv"                "SID:a7"
abbreviate(a)
##              Murciélago Un pájaro en la ventana Su ID: adf7149q#csl&232 
##                  "Mrcl"                 "Upelv"                  "SIDa"

strsplit(): Divide las sartas basado en el patrón de busqueda y la transforma en un vector.

strsplit(a,"l")
## [[1]]
## [1] "Murcié" "ago"   
## 
## [[2]]
## [1] "Un pájaro en " "a ventana"    
## 
## [[3]]
## [1] "Su ID: adf7149q#cs" "&232"
strsplit(a,"[[:punct:]]")
## [[1]]
## [1] "Murciélago"
## 
## [[2]]
## [1] "Un pájaro en la ventana"
## 
## [[3]]
## [1] "Su ID"     " adf7149q" "csl"       "232"
strsplit(a,"(é|á|[[:blank:]])")
## [[1]]
## [1] "Murci" "lago" 
## 
## [[2]]
## [1] "Un"      "p"       "jaro"    "en"      "la"      "ventana"
## 
## [[3]]
## [1] "Su"               "ID:"              "adf7149q#csl&232"

Paquete stringr

Este paquete hace parte del universo tidyverse y sirve para trabajar análisis de texto.

install.packages("stringr",dependencies = T)
library(stringr)

str_detect(cadena, patrón): Detecta la presencia de un patrón o la coincidencia en una cadena.

str_detect(a,"(élag|ája)")
## [1]  TRUE  TRUE FALSE
str_detect(a,"[[:digit:]]")
## [1] FALSE FALSE  TRUE

str_which(cadena, patrón): Encuentra los índices de las cadenas que contienen un patrón coincidente.

str_which(a,"(élag|ája)")
## [1] 1 2
str_which(a,"[[:blank:]]")
## [1] 2 3

str_count(cadena, patrón): Cuenta el número de coincidencias en una cadena.

str_count(a,"[[:lower:]]")
## [1]  9 18  8
str_count(a,"[[:blank:]]")
## [1] 0 4 2

str_locate(cadena, patrón): Localiza las posiciones del patrón que coincide en la cadena. También str_locate_all.

str_locate(a,"la")
##      start end
## [1,]     7   8
## [2,]    14  15
## [3,]    NA  NA
str_locate_all(a,"la")
## [[1]]
##      start end
## [1,]     7   8
## 
## [[2]]
##      start end
## [1,]    14  15
## 
## [[3]]
##      start end
str_locate_all(a,"[[:punct:]]")
## [[1]]
##      start end
## 
## [[2]]
##      start end
## 
## [[3]]
##      start end
## [1,]     6   6
## [2,]    16  16
## [3,]    20  20
str_locate(a,"[[:digit:]]")
##      start end
## [1,]    NA  NA
## [2,]    NA  NA
## [3,]    11  11
str_locate_all(a,"[[:digit:]]")
## [[1]]
##      start end
## 
## [[2]]
##      start end
## 
## [[3]]
##      start end
## [1,]    11  11
## [2,]    12  12
## [3,]    13  13
## [4,]    14  14
## [5,]    21  21
## [6,]    22  22
## [7,]    23  23

str_sub(cadena, start = 1L, end = -1L): Extrae subcadenas de un vector de caracteres.

str_sub(a,3,7)
## [1] "rciél" " pája" " ID: "

str_subset(cadena, patrón): Devuelve solo las cadenas que contienen un patrón coincidente.

str_subset(a,"la")
## [1] "Murciélago"              "Un pájaro en la ventana"
str_subset(a,"[[:blank:]]")
## [1] "Un pájaro en la ventana" "Su ID: adf7149q#csl&232"

str_extract(cadena, patrón): Devuelve el primer patrón encontrado que coincide en cada cadena, como un vector. También str_extract_all para devolver cada patrón coincidente.

str_extract(a,"la")
## [1] "la" "la" NA
str_extract(a,"[[:blank:]]")
## [1] NA  " " " "
str_extract(a,"[[:punct:]]")
## [1] NA  NA  ":"
str_extract_all(a,"[[:punct:]]")
## [[1]]
## character(0)
## 
## [[2]]
## character(0)
## 
## [[3]]
## [1] ":" "#" "&"
str_extract_all(a,"[[:graph:]]")
## [[1]]
##  [1] "M" "u" "r" "c" "i" "é" "l" "a" "g" "o"
## 
## [[2]]
##  [1] "U" "n" "p" "á" "j" "a" "r" "o" "e" "n" "l" "a" "v" "e" "n" "t" "a" "n" "a"
## 
## [[3]]
##  [1] "S" "u" "I" "D" ":" "a" "d" "f" "7" "1" "4" "9" "q" "#" "c" "s" "l" "&" "2"
## [20] "3" "2"

str_match(cadena, patrón): Devuelve el primer patrón encontrado que coincide en cada cadena, como una matriz, con una columna para cada un metacaracter entre ( ) agrupado por patrón. También str_match_all.

str_match(a,"[[:alnum:]]")
##      [,1]
## [1,] "M" 
## [2,] "U" 
## [3,] "S"
str_match_all(a,"[[:space:]]")
## [[1]]
##      [,1]
## 
## [[2]]
##      [,1]
## [1,] " " 
## [2,] " " 
## [3,] " " 
## [4,] " " 
## 
## [[3]]
##      [,1]
## [1,] " " 
## [2,] " "
  • str_length(cadena): Los anchos de las cadenas (i.e. número de puntos de código, suele ser igual al número de caracteres).
  • str_pad(): Extiende cadenas a un ancho constante.
  • str_trunc(): Trunca el ancho de una cadena, eliminando el contenido sobrante.
  • str_trim(): Elimina los espacios en blanco desde el comienzo y/o el final de una cadena.
  • str_sub() <- valor: Reemplaza subcadenas identificadas con str_sub() y se asignan al resultado.
  • str_replace(cadena, patrón, reemplazo): Reemplaza el primer patrón coincidente en cada cadena.
  • str_replace_all(cadena, patrón, reemplazo): Remplaza todos los patrones coincidentes en cada cadena.
  • str_to_lower(cadena) Convierte cadenas a minúscula.
  • str_to_upper(cadena): Convierte cadenas a mayúsculas.
  • str_to_title(cadena): Convierte cadenas a título.

str_c(..., sep = "", collapse = NULL): Une múltiples cadenas en una.

str_c("Hola",a,sep = " ")
## [1] "Hola Murciélago"              "Hola Un pájaro en la ventana"
## [3] "Hola Su ID: adf7149q#csl&232"

str_c(..., sep = "", collapse = ""): Colapsa un vector de cadenas en una sola cadena.

str_c(a,collapse = " - ")
## [1] "Murciélago - Un pájaro en la ventana - Su ID: adf7149q#csl&232"
  • str_dup(cadena, veces): Repite cadenas varias veces.
  • str_split_fixed(cadena, patrón, n): Divide un vector de cadenas en una matriz de subcadenas (dividiendo en las ocurrencias del patrón de coincidencia). También str_split para devolver una lista de subcadenas.
  • str_order(): Devuelve el vector de índices que ordena un vector de caracteres. x[str_order(x)].
  • str_sort(): Ordena un vector de caracteres.
  • str_conv(cadena, encoding): Sobre escribe el tipo de codificación de una cadena.
  • str_view(cadena, patrón, match = NA): Vista en HTML de la primera coincidencia de expresión regular en cada cadena.
  • str_view_all(cadena, patrón, match = NA): Vista en HTML de todas las coincidencias de la expresión regular.
  • str_wrap(): Envuelve cadenas en párrafos de forma atractiva.

Web Scrapping

Esta metodología sirve para buscar patrones en internet y construir bases de datos estructuradas con el fin de realizar análisis estadísticos posteriores. El primer paso es identificar los patrones en las direcciones de las páginas web, luego identificar los nodos con la información de interés y finalmente extraer la información con Expresiones Regulares

Este es un ejemplo básico.

# install.packages("rvest",dependencies = T)
library(rvest)

curriculos <- ""
for (dip in seq(1,10,by=1)){
  url = paste0("http://www.congreso.es/portal/page/portal/Congreso/Congreso/Diputados/BusqForm?_piref73_1333155_73_1333154_1333154.next_page=/wc/fichaDiputado?idDiputado=",dip,"&idLegislatura=12")
  
  congreso <- read_html(url)
  curric <- congreso %>%
    html_node("#curriculum") %>%
    html_text %>%
    strsplit(split = "\n") %>%
    unlist() %>%
    .[. != ""]
  #Pequeña limpieza de texto
  curric <- trimws(curric)
  #Elimina las líneas sin contenido
  curric <- curric[which(curric!="")]
  #Nos quedamos justo con la linea que hay debajo de la palabra legislaturas
  linea <- curric[grep("legislatura", curric)+1]
  curriculos <- rbind(curriculos,linea)
}

curriculos <- data.frame(curriculos[-1])
palabras <- strsplit(as.matrix(curriculos)," ")
palabras <- as.character(unlist(palabras))
palabras <- data.frame(palabras)
names(palabras) = c("V1")
palabras$V1 <- sub("([[:space:]])","",palabras$V1)
palabras$V1 <- sub("([[:digit:]])","",palabras$V1)
palabras$V1 <- sub("([[:punct:]])","",palabras$V1)
palabras$largo <- nchar(palabras$V1)
palabras
palabras <- subset(palabras, largo>4)
palabras
library(plyr)
(conteo <- data.frame(ddply(palabras, "V1",summarise, cuenta=length(V1) )))
(conteo[order(-conteo$cuenta),])
require(wordcloud2)
wordcloud2(conteo,size=1,color='random-dark',gridSize = 10)