Preprocesamiento de Texto en R

Tokenización, lematización, limpieza y eliminación de ruido textual

Objetivos de la clase

  • Comprender el proceso de preprocesamiento de texto para análisis.
  • Aplicar tokenización, limpieza, stopwords, lematización y stemming en R.
  • Explorar un corpus real de debates presidenciales

¿Por qué preprocesar?

El texto, a diferencia de los datos estructurados, requiere pasos previos para convertirlo en representaciones analizables (vectores).

📚 ¿Qué significa “representaciones analizables (vectores)”?

Cuando hablamos de representaciones analizables en el contexto del análisis de texto, nos referimos a transformar el texto en una forma que las computadoras puedan entender, comparar y procesar matemáticamente.

Y eso, en general, significa convertir el texto en vectores.

🧠 ¿Qué es un vector en este contexto?

Un vector es simplemente una lista ordenada de números. En el caso del análisis de texto, un vector representa un documento como una secuencia de números que reflejan cosas como:

🧠 ¿Qué es un vector en este contexto?

  • cuántas veces aparece cada palabra en ese texto (frecuencia),
  • si una palabra aparece o no (presencia/ausencia),
  • qué tan importante es esa palabra en comparación con todo el corpus.

Ejemplo

Supongamos que queremos recolectar discursos que contengan estas palabras:

["salud", "educación", "derecho", "trabajo"]

“El acceso a la salud es un derecho”

Ejemplo

Supongamos que queremos recolectar discursos que contengan estas palabras:

["salud", "educación", "derecho", "trabajo"]

“El acceso a la salud es un derecho

Ejemplo

["salud", "educación", "derecho", "trabajo"]

“El acceso a la salud es un derecho

El vector que representa el texto sería: [1, 0, 1, 0]

  • Aparece “salud” → ✅
  • No aparece “educación” → ❌
  • Aparece “derecho” → ✅
  • No aparece “trabajo” → ❌

🔍 ¿Para qué sirve?

Una vez que tenés un vector, podés:

  • calcular similitudes entre documentos (medidas de distancia),

  • entrenar modelos de clasificación o predicción,

  • visualizar tendencias (ej: con análisis de componentes principales),

  • hacer clustering (agrupamientos),

  • aplicar cualquier técnica de machine learning que necesita datos numéricos.

¿Y cómo llegamos a eso?

con el preprocesamiento de texto que nos ayuda a convertir textos desordenados en vectores organizados listos para análisis.

Tokenización

🧩 ¿Qué es la tokenización?

✂️ Tokenizar un texto significa dividirlo en unidades más pequeñas llamadas tokens.

En general, los tokens son palabras, pero también pueden ser frases, oraciones o caracteres.

🧩 ¿Para qué sirve?

  • Convierte texto en bruto en una estructura manejable.
  • Permite contar palabras, detectar temas y patrones.
  • Es clave para transformar texto en vectores analizables
  • 🧠 Sin tokenización, no se puede hacer minería de texto ni análisis estadístico del lenguaje.

🧩 Ejemplo

“El acceso a la salud es un derecho”

Tokenizado por palabras:

  • “el”
  • “acceso”
  • “la”
  • “salud”
  • “es”
  • “un”
  • “derecho”

🧩 ¿Cómo se aplica en R?

unnest_tokens() → separa en palabras

library(dplyr)
library(tidytext)
# Simulamos una tabla con texto
textos <- tibble(id = 1, texto = "El acceso a la salud es un derecho")
# Tokenización
tokens <- textos %>%
  unnest_tokens(output = palabra, input = texto)
tokens
# A tibble: 8 × 2
     id palabra
  <dbl> <chr>  
1     1 el     
2     1 acceso 
3     1 a      
4     1 la     
5     1 salud  
6     1 es     
7     1 un     
8     1 derecho

🧩 ¿Cómo se aplica en R?

  • get_stopwords(language = "es") → trae una lista predefinida de palabras vacías en español

  • anti_join() → se queda solo con las palabras que no están en la lista de stopwords

🚫 Stopwords

Las stopwords son palabras muy comunes en un idioma que, por su alta frecuencia y bajo contenido semántico, suelen eliminarse del análisis. Ejemplos: el, la, de, en, y, a, que.

Eliminarlas permite que el análisis se enfoque en las palabras más informativas.

🧩 ¿Cómo se aplica en R?

stopwords_es <- get_stopwords(language = "es") 

