Este tutorial describe el procedimiento para crear un listado de aristas de una red semántica natural (rsn), a partir de una base de datos tradicional; a fin de graficarla y analizarla con el programa Gephi o cualquier otro programa de análisis y visualización de redes sociales. No obstante, si se prefiere, se puede graficar con R, como explicamos aquí mismo.
Es obvio que para entender este tutorial debes conocer la técnica de redes semánticas naturales y su análisis estructural. Si no sabes de que estamos hablando, te sugiero leer el libro: Marcas, Memoria y Significado: Análisis de Estructuras Semánticas. Así como saber utilizar R básico y, opcionalmente, un programa de análisis y visualización de redes sociales Gephi, NodeXl o cualquier otro.
En este tutorial, iremos avanzando como se describe a continuación:
En el siguiente código inventamos una base de datos, la cual hemos llamado coca.df. La base consta de 5 casos: folio 1 al 5; una varibale llamada demografico: m para masculino y f para femenino; y cinco variables: palabra1 a palabra5, las cuales simulan distintas palabras que se asocian con la palabra estímulo Coca Cola.
coca_df <- data.frame(folio = c(1:3, 3, 5),
demografico = c("m", "f", "m", "f", "m"),
palabra1 = c("Botella", "Sed",
"ENVASE", "botella", "PERJUDICIAL"),
palabra2 = c("Refresco ", "GAS",
"Azúcar", "refresco", "AZUCAR"),
palabra3 = c("Hielos", "comida",
"negra", "Fría", "Roja"),
palabra4 = c("fiesta", "rica",
" Hielo", "Liquido", "BEBIDA"),
palabra5 = c("Sed", "Familia",
"Dañina", "Rica", NA),
stringsAsFactors = F )
coca_df
## folio demografico palabra1 palabra2 palabra3 palabra4 palabra5
## 1 1 m Botella Refresco Hielos fiesta Sed
## 2 2 f Sed GAS comida rica Familia
## 3 3 m ENVASE Azúcar negra Hielo Dañina
## 4 3 f botella refresco Fría Liquido Rica
## 5 5 m PERJUDICIAL AZUCAR Roja BEBIDA <NA>
Por favor, nota que las palabras (palabra1 a palabra5) vienen en mayúsculas, minúsculas, con acentos y sin ellos; con caracteres especiales como la ñ de la palabra Dañina, y espacios en blanco entre palabras, como la palabra Refresco (caso 1, palabra2). Es común encontrar este debarajuste en muchas bases de datos, el cual debemos arreglar; más adelante te mostramos cómo.
La variable de identificación (v.gr. folio) es importante porque a través de ella se detectan todas las palabras que mencionó un sujeto; a fin de combinarlas en pares y crear el listado de aristas. Por esta razón, es necesario que ningun sujeto tenga el mismo número de identificación que otro. Si estás absolutamente seguro que la variable de identificación, por ejemplo, el folio de cada caso no se repite, entonces puedes brincarte este paso y utilizarlo en lugar del id nuevo que crearemos a continuación. Observa que en nuestro caso no se repite el folio; sin embargo, se crea la variable nueva id para ejemplificar el procedimiento.
Se requiere el paquete dplyr, el cual sirve para manipular y transformar una base de datos (data frame). dplyr forma parte de un conjunto de paquetes que funcionan de forma muy similar, compartiendo varias reglas y filosofías. Debido a ello el autor(es) los han agrupado bajo un mismo paquete llamado tidyverse; de tal forma que se puede cargar el paquete dplyr individualmente o en conjunto con todos los demás paquetes que integran tidyverse. Preferimos hacerlo a través del paquete tidyverse, porque más adelante utilizaremos otros paquetes que se encuentran dentro de éste.
El código utiliza la función mutate para crear variables nuevas en un data frame. Los argumentos son: el data frame, el nuestro es coca.df; el nombre de la variable nueva: id, la cual es igual al vector que va de 1 hasta el número de renglones de nuestra base de datos coca.df.
library(tidyverse)
coca_df <- mutate(coca_df, id = c(1:nrow(coca_df)))
coca_df
## folio demografico palabra1 palabra2 palabra3 palabra4 palabra5 id
## 1 1 m Botella Refresco Hielos fiesta Sed 1
## 2 2 f Sed GAS comida rica Familia 2
## 3 3 m ENVASE Azúcar negra Hielo Dañina 3
## 4 3 f botella refresco Fría Liquido Rica 4
## 5 5 m PERJUDICIAL AZUCAR Roja BEBIDA <NA> 5
Tidy data significa datos ordenados; es decir, hay que ordenar la base de datos. Esto no quiere decir que una base de datos clásica esté desordenada, a lo que se refiere es que las variables deben ordenarse en un formato largo en lugar de uno ancho, como es el caso de las bases de datos tradicionales. En ese formato largo, todas las palabras mencionadas se forman en una sola columna. Una base de datos con este formato permite procesar la información de manera más amigable e ideal para R.
Se requiere el paquete tidyr. Este paquete se usa para ordenar datos; por supuesto, está incluido en la paquetería de tidyverse. Los argumentos son, en este mismo orden: la base de datos que se desea ordenar (coca_df). Las variables que se quieren formar en una columna (palabra1 a palabra5). Una variable clave (key) donde se etiquete la columna de origen de cada palabra, le pusimos de nombre pregunta. Y por último, una variable donde se depositan todos los valores (value) de cada palabra, utilizaos el nombre palabra. Los nombres como pregunta y palabra se usan a discreción.
library(tidyr)
coca_df <- gather(coca_df, palabra1:palabra5,
key = "pregunta", value = "palabra")
coca_df
## folio demografico id pregunta palabra
## 1 1 m 1 palabra1 Botella
## 2 2 f 2 palabra1 Sed
## 3 3 m 3 palabra1 ENVASE
## 4 3 f 4 palabra1 botella
## 5 5 m 5 palabra1 PERJUDICIAL
## 6 1 m 1 palabra2 Refresco
## 7 2 f 2 palabra2 GAS
## 8 3 m 3 palabra2 Azúcar
## 9 3 f 4 palabra2 refresco
## 10 5 m 5 palabra2 AZUCAR
## 11 1 m 1 palabra3 Hielos
## 12 2 f 2 palabra3 comida
## 13 3 m 3 palabra3 negra
## 14 3 f 4 palabra3 Fría
## 15 5 m 5 palabra3 Roja
## 16 1 m 1 palabra4 fiesta
## 17 2 f 2 palabra4 rica
## 18 3 m 3 palabra4 Hielo
## 19 3 f 4 palabra4 Liquido
## 20 5 m 5 palabra4 BEBIDA
## 21 1 m 1 palabra5 Sed
## 22 2 f 2 palabra5 Familia
## 23 3 m 3 palabra5 Dañina
## 24 3 f 4 palabra5 Rica
## 25 5 m 5 palabra5 <NA>
Como mencionamos en la introducción, es necesario quitar los espacios en blanco que pudiera tener cualquier palabra antes o después, los acentos y caracteres especiales; así como convertir todas las palabras a mayúsculas o minúsculas, etc. Un par de palabras escritas de la misma forma, en las cuales una tiene espacios en blanco y la otra no, representan entidades distintas debido a estos espacios. Por ejemplo:" Refresco" (con espacio al inicio) es distinto de “Refresco”, misma palabra pero sin espacios. Para eliminar los espacios en blanco utilizaremos el paquete stringr, el cual sirve para manipular caracteres y expresiones regulares; viene incluido en tidyverse.
library(stringr)
coca_df$palabra <- str_trim(coca_df$palabra, side = "both")
coca_df
## folio demografico id pregunta palabra
## 1 1 m 1 palabra1 Botella
## 2 2 f 2 palabra1 Sed
## 3 3 m 3 palabra1 ENVASE
## 4 3 f 4 palabra1 botella
## 5 5 m 5 palabra1 PERJUDICIAL
## 6 1 m 1 palabra2 Refresco
## 7 2 f 2 palabra2 GAS
## 8 3 m 3 palabra2 Azúcar
## 9 3 f 4 palabra2 refresco
## 10 5 m 5 palabra2 AZUCAR
## 11 1 m 1 palabra3 Hielos
## 12 2 f 2 palabra3 comida
## 13 3 m 3 palabra3 negra
## 14 3 f 4 palabra3 Fría
## 15 5 m 5 palabra3 Roja
## 16 1 m 1 palabra4 fiesta
## 17 2 f 2 palabra4 rica
## 18 3 m 3 palabra4 Hielo
## 19 3 f 4 palabra4 Liquido
## 20 5 m 5 palabra4 BEBIDA
## 21 1 m 1 palabra5 Sed
## 22 2 f 2 palabra5 Familia
## 23 3 m 3 palabra5 Dañina
## 24 3 f 4 palabra5 Rica
## 25 5 m 5 palabra5 <NA>
En seguida, cambiamos el tipo de letra a minúscula para homologar todos los términos, sin que unos vengan en mayúsculas, otros en minúsculas o en formato de título.
coca_df$palabra <- str_to_lower(coca_df$palabra, locale = "es")
coca_df
## folio demografico id pregunta palabra
## 1 1 m 1 palabra1 botella
## 2 2 f 2 palabra1 sed
## 3 3 m 3 palabra1 envase
## 4 3 f 4 palabra1 botella
## 5 5 m 5 palabra1 perjudicial
## 6 1 m 1 palabra2 refresco
## 7 2 f 2 palabra2 gas
## 8 3 m 3 palabra2 azúcar
## 9 3 f 4 palabra2 refresco
## 10 5 m 5 palabra2 azucar
## 11 1 m 1 palabra3 hielos
## 12 2 f 2 palabra3 comida
## 13 3 m 3 palabra3 negra
## 14 3 f 4 palabra3 fría
## 15 5 m 5 palabra3 roja
## 16 1 m 1 palabra4 fiesta
## 17 2 f 2 palabra4 rica
## 18 3 m 3 palabra4 hielo
## 19 3 f 4 palabra4 liquido
## 20 5 m 5 palabra4 bebida
## 21 1 m 1 palabra5 sed
## 22 2 f 2 palabra5 familia
## 23 3 m 3 palabra5 dañina
## 24 3 f 4 palabra5 rica
## 25 5 m 5 palabra5 <NA>
Para juntar las palabras con un mismo significado, pero que fueron escritas con acento y sin él, los acentos tienen que ser removidos.
coca_df$palabra <- chartr('áéíóúñ','aeioun',
coca_df$palabra)
coca_df
## folio demografico id pregunta palabra
## 1 1 m 1 palabra1 botella
## 2 2 f 2 palabra1 sed
## 3 3 m 3 palabra1 envase
## 4 3 f 4 palabra1 botella
## 5 5 m 5 palabra1 perjudicial
## 6 1 m 1 palabra2 refresco
## 7 2 f 2 palabra2 gas
## 8 3 m 3 palabra2 azucar
## 9 3 f 4 palabra2 refresco
## 10 5 m 5 palabra2 azucar
## 11 1 m 1 palabra3 hielos
## 12 2 f 2 palabra3 comida
## 13 3 m 3 palabra3 negra
## 14 3 f 4 palabra3 fria
## 15 5 m 5 palabra3 roja
## 16 1 m 1 palabra4 fiesta
## 17 2 f 2 palabra4 rica
## 18 3 m 3 palabra4 hielo
## 19 3 f 4 palabra4 liquido
## 20 5 m 5 palabra4 bebida
## 21 1 m 1 palabra5 sed
## 22 2 f 2 palabra5 familia
## 23 3 m 3 palabra5 danina
## 24 3 f 4 palabra5 rica
## 25 5 m 5 palabra5 <NA>
En una red semántica natural siempre nos encontramos con palabras mal escritas o capturadas que requieren edición. Lo mismo sucede con la multiplicidad de términos, que en esencia son sinonimos (sinonimia) y significan lo mismo. Como en nuestro ejemplo: envase es lo mismo que botella. Todas esas instancias se deben editar juntando términos semejantes y corrigiendo los mal escritos. Eso se hace a través de un diccionario que se crea ex profeso. Este diccionario tendrá una aplicación muy útil. Se compara la base de datos original con él para anexarle las palabras corregidas, pero conservando el término original.
Crear un diccionario tiene varias ventajas:
El primer paso es extraer los términos o plabras únicas, no repetidas. El propósito es trabajar sobre un listado pequeño en lugar de uno larguísimo de términos repetidos. Para completar esta tarea vamos a emplear la función distinct del paquete dplyr. Los argumentos son una base de datos: coca.df, y la variable dentro de la cual se eliminan los términos repetidos.
coca_dicc <- distinct(coca_df, palabra)
coca_dicc
## palabra
## 1 botella
## 2 sed
## 3 envase
## 4 perjudicial
## 5 refresco
## 6 gas
## 7 azucar
## 8 hielos
## 9 comida
## 10 negra
## 11 fria
## 12 roja
## 13 fiesta
## 14 rica
## 15 hielo
## 16 liquido
## 17 bebida
## 18 familia
## 19 danina
## 20 <NA>
Como puedes observar, las palabras botella, sed, refresco, azucar y rica han sido removidas porque aparencen repetidas. De los 25 términos originales, ahora quedan 20. Sin embargo, el NA (Not Available) o missing data permanece, para removerlo utilizamos la función na.omit(), la cual es nativa de R, es decir, no necesitas ninguna librería adicional.
coca_dicc <- na.omit(coca_dicc)
coca_dicc
## palabra
## 1 botella
## 2 sed
## 3 envase
## 4 perjudicial
## 5 refresco
## 6 gas
## 7 azucar
## 8 hielos
## 9 comida
## 10 negra
## 11 fria
## 12 roja
## 13 fiesta
## 14 rica
## 15 hielo
## 16 liquido
## 17 bebida
## 18 familia
## 19 danina
Antes de exportar los términos obtenidos a Excel (donde haremos nuestro diccionario) hay que ordenar la base de datos para facilitar el trabajo de edición.
Usamos la función arrange de dplyr para ordenar por palabras. Los argumentos son la base de datos (coca.dicc) y la variable por la que hay que ordenar: palabra.
coca_dicc <- arrange(coca_dicc, palabra)
coca_dicc
## palabra
## 1 azucar
## 2 bebida
## 3 botella
## 4 comida
## 5 danina
## 6 envase
## 7 familia
## 8 fiesta
## 9 fria
## 10 gas
## 11 hielo
## 12 hielos
## 13 liquido
## 14 negra
## 15 perjudicial
## 16 refresco
## 17 rica
## 18 roja
## 19 sed
Asimismo, creamos una variable a la que llamaremos edicion. Allí copiaremos los términos originales para editarlos, con ello logramos que las palabras originales queden intactas.
El siguiente código crera una variable con la función mutate(), que ya conoces.
coca_dicc <- mutate(coca_dicc, edicion = palabra)
coca_dicc
## palabra edicion
## 1 azucar azucar
## 2 bebida bebida
## 3 botella botella
## 4 comida comida
## 5 danina danina
## 6 envase envase
## 7 familia familia
## 8 fiesta fiesta
## 9 fria fria
## 10 gas gas
## 11 hielo hielo
## 12 hielos hielos
## 13 liquido liquido
## 14 negra negra
## 15 perjudicial perjudicial
## 16 refresco refresco
## 17 rica rica
## 18 roja roja
## 19 sed sed
En la práctica querras hacer el trabajo de edición en Excel debido a que hay muchas palabras que editar, al menos la primera vez. Entonces lo que sigue es exportar tu base a formato .csv (valores separados por coma), el cual Excel lee fácilmente. La función write_csv() del paquete readr es adecuada para esta situación. Declara únicamente el archivo que deseas exportar, en este caso es coca.dicc, seguido del nombre de archivo exportado. Cómo te suena coca_dicc.csv. Nota que si tienes algún otro archivo con ese nombre R te lo sobreescribira automaticamente, así que ojo.
write_csv(coca_dicc, "coca_dicc.csv")
La tabla de abajo muestra el trabajo de edición hecho. Como se observa, la palabra envase (término 6) se editó transformándole en botella; hielos (caso 12) pasó al singular hielo; y perjudicial (palabra 15) se unifica con danina.
| palabra | edicion |
|---|---|
| 1. azucar | azucar |
| 2. bebida | bebida |
| 3. botella | botella |
| 4. comida | comida |
| 5. danina | danina |
| 6. envase | botella |
| 7. familia | familia |
| 8. fiesta | fiesta |
| 9. fria | fria |
| 10. gas | gas |
| 11. hielo | hielo |
| 12. hielos | hielo |
| 13. liquido | liquido |
| 14. negra | negra |
| 15. perjudicial | danina |
| 16. refresco | refresco |
| 17. rica | rica |
| 18. roja | roja |
| 19. sed | sed |
Ahora, ya estamos listos para juntar la base de datos coca.df con el diccionario coca_dicc.csv. Para ello vamos a usar la función left_join() de nuestro paquete aliado dplyr. ¿Qué hace esta función? Compara dos tablas (data frames) con base a una variable clave (en nuestro caso es palabra) y las fuisiona en una sola. La función se llama left_join (unión izquierda) porque anexa las columnas de la tabla derecha a la de la izquierda, cuando ambas coinciden en la misma variable (i.e. palabra). Cuando no hay coincidencias los casos de la tabla derecha desaparecen, pero los de la izquierda permanecen y son etiquetados con NA (Not Available). Es decir, no se encuentran en el diccionario. Esto es muy conveniente pues en una subsecuente medición nuestra función nos etiquetará todos los términos que no existen en el diccionario.
coca_dicc <- read_csv("coca_diccionario.csv")
coca_df <- left_join(coca_df, coca_dicc,
key = "palabra")
coca_df
## folio demografico id pregunta palabra edicion
## 1 1 m 1 palabra1 botella botella
## 2 2 f 2 palabra1 sed sed
## 3 3 m 3 palabra1 envase botella
## 4 3 f 4 palabra1 botella botella
## 5 5 m 5 palabra1 perjudicial danina
## 6 1 m 1 palabra2 refresco refresco
## 7 2 f 2 palabra2 gas gas
## 8 3 m 3 palabra2 azucar azucar
## 9 3 f 4 palabra2 refresco refresco
## 10 5 m 5 palabra2 azucar azucar
## 11 1 m 1 palabra3 hielos hielo
## 12 2 f 2 palabra3 comida comida
## 13 3 m 3 palabra3 negra negra
## 14 3 f 4 palabra3 fria fria
## 15 5 m 5 palabra3 roja roja
## 16 1 m 1 palabra4 fiesta fiesta
## 17 2 f 2 palabra4 rica rica
## 18 3 m 3 palabra4 hielo hielo
## 19 3 f 4 palabra4 liquido liquido
## 20 5 m 5 palabra4 bebida bebida
## 21 1 m 1 palabra5 sed sed
## 22 2 f 2 palabra5 familia familia
## 23 3 m 3 palabra5 danina danina
## 24 3 f 4 palabra5 rica rica
## 25 5 m 5 palabra5 <NA> <NA>
Seguramente notas que el sujeto 5 no proporcionó una quinta palabra (palabra 25); por tanto tampoco se encontró el termino en el diccionario y es etiquetado con NA. La próxima vez que hagas el estudio con el mismo concepto, los términos que no aprezacan en tu diccionario serán etiquetados con NA, de esa forma se facilita su identificación e incorporación al diccionario.
En ocasiones un sujeto porporciona la misma palabra más de una vez, o pudiera ser que al aplicar el diccionario, dos palabras que aprentemente son distintas se agrupan, por circunstancias de su sinomimia, en un mismo termino lo que ocasiona que un sujeto tenga palabras duplicadas. Por lo anterior, tenemos que eliminar la redundancia de términos por sujeto.
Usemos el mismo procedimiento con la función distinct; sin embargo en esta ocasión debemos utilizar un par de argumentos adicionales. El primero es el id, pues no queremos palabras repetidas por sujeto. El segundo es .keep_all = TRUE, que impide que sean borradas las variables adicionales a la usada o usadas para buscar los términos distintos.
coca_df <- distinct(coca_df, id, palabra, .keep_all = TRUE)
coca_df
Asimismo removemos los casos con NA.
palabras_tdy.df <- drop_na(palabras_tdy.df, palabra)
palabras_tdy.df
La combinación de palabras en pares se hace con la ayuda del paquete widyr Los argumentos de la función son:
library(widyr)
pairwise_count(tbl = palabras_tdy.df, item = palabra,
feature = id_nuevo, upper = FALSE,
diag = FALSE, sort = TRUE)
aristas.df <- gather(palabras.df, p1:p3, key = "pregunta", value = "palabras") %>%
distinct(folio, palabras) %>%
pairwise_count(palabras, folio, upper = FALSE, sort = TRUE) %>%
filter(n >= 2) %>%
mutate(type = "undirected") %>%
rename(source = item1, target = item2, weigth = n) %>%
write.csv("red_general.csv", row.names = F)