En este examen, se espera que apliquen las técnicas de procesamiento de texto aprendidas en el módulo 2 para analizar y visualizar un nuevo conjunto de datos, en este caso serán TODAS las conferencias sobre coronavirus del mes de julio de 2020. Se evaluará la correcta aplicación de las técnicas de preprocesamiento de texto, la calidad y relevancia de las visualizaciones generadas, así como la claridad y coherencia en la documentación y la interpretación de los resultados.
Aquí se te proporcionan 4 días de conferencias ejemplo para que detectes el patrón de links que se usa, pero como sabes, julio tiene 31 días. Conferencia 1 de julio de 2020: https://coronavirus.gob.mx/2020/07/01/conferencia-1-de-julio-2/ Conferencia 2 de julio de 2020: https://coronavirus.gob.mx/2020/07/02/conferencia-2-de-julio-2/ Conferencia 30 de julio de 2020: https://coronavirus.gob.mx/2020/07/30/conferencia-30-de-julio-2/ Conferencia 31 de julio de 2020: https://coronavirus.gob.mx/2020/07/31/conferencia-31-de-julio-2/
En este código, estaremos webscrapping que es la extracción de información de sitios web y estaremos realizando la limpieza de texto a un código creado para poder conocer la frecuencia de las palabras más repetidad en las conferencias con respecto al COVID 19. Esto en un lapso de tiempo del 1 de julio del 2020 al 31 de julio del 2020 y se hace con el fin de poder realizar futuras operaciones como analizar tendencias, conocer sus temas de interés
Primer paso: Se instalan las librerias que se utilizaran durante todo el proceso.
Paso 2: Cargamos las librerías rvest y magrittr que definimos también en el chunk anterior y definimos una función llamada scrape_y_guarda que realizará el web scraping y guardará los contenidos en archivos de texto. Es necesario que nuestros archivos de texto estén en español, por lo que cambiaremos el idioma a español utilizando el comando Sys.setlocale(“LC_TIME”, “es_ES.UTF-8”). Esto es importante para que el formato de fecha en español funcione correctamente y podamos correr todo el código siguiente.
library(rvest)
## Warning: package 'rvest' was built under R version 4.2.3
library(magrittr)
library(httr)
## Warning: package 'httr' was built under R version 4.2.3
paso 3: Después formateamos la fecha actual en día, mes y año para construir la URL de la página de conferencia correspondiente y poder identificarla de mejor manera. Con lo anterior, creamos la URL utilizando la fecha formateada en la variable fecha_url. Seguimos guardando el link que usaremos y del cuál extraeremos todas las mañaneras en una variable llamada “url”, seguido de nuestra variable de “fecha_url” para extraer cada mañanera diaria. Usamos de nuevo el comando read_html para obtener el contenido HTML de la página de conferencia, el cuál nos servirá para crear el nombre del archivo utilizando la fecha formateada, donde además cambiamos los guiones a guiones bajos en el nombre de cada archivo.
Paso 4: utilizamos de nuevo la función writeLines para guardar el contenido que extraimos en el archivo con el nombre creado anteriormente y la funicón lapply se usa para poder aplicar el comando scrape_y_guarda a cada fecha en el rango definido.La función lapply nos sirve para cuando quieres aplicar la misma función a múltiples elementos en una lista o base de datos.
# Ruta de la carpeta donde se guardaran los archivos seleccionados
carpeta_destino <- "C:\\Users\\Sicaru\\Desktop\\Tecnologico\\5to semestre\\Ciencia de datos II\\examen 2"
Sys.setlocale("LC_TIME","es_ES.UTF-8")
## [1] "es_ES.UTF-8"
# Se localizan las paginas y las fechas seleccionadas
fechas <- seq.Date(as.Date("2020-07-01"), as.Date("2020-07-31"), by="days")
paginas <- c(1:2)
userAgent <- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
for(fecha in fechas){
for(pagina in paginas){
fecha <- as.Date(fecha, origin = "1970-01-01")
dia <- as.numeric(format(fecha, "%d"))
mes <- format(fecha, "%B")
ano <- format(fecha, "%Y")
if(pagina == 2){
fecha_url <- paste(dia, paste("/conferencia", dia, "de", mes, pagina, sep="-"), sep = "")
}else{
fecha_url <- paste(dia, paste("/conferencia", dia, "de", mes, sep="-"), sep = "")
}
url_covid <- paste("https://coronavirus.gob.mx/2020/07", fecha_url, sep = "/")
# Valida que la página exista
validacion_url <- GET(
url = url_covid,
user_agent(userAgent)
)
# Si la página existe
if(validacion_url$status_code == 200){
web <- read_html(validacion_url)
texto <- web %>%
html_nodes(xpath = '//div[@class="elementor-text-editor elementor-clearfix"]/ul[@class="ul1 leer-esto"]') %>% # <-- reemplaza ".contenido-conferencia" con el selector CSS correcto
html_text()
# Crea el nombre del archivo y lo guarda
nombre_archivo <- paste("conferencia_", ano, "_", sprintf("%02d", dia), "_", mes, ".txt")
writeLines(texto, nombre_archivo)
}
}
}
Paso 5: Empezaremos utilizando la función list.files() que nos ayuda a obtener una lista de nombres de archivos de nuestro directorio y al escribir “.txt” delimitamos que sólo sean archivos de ese tipo y los almacenamos en la variable archivos.
Paso 6: Después hemos definido una variable llamada limpiar_textoCOVID que toma los archivos.Tenemos readLines(archivo, warn = FALSE): Esta función lee el archivo línea por línea y devuelve un vector donde cada elemento es una línea del archivo.
Paso 7: Después tenemos el argumento texto <- paste(texto, collapse = ” “): Concatena todas las líneas del archivo en un solo string, separándolas por espacios. Esto es útil para buscar la cadena de texto completa.
Paso 8: Aplicamos texto <- tolower(texto): este comando es muy importante porque en esta parte estamos convirtiendo todas las palabras de mayúsculas a minúsculas para que todo el texto se vuelva uniforme y su análisis sea más fácil.
Paso 9: texto <- gsub(“http\S+|www\.\S+”, ““, texto): Usamos este comando para encontrar las URLs que empiecen en http o www.
Paso 10: Siguiendo con la limpieza, texto <- gsub(“<.*?>“,”“, texto): elimina las etiquetas html.
Paso 11: También, usamos texto <- gsub(“[[:punct:]]”, ““, texto) que nos ayuda a liminar cualquier signo de puntuación (signos, puntos, etc).
Paso 12: eliminamos números con texto <- gsub(“\d+”, ““, texto) y remplazamos cualquier secuencia de espacios, con espacios únicos con la función texto <- gsub(”\s+“,” “, texto). Después de esto, el texto queda limpio.
Paso 13: Aplicar esta función de limpieza para todos los archivos y para esto utilizamos la antes mencionada función “lapply”. Esto significa que esta función se aplicará a cada archivo de mañanera y los textos limpios serán almacenados en la variable textos_limpios.
# Limpieza de archivos existentes en la misma carpeta de destino
archivosCOVID <- list.files(path = carpeta_destino, pattern = "*.txt")
#list.files(pattern = "*.txt"): Lista todos los archivos en el directorio de trabajo actual que tengan la extensión .txt. Estos nombres de archivos se guardan en el vector archivos.
# Función para limpiar el texto
limpiar_textoCOVID <- function(archivoCOVID) {
texto <- readLines(archivoCOVID, warn = FALSE)
texto <- paste(texto, collapse = " ")
#Eliminar URLs:gsub("http\S+|www\.\S+", "", texto): Usa una expresión regular para encontrar URLs que comiencen con "http" o "www" y las reemplaza con una cadena vacía, esencialmente eliminándolas.
texto <- gsub("http\\S+|www\\.\\S+", "", texto)
# Eliminar etiquetas HTML (si las hubiera): gsub("<.*?>", "", texto): Si hubiera alguna etiqueta HTML en el texto, esta expresión regular las identificaría y las eliminaría.
texto <- gsub("<.*?>", "", texto)
# Eliminar puntuación: gsub("[[:punct:]]", "", texto): Elimina cualquier carácter de puntuación del texto.
texto <- gsub("[[:punct:]]", "", texto)
# Eliminar números: gsub("\d+", "", texto): Elimina cualquier secuencia de números.
texto <- gsub("\\d+", "", texto)
# Eliminar espacios extra: gsub("\s+", " ", texto): Reemplaza cualquier secuencia de espacios (uno o más) con un único espacio.
texto <- gsub("\\s+", " ", texto)
# tolower(texto): Convierte todo el texto a minúsculas para que el análisis y limpieza sean uniformes.
texto <- tolower(texto)
return(texto)
# stopwoeds_es: elimina todas las stopwords en español
stopwords_es <- stopwords("es")
}
# Aplicar la función de limpieza a cada archivo
textos_limpios <- lapply(archivosCOVID, limpiar_textoCOVID)
Paso 14: Se toma una lista de textos almacenados en archivosCOVID, limpia cada uno de esos textos utilizando la función limpiar_textoCOVID, y luego combina todos los textos limpios en un solo vector llamado TextoLimpio. Esto puede ser útil cuando se necesita procesar y analizar un conjunto de textos de una manera más conveniente.
# Crear un vector llamado "Texto Limpio"
textos_limpios <- lapply(archivosCOVID, limpiar_textoCOVID)
# Combinar los textos limpios en un solo vector
TextoLimpio <- unlist(textos_limpios)
Paso 15:
library(udpipe)
## Warning: package 'udpipe' was built under R version 4.2.3
# Descarga y carga del modelo de lenguaje en español
ud_model <- udpipe_download_model(language = "spanish", overwrite = FALSE)
ud_model_loaded <- udpipe_load_model(ud_model$file_model)
# Definir una función para lematizar un texto
lematizar_texto <- function(texto) {
annotation <- udpipe_annotate(ud_model_loaded, x = texto)
df <- as.data.frame(annotation)
lemas <- df$lemma
return(paste(lemas, collapse = " "))
}
# Aplicar la lematización a los textos limpios
textos_lematizados <- lapply(textos_limpios, lematizar_texto)
## Warning in read_connlu(x, is_udpipe_annotation = TRUE, ...): No parsed data in
## x$conllu, returning default empty data.frame. Error message at x$error
## indicates e.g.:
## Warning in read_connlu(x, is_udpipe_annotation = TRUE, ...): No parsed data in
## x$conllu, returning default empty data.frame. Error message at x$error
## indicates e.g.:
## Warning in read_connlu(x, is_udpipe_annotation = TRUE, ...): No parsed data in
## x$conllu, returning default empty data.frame. Error message at x$error
## indicates e.g.:
## Warning in read_connlu(x, is_udpipe_annotation = TRUE, ...): No parsed data in
## x$conllu, returning default empty data.frame. Error message at x$error
## indicates e.g.:
Paso 17: utiliza la biblioteca tm para crear una matriz Document-Term Matrix (DTM) a partir de un corpus de textos limpios. Primero cargamos esa librería mencionada para posteriormente crear un corpus de los textos limpios. Un corpus es una colección de archivos de texto. La parte del comando VectorSource(textos_limpios) nos permite convertir los textos limpios en un objeto que se puede utilizar como fuente de datos para el corpus.
Paso 18: Después creamos una Document-Term Matrix (DTM) para crear la matriz a partir del corpus. Una DTM es una matriz en la que las filas representan archivos y las columnas representan las palabras. Cada celda es un recuento de cuántas veces aparece cierto término en específico.
Paso 19: inspeccionamos la matriz creada con la función inspect() para ver su contenido.Los documentos ahora tendrán forma de matriz.La DTM se utiliza para realizar análisis de un texto.
library(tm)
## Warning: package 'tm' was built under R version 4.2.3
## Loading required package: NLP
##
## Attaching package: 'NLP'
## The following object is masked from 'package:httr':
##
## content
library(NLP)
# Crear un Corpus con los textos lematizados
corpus <- Corpus(VectorSource(textos_lematizados))
#corpus: colección de documentos limpios los vectoriza y a partir de ese se hace matriz
# Crear la matriz de términos de documento
#Documetn Term Matrix
dtm <- DocumentTermMatrix(corpus)
#Ver la Matriz
inspect(dtm)
## <<DocumentTermMatrix (documents: 31, terms: 1230)>>
## Non-/sparse entries: 6525/31605
## Sparsity : 83%
## Maximal term length: 18
## Weighting : term frequency (tf)
## Sample :
## Terms
## Docs con covid él haber más para persona poder que ser
## 1 11 11 19 23 6 6 15 13 22 12
## 16 5 9 22 16 11 10 6 9 18 11
## 17 6 13 19 12 9 12 9 10 23 16
## 18 5 10 16 21 13 8 9 4 12 13
## 2 15 14 28 17 9 12 22 15 35 15
## 22 6 19 16 22 9 7 5 7 13 11
## 29 9 15 22 20 10 9 9 8 15 15
## 3 14 10 15 16 9 8 15 15 23 16
## 4 14 11 18 16 10 8 15 18 28 18
## 9 9 5 14 11 11 7 13 6 16 16
Paso 20: Sumar las columnas para obtener el conteo total de cada término. Matriz solamente de términos, y con colSums hace un total de cada columna. Suma de cada una de las veces que se dice un término
# Sumar las columnas para obtener el conteo total de cada término. Matriz solamente de términos, y con colSums hace un total de cada columna. Suma de cada una de las veces que se dice un término
conteo_total <- colSums(as.matrix(dtm))
# Ordenar y mostrar los términos más comúnes
terminos_comunes <- sort(conteo_total, decreasing = TRUE)
head(terminos_comunes, 25) # Mostrar los 25 términos más comunes
## él que haber ser persona covid más con para poder
## 456 445 413 318 289 271 253 197 197 180
## todo uno tener estado mucho méxico caso por estar seguir
## 174 165 157 156 142 138 137 133 120 115
## casa este cada cama mil
## 107 105 96 95 95
Paso 21: Se puede observar que las stopwords no se quitaron en la limpieza por lo que, se puede recurrir al plan b que es crear un nuevo corpus con su respectivo dtm para quitar las palabras no deseadas
# eliminar stopwords de nuestro corpus
corpus_limpio <- tm_map(corpus, removeWords, stopwords("es")) #Usar "es" (español) para stopwords en español
## Warning in tm_map.SimpleCorpus(corpus, removeWords, stopwords("es")):
## transformation drops documents
# Creamos nuevo dtm
dtm_limpio <- DocumentTermMatrix(corpus_limpio)
#Ver matriz
inspect(dtm_limpio)
## <<DocumentTermMatrix (documents: 31, terms: 1193)>>
## Non-/sparse entries: 5836/31147
## Sparsity : 84%
## Maximal term length: 18
## Weighting : term frequency (tf)
## Sample :
## Terms
## Docs casa caso covid haber méxico persona poder seguir ser tener
## 1 4 3 11 23 9 15 13 3 12 6
## 16 4 6 9 16 4 6 9 4 11 4
## 17 5 6 13 12 5 9 10 5 16 4
## 18 3 7 10 21 4 9 4 3 13 7
## 2 7 5 14 17 11 22 15 4 15 16
## 22 4 13 19 22 4 5 7 4 11 5
## 29 4 6 15 20 3 9 8 5 15 4
## 3 5 2 10 16 7 15 15 5 16 5
## 31 3 2 9 11 4 8 3 6 5 2
## 4 5 2 11 16 6 15 18 4 18 5
# Sumar las columnas para obtener el conteo total de cada término
conteo_total_limpio <- colSums(as.matrix(dtm_limpio))
# Ordenar y mostrar los términos más comúnes
terminos_comunes_limpio <- sort(conteo_total_limpio, decreasing = TRUE)
Paso 22: Crear una tabla de frecencias con los datos de la limpiez anterior
# Obtener la tabla de frecuencias de los términos
# Ordenar y mostrar los términos más comúnes
terminos_comunes_2 <- sort(conteo_total_limpio, decreasing = TRUE)
tabla_frecuencias <- table(conteo_total_limpio)
# Mostrar los términos más comunes junto con sus frecuencias
resultados <- data.frame(Termino = names(terminos_comunes_limpio),
Frecuencia = terminos_comunes_limpio,
Total = tabla_frecuencias[names(terminos_comunes_limpio)])
# Se despliega las primeras 25 palabras con mayor frecuencia
head(resultados, 25)
## Termino Frecuencia Total.conteo_total_limpio Total.Freq
## haber haber 413 <NA> NA
## ser ser 318 <NA> NA
## persona persona 289 <NA> NA
## covid covid 271 <NA> NA
## poder poder 180 <NA> NA
## tener tener 157 <NA> NA
## méxico méxico 138 <NA> NA
## caso caso 137 <NA> NA
## seguir seguir 115 <NA> NA
## casa casa 107 <NA> NA
## cada cada 96 <NA> NA
## cama cama 95 <NA> NA
## mil mil 95 <NA> NA
## nuevo nuevo 95 <NA> NA
## epidemia epidemia 88 <NA> NA
## salud salud 82 <NA> NA
## deber deber 77 <NA> NA
## mano mano 77 <NA> NA
## muerte muerte 75 <NA> NA
## país país 75 <NA> NA
## hacer hacer 69 <NA> NA
## enfermedad enfermedad 66 <NA> NA
## semáforo semáforo 66 <NA> NA
## california california 65 <NA> NA
## confirmar confirmar 62 <NA> NA
Antes de crear la visualización, es necesario analizar las palabras que aparecerán en la nube de palabras. Como se puede observar en el head algunas palabras como “haber” “poder” y demás verbos no son tan significativos para el analisis por lo que se procederá a hacer una limpieza manual ¿Por qué?
Se eliminan los verbos por practicidad y porque, la finalidad de las conferencias del 2020 con respecto al Covid era resguardar a la población y mantener a los y las cuidadanos a salvo, al poner los verbos no solo se hace enfasis en las acciones comunes del ser humano sino que además quitan espacio a las palabras que son temas y hechos que son importante con respecto al periodo, por ejemplo la gravedad de los casos, el famosos semaforo rojo que se identificaba en Julio del 2020.
palabras_eliminar <- c("haber","ser","persona","poder","tener","seguir","cada", "mil", "nuevo", "mano","deber", "hacer",
"ahora", "confirmar", "diez", "león", "parte", "sar","quedar","cuatro","sólo","número","casi","luis", "caso")
# La función removeWords toma solo dos argumentos: el objeto corpus y las palabras que deseas eliminar.
# Es por eso que al eliminar varias palabras, se tienen que hacer en dos etapas
# Eliminar palabras específicas. ETAPA 1
corpus_2 <- tm_map(corpus, removeWords, palabras_eliminar)
## Warning in tm_map.SimpleCorpus(corpus, removeWords, palabras_eliminar):
## transformation drops documents
# Eliminar stopwords en español
corpus_22 <- tm_map(corpus_2, removeWords, stopwords("es"))
## Warning in tm_map.SimpleCorpus(corpus_2, removeWords, stopwords("es")):
## transformation drops documents
# Repetimos el análisis y comparamos los términos y la nube
# Creamos nuevo dtm
dtm_2 <- DocumentTermMatrix(corpus_22)
# Sumar las columnas para obtener el conteo total de cada término
conteo_total_22 <- colSums(as.matrix(dtm_2))
# Obtener la tabla de frecuencias de los términos
# Ordenar y mostrar los términos más comúnes
terminos_comunes_2 <- sort(conteo_total_22, decreasing = TRUE)
tabla_frecuencias <- table(conteo_total_22)
# Mostrar los términos más comunes junto con sus frecuencias
resultados <- data.frame(Termino = names(terminos_comunes_2),
Frecuencia = terminos_comunes_2,
Total = tabla_frecuencias[names(terminos_comunes_2)])
# Se despliega las primeras 25 palabras con mayor frecuencia
head(resultados, 25)
## Termino Frecuencia Total.conteo_total_22 Total.Freq
## covid covid 271 <NA> NA
## méxico méxico 138 <NA> NA
## casa casa 107 <NA> NA
## cama cama 95 <NA> NA
## epidemia epidemia 88 <NA> NA
## salud salud 82 <NA> NA
## muerte muerte 75 <NA> NA
## país país 75 <NA> NA
## enfermedad enfermedad 66 <NA> NA
## semáforo semáforo 66 <NA> NA
## california california 65 <NA> NA
## gobierno gobierno 60 <NA> NA
## enferma enferma 58 <NA> NA
## contagio contagio 57 <NA> NA
## ocupado ocupado 57 <NA> NA
## enfermar enfermar 56 <NA> NA
## ciudad ciudad 55 <NA> NA
## quédate quédate 54 <NA> NA
## tabasco tabasco 51 <NA> NA
## municipio municipio 51 <NA> NA
## complicar complicar 50 <NA> NA
## hospital hospital 49 <NA> NA
## menos menos 49 <NA> NA
## nayarit nayarit 45 <NA> NA
## rojo rojo 44 <NA> NA
Para este procedimiento fue necesario hacerlo en dos etapas. La primera consiste en crear la función para que se eliminen las palabras especificas, pero como la función removeWords solo toma dos argumentos, en este caso el objeto (corpus_2) y las palabras a eliminar; la segunda etapa consiste en repetir el mismo procesamiento pero incluyendo a corpus_2 dentro de la instrucción tm_map, aplicando las tranformaicones del texto estructurado no solo de las palabras eliminadas manualmente, sino de las stopwords, creando así otra estructura de textos dtm_2
La matriz permite observar los terminos con sus respectivas frecuencias, posterior a ello se realizo un procedimiento basico de sumas totales y ordenamiento de texto para que mostrara las palabras más comunes ordenadas por la frecuencia en la que aparecen. Aunque el procesamiento de contar las columnas para obtener el conteo total de cada término parece un poco repetitivo, es indispensable para poder crear la dummy que utiliza el dataframe que despliega de manera ordenada las frecuencias de cada palabra. Como se puede observar a continución.
library(wordcloud)
## Warning: package 'wordcloud' was built under R version 4.2.3
## Loading required package: RColorBrewer
# Crear la nube de palabras
# se van a plotear los términos comunes (base) que aparecen más de una vez y máximo 100.
wordcloud(names(terminos_comunes_2), terminos_comunes, min.freq = 1, max.words = 100, random.order = FALSE, rot.per = 0.35, colors = brewer.pal(8, "Paired"))
Durante el procesamiento de los datos, se obtuvo diferentes resultados. Sin embargo la nube de palabras final nos indica que efectivamnete las palabras más frecuentes en las conferencias impartidas por Lopez Gatel estaban encaminadas a un discurso politico que buscaba el bienestar de la población pero también buscaba evaluar el comportamiento de los cuidadanos através de la exposición de las cifras y del estado del país con respecto a la pandemia del COVID 19. El canal de comunicación, es este caso conferencias de prensa duante el mes de Julio, tomo en cuenta los factores de fragilidad a través de la información revelada que podían influir en la responsabilidad tanto a nivel individual como colectivo (de parte del gobierno).
Bajo este mismo argumento se concluye que efectivamente la palabras como: covid, méxico, casa comparten una connotación importante, la cuál se analisa bajo el resguardo de la población mexicana. También se concluye que las conferencias aunque la mayoria comenzaba con “Quédate en casa”, las recomendaciones no eran lo único de lo que se hablaba, también se hablaba del la situación estatal del país, especificamente la región norte. Esto guarda sentido ya que en ese periodo seguian las regulaciones del paso de la frontera con Estados Unidos por lo que era más propenso que se hablara de los casos de norte debido al movimiento poblacional.