¿Cómo usar expresiones regulares en NLTK para analizar un corpus?
En el fascinante mundo de la lingüística computacional, las expresiones regulares juegan un papel crucial para realizar búsquedas avanzadas en grandes cantidades de texto, como un corpus. Si estás interesado en descubrir cómo construir patrones de búsqueda efectivos, estás en el lugar adecuado. En esta guía, desentrañamos el uso de las expresiones regulares con la librería NLTK (Natural Language Toolkit) y Python, desde lo básico hasta los patrones más sofisticados.
¿Qué es una expresión regular?
Las expresiones regulares son secuencias de caracteres que forman un patrón de búsqueda. Utilizadas en el procesamiento de texto, permiten navegar y filtrar información dentro de cadenas de texto para encontrar coincidencias específicas. Python cuenta con una poderosa librería llamada re que facilita su incorporación.
¿Cómo construir un arreglo filtrando palabras con expresiones regulares?
Comenzamos con la creación de un arreglo utilizando una expresión regular simple. A continuación, se muestra cómo definir patrones de búsqueda básicos y avanzados.
import re
# Ejemplo básico: Buscar palabras que contengan 'es'AR =[w for w in flatten if re.search(r'es', w)]
En este fragmento de código, utilizamos la función re.search() de la librería de expresiones regulares de Python, especificando un patrón y evaluando cada palabra en la lista flatten. Si el patrón 'es' se encuentra en una palabra, esta se añade al nuevo arreglo AR.
¿Cómo redefinir patrones de búsqueda utilizando metacaracteres?
Los metacaracteres enriquecen las búsquedas con expresiones regulares al permitir una mayor especificidad, como buscar coincidencias al principio o al final de las palabras.
$: Marca el final de una cadena.
# Ejemplo: Solo palabras que terminan en 'es'AR =[w for w in flatten if re.search(r'es$', w)]
^: Marca el inicio de una cadena.
# Ejemplo: Solo palabras que empiezan con 'es'AR =[w for w in flatten if re.search(r'^es', w)]
¿Cómo utilizar rangos en las expresiones regulares?
Los rangos permiten definir un conjunto de caracteres que pueden ocupar una posición específica dentro de una cadena de texto:
# Ejemplo: Buscar palabras que comienzan con 'g', 'h' o 'i'AR =[w for w in flatten if re.search(r'^[ghi]', w)]
En este ejemplo, creamos un arreglo donde filtramos palabras que empiezan con una letra ubicada entre 'g' y 'i'. Esto se logra definiendo un rango [ghi] como el primer carácter en las palabras seleccionadas en el arreglo.
¿Qué son las clausuras en las expresiones regulares?
Las clausuras especifican el número de repeticiones permitidas para un patrón dado:
*: Permite que un patrón se repita cero o más veces.
# Ejemplo: Patrones que pueden aparecer cero o más vecesAR =[w for w in flatten if re.search(r'^no*', w)]
+: Requiere que un patrón se repita al menos una vez.
# Ejemplo: Patrones que deben aparecer al menos una vezAR =[w for w in flatten if re.search(r'^no+', w)]
Cómo seguir aprendiendo sobre expresiones regulares
¡Esto es solo el comienzo! Las expresiones regulares son una herramienta impresionante para aquellos apasionados por la computación y el análisis lingüístico. A medida que avances, podrás explorar cómo definir tokenizadores usando estas técnicas, ayudando a estructurar texto de manera más eficiente. No dudes en experimentar y seguir practicando para dominar su uso. Tu viaje en el ámbito del procesamiento de lenguaje natural será increíblemente enriquecedor. ¡Adelante!
Definicion de metacaracter: Es una subcadena de texto que define un patron de busqueda muy basico. En el ejemplo tenemos:
re.search('es')
En donde nos trae todas las cadenas de texto que contengan en alguna parte la subcadena 'es'.
En las expresiones regulares podemos tener busquedas al inicio o al final.
Al inicio seria
re.search('es$')
Al final quedaria como:
re.search('^es')
El rango como su nombre lo indica es una expresion regular que nos da como resultado las cadenas que tengan a inicio o final lo contenido en dicho rango. Ejemplo:
re.search('^[ghi]')
Clausura:
Existen 2 tipos:
El * indica que se puede repetir 0 ó mas veces.
El + indica que se puede repetir 1 ó mas veces.
Hola, el simbolo $ es para final y ^ es para inicio, los pusiste al reves.
La función re.search(p, s) tiene dos parámetros. En p introducimos la expresión que queremos buscar y en s la "lista" en la que queremos buscar la expresión p.
También se puede hacer uno de un filtro así:
import nltk
from re importmatchimport functools
import operator
nltk.download('cess_esp')corpus = nltk.corpus.cess_esp.sents()flatten = functools.reduce(operator.iconcat, corpus,[])filtered_values =list(filter(lambda w:match('^[afc]', w), flatten))filtered_values[:10]
Hola Francisco, Generalmente los textos que me llegan o que me gustaría analizar están mal escritos. un ejemplo sencillo (cabeza): cabeeza, cabesa, cavesa, caveza, cab, alguna sugerencia para trabajar con estas palabras? generalmente uso frecuencias seguido de orden ...pero muchas veces cambiarlas una a una toma muchísimo tiempo. Gracias! Muy interesante el curso!
para estas aplicaciones que son mas cercanas a la data que uno encuentra en la vida real, es mejor usar un embedding basado en una red neuronal, ese es un tema que tocaremos en futuros cursos, por ahora puedo recomendarte que leas sobre modelos pre-entrenados con TensorFlow como el universal sentence encoder o BERT:
Este es un tema avanzado, pero es lo que con certeza te permítala ejecutar esa tarea de procesamiento con exito.
Estructura de la función re.search()
Esta función determina si el patrón de la expresión regular aplica en una cadena de texto, re.searhc(p, s)
arr =[word for word in flatten if re.search('es',word)]print(arr[:7])
Podemos ver que todos los elementos tienen dentro el texto es.🤯 Este es es un metacaracter que define un patrón de búsqueda muy básico. Podemos crear patrónes de busqueda mucho más complejos.
El caracter $ sirve para reemplazar cualquier caracter.
^ sirve para indicar que está al inicio de la cadena de texto.
arr =[word for word in flatten if re.search('es$', word)]print(arr[:5])arr =[word for word in flatten if re.search('^es', word)]print(arr[:5])
Ahora veremos que es el rango. La notación es [a-z], [ghi]. Cualquier letra en ese rango puede estar en dicho lugar
arr =[word for word in flatten if re.search('^[ghi]', word)]print(arr[:7])
Por último, tenemos clausuras, y hay dos tipos:
*: Una cadena de texto se puede repetir 0 o más veces.
+: La cadena se puede repetir 1 o más veces.
arr =[word for word in flatten if re.search('^(no)+', word)]print(arr[:10])
Que es ?
Esta funcion determmina el patron de busqueeda dee caracteres; p es la cadena a buscar y s es el arreglo de donde se sacara la informacion
re.search(p,s)
Estructura
La función re.search() en este caso buscara token con la cadena de caracteres. "es", en cualquier posición del token
arr =[w for w in flatten if re.search("es", w)]print(arr[:10])
entrega
['estatal','jueves','empresa','centrales','francesa','japonesa','millones','millones','dólares','millones']
La función re.search() en este caso las expresiones que terminen en estos caracteres entregados por parámetros
arr =[w for w in flatten if re.search("es$", w)]print(arr[:10])
entrega
['jueves','centrales','millones','millones','dólares','millones','millones','dólares','es','militantes']
La función re.search() en este caso las expresiones que comienzan en estos caracteres entregados por parámetros
arr =[w for w in flatten if re.search("^es", w)]print(arr[:10])
entrega
['estatal','es','esta','esta','eso','es','especial','especialmente','este','estas']
Rango
Con el rango podemos hacer un filtrado mayor, dato que tenemos varios caracteres en los que podemos buscar, el rango se escribe dentro de [ ]
arr =[w for w in flatten if re.search("^[ghi]", w)]print(arr[:10])
entrega
['grupo','hoy','gas','gas','intervendrá','invertir','gas','hoy','insulto','intervención']
Clausuras
Las clausuras nos ayudaran a delimitar la búsqueda por caracteres
*** repetirr 0 o mas veces**
+ repetir 1 o mas veces
con 0 repeticiones
arr =[w for w in flatten if re.search("^(no)*", w)]print(arr[:1
entrega
['El','grupo','estatal','Electricité_de_France','-Fpa-','EDF','-Fpt-','anunció','hoy',',']
con 1 o mas repeticiones
arr =[w for w in flatten if re.search("^(no)+", w)]print(arr[:10])
entrega
['norte','no','no','noche','no','no','notificación','no','no','no']
Estructura de la funcion re.search()
Esta funcion determina si el patron de búsqueda p está contenido en la cadena s
re.search(p, s)
Búsquedas en cadenas de texto con meta caracteres básicos
# Buscamos el 'es' en la cadena w en donde estearr =[w for w in flatten if re.search('es', w)]print(arr[:5])# Buscamos el 'es' en la cadena w al final arr =[w for w in flatten if re.search('es$', w)]print(arr[:5])# Buscamos el 'es' en la cadena w al principioarr =[w for w in flatten if re.search('^es', w)]print(arr[:5])
Patrones de búsqueda usando el concepto de rango
Ejemplos:
Rango [a-z]: Determina que el carácter debe estar ubicado entra la a y la z
Rango [ghi]: Determina que el carácter que este en esta posición puede ser cualquier letra entre la g, h e i.
# Buscamos que al principio de tu cadena de texto debe de ser entre la g, h y la iarr =[w for w in flatten if re.search('^[ghi]', w)]print(arr[:10])
Clausuras
Tipos:
El *: Esta clausura representa que se puede repetir 0 o más veces.
El +: Esta clausura representa que s puede repetir 1 o más veces.
# El patron de busqueda será que al principio aparezca no y que esa secuencia se puede repetir 0 o más veces arr1 =[w for w in flatten if re.search('^(no)*', w)]print(arr1[:20])# El patron de busqueda será que la sub cadena de texto no debe de aparecer al menos una vezarr2 =[w for w in flatten if re.search('^(no)+', w)]print(arr2[:20])
Hola, tengo una duda no hay diferencia entre la claurusa + y usar el metacaracter ' ' cierto?
<arr =[w for w in flatten if re.search('^(no)+', w)]print(arr[:20])['norte','no','no','noche','no','no','notificación','no','no','no','no_obstante','no','no','no','norte','no','no','no','no','norteamericano']arr =[w for w in flatten if re.search('^no', w)]print(arr[:20])['norte','no','no','noche','no','no','notificación','no','no','no','no_obstante','no','no','no','norte','no','no','no','no','norteamericano']>
Recordando el curso Autómatas y Lenguajes Formales.
No entiendo porque Francisco dice "0 o mas veces". Si es cero no hay mas veces.
Alguien tiene una explicación de porque utiliza esa expresión.
Gracias
A lo que se refiere es que no es obligatoria, puede no estar (0) o puede estar varias veces, por ejemplo si encuentra la palabra nono, como se ve en el ejemplo todas las palabras pueden cumplir porque cumplen con el no iniciar con no. Si se usa el símbolo + en lugar del * solo las palabras que comiencen con no van a ser válidas para la expresión regular.
Es FREE, en el ahi un modulo que es sobre expresiones regulares. Se los recomiendo.
Muy buena clase, si puedes tomar el curso de expresiones regulares del profesor Beco estos dos cursos seran una combinación potente en tu stack
🧠Expresiones Regulares con NLTK y Python
🔍 1. Qué son las expresiones regulares
Definición:
Son patrones de búsqueda formados por secuencias de caracteres.
Permiten encontrar, filtrar o manipular texto de manera automática y precisa.
💡 En Python: se utilizan con la librería re.
💬 En NLTK: ayudan a analizar texto dentro de corpus lingüísticos.
🧰 2. Herramientas necesarias
🧩 Librería re: maneja las expresiones regulares.
📘 Librería NLTK: analiza texto y corpus en el campo del Procesamiento del Lenguaje Natural (NLP).
🔗 Combinación ideal:
Usar NLTK + re para búsquedas y filtrados avanzados en textos.
💻 3. Ejemplo básico
import re
# Buscar palabras que contengan 'es'
AR = [w for w in flatten if re.search(r'es', w)]
📖 Qué hace:
Examina cada palabra en flatten.
Si encuentra “es”, la guarda en la lista AR.
📎 Resultado: obtienes solo las palabras que contienen el patrón “es”.
⚙️ 4. Metacaracteres esenciales
🔸 Inicio de cadena → ^
AR = [w for w in flatten if re.search(r'^es', w)]
➡️ Filtra palabras que empiezan con “es”.
🔸 Fin de cadena → $
AR = [w for w in flatten if re.search(r'es$', w)]
➡️ Filtra palabras que terminan con “es”.
🧠 Truco mental:
Piensa en ^ como una “flecha hacia el inicio”
y $ como una “marca final”.
🔤 5. Rangos de caracteres
Definen un conjunto de letras o símbolos permitidos en una posición.
# Palabras que empiezan con 'g', 'h' o 'i'
AR = [w for w in flatten if re.search(r'^[ghi]', w)]
🎯 Significado:
El patrón [ghi] busca palabras que comiencen con alguna de esas letras.
📎 Ejemplo: “hola”, “idea”, “gato”.
🔁 6. Clausuras o repeticiones
Permiten indicar cuántas veces puede repetirse un patrón.
✴️ Cero o más repeticiones → *
AR = [w for w in flatten if re.search(r'^no*', w)]
🌀 Interpreta así: la palabra puede tener ninguna o varias “o” después de la “n”.
📍 Ejemplo: “n”, “no”, “noo”, “nooo”...
➕ Una o más repeticiones → +
AR = [w for w in flatten if re.search(r'^no+', w)]
🔥 Interpreta así: la palabra debe tener al menos una “o” después de la “n”.
📍 Ejemplo: “no”, “noo”, “nooo”... (pero no solo “n”).
Entonces estas dos listas hacen lo mismo ?
arr1 = [w for w in flatten if re.search("^(no)+",w)]
arr2 = [w for w in flatten if re.search("^no",w)]
Hola @tarac21, en realidad lo que funciona igual es la expresión regular porque al indicarle que empiece con no, no importa si se repite 1 o más veces con que aparezca una ya entraría en ambas validaciones
y que hago con el archivo que tiene como extensión ipynb?.Lo abrí con vscode, pero aparece como texto plano y hasta aquí llega mi conocimiento
Puedes abrir el archivo con Jupyter Notebook
hola Carlos, puedes abrirlo con Jupyter pero es recomendable que lo abras desde Google Colab. Puedes guardarlo en tu Google Drive y le das la opción de abrir con Colaboratory (que es lo mismo que Google Colab)
Comprender cómo interactúan las palabras, los textos y los vocabularios es esencial para desarrollar aplicaciones efectivas en NLP.
Les recomiendo utilizar el método .compile() de la líbreria re en python, ya que nos brinda resultados más rápidos generalmente.
Aquí un pequeño test.
Usando solo expr.match como filtro sin la expresion lambda se obtienen mejores resultados.
print([re.findall(r'\w*es', line)for line in flatten if re.search(r'es$', line)][:5])print([re.findall(r'\w*es$', line)for line in flatten][:208])
Me pareció raro el código del profe porque pidas el patrón que pidas siempre te da la palabra entera que contiene la cadena, pero con este código puedes comprender el patrón que pides y lo que se está mostrando en pantalla, que es otro patrón.
La segunda función print() te ayudará a comprender el comportamiento del objeto flatten que es un iterador. Además puedes intercambiar entre: search, findall indistintamente así como los slices. Y por supuesto que los patrones y verás su comportamiento y naturaleza.