# Simulamos una tabla con texto
textos <- tibble(id = 1, texto = "El acceso a la salud es un derecho")

# Tokenización
tokens <- textos %>%
  unnest_tokens(output = palabra, input = texto)%>%
  anti_join(stopwords_es, by = c("palabra" = "word"))

tokens
# A tibble: 3 × 2
     id palabra
  <dbl> <chr>  
1     1 acceso 
2     1 salud  
3     1 derecho

🧩 Otras opciones

unnest_tokens(output, input, token = "words")      # palabras
unnest_tokens(output, input, token = "sentences")  # oraciones
unnest_tokens(output, input, token = "characters") # letras
unnest_tokens(output, input, token = "ngrams", n = 2)  # bigramas

🧹 Limpieza

🧹 Limpieza: ¿Qué es?

Es el conjunto de acciones para eliminar elementos “ruidosos” del texto: puntuación, números, mayúsculas, caracteres especiales, URLs, espacios en blanco, etc.

Muchos de estos elementos no aportan información relevante para el análisis del contenido del texto. Por ejemplo, la coma o los signos de exclamación no suelen ser útiles para saber de qué trata un texto.

🧹 Limpieza: ¿Por qué es útil?

Reduce el “ruido” en el análisis, mejora los resultados y hace más eficiente el procesamiento posterior. Además, ayuda a normalizar el texto (por ejemplo, convertir todo a minúsculas evita que R distinga entre Salud y salud como si fueran cosas distintas).

🧹 ¿Cómo limpiar texto en R?

Vamos a utilizar la librería {stringr} que tiene funciones para manipulación de texto (muchas las vimos en la clase n° 2)

library(stringr)
library(stringi)

🧹 ¿Cómo limpiar texto en R?

texto_sucio <- "🗣️ ¡Hola! Este es un ejemplo de texto con RUIDO: números (12345), símbolos $$$, @correos.com, http://link.com, #hashtags, signos!!! ¿¡y tildes? ÁÉÍÓÚ..."

df <- tibble(texto = texto_sucio)

🧹 Minúsculas y mayúsculas

df <- df %>%
  mutate(texto = str_to_lower(texto))

print(df$texto)
[1] "🗣️ ¡hola! este es un ejemplo de texto con ruido: números (12345), símbolos $$$, @correos.com, http://link.com, #hashtags, signos!!! ¿¡y tildes? áéíóú..."
df <- df %>%
  mutate(texto = str_to_upper(texto))

print(df$texto)
[1] "🗣️ ¡HOLA! ESTE ES UN EJEMPLO DE TEXTO CON RUIDO: NÚMEROS (12345), SÍMBOLOS $$$, @CORREOS.COM, HTTP://LINK.COM, #HASHTAGS, SIGNOS!!! ¿¡Y TILDES? ÁÉÍÓÚ..."

🧹 Eliminamos URLs

  • str_remove_all() elimina todo lo que coincide con determinado patrón

La clave: expresiones regulares

df_limpio <- df %>%
  # Convertimos todo a minúsculas
  mutate(texto = str_to_lower(texto)) %>%  
  # Eliminamos URLs
  mutate(texto = str_remove_all(texto, "http[s]?://\\S+"))

print(df_limpio$texto)
[1] "🗣️ ¡hola! este es un ejemplo de texto con ruido: números (12345), símbolos $$$, @correos.com,  #hashtags, signos!!! ¿¡y tildes? áéíóú..."

🧹 Eliminamos menciones

df_limpio <- df_limpio %>%
  # Menciones
  mutate(texto = str_remove_all(texto, "@\\w+")) |> 
  # Hashtags
  mutate(texto = str_remove_all(texto, "#\\w+")) 

print(df_limpio$texto)
[1] "🗣️ ¡hola! este es un ejemplo de texto con ruido: números (12345), símbolos $$$, .com,  , signos!!! ¿¡y tildes? áéíóú..."

🧹 Signos de puntuación

df_limpio <- df_limpio %>%
  # Signos de puntuación
  mutate(texto = str_remove_all(texto, "[[:punct:]]"))
  
print(df_limpio$texto)
[1] "🗣️ hola este es un ejemplo de texto con ruido números 12345 símbolos $$$ com   signos y tildes áéíóú"

🧹 Números

df_limpio <- df_limpio %>%
  # Signos de puntuación
  mutate(texto = str_remove_all(texto, "[[:digit:]]"))
  
print(df_limpio$texto)
[1] "🗣️ hola este es un ejemplo de texto con ruido números  símbolos $$$ com   signos y tildes áéíóú"

