FINAL Visualization
FINAL Visualization
FSC
Contents
La importancia de la visualización de datos 1
1
library(tidyverse)
library(readr)
300
200
100
0
murders$total
Para esta función podemos ajustar el tipo de punto con el parámetro pch:
plot(murders$total,murders$population/10^5,pch="*")
2
*
murders$population/10^5
300
*
200
* *
* *
100
*
** * * *
**
** * * ** *
** * *
*
*
* * *****
******** * *
0
murders$total
O el color:
plot(murders$total,murders$population/10^5,pch="*",col="red")
3
*
murders$population/10^5
300
*
200
* *
* *
100
*
** * * *
**
** * * ** *
** * *
*
*
* * *****
******** * *
0
murders$total
Cada vez que llamamos a la función plot() se abre una nueva ventana. Si queremos pintar en un gráfico ya
existente tenemos dos opciones:
plot(murders$total,murders$population/10^5,pch="*",col="red")
par(new=T)
plot(murders$total,murders$population/10^5,pch="o")
4
o*
murders$population/10^5
300
o*
200
o* o*
o o*
o* *
100
o*o o* o* o*
oo *
o*o* *o*o*oo* oo*o* o* o* o
o*oo* o*oo*o*o*o**o** *
o *
o o
***o***o* o*
o*o *
0
murders$total
o bien usar points() o lines() que pintan puntos o unen puntos por medio de líneas si los puntos ya están
dibujados. La función abline pinta una linea de pendiente b y ordenada en el origen a.
plot(murders$total,murders$population/10^5,pch="*",col="red")
points(murders$total,murders$population/10^5,lty=2)
abline(a=0,b=1,lty=2)
5
*
murders$population/10^5
300
*
200
* *
* *
100
*
** * * *
**
** * * ** *
** * *
*
*
* * *****
******** * *
0
murders$total
Histograms
Un histograma nos muestra la distribución de los elementos de una muestra. Es decir, nos dice cuántos
elementos de cada tipo hay.
hist(murders$total)
6
Histogram of murders$total
30
25
Frequency
20
15
10
5
0
murders$total
Es decir, hay unos 32-33 estados con menos de 200 asesinatos; hay unos 10 estados con entre 200 y 400
asesinatos y el resto (~10 estados) sufrieron más de 400 asesinatos. EN particular parece que hay 1 estado
con entre 1200 y 1400 asesinatos.
Vamos a comprobarlo con una tabla. Primero binarizamos nuestros resultados en bins de 200:
murders$[Link]=murders$total
murders$[Link][which(murders$total<=200)]=200
murders$[Link][which(murders$total>200 & murders$total<=400)]=400
murders$[Link][which(murders$total>400 & murders$total<=600)]=600
murders$[Link][which(murders$total>600 & murders$total<=800)]=800
murders$[Link][which(murders$total>800 & murders$total<=1000)]=1000
murders$[Link][which(murders$total>1000 & murders$total<=1200)]=1200
murders$[Link][which(murders$total>1200 & murders$total<=1400)]=1400
table(murders$[Link])
##
## 200 400 600 800 1000 1400
## 33 12 3 1 1 1
murders<-murders %>%
mutate(bin=case_when(total<=200~200,
between(total,200,400)~400,
between(total,400,600)~600,
between(total,600,800)~800,
between(total,800,1000)~1000,
between(total,1000,1200)~1200,
TRUE~1400))
7
murders
8
table(murders$bin)
##
## 200 400 600 800 1000 1400
## 33 12 3 1 1 1
El número de bins puede cambiarse fácilmente con el comando breaks()
hist(murders$total,breaks=10)
Histogram of murders$total
25
20
Frequency
15
10
5
0
murders$total
Y también podemos elegir ver la frecuencia (número de elementos en cada bin) o la probabilidad de tener un
elemento en cada bin (# elementos en bin/total numero de elementos)
hist(murders$total,freq = F)
9
Histogram of murders$total
0.0030
0.0020
Density
0.0010
0.0000
murders$total
Con este tipo de plot obtenemos una idea de cómo es la distribución de los datos: no simétrica, con el valor
mas probable entre 0 y 200 y con algunos valores muy distintos dl resto. Estas características serán las que
miraremos más adelante cuando queramos caracterizar distribuciones de datos.
Boxplot
Un boxplot también nos da pistas acerca de la distribución de un conjunto de datos
boxplot(murders$total)
10
1000
600
200
0
Vemos que la caja tiene una linea central (la mediana) que en este caso no está en el medio, lo cual significa
que el 50% de los valores más pequeños están más cerca entre si que los valores del 50% superior. Además
vemos tres puntos por encima de la linea (whishart). Estos son outliers. Tenemos 3 entre los datos más altos.
Los outliers o valores extremos están más allá del valor que deja a su izquierda el 75% de la distribución
multiplicado por 1.5. Todos estos datos se pueden observar usando la función summary() sobre un vector
numérico:
summary(murders$total)
11
1000
murders$total
600
200
0
murders$region
La región con el menor número de asesinatos en general es “West”, aunque hay dos estados que son outliers.
Podemos buscarlo:
[Link]<-filter(murders,region=="West")
[Link][[Link]([Link]$total),]
1. Utilizando un scatterplot plot() encontrar si existe una relación de algún tipo entre el peso al nacimiento
de los bebés y la edad gestacional (en semanas)
2. Compara utilizando un boxplot la distribución de los pesos al nacer de los niños con madres fumadoras
frente a aquellos con madres no fumadoras
3. Explora usando un histograma la distribución general de los pesos de los bebes.
12
Sumarizando datos y detectando outliers
Cuando tenemos muchos datos lo primero que solemos querer hacer es intentar resumir la información en un
sólo número. En principio esto debería de darnos una idea acerca de algunas de las características importantes
de nuestros datos. Queé medidas de sumarización se nos ocurren? La media, la mediana, la desviación
estandar. . . ahora vamos a ver cuando usar cada una de ellas, cuando son y cuando no son informativas.
## [1] 119.5769
sqrt(var(babies$bwt))
## [1] 18.23645
Recordando cómo era su distribución (simétrica, un sólo valor más probable. . . ) parece que estos valores son
bastantes informativos acerca de estos datos
Histogram of murders$total
30
25
Frequency
20
15
10
5
0
murders$total
13
mean(murders$total)
## [1] 184.3725
sqrt(var(murders$total))
## [1] 236.1261
Como veis estos dos valores nos harian pensar que hay numeros de asesinatos negativos en algunos estados,
no nos da pistas acerca del numero mas habitual de asesinatos que encontramos y no podriamos saber que el
numero de asesinatos es tan alto como 1400 en otros. Hay otros parámetros para sumarizar datos que no
siguen una distribución “normal”:
median(murders$total)
## [1] 97
IQR(murders$total)
## [1] 243.5
La mediana nos dice cual es el valor que deja el 50% de los datos a la izquierda de el y el 50% a su derecha.
El IQR (Interquantile Range) nos da una idea de en que intervalo cae el 50% de los datos. Podemos calcular
los quantiles de una distribucion usando:
summary(murders$total)
## 25%
## 24.5
q3=quantile(murders$total, p=0.75)
q3
## 75%
## 268
iqr=(q3-q1)
iqr
## 75%
14
## 243.5
r <- c(q1 - 1.5*iqr, q3 + 1.5*iqr)
r
## 25% 75%
## -340.75 633.25
Buscamos los outliers:
which(murders$total<=r[1])
## integer(0)
which(murders$total>=r[2])
## [1] 5 10 44
murders[which(murders$total>=r[2]),]
## 25% 75%
## -706.0 998.5
which(murders$total>=r2[2])
## [1] 5
murders[which(murders$total>=r2[2]),]
15
Normal Q−Q Plot
1000
Sample Quantiles
600
200
0
−2 −1 0 1 2
Theoretical Quantiles
Frente a esto, la distribución de los pesos de los bebes tienen una distribución mas o menos normal, con la
excepción de que las colas son mas pesadas.
qqnorm(babies$bwt)
qqline(babies$bwt)
16
Normal Q−Q Plot
180
Sample Quantiles
140
100
80
60
−3 −2 −1 0 1 2 3
Theoretical Quantiles
Finalmente, para datos no normales hay otra medida que nos da una idea de la dispersión, la mad: median
absolute deviation. Se trata de la suma de la distancia absoluta entre cada valor y la mediana.
mad(babies$bwt)
## [1] 16.3086
mad(murders$total)
## [1] 126.021
17
Visualizando datos con R: ggplot2()
Hay otras librerias para visualizar datos en R, como por ejemplo las funciones de la instalacion base que ya
hemos visto, grid o lattice. Sin embargo, ggplot2 se basa en la llamada grammar of graphics: al igual que
bloques gramaticales básicos permiten crear cientos de frases en ggplot2 un pequeño número de comandos
permite crear gráficos muy distintos.
En particular, ggplot2 está articulado sobre tres conceptos básicos que tienen que definirse cada vez que
vamos a plotear algo: data, geometry y aesthetics
• Data:
Los datos en ggplot2() tienen que estar en formato tidy. Ya hemos visto que esto significa que cada elemento
a dibujar está indexado por un sólo índice: el número de la fila. Eso si, para cada elemento a representar
podemos tener múltiples atributos. El [Link] murders es tidy porque cada estado aparece en una sola
fila aunque hay varios atributos (region, total, population) para cada estado. Si en lugar de una foto fija
tuvieramos una serie temporal cada combinacion (estado, año) sería la “key” de la tabla y apareceria tambien
una sola vez en la tabla en una fila.
• Geometry:
Queremos representar un scatterplot? Un histograma? Un boxplot?
• Aesthetic Mapping:
Que represento en el eje de las x? Que represento en el eje de las y? Que color uso? Que letra uso? Parte de
estos parámetros dependerán de la geometría del plot
Ejercicio 1:
1000
Total number of murders (log scale)
LA
M
SC
MSOKKY AL
100 DC AR CT
NV
NM KS CO
M
DE OR
NE
WV
UT
IA
AK
RI
MT MEID
10
SD HI
WY NH
ND
VT
1 3
Populations in millio
Para el siguiente plot, describe los datos, la geometria y el aesthetic mapping.
18
• Data: murders
• Geometria: Scatterplot
• Aesthetics Mapping:
++ x-axis: population size
++ y-axis: total number of murders
++ text: states
++ colors: the four different regions
LA MO GA IL
MD
VANCOH
AZ NJ
SC TN
IN
AL MA region
MSOKKY
100 DC AR CT WI
WA
NV a Northe
NM KS CO
MN a South
DE OR
NE a North
WV
UT
IA a West
AK
RI
MT MEID
10
SD HI
WY NH
ND
VT
1 3 10 30
Populations in millions (log scale)
Fijaos en la diferencia con:
19
US Gun Murders in 2010
CA
1000
TX
FL
NY
MI PA
Total number of murders (log scale)
LA MO GA IL
MD NC OH
SC TNAZ VANJ
IN
AL MA
MS OKKY
100 DC AR CT WIWA
NV
NM KS CO
MN
DE OR
NE
WV
UTIA
AK
RI
MT ME ID
10
SD HI
WY NH
ND
VT
1 3 10 30
Populations in millions (log scale)
Y con:
20
#alternativamente con pipe:
murders %>% ggplot()
21
p <- ggplot(data = murders)
class(p)
22
p
23
Geometria
La geometría define el tipo de representación de nuestros datos que estamos usando: cómo se situan los
valores en el plano o en el espacio.
Cada geometría necesita una serie de parámetros fijos para poder pintar y otros opcionales
Por ejemplo, un scatterplot con la función geom_point requiere obligatoriamente los valores en x y en y.
Además se le puede dar color, tamaño, etc. Queremos crear un scatterplot:
? geom_point
murders %>% ggplot() +
geom_point(aes(x = population/10^5, y = total))
24
1200
800
total
400
Aesthetics
Cuando hacemos un gráfico estamos transformando nuestro datos en valores que componen el gráfico final.
La iniciativa grammar of graphics (gg) lo que intenta es hacer esto de manera sistemática sea cual sea el tipo
de geometría que vamos a utilizar.
Con la función aes() estamos tratando de asignar a valores de nuestros datos (de nuestro data frame murders
en este caso) a características cuantificables del gráfico. Estas características son las aesthetics. Da igual si se
trata de un pie chart, de un scatterplot. . . al final ggplot2 lo que necesita es saber qué pone en cada dimensión
(x,y) para gráficos de dos dimensiones, (x,y,z) para gráficos 3D, el color, la fuente de la letra. . . Necesita saber
que valor pone en cada pixel de la pantalla y cuales son sus características. Esto es lo que tratamos de hacer
con aes(): mapear valores en características de un gráfico
La función aes() es la que le indica a la geometría que necesita pintar en el plot y cómo. Además se le pueden
dar muchas propiedades como color, tamaño, etc, en función de los datos. Cada geometría requiere un cierto
tipo de mapeo datos/visualización.
25
murders %>% ggplot(aes(x = population/10^5, y = total)) +
geom_point()
1200
800
total
400
p+geom_point()
26
1200
800
total
400
0 10 20 30
population/10^6
##Capas
Los gráficos en ggplot2 se definen usando diferentes capas que se unen unas a otras usando +
Una vez que hemos creado un objeto ggplot() como antes le vamos añadiendo capas, la primera de ellas
siempre es la geometria. Después podemos seguir añadiendo características.
Otra capa que queremos añadir es texto para cada punto. Se utiliza la función geom_text()
p+
geom_point(aes(col=region))+
geom_text(aes(label=state))
27
California
1200
South
North Central
New York
Pennsylvania West
400 Michigan
LouisianaGeorgia Illinois
Missouri Ohio
Maryland
North Carolina
Virginia
New
Arizona Jersey
Tennessee
South Carolina
Indiana
Alabama
Mississippi
Massachusetts
Kentucky
District of Oklahoma
Columbia
Connecticut
Wisconsin
Arkansas
Washington
Nevada
NewKansas
Mexico
Colorado
DelawareMinnesota
Oregon
Nebraska
West Virginia
Alaska
Rhode
South
New Utah
Iowa
Island
Montana
Idaho
Maine
Dakota
Hawaii
0Wyoming
North Hampshire
Dakota
Vermont
0 10 20 30
population/10^6
Si queremos visualizar la abreviación
p+
geom_point(aes(col=region))+
geom_text(aes(label=abb))
28
CA
1200
800 TX region
Northeast
FL
total
South
North Central
NY
PA West
400 MI
LA GA IL
MO
MD NCOH
AZVA
SCTN
NJ
MS KY IN
ALMA
DC NV
AROK
CT WI
WA
NMKS CO
DE
AKNE
WV
IDUT
RI
MT
ME ORMN
IA
SD
HI
0 WY
NH
ND
VT
0 10 20 30
population/10^6
Fuera de aes() no se reconocen las variables de los objetos para las que queremos mapear características
estéticas
p_test <- p +
geom_text(label = abb)
## Error in layer(data = data, mapping = mapping, stat = stat, geom = GeomText, : object 'abb' not found
Cuando en una capa no se requiere ese mapeo dato-característica del plot podemos no usar la función aes(),
pero para ello tenemos que haber definido globalmente las características básicas que necesita la función:
p<-murders %>%
ggplot(aes(x = population/10^6,
y = total,
label=abb))
p+geom_point()+
geom_text(col="red")
29
CA
1200
800 TX
FL
total
NY
PA
400 MI
LA GA IL
MO OH
MD NC
AZ VANJ
SC TN
MS KY IN
AL MA
DC NVAR OK
CT WIWA
NMKS COMN
DE
AKNEUT
WV
RI
MT
ID IAOR
0 ME
SD
WYHI
NH
ND
VT
0 10 20 30
population/10^6
# p+geom_point()+
# geom_text(col=region)
Las capas van tomando ese mapeado global hasta que lo sobre-escribimos:
murders %>%
ggplot(aes(x = population/10^5,
y = total,
label=abb))+
geom_point()+
#geom_text(col="red")+
geom_label(aes(x=10,y=800,label="Hello"))
30
1200
800 Hello
total
400
murders %>%
ggplot(aes(x = population/10^5,
y = total,
label=abb))+
geom_point()+
#geom_text(col="red")+
geom_label(aes(x=10,
y=800,
label="Hello"),col="blue")
31
1200
800 Hello
total
400
murders %>%
ggplot(aes(x = population/10^5,
y = total,
label=abb))+
geom_point()+
geom_text(col="red")+
geom_label(aes(x=10,y=800,label="Hello"))+
geom_text(col="blue")
32
CA
1200
800 Hello TX
FL
total
NY
PA
400 MI
LA GA IL
MO OH
MD NC
AZ VANJ
SC TN
MS KY IN
AL MA
DC NVAR OK
CT WIWA
NMKS COMN
DE
AKNEUT
WV
RI
MT
ID IAOR
0 ME
SD
WYHI
NH
ND
VT
0 100 200 300
population/10^5
Cada función requiere diferentes parámetros unos que son aesthetics y otros fijos. La diferencia es que
aesthetics mapea datos a propiedades estéticas (para uno o para todos los datos) mientras que lo que está
fuera de aes() afecta a todo el plot, no hay un mapeo dato->estética.
p<-murders %>% ggplot()
p +
geom_point(aes(population/10^5, total),
size = 3) +
geom_text(aes(population/10^5,
total,
label = abb))
33
CA
1200
800 TX
FL
total
NY
PA
400 MI
LA GA IL
MO OH
MD NC
AZ VANJ
SC TN
MS KY IN
AL MA
DC NVAR OK
CT WIWA
NMKS COMN
DE
AKNEUT
WV
RI
MT
ID IAOR
0 ME
SD
WYHI
NH
ND
VT
0 100 200 300
population/10^5
p +
geom_point(aes(population/10^5,
total,
col=region),
size =3) +
xlab("total pop")+
ylab("murders")
34
1200
800 region
Northeast
murders
South
North Central
West
400
geom_text(aes(population/10^5,
total,
label = abb),
nudge_x=25)
p +
geom_point(size = 3) +
geom_text(nudge_x = 0.1) +
scale_x_continuous(trans = "log10") +
xlab("log10(total pop)")+
scale_y_continuous(trans = "log10") +
ylab("log10(murders)")
35
CA
1000
TX
FL
NY
MI PA
GA IL
LA MO
MD
VA NCOH
AZ NJ
SC TN
IN
AL MA
MS OKKY
log10(murders)
100 DC AR CT WIWA
NV
NM KS CO
MN
DE OR
NE
WV
UTIA
AK
RI
MT ME ID
10
SD HI
WY NH
ND
VT
10 30 100 300
log10(total pop)
36
US Gun Murders in 2010
CA
1000
TX
FL
NY
MI PA
Total number of murders (log scale)
LA MO GA IL
MD NC OH
SC TNAZ VANJ
IN
AL MA
MS OKKY
100 DC AR CT WIWA
NV
NM KS CO
MN
DE OR
NE
WV
UTIA
AK
RI
MT ME ID
10
SD HI
WY NH
ND
VT
10 30 100 300
Populations in millions (log scale)
p+geom_point(aes(col=region),size=3)
37
US Gun Murders in 2010
CA
1000
TX
FL
NY
MI PA
Total number of murders (log scale)
LA MO GA IL
MD NCOH
AZ VA
SC TN
NJ
IN
AL MA region
MSOKKY
100 DC ARCT WIWA
NV Northeast
NM KS CO
MN South
DE OR
NE North Central
WV
UT
IA West
AK
RI
MT MEID
10
SD HI
WY NH
ND
VT
10 30 100 300
Populations in millions (log scale)
Los valores de x,y (las coordenadas) que precisa esta función geom_point las hereda de lo que hemos ya
definido en p. El mapping está en primera posición porque es lo que geom_point espera.
Añadiendo anotaciones
Si queremos añadir algo al plot que no está directamente asociado con el mapeo dato->estética no necesitamos
la función aes(). Lo hacíamos antes añadiendo un texto en unas coordenadas fijas:
murders %>%
ggplot(aes(x = population/10^5,
y = total,
label=abb))+
geom_point()+
geom_text(aes(col="red"))+
geom_label(x=10,y=800,label="Hello")
38
CA
1200
800 Hello TX
FL colour
total
a red
NY
PA
400 MI
LA GA IL
MO
MD NC OH
VA
AZ NJ
SC TN
MS KY IN
AL MA
DC NV
AROK
CT WI
WA
NMKS CO
DE
AKNE
WV
RI
MTID
ME UTORMN
IA
0 SD
HI
WY
NH
ND
VT
0 100 200 300
population/10^5
Imaginemos que queremos añadir al plot una linea que tenga como pendiente el rate medio de asesinatos en
USA.
Recordemos que usando dplyr podemos conseguir:
r <- murders %>%
summarize(rate = sum(total) / sum(population) * 10^5) %>%
.$rate
Le añadimos una linea con pendiente 1 e intercepta el log10 de ese ratio medio:
p +
geom_point(aes(col=region), size = 3) +
geom_abline(intercept = log10(r))
39
US Gun Murders in 2010
CA
1000
TX
FL
NY
MI PA
Total number of murders (log scale)
LA MO GA IL
MD NCOH
AZ VA
SC TN
NJ
IN
AL MA region
MSOKKY
100 DC ARCT WIWA
NV Northeast
NM KS CO
MN South
DE OR
NE North Central
WV
UT
IA West
AK
RI
MT MEID
10
SD HI
WY NH
ND
VT
10 30 100 300
Populations in millions (log scale)
40
US Gun Murders in 2010
CA
1000
TX
FL
NY
MI PA
Total number of murders (log scale)
LA MO GA IL
MD NCOH
AZ VA
SC TN
NJ
IN
AL MA region
MSOKKY
100 DC ARCT WIWA
NV Northeast
NM KS CO
MN South
DE OR
NE North Central
WV
UT
IA West
AK
RI
MT MEID
10
SD HI
WY NH
ND
VT
10 30 100 300
Populations in millions (log scale)
## Add-on packages
Otra de las ventajas de ggplot2() es, una vez mas, la existencia de muchos paquetes que nos proporcionan
estas features ya implementadas. Por ejemplo, con el paquete ggtheme() podemos cambiar el background y el
estilo de nuestro plot por otros ya implementados. O con ggrepel() podemos distanciar los puntos de manera
que no caigan unos encima de otros.
library(ggrepel)
library(ggthemes)
p + theme_economist()
41
US Gun Murders in 2010
region Northeast South North Central West
CA
1000
TX
FL
Total number of murders (log scale)
NY
LA MO MI PA
GA IL
NCOH
MD VANJ
SC AZ
TN
MS OKKY IN
AL MA
100 DC AR
NV CT WIWA
NM KS CO
MN
DE NE OR
WV
AK UTIA
RI
10
MT ME ID
SD HI
WY NH
ND
VT
10 30 100 300
Populations in millions (log scale)
library(ggthemes)
library(ggrepel)
42
US Gun Murders in 2010
Region Northeast South North Central West
CA
1000 TX
FL
MI GA PA
Total number of murders (log scale)
LA MO VA NY
SC MD AZ
OH
TN NJ
MS OK AL NC IL
100 NV AR KY MA IN
DC CT WI
NM KS CO WA
NE MN
DE UT OR
WV
AK RI IA
ID
10 MT ME
HI
WY SD
NH
ND
VT
10 30 100 300
Populations in millions (log scale)
##
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
##
## combine
43
[Link](p1,p2,p3, ncol = 3)
300
100
150
75
200
count
count
count
100
50
100
25 50
0 0 0
50 60 70 80 50 60 70 80 50 60 70 80
height height height
44