# Cargar las funciones desde el archivo funciones.R
source("C:/Users/PC/Desktop/PLE/Manipulación de dataframe/a/funciones.r")
1 Manipulación de data frame
1.1 Funciones, Módulos y Librerías principales en R
1.2 Funciones y módulos
- Funciones y Scripts: Puedes dividir tu código en funciones y scripts separados para organizarlo de manera más clara y reutilizable. Cada script podría contener un conjunto de funciones relacionadas entre sí.
- Paquetes: La construcción de paquetes es una forma poderosa de modularizar el código en R. Los paquetes son conjuntos de funciones, datos y documentación que se distribuyen para un propósito específico y se pueden compartir con otros usuarios. Puedes crear tus propios paquetes para organizar y compartir tu código de manera efectiva.
- Los paquetes en R son colecciones de funciones y conjunto de datos desarrollados por la comunidad. Estos incrementan la potencialidad de R mejorando las funcionalidades base en R, o añadiendo de nuevas. Por ejemplo, en el campo de Ciencia de los Datos cuando trabajamos con data.frames, probablemente usaremos los paquetes dplyr
o data.table
, dos de los paquetes mas populares en la comunidad.
- En R Studio, no necesitas una librería específica para importar módulos. Puedes utilizar la función source()
que viene integrada en R para cargar funciones, scripts o módulos desde archivos externos. La función source()
permite ejecutar código desde un archivo R en tu sesión actual. Por ejemplo, si tienes un archivo llamado “funciones.R” con las funciones que mencionamos anteriormente, puedes importar ese archivo utilizando source()
de esta manera:
source("ruta/al/archivo/funciones.R")
# Reemplaza con la ruta correcta de tu archivo`
1.2.1 Caso uno usando funciones
Ahora usando el módulo de “Funciones.r” para hacer calculos con números direrentes
# Ahora las funciones están disponibles para su uso en R Studio
<- Suma5(1, 2, 3, 4, 5)
resultado_suma
<- Potencia5(1, 2, 3, 4, 5)
resultados_potencia
<- Raiz5(1, 4, 9, 16, 25)
resultados_raiz
<- Varianza5(1, 2, 3, 4, 5) varianza_resultado
Imprimimos resultados de la funciones
# Imprimimos resultados de la funciones
print(resultado_suma)
[1] 15
print(resultados_potencia)
[1] 1 4 9 16 25
print(resultados_raiz)
[1] 1 2 3 4 5
print(varianza_resultado)
[1] 2.5
# Ejemplo de uso de las nuevas funciones
<- Seno(pi/2)
resultado_seno
<- Coseno(0)
resultado_coseno
<- Logaritmo(10)
resultado_log
<- Factorial(5) resultado_factorial
print(resultado_seno)
[1] 1
print(resultado_coseno)
[1] 1
print(resultado_log)
[1] 2.302585
print(resultado_factorial)
[1] 120
1.2.1.1 Ejemplo: Aplicación de funciones trigonométricas en arquitectura
Imagina que estás trabajando como arquitecto/a y necesitas diseñar una rampa para un edificio que cumpla con ciertas especificaciones. Utilizarás funciones trigonométricas para calcular la longitud de la rampa, la altura y la pendiente necesarias para asegurar la accesibilidad.
Supongamos que necesitas diseñar una rampa para un edificio con una altura vertical de 5 metros y quieres que la rampa tenga un ángulo de inclinación específico para que sea cómoda para los peatones.
Cálculo de la longitud de la rampa:
Utilizamos funciones trigonométricas para calcular la longitud de la rampa basada en la altura vertical y el ángulo de inclinación deseado.
<- 5 # Altura del edificio en metros
Altura
<- 10 # Ángulo de inclinación en grados
Angulo
# Convertir el ángulo a radianes para usar funciones trigonométricas en R
<- Angulo * (pi / 180)
Angulo_radianes
Angulo_radianes
[1] 0.1745329
# Calcular la longitud de la rampa usando trigonometría (hipotenusa)
<- Altura / sin(Angulo_radianes)
Longitud_rampa
Longitud_rampa
[1] 28.79385
Cálculo de la pendiente de la rampa:
La pendiente es la relación entre la altura y la longitud de la rampa.
# Calcular la pendiente de la rampa
<- Altura / Longitud_rampa
Pendiente
Pendiente
[1] 0.1736482
1.2.1.2 Ejemplo: Modelado del crecimiento poblacional
Imagina que eres un biólogo que estudia el crecimiento de una población de bacterias en un entorno controlado. Las bacterias se reproducen cada cierto período de tiempo, y quieres modelar este crecimiento utilizando funciones exponenciales.
Supongamos que has observado que, en tu entorno controlado, el número de bacterias se duplica cada 2 horas. Utilizarás una función exponencial para modelar este crecimiento.
Solución:
La fórmula exponencial que describe el crecimiento de las bacterias es:
\(N(t) = N_0 \times e^{rt}\)
Donde:
- \(N(t)\) es el número de bacterias en el tiempo \(t\).
- \(N_0\) es el número inicial de bacterias.
- \(r\) es la tasa de crecimiento.
- \(e\) es la base del logaritmo natural.
- \(t\) es el tiempo.
Supogamos que inicialmente se tiene 100 bacterias
# Definir la función exponencial para el crecimiento de las bacterias
<- function(t) {
CrecimientoBacterias
<- 100 # Número inicial de bacterias
N0
<- log(2) / 2 # La población se duplica cada 2 horas (log(2) / 2)
r
<- N0 * exp(r * t)
Nt
return(Nt)
}
Gráfico del crecimiento de las bacterias:
Puedes crear un gráfico para visualizar cómo crece la población de bacterias en función del tiempo.
# Crear un vector de tiempos (por ejemplo, de 0 a 10 horas)
<- seq(0, 10, by = 0.5)
tiempo
# Calcular el número de bacterias en cada tiempo
<- sapply(tiempo, CrecimientoBacterias)
poblacion
# Graficar el crecimiento de las bacterias en función del tiempo
plot(tiempo, poblacion, type = "l", xlab = "Tiempo (horas)", ylab = "Número de bacterias",
main = "Crecimiento de bacterias en función del tiempo")
1.3 Librerías
En R, una librería (también conocida como paquete) es un conjunto de funciones, datos y documentación que extiende la funcionalidad del lenguaje base. Estos paquetes son desarrollados por la comunidad de R y permiten a los usuarios acceder a una amplia gama de herramientas y funcionalidades especializadas para diferentes tipos de análisis y tareas.
Puedes utilizar la función install.packages()
para instalar un paquete en R, y luego la función library()
para cargarlo y utilizar sus funciones en tu sesión actual. Por ejemplo:
install.packages("nombre_del_paquete")
Reemplaza “nombre_del_paquete” con el nombre del paquete que quieras instalar, por ejemplo: install.packages("ggplot2")
instalará el paquete ggplot2
para gráficos. Para cargar un paquete se usa library()
library("nombre_del_paquete")
1.4 Dataframe, Manipulación e Introducción al análisis de datos.
La manipulación de data frames significa distintas cosas para distintos investigadores. A veces queremos seleccionar ciertas observaciones (filas) o variables (columnas), otras veces deseamos agrupar los datos en función de una o más variables, o queremos calcular valores estadísticos de un conjunto. Podemos hacer todo ello usando las habituales operaciones básicas de R:
EJEMPLOS:
#Data Frame
##caso 1
=c('a','b','c','d')
x
=c(20,32,53,56)
x1
=c('masculino','femenino','masculino','masculino')
x2
=data.frame(casos=x,edadDeCasos=x1,sexoDecasos=x2) DataFrame1
Luego de correrlo, vemos en Environment que este código creó tres vectores. Un vector (x) tiene los nombres o IDs de las filas. Los nombres de los vectores (“x”,“x1”,“x2”) no son informativos de sus contenidos de datos. El comando data.frame enlaza a todos los tres vectores como columnas y nos brinda un nombre explícito para cada columna.
Para ver el data frame generado, correr el siguiente código:
DataFrame1
casos edadDeCasos sexoDecasos
1 a 20 masculino
2 b 32 femenino
3 c 53 masculino
4 d 56 masculino
##caso 2
=c('a','b','c','d')
casos
=c(20,32,53,56)
edadDeCasos
=c('masculino','femenino','masculino','masculino')
sexoDeCasos
=data.frame(edadDeCasos,sexoDeCasos,row.names=casos) DataFrame2
Luego de correrlo, vemos en Environment que este código creó tres vectores. Un vector (casos
) tiene los nombres o IDs de las filas. Los nombres de los vectores (“casos
”,“edadDeCasos
”,“sexoDeCasos
”) informan acerca de qué tratan sus contenidos. El comando data.frame enlaza los vectores como columnas, y los nombres de los vectores son los nombres de las columnas en el data frame. [Notar el uso de la opción `row.names`]
Para ver el data frame generado, correr el siguiente código:
DataFrame2
edadDeCasos sexoDeCasos
a 20 masculino
b 32 femenino
c 53 masculino
d 56 masculino
##caso3
=list(edadDeCasos=20,sexoDeCasos='masculino')
a
=list(edadDeCasos=32,sexoDeCasos='femenino')
b
=list(edadDeCasos=53,sexoDeCasos='masculino')
c
=list(edadDeCasos=56,sexoDeCasos='masculino')
d
=data.frame(rbind(a,b,c,d)) DataFrame3
Luego de correrlo, vemos en Environment que este código creó cuatro listas (“a”,“b”,“c”,“d”). Cada lista tiene la información de la entrada de una fila. Cada elemento de la lista asocia cada valor a una variable. El comando data.frame enlaza todas las listas como filas, con la ayuda del comando rbind. Esta última es una forma alternativa de crear data frames, en caso tengas los datos por unidad de análisis (vale decir, por filas).
DataFrame3
edadDeCasos sexoDeCasos
a 20 masculino
b 32 femenino
c 53 masculino
d 56 masculino
Ejemplo con github
# Descargar el archivo RData desde GitHub
<- "https://github.com/hllinas/DatosPublicos/raw/main/Estudiantes.Rdata"
url
<- "Estudiantes.Rdata"
dest_file
download.file(url, dest_file, mode = "wb")
# Cargar los datos desde el archivo RData descargado
load("Estudiantes.Rdata")
# Verificar los nombres de los objetos cargados
ls()
[1] "a" "Altura" "Angulo"
[4] "Angulo_radianes" "b" "c"
[7] "casos" "Coseno" "CrecimientoBacterias"
[10] "d" "DataFrame1" "DataFrame2"
[13] "DataFrame3" "dest_file" "edadDeCasos"
[16] "Estudiantes" "Factorial" "has_annotations"
[19] "Logaritmo" "Longitud_rampa" "Pendiente"
[22] "poblacion" "Potencia5" "Raiz5"
[25] "resultado_coseno" "resultado_factorial" "resultado_log"
[28] "resultado_seno" "resultado_suma" "resultados_potencia"
[31] "resultados_raiz" "Seno" "sexoDeCasos"
[34] "Suma5" "tiempo" "url"
[37] "varianza_resultado" "Varianza5" "x"
[40] "x1" "x2"
# Si "Estudiantes" es el nombre del objeto que contiene los datos
<- Estudiantes datosCompleto
Ejemplo de Drive
<- "http://bit.ly/Database-Estudiantes"
url.dat
<- read.delim(url.dat) datosCompleto
Visualizar una parte de la información
head(datosCompleto) #2) Por defecto, solo las primeras 6 observaciones
Observacion ID Sexo SexoNum Edad Fuma Estatura Colegio
1 1 SB11201910010435 Femenino 0 21.36 No Alta Privado
2 2 SB11201910004475 Masculino 1 21.07 Si Baja Privado
3 3 SB11201910011427 Masculino 1 20.92 Si Alta Privado
4 4 SB11201910041975 Masculino 1 18.41 Si Alta Privado
5 5 SB11201910013623 Femenino 0 16.64 Si Alta Privado
6 6 SB11201910038122 Femenino 0 16.02 No Baja Privado
Estrato Financiacion Acumulado P1 P2 P3 Final Definitiva Gastos Ingreso
1 1 Beca 3.92 1.5 5.0 5.0 4.5 4.00 48.9 1.61
2 2 Beca 3.96 2.3 4.9 3.7 3.3 3.55 72.1 2.07
3 2 Beca 3.85 3.4 3.6 2.0 1.9 2.73 85.2 2.84
4 2 Beca 3.69 2.5 4.2 5.0 2.5 3.55 56.6 1.55
5 1 Beca 4.01 3.1 3.5 5.0 3.0 3.65 64.6 2.32
6 2 Beca 3.80 3.8 4.4 4.2 5.0 4.35 63.0 2.10
Gas Clases Ley PandemiaCat PandemiaNum
1 27.45 Virtual En desacuerdo De acuerdo 3
2 24.17 Presencial En desacuerdo De acuerdo 3
3 22.27 Virtual En desacuerdo De acuerdo 3
4 23.08 Virtual En desacuerdo De acuerdo 3
5 27.26 Virtual En desacuerdo Ni de acuerdo, ni en desacuerdo 2
6 17.16 Presencial De acuerdo De acuerdo 3
Likert1 Likert2 Likert3 Likert4 Likert5 AGPEQ1
1 4 5 1 3 1 Totalmente de acuerdo
2 3 2 4 3 2 Ni de acuerdo, ni en desacuerdo
3 2 3 3 4 2 De acuerdo
4 5 4 2 3 5 De acuerdo
5 1 1 5 2 5 Totalmente de acuerdo
6 3 2 3 1 1 De acuerdo
AGPEQ2 AGPEQ3
1 De acuerdo Totalmente de acuerdo
2 En desacuerdo En desacuerdo
3 En desacuerdo De acuerdo
4 Ni de acuerdo, ni en desacuerdo Totalmente de acuerdo
5 Ni de acuerdo, ni en desacuerdo Totalmente en desacuerdo
6 En desacuerdo En desacuerdo
SATS1 SATS2 SATS3
1 Indeciso De acuerdo En desacuerdo
2 En desacuerdo De acuerdo Indeciso
3 En desacuerdo Totalmente de acuerdo Indeciso
4 Totalmente en desacuerdo Totalmente de acuerdo En desacuerdo
5 Indeciso De acuerdo En desacuerdo
6 De acuerdo Indeciso En desacuerdo
SATS4 IDARE1.1 IDARE1.2 IDARE1.3
1 De acuerdo Bastante Poco Bastante
2 Totalmente en desacuerdo Bastante Poco Mucho
3 De acuerdo Bastante Poco Bastante
4 De acuerdo Poco No en lo absoluto Bastante
5 Indeciso Poco Poco Bastante
6 De acuerdo Mucho Mucho Poco
IDARE1.4 IDARE1.5 IDARE2.6 IDARE2.7
1 Bastante Poco Frecuentemente Casi siempre
2 No en lo absoluto Bastante Frecuentemente Algunas veces
3 Bastante Poco Algunas veces Algunas veces
4 Bastante No en lo absoluto Casi siempre Frecuentemente
5 Bastante Poco Algunas veces Algunas veces
6 No en lo absoluto Mucho Casi siempre Casi nunca
IDARE2.8 IDARE2.9 IDARE2.10 Puntaje
1 Frecuentemente Casi siempre Casi siempre 81
2 Algunas veces Frecuentemente Frecuentemente 78
3 Algunas veces Frecuentemente Algunas veces 77
4 Frecuentemente Casi nunca Algunas veces 70
5 Frecuentemente Casi nunca Casi nunca 68
6 Algunas veces Algunas veces Frecuentemente 65
head(datosCompleto, 3) #3) Solo las primeras 3 observaciones
Observacion ID Sexo SexoNum Edad Fuma Estatura Colegio
1 1 SB11201910010435 Femenino 0 21.36 No Alta Privado
2 2 SB11201910004475 Masculino 1 21.07 Si Baja Privado
3 3 SB11201910011427 Masculino 1 20.92 Si Alta Privado
Estrato Financiacion Acumulado P1 P2 P3 Final Definitiva Gastos Ingreso
1 1 Beca 3.92 1.5 5.0 5.0 4.5 4.00 48.9 1.61
2 2 Beca 3.96 2.3 4.9 3.7 3.3 3.55 72.1 2.07
3 2 Beca 3.85 3.4 3.6 2.0 1.9 2.73 85.2 2.84
Gas Clases Ley PandemiaCat PandemiaNum Likert1 Likert2
1 27.45 Virtual En desacuerdo De acuerdo 3 4 5
2 24.17 Presencial En desacuerdo De acuerdo 3 3 2
3 22.27 Virtual En desacuerdo De acuerdo 3 2 3
Likert3 Likert4 Likert5 AGPEQ1 AGPEQ2
1 1 3 1 Totalmente de acuerdo De acuerdo
2 4 3 2 Ni de acuerdo, ni en desacuerdo En desacuerdo
3 3 4 2 De acuerdo En desacuerdo
AGPEQ3 SATS1 SATS2 SATS3
1 Totalmente de acuerdo Indeciso De acuerdo En desacuerdo
2 En desacuerdo En desacuerdo De acuerdo Indeciso
3 De acuerdo En desacuerdo Totalmente de acuerdo Indeciso
SATS4 IDARE1.1 IDARE1.2 IDARE1.3 IDARE1.4
1 De acuerdo Bastante Poco Bastante Bastante
2 Totalmente en desacuerdo Bastante Poco Mucho No en lo absoluto
3 De acuerdo Bastante Poco Bastante Bastante
IDARE1.5 IDARE2.6 IDARE2.7 IDARE2.8 IDARE2.9
1 Poco Frecuentemente Casi siempre Frecuentemente Casi siempre
2 Bastante Frecuentemente Algunas veces Algunas veces Frecuentemente
3 Poco Algunas veces Algunas veces Algunas veces Frecuentemente
IDARE2.10 Puntaje
1 Casi siempre 81
2 Frecuentemente 78
3 Algunas veces 77
tail(datosCompleto) #4) Por defecto, solo las últimas 6 observaciones
Observacion ID Sexo SexoNum Edad Fuma Estatura Colegio
395 395 SB11201910060914 Femenino 0 16.54 Si Media Publico
396 396 SB11201910040869 Masculino 1 17.97 No Media Publico
397 397 SB11201910040887 Masculino 1 17.22 Si Media Publico
398 398 SB11201910040981 Femenino 0 20.41 No Media Publico
399 399 SB11201910040935 Femenino 0 18.72 Si Media Publico
400 400 SB11201910043103 Masculino 1 17.04 Si Media Publico
Estrato Financiacion Acumulado P1 P2 P3 Final Definitiva Gastos Ingreso
395 3 Otro 4.04 4.0 4.8 3.0 3.1 3.73 33.6 1.12
396 3 Otro 4.15 4.5 5.0 3.3 1.9 3.68 62.6 2.42
397 3 Otro 3.90 5.0 3.8 4.2 3.9 4.23 41.4 1.39
398 3 Otro 3.64 3.5 3.6 3.8 4.9 3.95 40.8 1.36
399 1 Otro 4.42 4.9 5.0 4.4 3.3 4.40 53.3 2.11
400 1 Otro 3.45 2.5 4.3 3.9 4.5 3.80 56.8 1.89
Gas Clases Ley PandemiaCat PandemiaNum
395 19.46 Virtual En desacuerdo De acuerdo 3
396 16.02 Presencial En desacuerdo En desacuerdo 1
397 17.04 Presencial De acuerdo Ni de acuerdo, ni en desacuerdo 2
398 20.83 Presencial De acuerdo De acuerdo 3
399 18.72 Virtual En desacuerdo En desacuerdo 1
400 18.45 Presencial De acuerdo Ni de acuerdo, ni en desacuerdo 2
Likert1 Likert2 Likert3 Likert4 Likert5 AGPEQ1
395 1 1 4 4 3 De acuerdo
396 2 1 3 4 1 De acuerdo
397 5 2 3 2 3 De acuerdo
398 1 5 2 5 1 De acuerdo
399 2 3 5 1 1 En desacuerdo
400 1 2 2 2 3 Totalmente de acuerdo
AGPEQ2 AGPEQ3
395 Totalmente en desacuerdo En desacuerdo
396 Ni de acuerdo, ni en desacuerdo Ni de acuerdo, ni en desacuerdo
397 De acuerdo De acuerdo
398 Ni de acuerdo, ni en desacuerdo Ni de acuerdo, ni en desacuerdo
399 Totalmente de acuerdo Totalmente en desacuerdo
400 En desacuerdo Totalmente en desacuerdo
SATS1 SATS2 SATS3
395 Totalmente de acuerdo Indeciso Totalmente en desacuerdo
396 De acuerdo Indeciso En desacuerdo
397 De acuerdo En desacuerdo En desacuerdo
398 Totalmente de acuerdo En desacuerdo En desacuerdo
399 De acuerdo De acuerdo Indeciso
400 De acuerdo Totalmente en desacuerdo En desacuerdo
SATS4 IDARE1.1 IDARE1.2 IDARE1.3 IDARE1.4 IDARE1.5
395 De acuerdo Mucho Mucho Poco Poco Bastante
396 En desacuerdo Mucho Bastante Poco No en lo absoluto Bastante
397 De acuerdo Bastante Bastante Poco No en lo absoluto Bastante
398 Indeciso Poco Bastante Poco No en lo absoluto Mucho
399 En desacuerdo Poco Poco Mucho Bastante Poco
400 De acuerdo Bastante Poco Poco Poco Poco
IDARE2.6 IDARE2.7 IDARE2.8 IDARE2.9 IDARE2.10
395 Algunas veces Algunas veces Algunas veces Algunas veces Algunas veces
396 Frecuentemente Frecuentemente Frecuentemente Casi nunca Casi nunca
397 Frecuentemente Algunas veces Casi nunca Casi nunca Algunas veces
398 Casi siempre Casi nunca Casi nunca Casi nunca Casi nunca
399 Frecuentemente Algunas veces Algunas veces Casi nunca Casi nunca
400 Casi siempre Algunas veces Casi nunca Algunas veces Algunas veces
Puntaje
395 27
396 19
397 18
398 15
399 17
400 19
tail(datosCompleto, 2) #5) Solo las últimas 2 observaciones
Observacion ID Sexo SexoNum Edad Fuma Estatura Colegio
399 399 SB11201910040935 Femenino 0 18.72 Si Media Publico
400 400 SB11201910043103 Masculino 1 17.04 Si Media Publico
Estrato Financiacion Acumulado P1 P2 P3 Final Definitiva Gastos Ingreso
399 1 Otro 4.42 4.9 5.0 4.4 3.3 4.4 53.3 2.11
400 1 Otro 3.45 2.5 4.3 3.9 4.5 3.8 56.8 1.89
Gas Clases Ley PandemiaCat PandemiaNum
399 18.72 Virtual En desacuerdo En desacuerdo 1
400 18.45 Presencial De acuerdo Ni de acuerdo, ni en desacuerdo 2
Likert1 Likert2 Likert3 Likert4 Likert5 AGPEQ1
399 2 3 5 1 1 En desacuerdo
400 1 2 2 2 3 Totalmente de acuerdo
AGPEQ2 AGPEQ3 SATS1
399 Totalmente de acuerdo Totalmente en desacuerdo De acuerdo
400 En desacuerdo Totalmente en desacuerdo De acuerdo
SATS2 SATS3 SATS4 IDARE1.1 IDARE1.2
399 De acuerdo Indeciso En desacuerdo Poco Poco
400 Totalmente en desacuerdo En desacuerdo De acuerdo Bastante Poco
IDARE1.3 IDARE1.4 IDARE1.5 IDARE2.6 IDARE2.7 IDARE2.8
399 Mucho Bastante Poco Frecuentemente Algunas veces Algunas veces
400 Poco Poco Poco Casi siempre Algunas veces Casi nunca
IDARE2.9 IDARE2.10 Puntaje
399 Casi nunca Casi nunca 17
400 Algunas veces Algunas veces 19
Explorar atributos y funciones
str(datosCompleto) #6) Estructura de los datos
'data.frame': 400 obs. of 46 variables:
$ Observacion : int 1 2 3 4 5 6 7 8 9 10 ...
$ ID : chr "SB11201910010435" "SB11201910004475" "SB11201910011427" "SB11201910041975" ...
$ Sexo : chr "Femenino" "Masculino" "Masculino" "Masculino" ...
$ SexoNum : int 0 1 1 1 0 0 0 0 0 1 ...
$ Edad : num 21.4 21.1 20.9 18.4 16.6 ...
$ Fuma : chr "No" "Si" "Si" "Si" ...
$ Estatura : chr "Alta" "Baja" "Alta" "Alta" ...
$ Colegio : chr "Privado" "Privado" "Privado" "Privado" ...
$ Estrato : int 1 2 2 2 1 2 1 1 2 1 ...
$ Financiacion: chr "Beca" "Beca" "Beca" "Beca" ...
$ Acumulado : num 3.92 3.96 3.85 3.69 4.01 3.8 4.35 3.76 3.57 3.15 ...
$ P1 : num 1.5 2.3 3.4 2.5 3.1 3.8 5 4 2.5 2.4 ...
$ P2 : num 5 4.9 3.6 4.2 3.5 4.4 3 2.3 3.3 2.6 ...
$ P3 : num 5 3.7 2 5 5 4.2 3.5 4.6 3.8 4.3 ...
$ Final : num 4.5 3.3 1.9 2.5 3 5 3.6 4.3 1.9 5 ...
$ Definitiva : num 4 3.55 2.73 3.55 3.65 4.35 3.78 3.8 2.88 3.58 ...
$ Gastos : num 48.9 72.1 85.2 56.6 64.6 63 40.8 65.4 37.3 63 ...
$ Ingreso : num 1.61 2.07 2.84 1.55 2.32 2.1 1.69 2.18 1.71 2.1 ...
$ Gas : num 27.4 24.2 22.3 23.1 27.3 ...
$ Clases : chr "Virtual" "Presencial" "Virtual" "Virtual" ...
$ Ley : chr "En desacuerdo" "En desacuerdo" "En desacuerdo" "En desacuerdo" ...
$ PandemiaCat : chr "De acuerdo" "De acuerdo" "De acuerdo" "De acuerdo" ...
$ PandemiaNum : int 3 3 3 3 2 3 3 3 1 3 ...
$ Likert1 : int 4 3 2 5 1 3 4 1 2 5 ...
$ Likert2 : int 5 2 3 4 1 2 3 2 1 4 ...
$ Likert3 : int 1 4 3 2 5 3 3 3 4 1 ...
$ Likert4 : int 3 3 4 3 2 1 4 3 2 5 ...
$ Likert5 : int 1 2 2 5 5 1 2 2 5 2 ...
$ AGPEQ1 : chr "Totalmente de acuerdo" "Ni de acuerdo, ni en desacuerdo" "De acuerdo" "De acuerdo" ...
$ AGPEQ2 : chr "De acuerdo" "En desacuerdo" "En desacuerdo" "Ni de acuerdo, ni en desacuerdo" ...
$ AGPEQ3 : chr "Totalmente de acuerdo" "En desacuerdo" "De acuerdo" "Totalmente de acuerdo" ...
$ SATS1 : chr "Indeciso" "En desacuerdo" "En desacuerdo" "Totalmente en desacuerdo" ...
$ SATS2 : chr "De acuerdo" "De acuerdo" "Totalmente de acuerdo" "Totalmente de acuerdo" ...
$ SATS3 : chr "En desacuerdo" "Indeciso" "Indeciso" "En desacuerdo" ...
$ SATS4 : chr "De acuerdo" "Totalmente en desacuerdo" "De acuerdo" "De acuerdo" ...
$ IDARE1.1 : chr "Bastante" "Bastante" "Bastante" "Poco" ...
$ IDARE1.2 : chr "Poco" "Poco" "Poco" "No en lo absoluto" ...
$ IDARE1.3 : chr "Bastante" "Mucho" "Bastante" "Bastante" ...
$ IDARE1.4 : chr "Bastante" "No en lo absoluto" "Bastante" "Bastante" ...
$ IDARE1.5 : chr "Poco" "Bastante" "Poco" "No en lo absoluto" ...
$ IDARE2.6 : chr "Frecuentemente" "Frecuentemente" "Algunas veces" "Casi siempre" ...
$ IDARE2.7 : chr "Casi siempre" "Algunas veces" "Algunas veces" "Frecuentemente" ...
$ IDARE2.8 : chr "Frecuentemente" "Algunas veces" "Algunas veces" "Frecuentemente" ...
$ IDARE2.9 : chr "Casi siempre" "Frecuentemente" "Frecuentemente" "Casi nunca" ...
$ IDARE2.10 : chr "Casi siempre" "Frecuentemente" "Algunas veces" "Algunas veces" ...
$ Puntaje : int 81 78 77 70 68 65 54 50 36 35 ...
class(datosCompleto) #7) Muestra el tipo de objeto.
[1] "data.frame"
names(datosCompleto) #8) Muestra los nombres de las columnas.
[1] "Observacion" "ID" "Sexo" "SexoNum" "Edad"
[6] "Fuma" "Estatura" "Colegio" "Estrato" "Financiacion"
[11] "Acumulado" "P1" "P2" "P3" "Final"
[16] "Definitiva" "Gastos" "Ingreso" "Gas" "Clases"
[21] "Ley" "PandemiaCat" "PandemiaNum" "Likert1" "Likert2"
[26] "Likert3" "Likert4" "Likert5" "AGPEQ1" "AGPEQ2"
[31] "AGPEQ3" "SATS1" "SATS2" "SATS3" "SATS4"
[36] "IDARE1.1" "IDARE1.2" "IDARE1.3" "IDARE1.4" "IDARE1.5"
[41] "IDARE2.6" "IDARE2.7" "IDARE2.8" "IDARE2.9" "IDARE2.10"
[46] "Puntaje"
help(datosCompleto) #9) Muestra la ayuda asociada para el archivo de datos (si la hay).
No documentation for 'datosCompleto' in specified packages and libraries:
you could try '??datosCompleto'
#10) Muestra la ayuda asociada para el archivo de datos en la web (si la hay). ??datosCompleto
starting httpd help server ... done
Verificar tamaños
length(datosCompleto) #11) Revisando número de variables del objeto
[1] 46
dim(datosCompleto) #12) Muestra las dimensiones del objeto.
[1] 400 46
ncol(datosCompleto) #13) Muestra el número de columnas del objeto.
[1] 46
nrow(datosCompleto) #14) Muestra el número de filas del objeto.
[1] 400
1.5 Análisis de datos
Vamos a trabajar con un conjunto de datos que recoge asociaciones mentales con la expresión “Big data”. Este conjunto se forma a partir de respuestas a una breve encuesta que solicitaba palabras o frases asociadas a esta expresión, junto con la valoración positiva o negativa de dichas ideas. También registramos el orden en que se introdujeron las palabras, normalmente entre 1 y 5, aunque los participantes podían agregar más términos.
Usando este conjunto de datos y siguiendo las tareas descritas, nuestro objetivo es descubrir las ideas predominantes sobre el big data. Este enfoque se enmarca en la psicología social, específicamente en la teoría de la representación social, adoptando la perspectiva estructural de Abric (2001) y empleando métodos cuantitativos. Al final del análisis, llevaremos a cabo un “análisis prototípico” de esta teoría y debatiremos la interpretación de los resultados.
1.5.1 Cargar datos y recursos
Lo primero que haremos es cargar algunas librerias (package
) que van a poner a nuestra disposición un conjunto de funciones que utilizaremos a lo largo de todo el ejercicio. Recordá que una función es una secuencia de comandos que se aplican a un objeto que se le pasa a la función, referenciándolo entre sus paréntesis. Por ejemplo, utilizaremos la función `library()` y el nombre de las librerías para habilitar las funciones de readr para importar datos, y el conjunto de librerías del tidyverse
para manipular y visualizar.
# una vez instaladas hay que cargarlas en memoria
library(readr)
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.3 ✔ purrr 1.0.2
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.4.4 ✔ tibble 3.2.1
✔ lubridate 1.9.3 ✔ tidyr 1.3.0
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Luego importaremos los datos con la función read_csv()
de la librería readr
. En RStudio podés listar a las funciones de un paquete si tipeas su nombre seguido de ::
. Esta forma de vincular paquetes y funciones es recomendada, en tanto los nombres de las funciones pueden pisarse, dependiendo del orden en que cargamos los paquetes.
Nos interesa que esos datos importados se guarden como un objeto en memoria, ya que estaremos trabajando con ellos en lo que sigue. Para ello, utilizamos un operador de asignación <-
, precedido del nombre que le daremos al objeto (en nuestro caso asociaciones).
<- readr::read_csv(file = "https://raw.githubusercontent.com/gastonbecerra/curso-intro-r/main/data/asociaciones.csv") asociaciones
Rows: 1707 Columns: 4
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (2): id, palabra
dbl (2): orden, valoracion
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
1.5.2 Exploración de datos
El objetivo del momento de exploración de los datos es familiarizarnos con la estructura de los datos, y transformarlos para poder realizar nuestros análisis. Por lo general, aquí se empiezan a decidir las tareas de limpieza.
Lo primero que vamos a hacer es ver el tamaño de la tabla con dim()
, y los primeros registros con head()
.
Esto nos va a permitir saber:
-la cantidad de registros y columnas;
- los nombres de las columnas y su tipo de dato;
- el contenido de los primeros registros.
dim(asociaciones)
[1] 1707 4
head(asociaciones, n = 10)
# A tibble: 10 × 4
id palabra orden valoracion
<chr> <chr> <dbl> <dbl>
1 -M0-9OQkabuGoSmceB5E información 1 5
2 -M0-9OQkabuGoSmceB5E análisis 2 5
3 -M0-9OQkabuGoSmceB5E investigación 3 5
4 -M0-9OQkabuGoSmceB5E comercial 4 4
5 -M0-9OQkabuGoSmceB5E filtración 5 -5
6 -M0U7_pJAU9Ehga0LIWq información 1 5
7 -M0U7_pJAU9Ehga0LIWq tecnología 2 5
8 -M0U7_pJAU9Ehga0LIWq sistemas 3 5
9 -M0U7_pJAU9Ehga0LIWq computadora 4 0
10 -M0U7_pJAU9Ehga0LIWq freaks 5 -3
Por lo que podemos ver, tenemos 4 columas: `id
` y palabra son variables de texto (`<chr>
`), mientras `orden
` y `valoracion
` son numéricas. Otro posible tipo de columna es el factor (`<fct>
`) que sirve para registrar categorías, donde cada valor posible es un level.
Podemos ver que el valor de id se repite entre filas, lo que nos da la pauta que varios registros corresponden naturalmente juntos. En este caso, se tratan de las distintas palabras mencionadas por un mismo participante frente a “big data”. Este diseño de tabla donde hay n registros x 1 participante, a diferencia de tener sólo registro con muchas columnas tiene muchas ventajas. Por el momento señalemos sólo 1: todas nuestras palabras quedan en la misma columna, de modo que si queremos procesarlas será muy fácil referenciarlas. Cada palabra propuesta tiene, además, el orden de evocación (`orden
`) y la valoración dada (`valoracion
`).
Luego, es útil tener una idea de los valores posibles de las distintas columnas o variables. `summary
` nos devuelve un resumen de estadísticas descriptivas, que nos permite saber, por ejemplo, en qué rango se registran las valoraciones, o cómo se distribuyen los ordenes de evocación.
summary(asociaciones)
id palabra orden valoracion
Length:1707 Length:1707 Min. : 1.00 Min. :-5.000
Class :character Class :character 1st Qu.: 2.00 1st Qu.:-1.000
Mode :character Mode :character Median : 3.00 Median : 1.000
Mean : 3.06 Mean : 1.053
3rd Qu.: 4.00 3rd Qu.: 5.000
Max. :14.00 Max. : 5.000
Otras tareas que nos pueden interesar en el análisis exploratorios son:
- ver la cantidad de datos vacíosview(asociaciones)
- ver la cantidad de datos redundantes
- ver relaciones entre variables
- graficar el rango de valores de una o más variables
Recordá que podes ver la tabla, como si estuvieras viendo una planilla, con `view(asociaciones)
`.
1.5.3 Transformar, visualizar y limpiar
Ahora vamos a ver de qué manera podemos transformar los datos para obtener respuestas a las siguientes preguntas:
- ¿cuáles son las palabras más frecuentes?
- ¿cuáles son las palabras con valoraciones más extremas?
- ¿cuáles son las palabras que se evocaron más rápido?
Para responder esto vamos a utilizar verbos de manipulación (de dplyr
, una librería incluida en tidyverse
) sobre nuestra tabla. Algunos de estos verbos son:
- filter()
para filtrar los registos/observaciones por alguna condición de sus valores;
- mutate()
para agregar una columna/variable con el resultado de alguna operación sobre otras columnas;
- group_by()
y summarise()
para realizar alguna operación sobre los datos de distintos registros, reduciendolos en uno sólo por grupos;
- n()
que nos devuelve el conjunto de registros de un grupo (y que por ello se hace luego de group_by()
); algo que podemos simplificar con count()
;
- arrange()
ordena los datos ascendente o descendentemente;
Luego, para encadenar estas acciones vamos a utlizar un operador denominado pipe (%>%
) que funciona como un tubo: toma el objeto a su izquierda y lo hace pasar por la función a su derecha, devolviendonos el resultado. Esto nos permite una manera más fácil de pensar a la hora de escribir el código para manipular un objeto, que su alternativa de incluir al objeto entre los paréntesis de una función, ya que en primer lugar lo mencionamos y luego iremos paso a paso introduciendole transformaciones.
Antes que nada, empecemos por chusmear (glimpse
) la estructura de la base para recordar las columnas/variables con las que podemos trabajar. Los nombres de las columnas aparecen precedidos con un $
, una debajo de la otra, para que sea más facil de observar tablas largas. Luego, nos informa el tipo de variable y nos permite ver los primeros valores (que en entran en pantalla)
Nuestra tabla tiene las palabras que los participantes respondieron en la columna
- asociaciones$palabra
, el orden en que dichas palabras fueron ingresadas por el participante en asociaciones$orden
, y una valoración sobre esa palabra expresada en forma númerica en asociaciones$valoracion
.
Tenemos todos los elementos para responder las preguntas. Sólo falta diseñar un camino de operaciones para visibilizar la respuesta:
(Paso1) vamos a tomar la tabla que nos interesa asociaciones, y la vamos a pasar, para… (Paso2) …armar grupos de registros que compartan el valor en asociaciones$palabra
, y para cada cual vamos a: (Paso3) contar la cantidad de registros (dandonos la frecuencia con que dicha palabra fue asociada a big data); (Paso4) y calcular la media de las valoraciones en asociaciones$valoracion
, (Paso5) así como la media del orden en que fue evocado (asociaciones$orden
) (Paso0) … el resultado de esta operación la vamos a guardar en una tabla nueva, que luego operaremos para responder nuestras 2 preguntas. En tanto esta tabla describe la información de la anterior, notaremos que tiene muchos menos registros.
Para estas operaciones vamos a usar los comandos recién vistos:
library(dplyr)
glimpse(asociaciones)
Rows: 1,707
Columns: 4
$ id <chr> "-M0-9OQkabuGoSmceB5E", "-M0-9OQkabuGoSmceB5E", "-M0-9OQkab…
$ palabra <chr> "información", "análisis", "investigación", "comercial", "f…
$ orden <dbl> 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5,…
$ valoracion <dbl> 5, 5, 5, 4, -5, 5, 5, 5, 0, -3, 2, 4, 4, 3, 2, 5, 4, 0, 4, …
<- asociaciones %>% # (Paso0) y (Paso1)
asoc_frecuentes
group_by(palabra) %>% # (Paso2)
summarize(
freq = n(), # (Paso3)
valoracion_media = mean(valoracion), # (Paso4)
orden_media = mean(orden) #(Paso5)
)
glimpse(asoc_frecuentes)
Rows: 867
Columns: 4
$ palabra <chr> ".", "...", "0-1-2", "1984", "aa", "abiertos", "abund…
$ freq <int> 3, 2, 1, 1, 1, 1, 1, 1, 1, 4, 5, 1, 1, 1, 1, 1, 1, 1,…
$ valoracion_media <dbl> 0.00, 0.00, 0.00, -5.00, 0.00, 3.00, 3.00, 5.00, 0.00…
$ orden_media <dbl> 4.0, 4.5, 5.0, 2.0, 5.0, 2.0, 1.0, 2.0, 5.0, 2.5, 3.6…
Más sintéticamente podríamos usar tally()
o count()
. Recordá que podés obtener ayuda sobre estos comando ejecutando ? tally()
.
Si ordenamos esta tabla ya estamos en condiciones de indicar cuáles son las palabras más/menos frecuentes. Para esto vamos a usar slice_max()
, que ordena los datos y los corta en alguna posición.
%>% # no guardamos el resultado, solo lo imprimimos
asoc_frecuentes
slice_max(order_by = freq, n=10) # ordenamos por freq y cortamos en 10 registros
# A tibble: 10 × 4
palabra freq valoracion_media orden_media
<chr> <int> <dbl> <dbl>
1 información 102 2.58 2.08
2 datos 81 2.15 1.96
3 control 35 -2.31 2.57
4 internet 34 2.94 2.91
5 tecnología 29 2.45 2.97
6 informacion 28 2.29 2.54
7 grande 20 2.7 2
8 análisis 19 3.11 2.89
9 manipulación 18 -3.44 2.5
10 conocimiento 16 4.44 2.75
La palabra más evocada fue “información”, junto con un conjunto de otras palabras que podemos decir que remiten al manejo de los datos mediados por la tecnología, con diversos productos, como puede ser el análisis de información y la generación de conocimiento, o la manipulación y el control (las únicas palabras que tienen una valoración negativa).
Para conocer las palabras más/menos valoradas deberemos generar otros cortes.
%>%
asoc_frecuentes
slice_max(order_by = valoracion_media, n=10) # las de valor mas alto
# A tibble: 176 × 4
palabra freq valoracion_media orden_media
<chr> <int> <dbl> <dbl>
1 abundante 1 5 2
2 accionar 1 5 3
3 actualizaciones 1 5 3
4 algo superior 1 5 3
5 almacenamiento de datos 2 5 2
6 amigos 1 5 1
7 amor 1 5 4
8 amplitud de usos 1 5 5
9 análisis datos 1 5 2
10 análisis de grandes masas de datos 1 5 1
# ℹ 166 more rows
%>%
asoc_frecuentes
slice_min(order_by = valoracion_media, n=10) # las de valor mas bajo
# A tibble: 108 × 4
palabra freq valoracion_media orden_media
<chr> <int> <dbl> <dbl>
1 1984 1 -5 2
2 acción 1 -5 4
3 acoso mediático 1 -5 2
4 altgorismo 1 -5 4
5 atraso 1 -5 4
6 ausencia de intimidad 1 -5 4
7 avismo 1 -5 4
8 buenas noticias 1 -5 3
9 camdbridge analitycs 1 -5 2
10 campaña politica 1 -5 2
# ℹ 98 more rows
Más allá de que se puede inferir ciertos temas en las palabras (especialmente las negativas), nos debemos preguntar si tiene sentido trabajar con ideas y expresiones idiosincráticas, introducidos por un sólo participante. A fin de cuentas, la pregunta que guía toda nuestra exploración es sobre lso sentidos comunes o compartidos. Podemos entonces establecer un umbral o mínimo de repeticiones para que una palabra nos resulte relevante o informativa.
Miremos entonces las frecuencias. Otra vez, diseñemos un camino de operaciones:
(Paso1) vamos a tomar la tabla que nos interesa asoc_frecuentes
, y la vamos a pasar, para… (Paso2) …armar grupos de registros que compartan el valor en asociaciones$freq
, y para cada cual vamos a: (Paso3) contar la cantidad de registros (dandonos la cantidad de palabras que fueron dicha la misma cantidad de veces); (Paso4) vamos a visualizarlo en un gráfico de puntos que cruce la frecuencia y la cantidad de palabras.
Por su parte, el diseño del gráfico va a requerir 3 componentes (mínimos): que insertemos datos (en este caso, vamos a estar pasando la tabla hecha hasta el paso 3 con un pipe, de modo que no necesitamos declararla de nuevo), que mapeemos algunos de esos datos a propiedades visuales del gráfico (como por ejemplo, un cierta columna/variable para un eje del gráfico), y que elijamos un sistema de representación o “geometry” (puntos, barras, áreas, etc.)
library(ggplot2) # Carga la librería ggplot2
%>% # Paso1
asoc_frecuentes
group_by(freq) %>% # Paso2
summarize(cant_palabras = n()) %>% # Paso3
ggplot( # Paso 4: usamos la librería ggplot2 y la función ggplot
aes(x=cant_palabras,y=freq) # mapeeamos los datos en los ejes x e y
+ # los componentes de ggplot se concatenan con +, ya que no son pasos secuenciales
)
geom_point()
Por lo visto, tenemos una distribución que sigue la ley de Zipf: muy poca cantidad de palabras tienen valores que se repiten muchas veces (los sentidos más comúnes), y hay casi 700 palabras que se repiten 1 sola vez. En vistas de esto podemos quedarnos con las palabras que se repiten más de 1 vez, criterio que utilizaremos para establecer un filtro (filter()
). En esta ocasión, por simpleza, vamos a “pisar” nuestra tabla de datos con un fragmento de ella misma.
<- asoc_frecuentes %>% # vamos a pisar la tabla con el resultado
asoc_frecuentes
filter(freq > 1)
glimpse(asoc_frecuentes)
Rows: 188
Columns: 4
$ palabra <chr> ".", "...", "accesibilidad", "acceso", "algoritmos", …
$ freq <int> 3, 2, 4, 5, 4, 7, 2, 2, 6, 19, 2, 2, 2, 3, 3, 2, 4, 1…
$ valoracion_media <dbl> 0.0000000, 0.0000000, 1.7500000, 0.6000000, 1.2500000…
$ orden_media <dbl> 4.000000, 4.500000, 2.500000, 3.600000, 3.500000, 3.1…
Con este nuevo dataset deberíamos repetir los análisis anteriores sobre las palabras mas/menos valoradas. Este es un escenario al que deberemos acostrumbrarnos: el proceso de transformación-visualización-limpieza es iterativo. En la medida en que nos familiaricemos más con nuestros datos, que aclaremos nuestras preguntas, y que decidamos y programemos los análisis, deberemos repetirnos varias veces.
Por último, nos queda indagar cuáles son las palabras que más rápidamente fueron evocadas en la encuesta, es decir, las que tiene un orden de evocación más cercano a 1. Estas son las ideas que probablemente sean las más accesibles y memorables. Pero ahora en lugar de una lista, veamos un gráfico en el que podamos incluir otra información: la valoración media de la palabra.
%>%
asoc_frecuentes
slice_min(order_by = orden_media, n=10) %>% # las de valor mas bajo
ggplot( # vamos a usar ggplot para graficar
aes( # dentro de aes indicamos las variables a vincular con las partes del gráfico
y = palabra, # en el eje y vamos a poner la palabra
x = orden_media, # en el eje x el orden de evocación
fill = valoracion_media # en el color vamos a poner la valoración (-5 y 5)
)
+
)
geom_col()
Estos primeros análisis ya nos dan una idea de la estructura de los datos, y algunas pistas sobre las respuestas…
1.5.4 Funciones
<- function (tabla_evocaciones) {
analisis_proto
# las operaciones van aca…
# por ahora no vamos a hacer nada mas que asignar nuestro input a un nuevo objeto…
<- tabla_evocaciones
objeto_a_devolver
return(objeto_a_devolver) # … y lo devolvemos
}
Podemos llamar a la función con analisis_proto(asociaciones)
. Dada las operaciones que le definimos dentro, no nos debe sorprender que la función no haga más que llamar al objeto.
analisis_proto(asociaciones)
# A tibble: 1,707 × 4
id palabra orden valoracion
<chr> <chr> <dbl> <dbl>
1 -M0-9OQkabuGoSmceB5E información 1 5
2 -M0-9OQkabuGoSmceB5E análisis 2 5
3 -M0-9OQkabuGoSmceB5E investigación 3 5
4 -M0-9OQkabuGoSmceB5E comercial 4 4
5 -M0-9OQkabuGoSmceB5E filtración 5 -5
6 -M0U7_pJAU9Ehga0LIWq información 1 5
7 -M0U7_pJAU9Ehga0LIWq tecnología 2 5
8 -M0U7_pJAU9Ehga0LIWq sistemas 3 5
9 -M0U7_pJAU9Ehga0LIWq computadora 4 0
10 -M0U7_pJAU9Ehga0LIWq freaks 5 -3
# ℹ 1,697 more rows
Es importante notar una cosa. Si prestamos atención al entorno, vamos a ver que el objeto_a_devolver
no aparece en nuestra lista de objetos. Esto es porque quedó “encapsulado” en la función, y no está disponible por fuera de ella. Lo mismo puede decirse de tabla_evocaciones
, que es la forma en que en la función llamamos a nuestro primer parámetro (los datos).
Aclarada la estructura y el uso de una función, ya sólo resta pensar en cuáles son los pasos a seguir para realizar el análiasis prototípico. Para eso, volvamos a la definición más arriba, y pensemos la secuencia de operaciones que necesitamos:
(paso 1) primero debemos calcular las frecuencias de cada palabra y sus medias de valoracion y orden; (paso 2) deberemos definir una frecuencia mínima; (paso 3) vamos a calcular los criterios de corte para distinguir los mas/menos frecuentes y los evocados mas/menos rápidamente; (paso 4) vamos a utilizar estos criterios de corte para segmentar las asociaciones, indicando qué palabras corresponden a qué segmento;
Como la idea es poder probar distintos criterios y decisiones, algunos de estos pasos suponen que podamos introducir algún parámetro: (paso 2) vamos a introducir una frecuencia mínima; (paso 3) vamos a indicar si queremos usar la media o la mediana para calcular el criterio de corte, es decir si aplicamos mean()
o median()
, esta operación condicional la haremos con una estructura de control: if
( criterio ) { … } else
{ … }. Estos 2 parámetros los vamos a incluir en la función, con un valor por defecto: 2 para la frecuencia mínima, y media para calcular el criterio. Vamos a utilizar el comando message()
para que al correr la función se muestren estos parámetros, y también para observar la cantidad de palabras que quedan en cada segmento, dados estos parametros (paso 5).
<- function (tabla_evocaciones, frecuencia_minima = 2, criterio_corte = "media") {
analisis_proto
# (paso 1) tabla de frecuencias
<- tabla_evocaciones %>%
asoc_frecuentes
group_by(palabra) %>%
summarize(
freq = n(),
valoracion_media = mean(valoracion),
orden_media = mean(orden)
)
# (paso 2) establecemos un umbral de frecuencia minima (usando parametro)
<- asoc_frecuentes %>%
asoc_frecuentes
filter(freq > frecuencia_minima)
message("frecuencia minima =", frecuencia_minima)
# (paso 3) calculamos el corte de frecuencia (usamos mean o median, segun parametro)
if (criterio_corte == "media") {
<- mean(asoc_frecuentes$freq)
freq_cut
<- mean(asoc_frecuentes$orden_media)
orden_cut
else {
}
<- median(asoc_frecuentes$freq)
freq_cut
<- median(asoc_frecuentes$orden_media)
orden_cut
}
message("valor corte frecuencia =", freq_cut)
message("valor corte orden =", orden_cut)
# (paso 4) segmentamos las palabras
<- asoc_frecuentes %>% mutate( segmento = case_when(
prototipico
>= freq_cut & orden_media < orden_cut ~ 1,
freq
>= freq_cut & orden_media >= orden_cut ~ 2,
freq
< freq_cut & orden_media < orden_cut ~ 3,
freq
< freq_cut & orden_media >= orden_cut ~ 4
freq
)
%>% arrange(segmento, desc(freq),desc(orden_media))
)
# (paso 5) vamos a contar las palabras en cada segmento y lo mostramos en pantalla
<- prototipico %>%
palabras_por_segmento
count(segmento) %>%
pull(n) # pull extrae una variable, quedando como vector
message("palabras en cada segmento =",
paste(palabras_por_segmento, collapse = " | "))
# … y lo devolvemos
return(prototipico)
}
Veamos el objeto que nos devuelve, por ahora con los valores por defecto:
analisis_proto(tabla_evocaciones = asociaciones)
frecuencia minima =2
valor corte frecuencia =8.15094339622642
valor corte orden =2.98106020168724
palabras en cada segmento =12 | 5 | 33 | 56
# A tibble: 106 × 5
palabra freq valoracion_media orden_media segmento
<chr> <int> <dbl> <dbl> <dbl>
1 información 102 2.58 2.08 1
2 datos 81 2.15 1.96 1
3 control 35 -2.31 2.57 1
4 internet 34 2.94 2.91 1
5 tecnología 29 2.45 2.97 1
6 informacion 28 2.29 2.54 1
7 grande 20 2.7 2 1
8 análisis 19 3.11 2.89 1
9 manipulación 18 -3.44 2.5 1
10 conocimiento 16 4.44 2.75 1
# ℹ 96 more rows
Ahora podemos probar otros parámetros
analisis_proto(tabla_evocaciones = asociaciones, frecuencia_minima = 3, criterio_corte = "mediana")
frecuencia minima =3
valor corte frecuencia =6
valor corte orden =3
palabras en cada segmento =23 | 18 | 9 | 24
# A tibble: 74 × 5
palabra freq valoracion_media orden_media segmento
<chr> <int> <dbl> <dbl> <dbl>
1 información 102 2.58 2.08 1
2 datos 81 2.15 1.96 1
3 control 35 -2.31 2.57 1
4 internet 34 2.94 2.91 1
5 tecnología 29 2.45 2.97 1
6 informacion 28 2.29 2.54 1
7 grande 20 2.7 2 1
8 análisis 19 3.11 2.89 1
9 manipulación 18 -3.44 2.5 1
10 conocimiento 16 4.44 2.75 1
# ℹ 64 more rows
Otra vez, es hora de tomar decisiones. Como vemos, esta última configuración logra quedarse con menos palabras, pero a la vez incrementa el tamaño del 1er segmento, que dado que es donde iremos a buscar los sentidos centrales, conviene que sea más pequeño. Podemos asumir que un umbral de frecuencia mínimas más alto, y una división por medias debería dar un conjnto más chico de palabras en el segmento 1, y menos palabras en total.
analisis_proto(tabla_evocaciones = asociaciones, frecuencia_minima = 5, criterio_corte = "media")
frecuencia minima =5
valor corte frecuencia =15.219512195122
valor corte orden =2.87623694419952
palabras en cada segmento =7 | 3 | 13 | 18
# A tibble: 41 × 5
palabra freq valoracion_media orden_media segmento
<chr> <int> <dbl> <dbl> <dbl>
1 información 102 2.58 2.08 1
2 datos 81 2.15 1.96 1
3 control 35 -2.31 2.57 1
4 informacion 28 2.29 2.54 1
5 grande 20 2.7 2 1
6 manipulación 18 -3.44 2.5 1
7 conocimiento 16 4.44 2.75 1
8 internet 34 2.94 2.91 2
9 tecnología 29 2.45 2.97 2
10 análisis 19 3.11 2.89 2
# ℹ 31 more rows
1.5.5 Interpretación
Siguiendo el análisis prototípico, nos interesan las asociaciones registradas con una frecuencia mayor y un rango por debajo de la media, es decir, las más frecuentes y salienten, ya que son las principales candidatas a expresar los sentidos más centrales y consensuados de la representación. En nuestra tabla serían aquellos registros con `segmento == 1
`.
En Becerra and López-alurralde (2020) con un dataset muy similar a este sugeríamos:
El primer segmento comprende a las palabras enunciadas más frecuentemente y de más rápida evocación, es decir, las más comunes y accesibles. Estos son los términos que se puede decir que constituyen el núcleo de la representación: información, dato, internet, control, grande, bases de datos, manipulación, conocimiento, marketing, poder, computadora, espionaje, y grandes datos. Mayormente refieren a lo que denominamos la “premisa” del big data: la disponibilidad de grandes bases de datos, plausibles de otorgar información. Es interesante señalar que el término grande (lemma en el que convergen distintos términos, tales como grandes, mucho) es el único en el núcleo que remite a las famosas 3 V’s –volumen, velocidad y variedad– que popularizara Laney y que se referencia en prácticamente todas las noticias que buscan introducir al big data a un público masivo …
Mayormente estos términos están asociados con una valoración positiva, … siendo conocimiento la palabra de mayor valor medio … Sin embargo, también aparecen en este mismo segmento, las 3 palabras de menor valoración en todo el corpus: manipulación, espionaje y control. … La distribución de estas valoraciones es indicativa de la polaridad que recubre el campo semántico del big data, en tanto la imagen de la “gran oportunidad” que ofrece su promesa epistémica, convive con una retórica de sospecha frente a los riesgos de su explotación para el sometimiento y el condicionamiento de otros, como un “gran hermano”.
RS de “trabajo”
El cuadro está compuesto por 4 cuadrantes, resultante de ordenar las palabras por frecuencia y orden de evocación, ambas cortadas en 2 segmentos por el punto medio. La tabla es clara en segmentar palabras, aunque no hay manera fácil de identificar los segmentos si no es comparando frecuencias. Además, si quisierámos agregar una variable, como es valoración en nuestro caso, las tablas se vuelven extensas para compararlas.
Un gráfico debería debería permitirnos visualizar esto mejor!
Vamos a dibujar un gráfico que: permita dibujar puntos en el cruce de frecuencia (X) y orden de evocación (Y), * que incluya las palabras en el gráfico, de modo tal que podamos leerlas por grupitos, que señale con color la valoración, que muestre los puntos de corte en frecuencia (X) y orden de evocación (Y), y que remarque el cuadrante del núcleo central.
<- analisis_proto(tabla_evocaciones = asociaciones, frecuencia_minima = 5, criterio_corte = "media") prototipico
frecuencia minima =5
valor corte frecuencia =15.219512195122
valor corte orden =2.87623694419952
palabras en cada segmento =7 | 3 | 13 | 18
glimpse(prototipico)
Rows: 41
Columns: 5
$ palabra <chr> "información", "datos", "control", "informacion", "gr…
$ freq <int> 102, 81, 35, 28, 20, 18, 16, 34, 29, 19, 15, 10, 8, 8…
$ valoracion_media <dbl> 2.5784314, 2.1481481, -2.3142857, 2.2857143, 2.700000…
$ orden_media <dbl> 2.078431, 1.962963, 2.571429, 2.535714, 2.000000, 2.5…
$ segmento <dbl> 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,…
%>%
prototipico
ggplot(aes(x=freq,y=orden_media,label=palabra)) + # frecuencia x orden
scale_x_continuous(trans='log') + # vamos a aplicar una transformación al eje X para ver mejor los puntos
geom_hline(yintercept = 2.87623694419952, linetype = 2) + # tomamos este valor del mensaje de la función
geom_vline(xintercept = 15.219512195122, linetype = 2) + # tomamos este valor del mensaje de la función
geom_point(aes(size=freq, colour=valoracion_media), show.legend = TRUE) + # agregamos los puntos
scale_colour_gradient(low = "red", high = "green", na.value = NA) + # gama de colores para valores continuos
geom_text( aes(size=20, colour=valoracion_media), fontface = "bold",
show.legend = FALSE, nudge_y = -.1, check_overlap = TRUE) + # agregamos las palabras
labs(y="Orden de evocación", x = "Frecuencia (log)") + # ponemos labels en los ejes
theme_minimal() # borremos estilos innecesarios
1.6 Importación de datos
- CSV o archivos de texto plano: Puedes usar la función `
read.csv()
` para importar datos desde un archivo CSV. Por ejemplo:
<- read.csv("C:/Users/PC/Desktop/PLE/2/StudentsPerformance.csv", check.names = FALSE) datos
head(datos)
g\xe9nero,"raza/etnia","nivel educativo de los padres","almuerzo","curso de preparaci\xf3n para el examen","puntuaci\xf3n en matem\xe1ticas","puntuaci\xf3n en lectura","puntuaci\xf3n en escritura"
1 female,"group B","bachelor's degree","standard","none","72","72","74"
2 female,"group C","some college","standard","completed","69","90","88"
3 female,"group B","master's degree","standard","none","90","95","93"
4 male,"group A","associate's degree","free/reduced","none","47","57","44"
5 male,"group C","some college","standard","none","76","78","75"
6 female,"group B","associate's degree","standard","none","71","83","78"
summary(datos)
g\xe9nero,"raza/etnia","nivel educativo de los padres","almuerzo","curso de preparaci\xf3n para el examen","puntuaci\xf3n en matem\xe1ticas","puntuaci\xf3n en lectura","puntuaci\xf3n en escritura"
Length:1000
Class :character
Mode :character
- En excel
library(readxl)
<- read_excel("C:/Users/PC/Desktop/PLE/HLTH1025_2016.xlsx") datos_excel
New names:
• `` -> `...2`
• `` -> `...3`
• `` -> `...4`
head(datos_excel)
# A tibble: 6 × 4
`Health & Society Student Health Survey Metadata` ...2 ...3 ...4
<chr> <chr> <chr> <chr>
1 <NA> <NA> <NA> <NA>
2 Variable name Variable label Vari… Valu…
3 ID Participant ide… Cont… <NA>
4 sex What is your ge… Cate… 1: M…
5 <NA> <NA> <NA> 2: F…
6 <NA> <NA> <NA> 99: …
summary(datos_excel)
Health & Society Student Health Survey Metadata ...2
Length:205 Length:205
Class :character Class :character
Mode :character Mode :character
...3 ...4
Length:205 Length:205
Class :character Class :character
Mode :character Mode :character
- Importar archci stata
library(haven)
<- read_dta("C:/Users/PC/Desktop/PLE/auto.dta") datos_stata
head(datos_stata)
# A tibble: 6 × 12
make price mpg rep78 headroom trunk weight length turn displacement
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 AMC Concord 4099 22 3 2.5 11 2930 186 40 121
2 AMC Pacer 4749 17 3 3 11 3350 173 40 258
3 AMC Spirit 3799 22 NA 3 12 2640 168 35 121
4 Buick Centu… 4816 20 3 4.5 16 3250 196 40 196
5 Buick Elect… 7827 15 4 4 20 4080 222 43 350
6 Buick LeSab… 5788 18 3 4 21 3670 218 43 231
# ℹ 2 more variables: gear_ratio <dbl>, foreign <dbl+lbl>
summary(datos_stata)
make price mpg rep78
Length:74 Min. : 3291 Min. :12.00 Min. :1.000
Class :character 1st Qu.: 4220 1st Qu.:18.00 1st Qu.:3.000
Mode :character Median : 5006 Median :20.00 Median :3.000
Mean : 6165 Mean :21.30 Mean :3.406
3rd Qu.: 6332 3rd Qu.:24.75 3rd Qu.:4.000
Max. :15906 Max. :41.00 Max. :5.000
NA's :5
headroom trunk weight length turn
Min. :1.500 Min. : 5.00 Min. :1760 Min. :142.0 Min. :31.00
1st Qu.:2.500 1st Qu.:10.25 1st Qu.:2250 1st Qu.:170.0 1st Qu.:36.00
Median :3.000 Median :14.00 Median :3190 Median :192.5 Median :40.00
Mean :2.993 Mean :13.76 Mean :3019 Mean :187.9 Mean :39.65
3rd Qu.:3.500 3rd Qu.:16.75 3rd Qu.:3600 3rd Qu.:203.8 3rd Qu.:43.00
Max. :5.000 Max. :23.00 Max. :4840 Max. :233.0 Max. :51.00
displacement gear_ratio foreign
Min. : 79.0 Min. :2.190 Min. :0.0000
1st Qu.:119.0 1st Qu.:2.730 1st Qu.:0.0000
Median :196.0 Median :2.955 Median :0.0000
Mean :197.3 Mean :3.015 Mean :0.2973
3rd Qu.:245.2 3rd Qu.:3.353 3rd Qu.:1.0000
Max. :425.0 Max. :3.890 Max. :1.0000
- Importarten formato
<- read.delim("C:/Users/PC/Desktop/PLE/sample-1.tsv") datos_tsv
head(datos_tsv)
X X.1 X.2 X.3 X.4 X.5 X.6 X.7 X.8 X.9 X.10 X.11 X.12 X.13 X.14 X.15
1 NA JANUARY NA FEBRUARY
2 NA S M T W T F S NA S M T W T F S
3 NA 1 NA 1 2 3 4 5
4 NA 2 3 4 5 6 7 8 NA 6 7 8 9 10 11 12
5 NA 9 10 11 12 13 14 15 NA 13 14 15 16 17 18 19
6 NA 16 17 18 19 20 21 22 NA 20 21 22 23 24 25 26
X.16 X.17 X.18 X.19 X.20 X.21 X.22 X.23 X.24 X2022
1 NA MARCH NA NA
2 NA S M T W T F S NA NA
3 NA 1 2 3 4 5 NA NA
4 NA 6 7 8 9 10 11 12 NA NA
5 NA 13 14 15 16 17 18 19 NA NA
6 NA 20 21 22 23 24 25 26 NA NA
Create.more.with.themes..............Go.to..Format.....Theme
1 NA
2 NA
3 NA
4 NA
5 NA
6 NA
summary(datos_tsv)
X X.1 X.2 X.3
Mode:logical Length:35 Length:35 Length:35
NA's:35 Class :character Class :character Class :character
Mode :character Mode :character Mode :character
X.4 X.5 X.6 X.7
Length:35 Length:35 Length:35 Length:35
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
X.8 X.9 X.10 X.11
Mode:logical Length:35 Length:35 Length:35
NA's:35 Class :character Class :character Class :character
Mode :character Mode :character Mode :character
X.12 X.13 X.14 X.15
Length:35 Length:35 Length:35 Length:35
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
X.16 X.17 X.18 X.19
Mode:logical Length:35 Length:35 Length:35
NA's:35 Class :character Class :character Class :character
Mode :character Mode :character Mode :character
X.20 X.21 X.22 X.23
Length:35 Length:35 Length:35 Length:35
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
X.24 X2022
Mode:logical Mode:logical
NA's:35 NA's:35
Create.more.with.themes..............Go.to..Format.....Theme
Mode:logical
NA's:35