25 + 35
[1] 60
Parte 1: Introducción a R
David Torres Irribarra e Isidora Naranjo López
14 de marzo de 2024
Uno realiza análisis de datos porque está motivado por la curiosidad, ya sea para explorar y conocer de forma abierta o con el fin de responder preguntas específicas. El poder conocer grandes cantidades de datos empíricos y usarlos para entender algo de mejor forma, el responder una pregunta relevante o el mostrar evidencia respecto a alguna temática es algo que hoy en día es extremadamente más sencillo de llevar a cabo que en el pasado gracias a la disponibilidad de recursos computacionales y software.
Durante el semestre aprenderemos a usar R1, un lenguaje de programación estadística, que les permitirá leer, procesar, analizar datos y generar reportes de resultados. R es un lenguaje muy utilizado, disponible para los principales sistemas operativos existentes y se distribuye gratuitamente.
El aprender a usar R es una competencia que les será útil mucho más allá de este curso, siendo aplicable durante la carrera en múltiples contextos y puede ser en el futuro una ventaja profesional importante al momento de posicionarse en su campo laboral.
Teniendo en mente que todo análisis se realiza en un contexto de uso más general, tipicamente en respuesta a una pregunta, el producto final de un proceso de análisis es la presentación de resultados. Para entender cómo podemos llegar a producir estos resultados usaremos un modelo que considera cuatro grandes etapas.
En estos apuntes revisaremos los elementos básicos que permitirán que al finalizar el curso estén en condiciones de realizar varios análisis estadísticos y, más importante aún, que estén en condiciones de usar R en otros contextos a futuro.
En esta sección revisaremos los conceptos básicos que nos permitirán empezar a explorar R.
El uso más sencillo que se le puede dar a R, y quizá el menos interesante, es de una calculadora.
Al abrir R verán una pantalla similar a lo que se muestra a continuación:
R version 4.0.2 (2020-06-22) -- "Taking Off Again"
Copyright (C) 2020 The R Foundation for Statistical Computing
Platform: x86_64-apple-darwin17.0 (64-bit)
R es un software libre y viene sin GARANTIA ALGUNA.
Usted puede redistribuirlo bajo ciertas circunstancias.
Escriba 'license()' o 'licence()' para detalles de distribucion.
R es un proyecto colaborativo con muchos contribuyentes.
Escriba 'contributors()' para obtener más información y
'citation()' para saber cómo citar R o paquetes de R en publicaciones.
Escriba 'demo()' para demostraciones, 'help()' para el sistema on-line de ayuda,
o 'help.start()' para abrir el sistema de ayuda HTML con su navegador.
Escriba 'q()' para salir de R.
[R.app GUI 1.72 (7847) x86_64-apple-darwin17.0]
[History restored from /Users/dti/.Rapp.history]
>
Y verán que pueden escribir directamente en el prompt representado con el caracter >
y puede “enviar” el código o comando apretando return
o enter
.
Por ejemplo, pueden escribir 25 + 35
, apretar return
y verán que R les presentará el resultado:
De esta misma manera pueden usar R para realizar cualquier cálculo que harían en una calculadora:
Si bien el usar R como calculadora no es muy interesante en sí mismo, sirve para ilustrar la manera básica en que funciona el programa:
El paso 3 es virtualmente invisible para la mayoría de los casos que veremos en este curso, pero al realizar análisis más avanzados o usar computadores menos veloces R puede usar cantidades de tiempo visiblemente más extensas antes de pasar al siguiente paso.
Una excepción a este guión ocurre cuando el código ingresado en el primer paso está incompleto. En ese caso R “queda a la espera” de que el usuario complete el código. Por ejemplo, si escribimos solamente 24 +
y presionamos return
:
Vemos que R nos presenta una línea nueva con el signo +
, lo que indica que está a la espera de que completemos el código inicial, el que podemos completar escribiendo en este caso 18
y apretando nuevamente return
para concluir el código y ver el resultado.
Supongamos que quiero calcular mi promedio de notas en tres controles usando R como una calculadora:
La principal ventaja de R es que puedo usar funciones para ejecutar una o más operaciones considerando todos los datos contenidos en una estructura de datos.
Una función es una pieza de código diseñada para ejecutar una serie de pasos. Toda función tiene un nombre (que usamos para referirnos a ella en el código) y requiere de ciertas piezas de información inicial llamadas argumentos que son declarados entre paréntesis ()
después del nombre de la función. Las funciones arrojan el resultado final después de realizar todos los pasos.
Consideremos tres métodos, el primero manual y los otros dos usando funciones sobre un vector:
sum
para sumar todos los contenidos del vector y luego dividir por el número de elementos en el vector calculado con length
.mean
le entregamos los argumentos que necesita: los valores a promediar y mean
arroja como resultado el promedio.[1] 5.433333
# Creamos el vector que usaremos en las siguientes alternativas:
mis_3_primeras_notas <- c(4.8, 5.3, 6.2)
# Alternativa 2:
sum(mis_3_primeras_notas)/length(mis_3_primeras_notas)
[1] 5.433333
[1] 5.433333
Como pueden ver, los tres métodos arrojan los mismos resultados, y podemos ver que el uso de una función como mean
es mucho más rápido que el método manual, especialmente si tengo más datos:
notas_de_controles <- c(4.8,5.3,6.2,4.6,5.9,6.0,5.3,5.1,6.5,4.2)
mi_promedio_final <- mean(notas_de_controles)
mi_promedio_final
[1] 5.39
En el ejemplo anterior, mean
es una función que usa todos los valores que se le entregan para generar un resultado, en este caso el promedio. Y puedo guardar el valor que arroja la función en el escalar mi_promedio_final
.
Pero las funciones pueden hacer uso de los datos de distintas formas. Por ejemplo, podemos usar una función para identificar un valor que nos interesa como la nota máxima o la nota mínima.
[1] 4.8 5.3 6.2 4.6 5.9 6.0 5.3 5.1 6.5 4.2
[1] 6.5
[1] 4.2
[1] 9
[1] 10
R permite también usar operaciones/funciones que se aplicarán a cada elemento por separado. Por ejemplo, pidiéndole que identifique las notas mayores que 5.5, o qué controles fueron iguales a 6.0 o que convirta las notas a escala de porcentaje.
Los operadores aritméticos en R como +
, -
, *
, /
, operadores de mayor que >
, menor que <
, mayor o igual que >=
menor o igual que <=
y los operadores lógicos como igual ==
, distinto !=
son también funciones, pero son especiales en el sentido que pueden ser usadas “como en una calculadora” y no requieren de la estructura nombre_funcion(argumentos)
.
[1] FALSE FALSE TRUE FALSE TRUE TRUE FALSE FALSE TRUE FALSE
[1] FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
[1] 68.57143 75.71429 88.57143 65.71429 84.28571 85.71429 75.71429 72.85714
[9] 92.85714 60.00000
Como pueden ver, estas operaciones/funciones arrojan como resultados un vector del mismo tamaño que el vector original, en donde cada elemento fue transformado de acuerdo a las operaciones utilizadas.
Ese último resultado no se ve claramente por tener demasiados decimales. Podemos resolver eso aplicando la función para redondear en R (round
).
La función round
requiere de dos argumentos:
Lo que genera un nuevo vector con las notas en escala de porcentaje redondeadas.
En R se puede pedir ayuda (en inglés) para todas las funciones. La ayuda se pide de dos maneras principales:
Ahora que conocemos los elementos básicos para operar en R vamos a empezar a aplicar lo aprendido a un ejemplo real. Para este ejemplo vamos a utilizar una base de datos de respuestas al cuestionario de los “Big 5”, basado en una influyente teoría de personalidad desarrollada originalmente por McCrae y Costa (1987).
Esta base de datos está disponible para ser descargada en la sección de archivos en la página de Canvas. El formato del archivo es CSV, que significa que es un archivo separado por comas (Comma Separated Values). R puede leer directamente este tipo de archivos con el comando read.csv
o con la variante read.csv2
.
El comando read.csv
requiere un argumento principal, la dirección donde se encuentra el archivo. Esta dirección puede ser un lugar en el disco duro de la computadora local o una dirección web, como en el ejemplo a continuación:
El comando read.csv
produce un data frame que, en el caso anterior, acabamos de guardar en el objeto big5
. Una vez que hemos leído el archivo de datos vamos a revisar sus contenidos usando distintos comandos:
'data.frame': 500 obs. of 56 variables:
$ age : int 27 21 23 40 16 22 29 NA 23 16 ...
$ gender : int 2 2 2 2 1 2 1 1 1 2 ...
$ hand : int 1 1 1 2 1 1 1 1 1 1 ...
$ country : chr "KE" "ZA" "ZA" "CM" ...
$ e1 : int 1 4 3 1 5 4 4 4 1 5 ...
$ e2 : int 1 4 3 3 2 4 4 1 5 1 ...
$ e3 : int 3 2 4 2 4 4 4 5 2 5 ...
$ e4 : int 4 4 3 4 2 2 3 1 5 5 ...
$ e5 : int 3 4 4 2 4 4 2 5 3 5 ...
$ e6 : int 4 1 3 2 3 5 3 1 5 1 ...
$ e7 : int 1 4 4 1 4 5 3 5 1 5 ...
$ e8 : int 2 2 5 4 2 3 4 3 5 3 ...
$ e9 : int 1 5 3 2 4 5 4 3 1 5 ...
$ e10 : int 5 4 5 4 3 3 4 3 5 1 ...
$ n1 : int 1 4 3 2 1 2 2 1 5 1 ...
$ n2 : int 2 3 3 2 5 3 5 2 1 5 ...
$ n3 : int 1 4 4 2 2 2 4 5 5 5 ...
$ n4 : int 2 2 3 4 4 3 3 1 5 5 ...
$ n5 : int 4 2 4 2 3 2 2 3 5 1 ...
$ n6 : int 1 2 3 2 2 2 3 1 4 1 ...
$ n7 : int 2 2 1 2 3 3 3 1 5 4 ...
$ n8 : int 1 1 2 2 2 1 3 1 5 3 ...
$ n9 : int 1 2 4 2 2 3 4 3 5 1 ...
$ n10 : int 1 1 2 4 2 1 4 5 4 4 ...
$ a1 : int 1 2 1 2 2 2 1 5 1 5 ...
$ a2 : int 5 5 4 2 4 2 4 5 2 5 ...
$ a3 : int 1 4 1 1 2 1 1 4 3 3 ...
$ a4 : int 5 5 5 2 3 3 4 3 5 4 ...
$ a5 : int 1 1 2 4 2 3 2 1 2 3 ...
$ a6 : int 5 4 5 2 2 2 5 5 3 5 ...
$ a7 : int 1 1 2 4 2 1 1 1 3 1 ...
$ a8 : int 5 4 4 2 4 1 5 4 5 3 ...
$ a9 : int 5 5 4 2 2 3 5 5 4 4 ...
$ a10 : int 1 4 4 2 3 4 4 2 3 3 ...
$ c1 : int 5 5 5 3 2 3 4 3 1 4 ...
$ c2 : int 4 4 1 2 4 4 3 3 3 3 ...
$ c3 : int 5 4 4 5 4 4 4 5 5 5 ...
$ c4 : int 2 2 2 1 3 1 1 4 5 5 ...
$ c5 : int 4 4 5 4 2 4 3 4 1 4 ...
$ c6 : int 2 5 2 1 3 4 2 3 1 3 ...
$ c7 : int 5 4 5 5 3 4 5 3 5 3 ...
$ c8 : int 2 3 2 3 3 1 3 2 3 3 ...
$ c9 : int 1 5 5 4 1 3 5 2 1 3 ...
$ c10 : int 2 4 4 4 3 5 4 5 3 5 ...
$ o1 : int 5 4 4 5 3 4 4 2 4 4 ...
$ o2 : int 1 2 4 1 3 1 5 1 3 1 ...
$ o3 : int 5 5 3 5 3 5 5 4 4 5 ...
$ o4 : int 1 1 4 1 2 1 4 1 3 1 ...
$ o5 : int 3 4 4 5 4 5 4 4 3 5 ...
$ o6 : int 5 1 4 1 2 1 1 1 1 1 ...
$ o7 : int 5 5 4 5 4 5 4 5 4 5 ...
$ o8 : int 2 4 2 5 1 1 4 3 3 4 ...
$ o9 : int 5 2 4 5 2 3 4 5 5 2 ...
$ o10 : int 2 5 4 5 4 5 4 4 4 5 ...
$ region : chr "Eastern Africa" "Southern Africa" "Southern Africa" "Middle Africa" ...
$ continent: chr "Africa" "Africa" "Africa" "Africa" ...
Podemos ver en el resumen que produce str
que:
Otros dos comandos que pueden ser de utilidad para explorar la base de datos son names
, que listará todos los nombres de variables en el data frame y head
que nos mostrará los primeros 6 casos en la base de datos. Finalmente, si quieren examinar la base de datos en una ventana aparte, pueden usar el comando View
para abrir una vista previa de la base de datos.
[1] "age" "gender" "hand" "country" "e1" "e2"
[7] "e3" "e4" "e5" "e6" "e7" "e8"
[13] "e9" "e10" "n1" "n2" "n3" "n4"
[19] "n5" "n6" "n7" "n8" "n9" "n10"
[25] "a1" "a2" "a3" "a4" "a5" "a6"
[31] "a7" "a8" "a9" "a10" "c1" "c2"
[37] "c3" "c4" "c5" "c6" "c7" "c8"
[43] "c9" "c10" "o1" "o2" "o3" "o4"
[49] "o5" "o6" "o7" "o8" "o9" "o10"
[55] "region" "continent"
age gender hand country e1 e2 e3 e4 e5 e6 e7 e8 e9 e10 n1 n2 n3 n4 n5 n6 n7
1 27 2 1 KE 1 1 3 4 3 4 1 2 1 5 1 2 1 2 4 1 2
2 21 2 1 ZA 4 4 2 4 4 1 4 2 5 4 4 3 4 2 2 2 2
3 23 2 1 ZA 3 3 4 3 4 3 4 5 3 5 3 3 4 3 4 3 1
4 40 2 2 CM 1 3 2 4 2 2 1 4 2 4 2 2 2 4 2 2 2
5 16 1 1 ZA 5 2 4 2 4 3 4 2 4 3 1 5 2 4 3 2 3
6 22 2 1 MA 4 4 4 2 4 5 5 3 5 3 2 3 2 3 2 2 3
n8 n9 n10 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 o1 o2
1 1 1 1 1 5 1 5 1 5 1 5 5 1 5 4 5 2 4 2 5 2 1 2 5 1
2 1 2 1 2 5 4 5 1 4 1 4 5 4 5 4 4 2 4 5 4 3 5 4 4 2
3 2 4 2 1 4 1 5 2 5 2 4 4 4 5 1 4 2 5 2 5 2 5 4 4 4
4 2 2 4 2 2 1 2 4 2 4 2 2 2 3 2 5 1 4 1 5 3 4 4 5 1
5 2 2 2 2 4 2 3 2 2 2 4 2 3 2 4 4 3 2 3 3 3 1 3 3 3
6 1 3 1 2 2 1 3 3 2 1 1 3 4 3 4 4 1 4 4 4 1 3 5 4 1
o3 o4 o5 o6 o7 o8 o9 o10 region continent
1 5 1 3 5 5 2 5 2 Eastern Africa Africa
2 5 1 4 1 5 4 2 5 Southern Africa Africa
3 3 4 4 4 4 2 4 4 Southern Africa Africa
4 5 1 5 1 5 5 5 5 Middle Africa Africa
5 3 2 4 2 4 1 2 4 Southern Africa Africa
6 5 1 5 1 5 1 3 5 Northern Africa Africa
Podemos ver que la base de datos tiene distintos grupos de variables:
Si queremos explorar los contenidos de una de las variables podemos pedir a R que nos muestre parcialmente sus datos usando nuevamente la función sample
nos permite tomar una muestra al azar de nuestros datos. Esta función toma como argumentos los datos que queremos muestrear y el argumento size
para indicar cuántos elementos queremos obtener:
[1] "Europe" "Europe" "Oceania" "Americas" "Oceania" "Americas"
[7] "Africa" "Oceania" "Asia" "Americas" "Europe" "Americas"
[13] "Europe" "Europe" "Oceania" "Oceania" "Oceania" "Europe"
[19] "Asia" "Asia" "Oceania" "Oceania" "Africa" "Americas"
[25] "Asia" "Americas" "Europe" "Africa" "Europe" "Asia"
[31] "Asia" "Oceania" "Africa" "Oceania" "Americas" "Africa"
[37] "Asia" "Oceania" "Oceania" "Oceania" "Asia" "Africa"
[43] "Europe" "Africa" "Asia" "Asia" "Oceania" "Americas"
[49] "Asia" "Americas"
Podemos explorar en más detalle algunas de estas variables usando tablas para resumir sus contenidos:
Africa Americas Asia Europe Oceania
100 100 100 100 100
1 2 3
190 308 1
Podemos ver que si bien hay 500 resultados al tabular los continentes, solo vemos 499 casos al tabular género (190 + 308 + 1 = 499). Si queremos ver esto automáticamente podemos usar la función ‘addmargins’, que sirve para agregar los totales calculados a una tabla.
Africa Americas Asia Europe Oceania Sum
100 100 100 100 100 500
1 2 3 Sum
190 308 1 499
¿Qué pasó con el caso faltante en esta variable? La respuesta es que esta base de datos, como muchas otras, tiene datos perdidos. Los datos perdidos pueden ocurrir, por ejemplo, porque una persona se abstiene de responder una pregunta. Cuando esto ocurre el dato está “vacío” y, si R detecta esto, le asignará un tipo de valor especial: NA
.
Podemos ver los valores NA
en una variable si agregamos un argumento adicional al comando table
:
# Tabulemos indicando que siempre queremos ver cuántos casos son NA
table(big5$continent, useNA = "always")
Africa Americas Asia Europe Oceania <NA>
100 100 100 100 100 0
# Tabulemos indicando que siempre queremos ver cuántos casos son NA
table(big5$gender, useNA = "always")
1 2 3 <NA>
190 308 1 1
Podemos usar el comando table
para hacer cruces de datos en nuestro data.frame. Esto se hace entregando dos argumentos iniciales: las dos variables que queremos cruzar.
1 2 3 <NA> Sum
Africa 29 71 0 0 100
Americas 36 63 0 1 100
Asia 44 56 0 0 100
Europe 45 54 1 0 100
Oceania 36 64 0 0 100
<NA> 0 0 0 0 0
Sum 190 308 1 1 500
Usando lo que hemos visto antes, podemos seleccionar datos específicos en nuestra base de datos, por ejemplo, las respuestas a las preguntas de extroversión, y podemos calcular el promedio de las respuestas a estas preguntas usando el comando rowMeans
, que en inglés literalmente significa promedio de las filas.
# Promedio de las preguntas de extroversión
rowMeans(big5[,c("e1","e2","e3","e4","e5","e6","e7","e8","e9","e10")])
[1] 2.5 3.4 3.7 2.5 3.3 3.9 3.5 3.1 3.3 3.6 3.2 3.5 3.0 3.2 3.5 2.7 3.6 3.4
[19] 3.0 2.9 3.1 2.9 2.6 2.3 2.8 3.6 3.6 3.0 3.3 3.0 3.1 3.3 2.8 2.7 2.9 3.0
[37] 2.6 3.0 3.0 3.3 3.1 2.9 2.7 2.9 2.8 3.0 3.8 2.6 3.0 2.7 2.6 3.2 3.0 3.2
[55] 3.4 4.2 3.7 3.2 2.6 3.4 3.0 2.6 3.0 3.3 3.2 3.3 3.6 3.4 3.1 3.3 3.1 2.9
[73] 4.6 3.5 3.1 3.3 4.0 3.0 3.4 2.7 3.5 3.4 3.3 2.8 3.3 3.2 3.0 3.4 3.5 3.0
[91] 3.3 3.3 3.4 2.6 2.8 3.4 3.3 3.1 2.7 3.1 2.9 3.8 2.7 3.0 3.0 2.7 2.8 3.1
[109] 3.2 3.4 2.5 2.8 2.9 3.4 2.6 2.9 2.7 3.1 3.1 2.8 3.5 3.1 3.1 3.0 2.8 3.4
[127] 3.4 3.1 3.0 2.6 2.7 3.0 3.3 2.7 3.2 3.2 3.4 3.6 2.9 3.7 3.3 3.2 3.2 2.5
[145] 3.0 2.3 3.4 3.3 3.3 2.9 3.2 3.0 3.1 3.2 3.1 2.7 2.4 3.7 2.5 3.3 3.0 2.8
[163] 3.0 2.7 2.5 3.6 3.0 3.2 2.5 3.3 2.9 2.4 3.0 3.8 2.9 3.2 2.9 2.8 3.1 3.3
[181] 3.1 2.9 2.9 3.0 2.8 3.2 2.9 3.1 2.8 3.0 3.0 3.2 3.3 2.9 3.7 3.2 2.9 3.3
[199] 3.3 3.2 3.5 3.1 3.2 3.7 3.0 3.7 4.2 2.8 4.2 3.9 3.4 3.2 2.5 2.6 2.9 3.7
[217] 3.1 2.8 2.8 3.5 2.5 2.7 3.4 3.3 3.1 2.8 3.4 3.0 3.3 2.6 2.7 3.1 3.3 3.4
[235] 3.1 3.4 3.2 3.2 2.7 2.5 3.2 2.4 2.6 3.2 3.5 2.7 3.2 3.2 3.1 3.2 3.1 3.6
[253] 3.1 3.3 2.8 3.1 2.8 2.8 3.5 2.7 3.0 2.5 3.2 3.3 3.3 3.6 2.7 3.0 3.4 3.1
[271] 3.2 3.3 3.5 2.9 3.5 2.4 3.4 3.1 2.9 3.0 3.4 3.5 3.0 2.9 3.4 2.9 3.1 3.0
[289] 3.2 3.3 2.9 3.3 3.2 3.3 3.3 2.8 3.1 3.1 3.1 3.1 3.4 3.3 2.9 3.5 3.2 3.2
[307] 3.1 2.9 3.3 3.4 3.8 3.0 3.5 2.6 3.4 3.1 2.7 3.1 3.3 3.2 2.9 3.7 2.9 3.0
[325] 3.0 2.8 3.1 3.3 2.8 2.6 3.4 2.5 3.1 3.0 3.0 3.2 3.2 3.4 3.3 2.8 2.7 3.2
[343] 2.7 3.4 2.7 3.0 3.1 2.6 3.2 3.2 3.6 2.4 3.2 3.2 2.9 2.8 3.2 3.3 2.9 3.1
[361] 3.0 3.2 3.6 2.6 2.9 2.5 3.2 2.9 2.4 3.1 3.4 3.5 3.4 3.2 3.5 3.5 3.0 3.9
[379] 3.1 3.1 3.3 3.1 3.9 3.1 2.8 3.2 3.2 3.0 3.0 2.9 2.8 3.0 3.4 2.8 3.2 3.0
[397] 3.0 3.7 3.0 3.0 3.4 3.0 2.8 2.8 2.9 3.5 3.2 3.3 3.1 2.9 2.8 3.7 3.2 3.2
[415] 2.9 2.9 3.3 3.6 3.4 3.0 2.3 2.7 2.8 3.4 3.1 3.5 3.5 2.6 3.3 3.3 3.6 3.0
[433] 3.1 3.0 3.0 2.9 3.3 2.7 2.9 2.6 3.1 3.1 3.1 2.9 3.2 2.3 3.0 2.7 3.0 2.8
[451] 3.1 3.0 3.0 3.3 2.2 3.2 3.6 3.0 3.7 3.4 2.9 3.2 3.5 3.0 3.2 3.3 3.2 3.1
[469] 3.0 3.0 4.2 3.2 3.1 3.3 3.2 2.6 3.2 3.3 2.6 2.8 1.0 3.6 2.9 3.0 2.7 3.2
[487] 2.9 3.2 3.0 3.2 3.6 3.5 2.9 3.1 2.7 3.0 3.3 2.9 3.2 2.9
O podemos ver el promedio de cada pregunta, usando colMeans
(promedios de columnas)
# Promedio de las preguntas de extroversión
colMeans(big5[,c("e1","e2","e3","e4","e5","e6","e7","e8","e9","e10")])
e1 e2 e3 e4 e5 e6 e7 e8 e9 e10
2.632 2.830 3.408 3.148 3.396 2.550 2.858 3.430 3.124 3.628
O, puedo usar la función aggregate
para ver cómo cambia el promedio de respuesta a una pregunta dependiendo del continente:
Pueden descargar R en esta página eligiendo el sistema operativo correspondiente.↩︎