Bienvenido, me llamo Luis y esta vez les traigo otro nuevo post.
Índice
Secretos para trabajar con texto usando herramientas avanzadas de expresiones regulares en R
Entonces, ya conoce los conceptos básicos de las expresiones regulares, o regex
, en R
. Cosas como cómo usar conjuntos de caracteres, metacaracteres, cuantificadores y grupos de captura.
Estos son los bloques de construcción básicos, pero usted es un usuario avanzado, nunca se satisface sólo con lo básico.
Sus problemas de resolución de textos son mucho más intrincados de lo que podría esperar resolver con esas herramientas.
Por suerte para ti, hay más conceptos de expresiones regulares en R
para aprender. ¡Está lejos para más bondad de disputas de texto!
(Text)
¡Anclas fuera!
Antes de que podamos zarpar en las Expresiones Regulares SS, necesitamos discutir el ancla. Más específicamente, anclajes de texto. Un ancla de texto dice que busque coincidencias al principio o al final de una cadena. En R
, hay 2
tipos de anclajes:
-
^
: Coincide con la siguiente expresión regular al principio de una cadena. -
$
: Coincide con la expresión regular anterior al final de una cadena.
Como recordatorio, para usar regex en R
, debe usar el paquete stringr
. La función str_extract_all()
es particularmente útil cuando se experimenta con nuevos temas de expresiones regulares, como anclas.
Devolverá una lista que contiene un vector de los valores reales de las coincidencias en la cadena. Asegúrese de cargar el paquete stringr
antes de comenzar.
library(stringr)
Para zarpar, debemos levantar el ancla al inicio del viaje. Cuando trabaje con datos de texto, es posible que deba hacer coincidir un patrón de expresiones regulares, pero solo si aparece como lo primero en la cadena. Para hacer eso, usamos el ancla ^
.
Para demostrarlo, nuestro objetivo es encontrar la palabra "el"
, pero solo si aparece al principio de una cadena. Aquí hay algunas cadenas de ejemplo que se pueden usar para probarlo.
anchor <- "The ship sets sail on the ocean" anchor_n <- "Ships set sail on the ocean to go places"
Empezando por el anchor
cadena, cuando usamos el anchor ^
para encontrar "the"
, solo tenemos una instancia de ella devuelta.
str_extract_all(anchor, "^[Tt]he") [[1]] [1] "The"
Sabemos que esta es la primera instancia porque "The"
al principio de la cadena está en mayúscula. Ahora con anchor_n
, no se devuelven resultados.
La expresión regular coincidiría normalmente con "the"
en la oración, pero con el anchor ^
es solo verificar el comienzo de la oración.
str_extract_all(anchor_n, "^[Tt]he") [[1]] character(0)
Al final de nuestro crucero de expresiones regulares, tenemos que echar el ancla. A veces es necesario hacer coincidir un patrón de expresiones regulares solo si aparece al final de una cadena. Esto se logra con el ancla $
.
Echemos otro vistazo a la cadena anchor
, esta vez buscando "océano"
al final de la cadena. Tendremos un resultado, "océano"
.
str_extract_all(anchor, "ocean$") [[1]] [1] "ocean"
De nuevo, si miramos anchor_n
, esta vez usando el $
o end anchor
, no obtendremos coincidencias, aunque aparezca "océano"
en la cadena. Si no está al final de la cadena, el $
el ancla no lo recogerá.
str_extract_all(anchor_n, "ocean$") [[1]] character(0)
Negación Regex (Avoiding Icebergs – Evitar icebergs)
Ahora que sabemos cómo hacer coincidir los patrones al principio y al final de las cadenas (subiendo y bajando el ancla de las expresiones regulares SS
), podemos pasar al siguiente concepto: decirle a regex qué no para que coincida.
Imagínese por un momento que es el capitán de un gran barco y está en su viaje inaugural. Llamemos a este barco El Titanic. Como capitán de ese barco, probablemente esté muy interesado en no golpear un iceberg.
En cadenas, es posible que desee especificar ciertos patrones para evitar. Para hacer esto, use negaciones. Estos coincidirán con cualquier cosa EXCEPTO
lo que especifique. Hay dos formas principales de manejarlos en R
:
- Metacaracteres en mayúscula: los metacaracteres coinciden con un conjunto específico de caracteres. Un meta personaje en mayúscula generalmente coincidirá con todo menos con ese conjunto de caracteres
-
^
y conjuntos de caracteres: usando un^
junto con un juego de caracteres coincidirá con todo excepto lo que se especifica en el juego de caracteres
En mi artículo anterior sobre expresiones regulares en R
, cubrimos tres metacaracteres diferentes: \s
, \w
y \d
.
Como recordatorio, coinciden con un determinado conjunto de caracteres en una cadena: \s
coincide con caracteres de espacio en blanco (espacios, tabulaciones y nuevas líneas), \w
coincide con caracteres alfanuméricos (letras y números), y \d
coincide con cualquier dígito (números).
Cuando ponga en mayúscula cualquiera de estos metacaracteres, coincidirá con todo EXCEPTO
lo que normalmente coincidiría. Para verlos en acción, creemos una nueva cadena que tenga espacios, números, letras y puntuación:
negation <- "I sail my 3 ships on the 7 seas."
Cuando echemos un vistazo a nuestros metacaracteres en mayúscula, veremos cómo operan de manera diferente a sus contrapartes en minúsculas.
-
\S
: Esto coincidirá con cualquier cosaEXCEPTO
los espacios. Vemos en la salida todas las letras, números y puntuación de la cadenanegation
.
str_extract_all(negation, "\S")[[1]] [1] "I" "s" "a" "i" "l" "m" "y" "3" "s" "h" "i" "p" "s" "o" "n" "t" "h" "e" "7" "s" "e" "a" "s" "."
-
\W
: Esto coincidirá con cualquier cosaEXCEPTO
letras y números. Nuestro resultado aquí es cada espacio y el punto al final de la oración.
str_extract_all(negation, "\W")[[1]] [1] " " " " " " " " " " " " " " " " "."
-
\D
: Esto coincidirá con cualquier cosaEXCEPTO
números. La salida, como habrás adivinado, tiene letras, espacios y puntuación.
str_extract_all(negation, "\D")[[1]] [1] "I" " " "s" "a" "i" "l" " " "m" "y" " " " " "s" "h" "i" "p" "s" " " "o" "n" " " "t" "h" "e" " " " " "s" "e" "a" "s" "."
Algunos casos de uso requieren la negación con más flexibilidad de la que pueden proporcionar los metacaracteres. Veamos un escenario de ejemplo:
- Coincidir con todas las consonantes en una cadena determinada.
Analicemos este problema. Hay 21
consonantes en el alfabeto y las queremos todas. No son consecutivos, por lo que no podemos simplemente usar un rango de letras en un conjunto de caracteres para obtenerlos.
Sabemos que las vocales y consonantes son mutuamente excluyentes y que solo hay 5
vocales. Si podemos encontrar todas las vocales, deberíamos poder negarlo para obtener todas las consonantes.
Comencemos con un repaso de cómo encontrar vocales con un conjunto de caracteres.
str_extract_all(negation, "[AEIOUaeiou]")[[1]] [1] "I" "a" "i" "i" "o" "e" "e" "a"
Los caracteres dentro de los corchetes definen el juego de caracteres. En este caso, todas las vocales coinciden. Para obtener todo excepto las vocales, podemos usar el ^
dentro del juego de caracteres. Esto negará todo lo que hay dentro.
str_extract_all(negation, "[^AEIOUaeiou]")[[1]] [1] " " "s" "l" " " "m" "y" " " "3" " " "s" "h" "p" "s" " " "n" " " "t" "h" " " "7" " " "s" "s" "."
… Pero esas no son las consonantes. Todavía queda un poco de trabajo por hacer. Tenemos espacios, dígitos y puntuación en nuestros resultados.
Como todo se niega en el grupo de captura, simplemente hacemos coincidir todo lo que no queremos en el resultado. \s
cuida los espacios, \d
se encarga de los dígitos y \.
cuida el período.
str_extract_all(negation, "[^AEIOUaeiou\s\d\.]")[[1]] [1] "s" "l" "m" "y" "s" "h" "p" "s" "n" "t" "h" "s" "s"
Después de agregar todos los caracteres que necesitábamos para terminar con solo consonantes, tal vez eso no sea más rápido que escribir 21
consonantes diferentes, pero demuestra cómo podemos sumar todo y usar expresiones regulares para obtener exactamente lo que queremos.
Mira a tu alrededor (Viewing the Wildlife – Viendo la vida silvestre)
Cuando estamos en el mar, es posible que tengamos algo a lo que estemos atentos. Ver algo de vida salvaje sería un viaje más interesante. Buscamos la vida silvestre para poder encontrar un lugar cercano para nuestro barco.
De manera similar a cómo queremos buscar entre la vida silvestre un lugar para estacionar, es posible que deseemos buscar en algún hilo la información que realmente queremos.
Como ocurre con la mayoría de las tareas, las expresiones regulares facilitan mucho esta tarea. Para hacerlo, usamos algo llamado mira alrededor.
Mire a su alrededor para buscar una coincidencia específica en la cadena, luego devuelva algo inmediatamente antes o después. Esto nos deja con dos tipos principales de mirar a nuestro alrededor: mirar hacia adelante y mirar hacia atrás.
Usemos la siguiente cadena como un ejemplo de cómo funcionan ambos.
lookaround <- "A penguin costs 2.99, a whale costs 5.99, I only have 3.50 left."
Tendremos dos escenarios para la información que queremos extraer de esta cadena.
- ¿Cuál es el costo de cada animal?
- ¿Qué animales están a la venta?
Al principio, puede que se pregunte por qué necesitamos mirar a nuestro alrededor para hacer esto. Simplemente puede buscar un dígito, un punto y dos dígitos más. Algo como esto:
str_extract_all(lookaround, "\\d\\.\\d {2}")
Ese no es un mal comienzo, pero la salida de esa línea de código le daría tres precios.
[[1]] [1] "2.99" "5.99" "3.50"
Solo hay dos precios de animales, el último no está relacionado, por lo que querríamos excluirlo. Mirar a nuestro alrededor nos ayudará a eliminar el último y a poner todo bien en un marco de datos.
Mirando a la cadena lookaround
, vemos que el precio de cada animal está precedido por la palabra "costos"
. Usaremos un look behind
.
Esto coincidirá con lo que normalmente coincidiríamos, pero solo si tiene una coincidencia de otra cosa antes. La fórmula general para mirar hacia adelante es "(?<=if preceded by this)match_this"
.
En nuestro caso, esto se traduciría como a continuación (\s
se agrega para tener en cuenta el espacio entre la palabra y los números):
# Look behind prices <- str_extract_all(lookaround, "(?<=costs)\\s\\d\\. \\d {2}") prices
Ahora tenemos los precios de cada uno de nuestros animales, excluyendo la cantidad de dinero que me queda en la cadena.
[[1]] [1] " 2.99" " 5.99"
Si miras de cerca, notarás que hay espacio en las cuerdas. No se preocupe por ellos por ahora, nos ocuparemos de ellos cuando creemos un marco de datos para mantener nuestra lista de precios.
Ahora que tenemos los precios de nuestros animales de la cadena, queremos obtener los nombres de los animales para nuestro marco de datos de lista de precios.
Para hacer esto, ahora necesitamos hacer coincidir la palabra directamente antes de la palabra "costos"
. Para esto usaremos look aheads
.
La fórmula básica para mirar hacia adelante es la siguiente: "match this(?=if followed by this)"
. Para obtener los nombres de los animales de nuestra cadena, se vería así:
# Look Aheads animals <- str_extract_all(lookaround, "\w+\s(?=costs)") animals
Así, hemos capturado cada palabra que viene antes de que la palabra cueste. En nuestra cadena están los nombres de todos los animales.
[[1]] [1] "penguin " "whale "
Para crear el marco de datos para los precios de nuestros animales, ya tenemos la mayor parte de lo que necesitamos. Simplemente creamos un marco de datos con los vectores animals
y prices
como las columnas.
animal_prices <- data.frame( animals=animals[[1]], prices=prices[[1]], stringsAsFactors=FALSE )
En caso de que lo hayas olvidado, cuando usamos str_extract_all()
, devuelve una lista con un vector de cadenas. Para acceder a ese vector de cadenas, usamos la notación de doble corchete (animals[[1]]
).
El argumento stringsAsFactors
se establece en falso; de lo contrario, R
creará las columnas como factores, no como cadenas.
Nuestro siguiente paso es cuidar esos espacios adicionales. Para un marco de datos con más columnas, podríamos considerar usar un función map
de el paquete purrr
, pero como el nuestro es pequeño podemos hacer el proceso manualmente.
Usaremos la función str_trim()
. Elimina los espacios al principio y al final de una cadena de forma predeterminada.
animal_prices$animals <- str_trim(animal_prices$animals) animal_prices$prices <- as.numeric(str_trim(animal_prices$prices))
Se agregó la función as.numeric()
para corregir el tipo de columna prices
de un carácter a numérico. El marco de datos resultante se parece al siguiente:
animals prices 1 penguin 2.99 2 whale 5.99
Conclusión
Así, su crucero en SS Regular Expressions
ha llegado a su fin. Aprendiste:
- Cómo hacer coincidir los patrones que aparecen al principio o al final de una cadena
- Cómo usar la negación para que coincida con cualquier cosa excepto lo que especifique
- Cómo usar mirar alrededor para que coincida con algo seguido o precedido por otra cosa que especifique
Aquí hay algunos otros recursos relacionados con la expresión regular en R
que pueden resultarle útiles:
- El oficial
stringr
página en el sitio tidyverse: La gente de RStudio han recopilado recursos para ayudar a aprender paquetes comostringr
. Incluso incluyeron unstringr
hoja de trucos que puede imprimir y hacer referencia. - R para ciencia de datos: Escrito por Hadley Wickham, autor del paquete
stringr
, este libro es una buena referencia para todo enR
. Hay incluso un capítulo que cubre expresiones regulares avanzadas enR
. Está disponible en línea de forma gratuita aquí, o puede comprar una copia impresa aquí (Enlace PAGADO). - Cursos de Datacamp (Enlace de pago): una comunidad de aprendizaje en línea dedicada a la ciencia de datos, el aprendizaje automático y la visualización de datos. Consulte su curso
"Manipulación de cadenas con stringr en R"
. ¡El primer capítulo de cada curso en Datacamp es gratis!
Como siempre, avíseme si le gustó el contenido. ¿No te gusta cómo uso las expresiones regulares? Dimelo en los comentarios. De cualquier manera, suscríbete para recibir una notificación cada vez que publique contenido nuevo.
Gracias por leer este post.
Añadir comentario