He seleccionado un fragmento de la canción “Latinoamérica” de Calle 13. El motivo de la selección radica en su riqueza léxica y el uso de metáforas que involucran elementos geográficos, climáticos y sociales, lo cual permite un análisis robusto de conceptos de Procesamiento de Lenguaje Natural (PLN).
“Soy lo que dejaron, soy toda la sobra de lo que te robaron. Un pueblo escondido en la cima, mi piel es de cuero por eso aguanta cualquier clima. Soy una fábrica de humo, mano de obra campesina para tu consumo. Frente de frío en medio del verano, el amor en los tiempos del cólera, mi hermano.”
texto_bruto <- "Soy lo que dejaron, soy toda la sobra de lo que te robaron. Un pueblo escondido en la cima, mi piel es de cuero por eso aguanta cualquier clima. Soy una fábrica de humo, mano de obra campesina para tu consumo. Frente de frío en medio del verano, el amor en los tiempos del cólera, mi hermano."Un léxico \(L\) se define como el conjunto de términos significativos \(w\) dentro de un dominio \(D\):\[L = \{w_1, w_2, ..., w_n\} \subseteq D\]A continuación, se presenta el léxico conceptual (\(n=15\)):
lexico_data <- data.frame(
Item = c("Pueblo", "Cima", "Piel", "Cuero", "Clima", "Fábrica", "Humo", "Campesina", "Consumo", "Frío", "Verano", "Amor", "Cólera", "Hermano", "Sobra"),
Categoria = c("Lugar", "Lugar", "Cuerpo", "Material", "Fenómeno", "Lugar", "Elemento", "Sujeto", "Acción", "Sensación", "Tiempo", "Emoción", "Estado", "Relación", "Objeto"),
Interpretación = c("Comunidad humana", "Punto más alto", "Órgano externo", "Material resistente", "Condición atmosférica", "Sitio de producción", "Producto de combustión", "Relativo al campo", "Uso de bienes", "Baja temperatura", "Estación del año", "Sentimiento afectivo", "Enfermedad/Pasión", "Vínculo fraterno", "Resto de algo")
)
kable(lexico_data) %>% kable_styling(bootstrap_options = c("striped", "hover"))| Item | Categoria | Interpretación |
|---|---|---|
| Pueblo | Lugar | Comunidad humana |
| Cima | Lugar | Punto más alto |
| Piel | Cuerpo | Órgano externo |
| Cuero | Material | Material resistente |
| Clima | Fenómeno | Condición atmosférica |
| Fábrica | Lugar | Sitio de producción |
| Humo | Elemento | Producto de combustión |
| Campesina | Sujeto | Relativo al campo |
| Consumo | Acción | Uso de bienes |
| Frío | Sensación | Baja temperatura |
| Verano | Tiempo | Estación del año |
| Amor | Emoción | Sentimiento afectivo |
| Cólera | Estado | Enfermedad/Pasión |
| Hermano | Relación | Vínculo fraterno |
| Sobra | Objeto | Resto de algo |
Fonemas: Unidades mínimas de sonido que distinguen significado (abstracción sonora).
Grafemas: Unidades mínimas de la escritura (letras o dígrafos) que representan fonemas.
Morfemas: Unidades mínimas con significado propio (raíces, prefijos, sufijos).
Palabra: “Pueblo”
Grafemas: p-u-e-b-l-o (6 unidades).
Morfema: “Puebl-” (raíz), “-o” (género).
Palabra: “Campesina”
Grafemas: c-a-m-p-e-s-i-n-a (9 unidades).
Morfema: “Camp-” (raíz: campo), “-es-” (interfijo), “-in-” (sufijo de pertenencia), “-a” (género).
La tokenización es la función \(f: T \rightarrow \{t_1, t_2, ..., t_k\}\) que mapea un texto \(T\) a una secuencia de tokens.
df_texto <- data.frame(text = texto_bruto)
tokens_palabras <- df_texto %>% unnest_tokens(word, text)
# Gráfico de frecuencias
tokens_palabras %>%
count(word, sort = TRUE) %>%
head(10) %>%
ggplot(aes(x = reorder(word, n), y = n, fill = n)) +
geom_col(show.legend = FALSE) +
coord_flip() +
labs(title = "Top 10 Tokens más frecuentes", x = "Tokens", y = "Frecuencia") +
theme_minimal()
Interpretación: El token más frecuente es “de” (\(n=6\)), seguido por “soy” (\(n=3\)). Esto indica una estructura
descriptiva basada en la identidad del sujeto.
Utilizamos expresiones regulares para extraer entidades. Sea \(R\) una expresión regular, el conjunto de coincidencias es \(C = \{s \in T \mid s \text{ cumple } R\}\).
Entidades terminadas en ‘o’ o ‘a’ (Género):
\b\w+[oa]\b
Palabras con más de 7 caracteres: \b\w{8,}\b
regex_genero <- "\\b\\w+[oa]\\b"
matches_genero <- str_extract_all(texto_bruto, regex_genero)[[1]]
regex_largas <- "\\b\\w{8,}\\b"
matches_largas <- str_extract_all(texto_bruto, regex_largas)[[1]]Resultados extraídos: lo, toda, la, sobra, lo… y escondido, cualquier, campesina.
La normalización busca reducir la varianza léxica. Comparamos el vocabulario original \(V_{orig}\) vs el normalizado \(V_{norm}\).\[V_{norm} = \{stem(w) \mid w \in V_{orig}, w \notin \text{Stopwords}\}\]
stop_es <- data.frame(word = stopwords("es"))
vocab_comp <- tokens_palabras %>%
mutate(Tipo = "Original") %>%
bind_rows(
tokens_palabras %>%
anti_join(stop_es, by = "word") %>%
mutate(word = wordStem(word, language = "spanish"), Tipo = "Normalizado")
)
# Gráfico comparativo de tamaño de vocabulario
vocab_comp %>%
group_by(Tipo) %>%
summarise(Unidades_Unicas = n_distinct(word)) %>%
ggplot(aes(x = Tipo, y = Unidades_Unicas, fill = Tipo)) +
geom_bar(stat = "identity", width = 0.5) +
geom_text(aes(label = Unidades_Unicas), vjust = -0.5) +
labs(title = "Reducción de Vocabulario por Normalización", y = "N° de Palabras Únicas") +
theme_classic()Discusión: La normalización reduce el ruido. Al eliminar stopwords, el tamaño del vocabulario cae de 44 a 26 unidades.
La construcción del vocabulario es un proceso de reducción de dimensionalidad. Mientras que la tokenización fragmenta el flujo continuo del lenguaje en unidades discretas, la normalización (vía stemming y filtrado de stopwords) permite agrupar términos bajo una misma raíz conceptual. Matemáticamente, esto transforma un espacio vectorial de alta dispersión (sparse) en uno más denso y manejable para modelos de Inteligencia Artificial.
Semilla: set.seed(2026)
Versiones de librerías:
Sistema: R version 4.4.2 (2024-10-31 ucrt)