RParaAnalisisDeDatos PDF
RParaAnalisisDeDatos PDF
RParaAnalisisDeDatos PDF
Este es el primer de 2 juegos de notas introductorias a R con un enfoque en análisis de datos. A diferencia
de otros recursos, no se pretende dar una introducción general a R sino mostrar las herramientas más
importantes para comenzar a utilizar R en análisis de datos. En este primer juego se cubre la sección de
visualización. Más adelante aprenderemos a usar R para manipulación de datos y modelación. Estas
notas siguen material e ideas de Hadley Wickham y en particular el libro R for Data Science. Las notas
están ordenadas como sigue:
• El ambiente y el lenguaje R
• Introducción a R para análisis de datos: paquetes, vectores y data frames
• Datos faltantes
• Lectura de datos y guardar datos
• Visualización: gráficas con ggplot2
El ambiente y el lenguaje R
¿Qué es R?
¿Cómo entender R?
¿Por qué R?
• R funciona en casi todas las plataformas (Mac, Windows, Linux e incluso en Playstation 3).
• R es un lenguaje de programación completo, permite desarrollo de DSLs.
• R promueve la investigación reproducible.
• R está actualizado gracias a que tiene una activa comunidad. Solo en CRAN hay cerca de 10,000
paquetes (funcionalidad adicional de R creadas creada por la comunidad).
• R se puede combinar con otras herramientas.
• R tiene capacidades gráficas muy sofisticadas.
• R es popular (Revolutions blog).
Investigación reproducible en R
Un estándar mínimo para el análisis de datos es la reproducibilidad: debe ser posible reproducir el
análisis en todos sus pasos y en cualquier momento. Para ello los pasos del análisis deben estar
UVM
documentados apropiadamente, de manera que las decisiones importantes puedan ser entendidas
claramente.
Estos dos principios generalmente implican que debemos trabajar escribiendo código, más que usando
interfaces gráficas de point and click. Esto permite crear programas reproducibles que son fácilmente
documentados, y tiene otras consecuencias positivas como la facilidad de comunicación (compartir
código), la posibilidad de trabajar con versiones que documenten la historia del desarrollo, respaldos
fáciles del trabajo, e incluso el uso de lenguajes de programación más flexibles que integren nuestro
trabajo en procesos de producción de reportes o monitoreo.
Los scripts de R son oportunos para llevar a cabo análisis reproducbiles, pero
hay más herramientas que nos ayudan a documentar y compartir nuestro trabajo:
• Los paquetes rmarkdown y knitr se utilizan para generar documentos en formato pdf, html o
word que integran texto, código de R y resultados producidos por el código.
• Packrat: Sistema para administrar dependencias de paquetes en R.
Organizar los análisis para ser reproducibles no es trivial pero es una buena práctica que te agradecerán
los que consulten o utilicen tu trabajo (incluído tu yo del futuro), puedes leer más recomendaciones para
lograr análisis reproducibles en initial steps toward reproducible research. También es conveniente usar
un controlador de versiones este es un buen tutorial para Git y Github con R.
Descargar R y RStudio
Para comenzar se debe descargar R, esta descarga incluye R básico y un editor de textos para escribir
código. Después de descargar R se recomienda descargar RStudio (gratis y libre).
Rstudio es un ambiente de desarrollo integrado para R: incluye una consola, un editor de texto y un
conjunto de herramientas para administrar el espacio de trabajo cuando se utiliza R.
Algunos shortcuts útiles:
En el editor
En la consola
Paquetes y el Tidyverse
La mejor manera de usar R para análisis de datos es aprovechando la gran cantidad de paquetes que
aportan funcionalidad adicional. Desde Rstudio podemos instalar paquetes (Tools - > Install packages o
usar la función install.packages("nombre_paquete")). Una vez instalados, podemos cargarlos a nuestra
sesión de R mediante library. Por ejemplo, para cargar el paquete readr hacemos:
UVM
# print(read_csv)
# Error in print(read_csv) : object 'read_csv' not found
library(tidyverse)
print(read_csv)
## function (file, col_names = TRUE, col_types = NULL, locale = default_loca
le(),
## na = c("", "NA"), quoted_na = TRUE, quote = "\\"", comment = "",
## trim_ws = TRUE, skip = 0, n_max = Inf, guess_max = min(1000,
## n_max), progress = show_progress())
## {
## tokenizer <- tokenizer_csv(na = na, quoted_na = TRUE, quote = quote,
## comment = comment, trim_ws = trim_ws)
## read_delimited(file, tokenizer, col_names = col_names, col_types = co
l_types,
## locale = locale, skip = skip, comment = comment, n_max = n_max,
## guess_max = guess_max, progress = progress)
## }
## <environment: namespace:readr>
read_csv es una función que aporta el paquete readr, que a su vez está incluido en el tidyverse.
Los paquetes se instalan una sola vez, sin embargo, se deben cargar (ejecutar library(tidyverse)) en
cada sesión de R que los ocupemos.
En estas notas utilizaremos la colección de paquetes incluídos en el tidyverse. Estos paquetes de R
están diseñados para ciencia de datos, y para funcionar juntos como parte de un flujo de trabajo.
La siguiente imagen tomada de Why the tidyverse (Joseph Rickert) indica que paquetes del tidyverse
se utilizan para cada etapa del análisis de datos.
knitr::include_graphics("imagenes/tidyverse.png")
UVM
1
readxl tidyr forcats
haven hms
httr
Program lubridate . Model
rvest stringr
xml2 purrr broom
magrittr modelr
Software estadístico
Estructuras de datos
En R se puede trabajar con distintas estructuras de datos, algunas son de una sola dimensión y otras
permiten más, como indica el diagrama de abajo:
1d Vector List
1 1
2d Matrix ........................-·-··· Data trame
1
nd Array
b <- a + 10
b
## [1] 15.0 12.0 14.1 17.0 19.2
d <- sqrt(a)
d
## [1] 2.236068 1.414214 2.024846 2.645751 3.033150
a + d
## [1] 7.236068 3.414214 6.124846 9.645751 12.233150
10 * a
## [1] 50 20 41 70 92
a * d
## [1] 11.180340 2.828427 8.301867 18.520259 27.904982
Podemos juntar vectores del mismo tamaño en tablas, que se llaman data.frame. Por ejemplo:
Los data frames son estructuras rectangulares donde cada columna es del mismo tipo (e.g. categórica o
factor, numérica, caracter) pero columnas distintas pueden tener diferentes tipos.
library(ggplot2)
head(diamonds)
UVM
## # A tibble: 6 x 10
## carat cut color clarity depth table price x y z
## <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
## 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43
## 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31
## 3 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31
## 4 0.29 Premium I VS2 62.4 58 334 4.20 4.23 2.63
## 5 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75
## 6 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48
str(diamonds)
## Classes 'tbl_df', 'tbl' and 'data.frame': 53940 obs. of 10 variables:
## $ carat : num 0.23 0.21 0.23 0.29 0.31 0.24 0.24 0.26 0.22 0.23 ...
## $ cut : Ord.factor w/ 5 levels "Fair"<"Good"<..: 5 4 2 4 2 3 3 3 1 3
...
## $ color : Ord.factor w/ 7 levels "D"<"E"<"F"<"G"<..: 2 2 2 6 7 7 6 5 2
5 ...
## $ clarity: Ord.factor w/ 8 levels "I1"<"SI2"<"SI1"<..: 2 3 5 4 2 6 7 3 4
5 ...
## $ depth : num 61.5 59.8 56.9 62.4 63.3 62.8 62.3 61.9 65.1 59.4 ...
## $ table : num 55 61 65 58 58 57 57 55 61 61 ...
## $ price : int 326 326 327 334 335 336 336 337 337 338 ...
## $ x : num 3.95 3.89 4.05 4.2 4.34 3.94 3.95 4.07 3.87 4 ...
## $ y : num 3.98 3.84 4.07 4.23 4.35 3.96 3.98 4.11 3.78 4.05 ...
## $ z : num 2.43 2.31 2.31 2.63 2.75 2.48 2.47 2.53 2.49 2.39 ...
Para lograr una programación eficiente en R es importante conocer las técnicas de indexar data
frames:
como vemos arriba para indexar los data frames tenemos que indicar filas y columnas, en el lado
izquierdo de los corchetes se indica (con un vector) que filas queremos extraer, y en el lado derecho se
indican las columnas: diamonds[filas, columnas]. También vale la pena notar que diamonds$x regresa la
columna x como vector, es decir, diamonds$x es de una sola dimensión.
Datos faltantes
En R los datos faltantes se expresan como NA, ¿qué regresan las siguientes expresiones?
5 + NA
NA / 2
sum(c(5, 4, NA))
mean(c(5, 4, NA))
NA < 3
NA == 3
NA == NA
UVM
Las expresiones anteriores regresan NA, el hecho que la media de un vector que incluye NAs o su suma
regrese NAs se debe a que el default en R es propagar los valores faltantes, esto es, si deconozco el valor
de una de las componentes de un vector, también desconozco la suma del mismo; sin embargo, muchas
funciones tienen un argumento na.rm para removerlos,
NA == NA
## [1] NA
La expresión anterior puede resultar confusa, una manera de pensar en esto es considerar los NA
como no sé, por ejemplo, si no se la edad de Juan y no se la edad de Esteban, la pregunta a ¿Juan tiene
la misma edad que Esteban? es no sé (NA).
edad_Juan <- NA
edad_Esteban <- NA
edad_Juan == edad_Esteban
## [1] NA
edad_Jose <- 32
# Juan es menor que José?
edad_Juan < edad_Jose
## [1] NA
Ambiente interactivo
a <- 10
a
## [1] 10
(a <- 15)
## [1] 15
o-
1 1 1 1 1 1
o 1 2 3 4 5
carat
Lenguaje de programación
Funciones y reglas de búsqueda lexica (lexical scoping rules)
Las funciones son una base importante de la programación en R. Veamos un ejemplo:
body(wtd_mean)
## {
## sum(x * wt)/sum(wt)
## }
2. Los formales, la lista de argumentos que controlan como puedes llamar a la función
formals(wtd_mean)
## $x
##
##
## $wt
## rep(1, length(x))
environment(wtd_mean)
## <environment: R_GlobalEnv>
environment(qplot)
## <environment: namespace:ggplot2>
# 1
x <- 5
f <- function(){
y <- 10
c(x = x, y = y)
}
rm(x, f)
# 2
x <- 5
g <- function(){
UVM
x <- 20
y <- 10
c(x = x, y = y)
}
# 3
x <- 5
h <- function(){
y <- 10
i <- function(){
z <- 20
c(x = x, y = y, z = z)
}
i()
}
Las reglas de búsqueda determinan como se busca el valor de una variable libre en una función. A nivel
lenguaje R usa lexical scoping, una alternativa es dynamic scoping. En R (lexical scoping) los valores de
los símbolos se basan en como se anidan las funciones cuando fueron creadas y no en como son
llamadas. Esto es, en R no importa como son las llamadas a una función para saber como se va a buscar
el valor de una variable. Una consecuencia de las reglas de búsqueda es que todos los objetos deben ser
guardados en memoria.
Recursos
• Buscar ayuda: Google, StackOverflow. Para aprender más sobre un paquete o una función
pueden visitar Rdocumentation.org.
• La referencia principal de estas notas es el libro R for Data Science de Hadley Wickham.
• Para aprender los comandos básicos de R Try R y Datacamp cuentan con excelentes cursos
interactivos.
• Para aprender programación avanzada en R, el libro gratuito Advanced R de Hadley Wickham
es una buena referencia. En particular es conveniente leer la guía de estilo (para todos:
principiantes, intermedios y avanzados).
• Para mantenerse al tanto de las noticias de la comunidad de R pueden visitar R-bloggers.
• Más del tidyverse: Why the tidyverse
Visualización
Utilizaremos el paquete ggplot2 y cubriremos los siguientes puntos:
• Gráfica de dispersión
• Páneles
• Distintos tipos de gráficas
Gráficas de dispersión
Usaremos el conjunto de datos mpg que se incluye en R, puedes encontrar información de esta base
de datos tecleando ?mpg.
?mpg
glimpse(mpg)
## Observations: 234
## Variables: 11
UVM
## $ manufacturer <chr> "audi", "audi", "audi", "audi", "audi", "audi", "...
## $ model <chr> "a4", "a4", "a4", "a4", "a4", "a4", "a4", "a4 qua...
## $ displ <dbl> 1.8, 1.8, 2.0, 2.0, 2.8, 2.8, 3.1, 1.8, 1.8, 2.0,...
## $ year <int> 1999, 1999, 2008, 2008, 1999, 1999, 2008, 1999, 1...
## $ cyl <int> 4, 4, 4, 4, 6, 6, 6, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6...
## $ trans <chr> "auto(l5)", "manual(m5)", "manual(m6)", "auto(av)...
## $ drv <chr> "f", "f", "f", "f", "f", "f", "f", "4", "4", "4",...
## $ cty <int> 18, 21, 20, 21, 16, 18, 18, 18, 16, 20, 19, 15, 1...
## $ hwy <int> 29, 29, 31, 30, 26, 26, 27, 26, 25, 28, 27, 25, 2...
## $ fl <chr> "p", "p", "p", "p", "p", "p", "p", "p", "p", "p",...
## $ class <chr> "compact", "compact", "compact", "compact", "comp...
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy))
UVM
•
40- •
••
••
•• • •
• ••
• •• ••• • ••
•
30-
>-
• • •• •
•• •• •• •• ••• • •••• ••• •
~
.e
••• •• •• • • ••
••• ••• • • • •• • • • •
• • • •• ••
• • •• ••• • • •• ••
20-
•• ••• • •
•• •• • •• •• • •• ••
• •• ••• • •••
•
2 3 4 5 6 7
displ
En ggplot2 se inicia una gráfica con la instrucción ggplot(), debemos especificar explicitamente que base
de datos usamos, este es el primer argumento en la función ggplot. Una vez que creamos la base
añadimos capas, y dentro de aes() escribimos las variables que queremos graficar y el atributo de la
gráfica al que queremos mapearlas.
La función geom_point() añade una capa de puntos, hay muchas funciones geometrías incluídas en
ggplot2: geom_line(), geom_boxplot(), geom_histogram,… Cada una acepta distintos argumentos
para mapear las variables en los datos a características estéticas de la gráfica. En el ejemplo de arriba
mapeamos displ al eje x, hwy al eje y, pero geom_point() nos permite representar más variables
usando la forma, color y/o tamaño del punto. Esta flexibilidad nos permite entender o descubrir
patrones más interesantes en los datos.
ggplot(mpg) +
geom_point(aes(x = displ, y = hwy, color = class))
UVM
•
40- •
•• class
.
••
.
• 2seater
• minivan
• • •• •
... . ..•. . ...... •••••.. .
•• • • pickup
• • • subcompact
20- • • • suv
• •••
. .. ••..... • •
•
•
2 3 4 5 6 7
displ
Experimenta con los aesthetics color (color), tamaño (size) y forma (shape).
¿Qué diferencia hay entre las variables categóricas y las continuas?
¿Qué ocurre cuando combinas varios aesthetics?
El mapeo de las propiedades estéticas se denomina escalamiento y depende del tipo de variable, las
variables discretas (por ejemplo, genero, escolaridad, país) se mapean a distintas escalas que las
variables continuas (variables numéricas como edad, estatura, etc.), los defaults para algunos atributos
son (estos se pueden modificar):
Discreta Continua
40-
30-
20-
1 1 1 1 1 1
2 3 4 5 6 7
displ
¿Qué problema tiene la siguiente gráfica?
• •
40- •
• •• •
•• • •
30- • •• •• •• •
•
>. •
• ••• ••• •••
••• ••• ••
~
..e
••• ••• • •• •• ••
•• •• •
20-
••• ••• •
•• ••• ••• ••
•• •
•
10 15 20 25 30 35
cty
p
+ geom_jitter()
UVM
• •
40- •
•• •
• ••
30- .
i·~·~· •
• •
•• •
•
~·-=.~
........ .
>-
3:
s:
V "'··
tA-~·
20-
10-
·~ 1
10
••
1
15
1
20
1
25
1
30
1
35
cty
¿Cómo podemos mejorar la siguiente gráfica?
• •
40- •
• •
• ••
• •
30- •• •••
>.
~ •• •• •••
s:
•• •• ••• •• ••
•• •• •• •• •• ••
• •• • •• ••
•• • •••
20-
• ••• ••
• ••
1
• •
2seater compact midsize minivan pickup subcompact suv
class
Intentemos reodenar los niveles de la variable clase
• •
40- •
• •
•• •
• •
30- ••• •••
>. •• ••
•••
3:
..c. •• •• •• •••
•• •• •• •• •• ••
• •• •• • •• •
••• ••• •
20-
•• •• •
• ••
• •
pickup suv minivan 2seater midsize subcompact compact
reorder( class, hwy)
Podemos probar otros geoms.
• •
40-
•
• • •
• •
• • •
.
....
• •
··' . -·' ••
., ,·.-.. .. . •.
• •• •• ~4·
30-
•
••• _. .... ...
.
.: .
: • ••._
......
.. -~
.... ·~ .,,,
•• •
• • •• • • • •• • • •
,. ....,
....
•A
20- ••
•
'. . .
•••••••••
•
1 1 1
• •
40- •
•
•
30-
>-
~
..e
••
•
••
• 9 9
20-
~
•
•1
• 1 1 1 1 1
40- ••
••
•••
•
~ 30-
.. ·i5 ~ ~ .
s:
•• •
20-
~A .. •
.....
tii?.~
1
pickup suv
1
minivan
1
2seater
1 1
reorder(class, hwy)
Lee la ayuda de reorder y repite las gráficas anteriores ordenando por la mediana de hwy.
¿Cómo harías para graficar los puntos encima de las cajas de boxplot?
Paneles
Veamos ahora como hacer páneles de gráficas, la idea es hacer varios múltiplos de una gráfica donde
cada múltiplo representa un subconjunto de los datos, es una práctica muy útil para explorar
relaciones condicionales.
En ggplot podemos usar facet_wrap() para hacer paneles dividiendo los datos de acuerdo a las
categorías de una sola variable
•
40- •
30-~. •
20-
•
10-
~ 6 8
s:
40-
·..:"' .' •
30-
..,•.L.•
••
41:': '~
,:.
• 1
•••
20-
•
10-
2
1 1
3
1
4
1
5
1
6
1
7
1
2
1
3
1
4
• 1
5
1
6
1
7
displ
También podemos hacer una cuadrícula de 2 dimensiones usando facet_grid(filas~columnas)
• •
40- •
•• •
~-
t
>. 30-
., '4 •
.,, ·a:•
·~. •.••
:s:
s:
•
'• • t.
·~·
20-
• • •
•
' '
2 3 4 5 6 7
' ' ' ' ' '
2 3 4 5 6 7
' ' ' ' ' '
2 3 4 5 6 7
' ' ' ' '
2 3 4 5 6 7
' ' ' '
2 3 4 5 6 7
' ' ' ' ' '
2 3 4 5 6 7
' ' ' ' ' '
• '
2 3 4 5 6 7
' ' ' '
displ
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_jitter() +
facet_grid(drv ~ class)
. ,•
40-
,.
•••
30-
• l.
.¡:,.
20- •
•
• •
•
,.•
40-
•••
t.• .,, I
""
c-, 30-
~
s: •
20-
•
40-
. •,.
30-
20- ••••
1 1 1 1 1 ' 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 • 1 1
2 3 4 5 6 7 2 3 4 5 6 7 2 3 4 5 6 7 2 3 4 5 6 7 2 3 4 5 6 7 2 3 4 5 6 7 2 3 4 5 6 7
displ
Los páneles pueden ser muy útiles para entender relaciones en nuestros datos. En la siguiente gráfica
es difícil entender si existe una relación entre radiación solar y ozono
data(airquality)
ggplot(airquality, aes(x = Solar.R, y = Ozone)) +
geom_point()
## Warning: Removed 42 rows containing missing values (geom_point).
•
150 -
•
• •
.... -• ••
••
a.> 100-
e • • ••
o ••
. .. ..
N
• •• •
o
• • ,
' •
• • • • . . ,. ,. .··
•
. •
....
50-
• ,
• • • • •••
o- • , ....
•
• • ••
:. \e • ...
ir •
• • •
•
1 1 1 1
library(Hmisc)
airquality$Wind.cat <- cut2(airquality$Wind, g = 3)
ggplot(airquality, aes(x = Solar.R, y = Ozone)) +
geom_point() +
facet_wrap(~ Wind.cat)
UVM
•
150-
•
•f •
•
.
100-
••
(1)
e
o •••• •
:-. •
..
•
.
N
o • •
• • •
.,,. . ... .,,,'··.....
.
• •
.
• •
••• •
•• • •• • • ••
50-
•• •• • • • •
•
• • ••• • • • •
'-· • • • • • •
o- 1 1 1
•
1 1 1
' 1 1 1 1
o
1
•
150 -
••
100 -
• •
(1)
e
o •
• • •
...
o
N
50 - • •• ••
• 1 • • •• •
o- •
1 1 1 1 1 1 1 1 1 1 1 1
library(babynames)
glimpse(babynames)
## Observations: 1,858,689
UVM
## Variables: 5
## $ year <dbl> 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880, 1880, 188...
## $ sex <chr> "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F...
## $ name <chr> "Mary", "Anna", "Emma", "Elizabeth", "Minnie", "Margaret"...
## $ n <int> 7065, 2604, 2003, 1939, 1746, 1578, 1472, 1414, 1320, 128...
## $ prop <dbl> 0.072384329, 0.026679234, 0.020521700, 0.019865989, 0.017...
Supongamos que queremos ver la tendencia del nombre “John”, para ello debemos generar un
subconjunto de la base de datos.
0.08- ---
c.
0.06-
'
ec. o.oa-
0.02-
0.00-
1 1 1 1
0.08-
0.06-
sex
a.
ea. o.oa- -F
-M
0.02-
0.00-
1 1 1 1
Tarea. Explora la base de datos gapminder, estos datos están incluidos en el paquete del
mismo nombre, para acceder a ellos basta con cargar el paquete:
# install.packages("gapminder")
library(gapminder)
gapminder
## # A tibble: 1,704 x 6
## country continent year lifeExp pop gdpPercap
## <fctr> <fctr> <int> <dbl> <int> <dbl>
## 1 Afghanistan Asia 1952 28.801 8425333 779.4453
## 2 Afghanistan Asia 1957 30.332 9240934 820.8530
## 3 Afghanistan Asia 1962 31.997 10267083 853.1007
## 4 Afghanistan Asia 1967 34.020 11537966 836.1971
## 5 Afghanistan Asia 1972 36.088 13079460 739.9811
UVM
## 6 Afghanistan Asia 1977 38.438 14880372 786.1134
## 7 Afghanistan Asia 1982 39.854 12881816 978.0114
## 8 Afghanistan Asia 1987 40.822 13867957 852.3959
## 9 Afghanistan Asia 1992 41.674 16317921 649.3414
## 10 Afghanistan Asia 1997 41.763 22227415 635.3414
## # ... with 1,694 more rows
realiza al menos 3 gráficas y explica las relaciones que encuentres. Debes usar lo que revisamos
en estas notas: al menos una de las gráficas debe ser de páneles, realiza una gráfica con datos de
México, y (opcional)si lo consideras interesante, puedes crear una variable categórica utilizando la
función cut2 del paquete Hmisc.
Bibliografía.
Ortiz, T. (s. f.). R para análisis de datos [Sitio en internet]. Recuperado de
https://tereom.github.io/est_computacional/01-Intro-R/R_analisis_datos_visualizacion