class: center, middle, inverse, title-slide # Introducción a R II ## Programación para el análisis de datos ### Departamento de Ciencias Sociales, UCU - Martín Opertti --- class: inverse, center, middle # Dataframes --- ## Dataframes - Un dataframe o marco de datos (es lo que nos solemos referir como "base de datos"). - Es por lejos la estructura más usada y útil para almacenar y analizar datos - Formalmente, son la conjunción de dos o más vectores (independientemente de su tipo) en una tabla con dimensiones (Grolemund, 2014) - Cada vector se transforma en una columna. - Es una forma de estructurar datos con filas y columnas. Las filas suelen ser las observaciones y las columnas las variables. - Cada columna **debe** tener la misma longitud (número de observaciones) --- ## Dataframes Posible estructura de un dataframe o marco de datos .center[ <img src="ima/dataframe.png" width="1000px" /> ] .right[(Grolemund, 2014)] --- ## Dataframes Normalmente los dataframes con los que trabajamos los importamos desde otro formato (lo veremos más adelante), pero podemos crearlos fácilmente en R. Supongamos que queremos estructurar los resultados de una encuesta muy corta: .codefont[ ```r # Usamos la función data.frame encuesta <- data.frame(edad = c(18,24,80,40,76), ideologia = c("Izquierda", "Izquierda", "Derecha", "Centro", "Derecha"), voto = c("Partido A", "Partido A", "Partido C", "Partido B", "Partido B")) class(encuesta) ``` ``` ## [1] "data.frame" ``` ] --- ## Dataframes .codefont[ ```r # Con la función head() puedo ver las primeras filas del dataframe head(encuesta) ``` ``` ## edad ideologia voto ## 1 18 Izquierda Partido A ## 2 24 Izquierda Partido A ## 3 80 Derecha Partido C ## 4 40 Centro Partido B ## 5 76 Derecha Partido B ``` ```r # Para la visión extendida usar view() o click en el objeto en el ambiente ``` ] --- ## Dataframes: indexación De forma similar a los vectores, la indexación `[]` nos permite acceder a datos dentro de nuestro dataframe. Como los dataframes tienen dos dimensiones (filas y columnas), tenemos que especificar cuáles valores queremos obtener. Para ello la indexación se divide en dos por una coma: antes de la coma nos referimos a las filas, y luego de la coma a las columnas: .codefont[ ```r # Valor de fila 1 y columna 1 encuesta[1, 1] ``` ``` ## [1] 18 ``` ```r # Valor de toda la columna 1 (no fijamos filas entonces nos devuelve todas) encuesta[, 1] ``` ``` ## [1] 18 24 80 40 76 ``` ```r # Valor de toda la fila 1 (no fijamos columnas entonces nos devuelve todas) encuesta[1, ] ``` ``` ## edad ideologia voto ## 1 18 Izquierda Partido A ``` ] --- ## Dataframes: indexación R nos permite utilizar funciones dentro de funciones. Por ejemplo, podemos usar el operador `:` para columnas consecutivas según orden o la función `c()` para referirnos a dos columnas en una indexación: ```r encuesta[1, 1:2] # Valor de fila 1 y las columnas 1 y 2 ``` ``` ## edad ideologia ## 1 18 Izquierda ``` ```r encuesta[1, c(1,3)] # Valor de fila 1 y las columnas 1 y 3 ``` ``` ## edad voto ## 1 18 Partido A ``` Los números negativos nos devuelven lo opuesto: ```r encuesta[1, -3] # Valor de fila 1 y las columnas 1 y 2 ``` ``` ## edad ideologia ## 1 18 Izquierda ``` --- ## Dataframes Una segunda manera para referirnos a datos dentro un dataframe es el usando el símbolo `$` . Es la manera más utilizada para refernirnos a una columna de un dataframe, y es muy sencillo de utilizar. .codefont[ ```r # Primero escribimos el nombre del dataframe, seguido por el símbolo $ y # el nombre de la variable (sin comillas) encuesta$edad # Esto imprime todos los valores de esa variable ``` ``` ## [1] 18 24 80 40 76 ``` ```r # En un dataframe cada variable es un vector y podemos fijarnos su clase class(encuesta$edad) ``` ``` ## [1] "numeric" ``` ```r mean(encuesta$edad) # Podemos aplicarle funciones (la media en este caso) ``` ``` ## [1] 47.6 ``` ] --- ## Ejercicio .content-box-blue[ *Crear un dataframe con tus 3 canciones favoritas e información sobre ellas (al menos dos variables más además del nombre)* ] --- class: inverse, center, middle # Funciones --- ## Funciones - Una función es una serie de instrucciones para realizar una tarea específica. La función suele necesitar un imput (generalmente datos) y suele devolver un output (generalmente datos luego de cierta regla) - Por ejemplo, en el caso anterior, usamos la función `mean()` para calcular la media de la variable "edad" del dataframe "encuesta" - Usar una función en sencillo: escribimos el nombre de la función, seguido de un paréntesis y dentro los datos a los que le queremos aplicar la función. Pueden ser objetos o directamente valores. Ej. `mean(c(10,20,30))` o `mean(objeto)` - Dentro de la función se especifican los argumentos, que pueden ser dividos en dos tipos. El primero son los datos a los que se le aplica la función y el resto detalles de cómo se computa la función. --- ## Funciones .center[ <img src="ima/ima_fun.png" width="1250px" /> ] --- ## Funciones (ejemplo) ```r # Supongamos que queremos calcular la media de: 12,24,36,48,60 (12 + 24 + 36 + 48 + 60)/5 # Calculo directamente la media ``` ``` ## [1] 36 ``` ```r data_ej <- c(12, 24, 36, 48, 60) # Genero el vector con los 5 números sum(data_ej) / length(data_ej) # Calculo con dos funciones su media ``` ``` ## [1] 36 ``` ```r mean(data_ej) # Calculo la media directamente con la función mean() ``` ``` ## [1] 36 ``` ```r # También se puede ingresar data directamente en el argumento x mean(c(12, 24, 36, 48, 60)) ``` ``` ## [1] 36 ``` --- ## Funciones: R Base - R viene con un cojunto de [funciones](https://stat.ethz.ch/R-manual/R-devel/library/base/html/00Index.html) - Las funciones que vienen "por defecto" son las que escribieron los creadores, al igual que en otros softwares no libres. - La ventaja de R es que cualquiera puede crear nuevas funciones y publicarlas. Colecciones de funciones (generalmente relacionadas) se llaman "paquetes". --- ## Funciones: argumentos - Las funciones generalmente cuentan con argumentos que van dentro de los paréntesis. - La mayoría de las funciones cuentan con el argumento "x" que suele ser el objeto al que le pasaremos la función. Al ser la mayoría de las veces el primer argumento, muchas veces no se explicita: ```r media_fun <- mean(data_ej) # Sin explicitar argumento x media_fun_x <- mean(x = data_ej) # Explicitando argumento x identical(media_fun, media_fun_x) # El mismo resultado ``` ``` ## [1] TRUE ``` --- ## Funciones: argumentos - Muchas funciones necesitan más de un argumento para funcionar de forma correcta. - Por ejemplo, pensemos en la función `identical()`: "The safe and reliable way to test two objects for being exactly equal. It returns `TRUE` in this case, `FALSE` in every other case.". - Por definición, `identical()` necesita dos conjuntos de datos distintos, para testear si son iguales. - En la documentación `help(identical)` podemos ver que cuenta no solo con el argumento x, sino que también con y. .codefont[ ```r # Dos maneras de aplicar la función identical(media_fun, media_fun_x) # por posición ``` ``` ## [1] TRUE ``` ```r identical(x = media_fun, y = media_fun_x) # por especificación ``` ``` ## [1] TRUE ``` ] --- ## Funciones: argumentos - A su vez, las funciones muchas veces cuentan con otros argumentos aparte de los datos que usan de insumo. Son detalles de cómo queremos aplicar la regla o el output que recibimos. - Volvamos a la función `mean()`. Voy a crear un dataframe con la posición que obtuvo Uruguay en los últimos 5 mundiales de futbol masculino .codefont[ ```r # Dataframe con el resultado de Uruguuay en los últimos 5 mundiales uru_mundial <- data.frame(year = c(2002, 2006, 2010, 2014, 2018), posicion = c(26, NA, 4, 12, 5)) # Veamos la posición promedio: mean(uru_mundial$posicion) ``` ``` ## [1] NA ``` ```r # Como tenemos un dato perdido, la función nos devuelve NA # Si especificamos el argumento na.rm (no tener en cuenta los datos perdidos): mean(uru_mundial$posicion, na.rm = TRUE) ``` ``` ## [1] 11.75 ``` ] --- ## Funciones: argumentos por defecto - Es importante entender que la función `mean()` <b> por defecto </b> tiene el argumento `na.rm = FALSE`. De esta forma, si nosotros solamente le pasamos el argumento x, no quitará los datos perdidos. - Leer la documentación de las funciones es fundamental, y sobretodo prestar atención a los argumentos por defecto. --- ## Funciones: argumentos ```r help(mean) ``` .center[ <img src="ima/ima_mean.jpeg" width="1000px" /> ] --- ## Funciones y código Normalmente al transformar datos utilizamos varias funciones. Esto se puede hacer de varias formas: - Correr funciones de a una, siempre al mismo objeto - Ir creando objetos intermedios a medida que aplicamos funciones - Anidar funciones (se aplicará primero la función más al centro y por último la primera desde la izquierda) - Pipeline ([magrittr](https://magrittr.tidyverse.org/)) --- ## Funciones y código: ejemplos Supongamos que queremos aplicar dos funciones a un vector númerico: `mean()` para calcular la media y `round()` para redondear el resultado a 1 dígito después de la coma. .codefontchico[ ```r data_ej <- c(12, 21, 33, 41, 27, 23) # Correr funciones de una, almismo objeto resultado_A <- mean(data_ej) # Primero estimo la media resultado_A <- round(resultado_A, digit = 1) # Redondeo # Correr funciones de una, con objetos intermedios resultado_B_1 <- mean(data_ej) # Creo un primer objeto con la media resultado_B_2 <- round(resultado_B_1, digits = 1) # Creo 2do objeto con la media redondeada # Corro las dos funciones en la misma línea resultado_C <- round(mean(data_ej), digits = 1) # Pruebo que los resultados sean iguales: identical(resultado_A, resultado_B_2) ``` ``` ## [1] TRUE ``` ```r identical(resultado_A, resultado_C) ``` ``` ## [1] TRUE ``` ] --- ## Errores y advertencias - Cuando utilizamos funciones podemos encontrarnos con errores (errors) y advertencias (warnings). La principal diferencia entre ellas es que el error implica que la función no se pudo aplicar, mientras que en la advertencia la función fue aplicada pero que algo no funcionó como esperado. También es posible ver mensajes (messages) que simplemente informan algo sobre la función ```r vector_ej <- rnorm(n = 10, mean = 10, sd = 5) # Creo valores aleatorios mean(Vector_ej) # Aplico función para obtener la media ``` ``` ## Error in mean(Vector_ej): object 'Vector_ej' not found ``` .content-box-blue[ *¿A qué se debe este error?* ] --- ## Errores y advertencias ```r vector_ej <- rnorm(n = 10, mean = 10, sd = 5) # Creo valores aleatorios mean(vector_ej) # Aplico función para obtener la media ``` ``` ## [1] 11.2697 ``` --- ## Errores y advertencias En el caso anterior, es sencillo entender porque la función no corrió. Sin embargo, muchas veces podemos no entender que es lo que salió mal y copiar y pegar el error en un buscador de internet es un buen primer paso. .codefontchico[ ```r vector_1 <- c("10", "35%", "35", "50") # Vector de caracteres que contiene números vector_1 ``` ``` ## [1] "10" "35%" "35" "50" ``` ```r vector_2 <- as.numeric(vector_1) # Transformo a vector númerico ``` ``` ## Warning: NAs introduced by coercion ``` ```r vector_2 # Los valores que además del número tenían (%) no pueden pasarse a númericos ``` ``` ## [1] 10 NA 35 50 ``` ```r vector_1 <- gsub("%", "", vector_1) # Quito los % del vector original vector_1 # Sin valores perdidos ``` ``` ## [1] "10" "35" "35" "50" ``` ```r vector_2 <- as.numeric(vector_1) # Transformo a vector númerico vector_2 # Los valores que además del número tenían (%) no pueden pasarse a númericos ``` ``` ## [1] 10 35 35 50 ``` ] --- class: inverse, center, middle # Paquetes --- ## Paquetes - Los paquetes son conjuntos de funciones, documentación de ayuda y datos- -- - El conjunto de funciones que vienen por defecto en R se le denomina "Base". Por ej. las funciones que hemos utilizado hasta ahora -`mean()`, `identical()`, `help()`- están dentro del R Base. -- - El repositorio principal donde se alojan los paquetes de R se llama Comprehensive R Archive Network [CRAN](https://cran.r-project.org/). Hay más de 10.000 paquetes alojados en CRAN. Aquí hay dos listas con algunos de los paquetes más útiles: [support.rstudio](https://support.rstudio.com/hc/en-us/articles/201057987-Quick-list-of-useful-R-packages) y [towardsdatascience](https://towardsdatascience.com/a-comprehensive-list-of-handy-r-packages-e85dad294b3d) -- - Los paquetes alojados en CRAN son testados antes de ser publicados. Por eso es recomendable tener cuidado con utilizar paquetes que no han sido publicados allí aún. -- - Los paquetes normalmente están relacionados por alguna temática, por ejemplo existen paquetes específicos para manipulación de datos [dplyr](https://cran.r-project.org/web/packages/dplyr/dplyr.pdf), visualización de datos [ggplot2](https://cran.r-project.org/web/packages/ggplot2/ggplot2.pdf) o importar y exportar datos [readr](https://cran.r-project.org/web/packages/readr/readr.pdf). Dado que R es libre, cualquier persona puede crear y publicar un paquete (publicarlo en CRAN requiere ciertos procesos igualmente), esto facilita que haya paquetes muy específicos para ciertas tareas que pueden ser de gran utilidad. Por ejemplo, existen paquetes para conectarse con la API de Twitter [rtweet](https://cran.r-project.org/web/packages/rtweet/rtweet.pdf), para utilizar los datos de [Gapminder](https://cran.csiro.au/web/packages/gapminder/gapminder.pdf) o para analizar datos electorales y de opinión pública en Uruguay [opuy](https://github.com/Nicolas-Schmidt/opuy/blob/master/man/figures/Manual_opuy.pdf) --- ## Paquetes: instalación - Cuando abrimos R solamente tenemos cargado por defecto el paquete Base. - La primera vez que queremos utilizar un paquete tenemos que descargarlo con el siguiente comando: ```r # Para descargar paquetes de CRAN, utilizamos la siguiente función: install.packages("nombre_del_paquete") install.packages("dplyr") # Ejemplo # Existen otros paquetes no alojados en CRAN, que se instalan con # el paquete "devtools" ``` --- ## Paquetes: cargar - Luego de instalarlo (una sola vez por versión de R), tenemos que cargar el paquete utilizando la función `library()` - Esto lo debemos realizar en cada sesión de R que vayamos a utilizar (cada vez que abrimos R). ```r library("nombre_del_paquete") library("dplyr") # Ejemplo ``` --- ## Paquetes En ocasiones los paquetes tienen funciones que se llaman igual, lo que puede llevar a errores. En estos casos -una vez instalado el paquete- podemos usar una función sin cargar el paquete de la siguiente manera: .codefont[ ```r df_1 <- data.frame(col_a = c(1, 2, 3), col_b = c(2, 4, 6)) df_2 <- data.frame(col_a = c(1, 2, 3), col_c = c(-2, 1, 6)) # Uso la función rbind.fill() que a diferencia de rbind() del Base, # permite unir datafranes con columnas que no matchean de forma exacta, # agregando NAs # No cargo todo el paquete plyr sino que llamo la función específica usando :: df_3 <- plyr::rbind.fill(df_1, df_2) ``` ] --- class: inverse, center, middle # Operadores --- ## Operadores aritméticos <table class="table table-striped table-hover table-condensed" style="font-size: 20px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> Operador </th> <th style="text-align:left;"> Descripcion </th> <th style="text-align:left;"> Ejemplo </th> <th style="text-align:left;"> Resultado </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> + </td> <td style="text-align:left;"> Suma </td> <td style="text-align:left;"> 2+2 </td> <td style="text-align:left;"> 4 </td> </tr> <tr> <td style="text-align:left;"> - </td> <td style="text-align:left;"> Resta </td> <td style="text-align:left;"> 2-2 </td> <td style="text-align:left;"> 0 </td> </tr> <tr> <td style="text-align:left;"> * </td> <td style="text-align:left;"> Multiplicación </td> <td style="text-align:left;"> 2*2 </td> <td style="text-align:left;"> 4 </td> </tr> <tr> <td style="text-align:left;"> % </td> <td style="text-align:left;"> División </td> <td style="text-align:left;"> 2%2 </td> <td style="text-align:left;"> 1 </td> </tr> <tr> <td style="text-align:left;"> ^ </td> <td style="text-align:left;"> Potencia </td> <td style="text-align:left;"> 2^3 </td> <td style="text-align:left;"> 8 </td> </tr> </tbody> </table> --- ## Operadores relacionales <table class="table table-striped table-hover table-condensed" style="font-size: 20px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> Operador </th> <th style="text-align:left;"> Descripcion </th> <th style="text-align:left;"> Ejemplo </th> <th style="text-align:left;"> Resultado </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> < </td> <td style="text-align:left;"> Menor a </td> <td style="text-align:left;"> 4 < 4 </td> <td style="text-align:left;"> FALSE </td> </tr> <tr> <td style="text-align:left;"> > </td> <td style="text-align:left;"> Mayor a </td> <td style="text-align:left;"> 6 > 2 </td> <td style="text-align:left;"> TRUE </td> </tr> <tr> <td style="text-align:left;"> <= </td> <td style="text-align:left;"> Menor o igual a </td> <td style="text-align:left;"> 4 <= 4 </td> <td style="text-align:left;"> TRUE </td> </tr> <tr> <td style="text-align:left;"> >= </td> <td style="text-align:left;"> Mayor o igual a </td> <td style="text-align:left;"> 6 >= 2 </td> <td style="text-align:left;"> TRUE </td> </tr> <tr> <td style="text-align:left;"> %in% </td> <td style="text-align:left;"> Está incluido dentro de </td> <td style="text-align:left;"> 2 %in% c(0, 1, 2) </td> <td style="text-align:left;"> TRUE </td> </tr> <tr> <td style="text-align:left;"> == </td> <td style="text-align:left;"> Igual a </td> <td style="text-align:left;"> hola == hello </td> <td style="text-align:left;"> FALSE </td> </tr> <tr> <td style="text-align:left;"> != </td> <td style="text-align:left;"> Distinto a </td> <td style="text-align:left;"> hola != hello </td> <td style="text-align:left;"> TRUE </td> </tr> </tbody> </table> --- ## Operadores booleanos <table class="table table-striped table-hover table-condensed" style="font-size: 20px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> Operador </th> <th style="text-align:left;"> Prueba </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> a & b </td> <td style="text-align:left;"> a y b son verdaderos </td> </tr> <tr> <td style="text-align:left;"> a | b </td> <td style="text-align:left;"> al menos una de a o b son verdaderas </td> </tr> <tr> <td style="text-align:left;"> !a </td> <td style="text-align:left;"> a no es verdadera </td> </tr> <tr> <td style="text-align:left;"> isTrue(a) </td> <td style="text-align:left;"> a es verdadera </td> </tr> </tbody> </table>