🧹 Espacios en blanco

  1. La función str_squish() elimina espacios consecutivos
  2. Reemplaza todos los espacios consecutivos (como varios espacios, tabs o saltos de línea) por un solo espacio ” ” pero
df_limpio <- df_limpio %>%
  # Espacios
  mutate(texto = str_squish(texto)) |> 
  # Otra opcion con expresiones regulares:
  mutate(texto = str_replace_all(texto, "\\s+", " "))

print(df_limpio$texto)
[1] "🗣️ hola este es un ejemplo de texto con ruido números símbolos $$$ com signos y tildes áéíóú"

🧹 Espacios en blanco

  1. La función str_trim() elimina espacios al principio y al final del texto
  2. Otras opciones son: stri_trim_both(), stri_trim_left(), stri_trim_right() eliminan espacios al inicio y/o final del texto.
df_limpio <- df_limpio %>%           
  mutate(texto = str_trim(texto))

print(df_limpio$texto)
[1] "🗣️ hola este es un ejemplo de texto con ruido números símbolos $$$ com signos y tildes áéíóú"

🧹 Tildes

  1. La función str_trim() elimina espacios al principio y al final del texto
df_limpio <- df_limpio %>%                                 
  mutate(texto = stri_trans_general(texto, "Latin-ASCII"))

print(df_limpio$texto)
[1] "🗣️ hola este es un ejemplo de texto con ruido numeros simbolos $$$ com signos y tildes aeiou"

🧹 Eliminar emojis

df_limpio <- df_limpio %>% 
  mutate(texto = stri_replace_all_regex(texto, "\\p{So}", ""))

print(df_limpio$texto)
[1] "️ hola este es un ejemplo de texto con ruido numeros simbolos $$$ com signos y tildes aeiou"

🧹 Eliminar simbolos

df_limpio <-  df_limpio %>% 
  mutate(texto = stri_replace_all_regex(texto,"\\p{Sc}", ""))

print(df_limpio$texto)
[1] "️ hola este es un ejemplo de texto con ruido numeros simbolos  com signos y tildes aeiou"

🌱 Stemming

🌱 ¿Qué es Stemming?

Es un proceso que reduce una palabra a su raíz gramatical. Por ejemplo, caminando, camina, caminamos se reducen a camin. Permite grupar diferentes formas de una misma palabra bajo una forma base común, sin importar la conjugación o el género

🌱 ¿Cómo se usa en R?

wordStem() del paquete {SnowballC} aplica un algoritmo para reducir palabras a su raíz gramatical, ignorando conjugaciones, plurales, géneros, etc.

library(SnowballC)

textos <- tibble(id = 1, texto = "Caminando caminamos caminé camina")

tokens <- textos %>%
  unnest_tokens(output = palabra, input = texto)

🌱 ¿Cómo se usa en R?

tokens
# A tibble: 4 × 2
     id palabra  
  <dbl> <chr>    
1     1 caminando
2     1 caminamos
3     1 caminé   
4     1 camina   

🌱 ¿Cómo se usa en R?

tokens_raiz <- tokens %>%
  mutate(raiz = wordStem(palabra, language = "spanish"))

tokens_raiz
# A tibble: 4 × 3
     id palabra   raiz 
  <dbl> <chr>     <chr>
1     1 caminando camin
2     1 caminamos camin
3     1 caminé    camin
4     1 camina    camin

🧠 Lematización

Es un proceso similar al stemming, pero más “inteligente”: en lugar de cortar la palabra, busca devolver su forma canónica o de diccionario (lema). Ejemplo: corriendo → correr.

Para mantener el sentido lingüístico correcto. A diferencia del stemming, no se pierde la forma reconocible de la palabra.

🧠 ¿Cómo se usa en R?

library(udpipe)
ejemplo <- c("somos", "soy", "seremos")
prueba <- udpipe(ejemplo, "spanish")

prueba[, c("token", "lemma", "upos")]
    token lemma upos
1   somos   ser  AUX
2     soy   ser  AUX
3 seremos   ser VERB

❗Limitaciones de algunos paquetes

  • Muchos paquetes en R, como udpipe, están entrenados principalmente para el inglés.
  • Por eso, si le das verbos o palabras en español, puede que no los reconozca o no devuelva su lema correctamente.
  • No da error, pero devuelve la palabra tal cual.

Recreo

Volvemos en 10 minutos para comenzar con el taller