Este código analiza los guiones de Aladdin de 1992 y 2019 para identificar similitudes y diferencias mediante técnicas de minería de texto. Primero, extrae el texto desde PDFs y páginas web, lo limpia eliminando palabras comunes, puntuación y números, y luego genera nubes de palabras y gráficos de barras para visualizar las palabras más frecuentes. Además, utiliza análisis de sentimientos para comparar las emociones predominantes en cada guion y resalta las palabras clave comunes entre ambas versiones. El objetivo es entender cómo los temas y el lenguaje han cambiado entre las dos adaptaciones.
# Librerías necesarias para el análisis
library("tm") # Text Mining
## Warning: package 'tm' was built under R version 4.2.3
## Loading required package: NLP
library("SnowballC") # Stemmer (procesamiento lingüístico)
## Warning: package 'SnowballC' was built under R version 4.2.3
library("wordcloud") # Generación de nubes de palabras
## Warning: package 'wordcloud' was built under R version 4.2.3
## Loading required package: RColorBrewer
library("RColorBrewer")# Paletas de colores para gráficos
library("syuzhet") # Análisis de sentimientos
## Warning: package 'syuzhet' was built under R version 4.2.3
library("pdftools") # Extracción de texto de PDFs
## Warning: package 'pdftools' was built under R version 4.2.3
## Using poppler version 22.04.0
library("rvest")
## Warning: package 'rvest' was built under R version 4.2.3
library("slam")
library("ggplot2")
##
## Attaching package: 'ggplot2'
## The following object is masked from 'package:NLP':
##
## annotate
Explicación:
Este chunk importa herramientas clave para el procesamiento, análisis y
visualización de datos textuales.
# Función para extraer texto de un archivo PDF
extract_text_from_pdf <- function(pdf_path) {
pdf_text <- pdf_text(pdf_path) # Convierte el PDF en texto
combined_text <- paste(pdf_text, collapse = "
") # Une todas las páginas
return(combined_text)
}
# Ruta al archivo PDF de SCRIPT 2019
pdf_path_2019 <- "C:/Users/sarao/Desktop/TEC - LIT/Minería de datos/doc.pdf"
script_2019_text <- extract_text_from_pdf(pdf_path_2019)
# Función para extraer el guion de una página web
get_script <- function(url) {
webpage <- read_html(url)
script_text <- webpage %>%
html_nodes("pre") %>% # Ajustar si no encuentra <pre>
html_text()
return(script_text)
}
# Descargar los guiones
script_1992 <- get_script("https://imsdb.com/scripts/Aladdin.html")
# Unir el texto de los guiones
script_1992_text <- paste(script_1992, collapse = "\n")
script_1992 <- Corpus(VectorSource(script_1992_text))
script_2019 <- Corpus(VectorSource(script_2019_text))
Explicación:
Se define una función reutilizable para extraer texto desde PDFs y se
aplica a cada archivo, generando las variables
script_2019_text y script_1992_text.
# Aplicar limpieza básica
script_2019 <- tm_map(script_2019, content_transformer(tolower)) # Convertir a minúsculas
## Warning in tm_map.SimpleCorpus(script_2019, content_transformer(tolower)):
## transformation drops documents
script_2019 <- tm_map(script_2019, removeNumbers) # Remover números
## Warning in tm_map.SimpleCorpus(script_2019, removeNumbers): transformation
## drops documents
script_2019 <- tm_map(script_2019, removeWords, stopwords("english")) # Remover palabras comunes
## Warning in tm_map.SimpleCorpus(script_2019, removeWords, stopwords("english")):
## transformation drops documents
script_2019 <- tm_map(script_2019, removePunctuation) # Remover puntuación
## Warning in tm_map.SimpleCorpus(script_2019, removePunctuation): transformation
## drops documents
script_2019 <- tm_map(script_2019, stripWhitespace) # Remover espacios extra
## Warning in tm_map.SimpleCorpus(script_2019, stripWhitespace): transformation
## drops documents
script_2019 <- tm_map(script_2019, removeWords, c( "aladdin", "jafar", "jasmine", "abu", "genie", "sultan", "iago", "carpet", "back", "prince", "like"))
## Warning in tm_map.SimpleCorpus(script_2019, removeWords, c("aladdin", "jafar",
## : transformation drops documents
# Aplicar limpieza básica
script_1992 <- tm_map(script_1992, content_transformer(tolower)) # Convertir a minúsculas
## Warning in tm_map.SimpleCorpus(script_1992, content_transformer(tolower)):
## transformation drops documents
script_1992 <- tm_map(script_1992, removeNumbers) # Remover números
## Warning in tm_map.SimpleCorpus(script_1992, removeNumbers): transformation
## drops documents
script_1992 <- tm_map(script_1992, removeWords, stopwords("english")) # Remover palabras comunes
## Warning in tm_map.SimpleCorpus(script_1992, removeWords, stopwords("english")):
## transformation drops documents
script_1992 <- tm_map(script_1992, removePunctuation) # Remover puntuación
## Warning in tm_map.SimpleCorpus(script_1992, removePunctuation): transformation
## drops documents
script_1992 <- tm_map(script_1992, stripWhitespace) # Remover espacios extra
## Warning in tm_map.SimpleCorpus(script_1992, stripWhitespace): transformation
## drops documents
script_1992 <- tm_map(script_1992, removeWords, c( "aladdin", "jafar", "jasmine", "abu", "genie", "sultan", "iago", "carpet", "back", "prince","like"))
## Warning in tm_map.SimpleCorpus(script_1992, removeWords, c("aladdin", "jafar",
## : transformation drops documents
Explicación:
Cada texto se limpia por separado, eliminando palabras comunes, números
y puntuación. El texto procesado se almacena en las variables
script_2019 y script_1992.
# Crear matriz de términos para SCRIPT 2019
dtm_2019 <- TermDocumentMatrix(script_2019)
matrix_2019 <- as.matrix(dtm_2019)
frequencies_2019 <- sort(rowSums(matrix_2019), decreasing = TRUE)
word_freq_2019 <- data.frame(word = names(frequencies_2019), freq = frequencies_2019)
head(word_freq_2019, 10)
## word freq
## page page 39
## will will 39
## ali ali 38
## can can 32
## just just 32
## know know 32
## never never 32
## wish wish 32
## now now 31
## right right 29
# Crear matriz de términos para SCRIPT 1992
dtm_1992 <- TermDocumentMatrix(script_1992)
matrix_1992 <- as.matrix(dtm_1992)
frequencies_1992 <- sort(rowSums(matrix_1992), decreasing = TRUE)
word_freq_1992 <- data.frame(word = names(frequencies_1992), freq = frequencies_1992)
head(word_freq_1992, 10)
## word freq
## looks looks 60
## lamp lamp 57
## one one 48
## princess princess 46
## head head 44
## just just 44
## see see 43
## turns turns 42
## pulls pulls 41
## ali ali 40
wordcloud(words = word_freq_2019$word, freq = word_freq_2019$freq,
min.freq = 15, max.words = 1000, random.order = FALSE,
colors = brewer.pal(8, "Set3"))
wordcloud(words = word_freq_1992$word, freq = word_freq_1992$freq,
min.freq = 15, max.words = 1000, random.order = FALSE,
colors = brewer.pal(8, "Set3"))
sentiments_2019 <- get_nrc_sentiment(paste(script_2019$content, collapse = " "))
sentiment_totals_2019 <- colSums(sentiments_2019)
barplot(sentiment_totals_2019, las = 2, col = rainbow(10),
main = "Sentimientos en SCRIPT 2019",
ylab = "Frecuencia")
sentiments_1992 <- get_nrc_sentiment(paste(script_1992$content, collapse = " "))
sentiment_totals_1992 <- colSums(sentiments_1992)
barplot(sentiment_totals_1992, las = 2, col = rainbow(10),
main = "Sentimientos en SCRIPT 1992",
ylab = "Frecuencia")
par(mfrow = c(1, 2)) # Configurar gráficos lado a lado
barplot(word_freq_2019[1:10,]$freq,
names.arg = word_freq_2019[1:10,]$word,
col = "lightblue",
main = "Frecuencia: SCRIPT 2019",
ylab = "Frecuencia",
las = 2, # Rotar etiquetas del eje x
cex.names = 0.8) # Reducir tamaño de las etiquetas
barplot(word_freq_1992[1:10,]$freq,
names.arg = word_freq_1992[1:10,]$word,
col = "pink",
main = "Frecuencia: SCRIPT 1992",
ylab = "Frecuencia",
las = 2, # Rotar etiquetas del eje x
cex.names = 0.8) # Reducir tamaño de las etiquetas
# Crear la matriz de términos (DTM)
dtm_script_1992 <- DocumentTermMatrix(script_1992)
dtm_script_2019 <- DocumentTermMatrix(script_2019)
# Calcular las frecuencias de las palabras en cada DTM
freq_1992 <- colSums(as.matrix(dtm_script_1992))
freq_2019 <- colSums(as.matrix(dtm_script_2019))
# Ordenar las frecuencias de mayor a menor
sorted_1992 <- sort(freq_1992, decreasing = TRUE)
sorted_2019 <- sort(freq_2019, decreasing = TRUE)
# Seleccionar las 20 palabras más comunes de cada guion
top_20_1992 <- names(sorted_1992)[1:20]
top_20_2019 <- names(sorted_2019)[1:20]
# Encontrar las palabras que están en ambos guiones
common_words <- intersect(top_20_1992, top_20_2019)
# Ver las palabras comunes
print(common_words)
## [1] "lamp" "one" "princess" "just" "see" "ali"
## [7] "now" "get" "got" "right" "will" "can"
# Crear un dataframe para comparar las frecuencias de las palabras comunes
common_comparison <- data.frame(
Word = common_words,
Frequency_1992 = sapply(common_words, function(word) freq_1992[word]),
Frequency_2019 = sapply(common_words, function(word) freq_2019[word])
)
# Crear un gráfico de comparación de las palabras comunes
ggplot(common_comparison, aes(x = Word, y = Frequency_1992, fill = "1992")) +
geom_bar(stat = "identity", position = "dodge") +
geom_bar(aes(y = Frequency_2019, fill = "2019"), stat = "identity", position = "dodge") +
labs(title = "Palabras Comunes en Ambos Guiones", x = "Palabras", y = "Frecuencia", fill = "Año") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
Al realizar el análisis, no se tomará todo lo que aparece en la página. Se excluirán elementos irrelevantes para nuestro objetivo, como etiquetas HTML, estilos, scripts y cualquier otro contenido técnico que no forme parte del texto significativo. Solo se analizará el contenido textual que aporte valor al propósito del análisis, eliminando ruido como palabras comunes (stopwords), números, puntuación y nombres propios de personajes. Esto se hace para centrarse en el mensaje principal del texto y evitar sesgos que puedan distorsionar los resultados.
Para obtener un análisis más sustancioso del texto, eliminamos elementos que podrían sesgar la información, como mayúsculas (convertidas a minúsculas), números, palabras comunes (stopwords) y puntuación. Además, excluimos los nombres de personajes, ya que queremos centrarnos en la esencia de la historia y no en la frecuencia de los nombres. En el análisis del guion de 2019, se observó un lenguaje más casual y moderno, con palabras como gonna (abreviación de going to) y términos recurrentes como Ali, lámpara y deseo. En cambio, el guion de 1992 utiliza un lenguaje más simple y directo, con palabras frecuentes como look, turn y pulls, sugiriendo un enfoque más físico. En cuanto a los sentimientos, el guion de 1992 se inclina hacia emociones negativas como odio y disgusto, mientras que el de 2019 muestra un tono más neutral o positivo. Estas diferencias reflejan tanto la evolución generacional como el estilo de escritura, donde el guion de 1992 conserva elementos de cuento de hadas, y el de 2019 adopta un estilo más cotidiano. Ambos guiones comparten palabras clave como lámpara, princesa, Ali y one, siendo interesante explorar el significado de esta última. Este análisis revela patrones narrativos y culturales, destacando cómo evolucionan las historias para adaptarse a su público.