Introducción

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.


1. Carga de Librerías

# 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.


2. Extracción del Texto de los PDFs

SCRIPT 2019

# 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.


3. Procesamiento de Texto

Limpieza del Texto de SCRIPT 2019

# 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

Limpieza del Texto de SCRIPT 1992

# 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.


4. Matriz de Términos y Frecuencias

SCRIPT 2019

# 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

SCRIPT 1992

# 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

5. Visualización: Nube de Palabras

SCRIPT 2019

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"))

SCRIPT 1992

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"))


6. Análisis de Sentimientos

SCRIPT 2019

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")

SCRIPT 1992

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")

7. Comparación de Frecuencias

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))

Conclusión y Análisis

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.

Pregunta 1: ¿Se tomará y analizará todo lo que aparece en la página? ¿Qué sí y qué no? ¿Por qué?

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.