-
Notifications
You must be signed in to change notification settings - Fork 20
/
03_graphs2v.Rmd
609 lines (455 loc) · 36.5 KB
/
03_graphs2v.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
# Gráficos para varias variables cuantitativas {#doscuanti}
En este capítulo se presentan funciones para la creación de gráficos que involucran varias variables cuantitativas.
## Función `plot`
Los gráficos de dispersión son muy útiles porque permiten ver la relación que existe entre dos variables cuantitativas, la función `plot` permite crear este tipo de gráficos. La estructura de la función `plot` con los argumentos más usuales se muestra a continuación:
```{r, eval=F}
plot(x, y, type, main, sub, xlab, ylab)
```
Los argumentos de la función `plot` son:
- `x`: vector numérico con las coordenadas del eje horizontal.
- `y`: vector numérico con las coordenadas del eje vertical.
- `type`: tipo de gráfico a dibujar. Las opciones son: {#par_type}
- `'p'` para obtener puntos, esta es la opción por defecto.
- `'l'` para obtener líneas.
- `'b'` para obtener los puntos y líneas que unen los puntos.
- `'c'` para obtener sólo las líneas y dejando los espacios donde estaban los puntos obtenidos con la opción `'b'`.
- `'o'` para obtener los puntos y lineas superpuestas.
- `'h'` para obtener líneas verticales desde el origen hasta el valor $y_i$ de cada punto, similar a un histograma.
- `'s'` para obtener escalones.
- `'S'` similar al anterior.
- `'n'` para que no dibuje.
- `...`: otros parámetros gráficos que pueden ser pasados como argumentos para `plot`.
### Ejemplo {-}
Crear 16 parejas de puntos tales que $x=-5, -4, \ldots, 9, 10$ con $y=-10+(x-3)^2$, dibujar los nueve diagramas de dispersión de $y$ contra $x$ usando todos los valores posibles para el parámetro `type`.
A continuación se muestra el código para crear las 16 parejas de $x$ e $y$. Los nueve diagramas de dispersión se observan en la Figura \@ref(fig:ex1plot), de esta figura se observa claramente el efecto que tiene el parámetro `type` en la construcción del diagrama de dispersión.
```{r ex1plot, fig.cap='Efecto del parámetro `type` en la función `plot`.', fig.height=6, fig.width=5}
x <- -5:10
y <- -10 + (x-3)^2
par(mfrow=c(3, 3))
plot(x=x, y=y, type='p', main="con type='p'")
plot(x=x, y=y, type='l', main="con type='l'")
plot(x=x, y=y, type='b', main="con type='b'")
plot(x=x, y=y, type='c', main="con type='c'")
plot(x=x, y=y, type='o', main="con type='o'")
plot(x=x, y=y, type='h', main="con type='h'")
plot(x=x, y=y, type='s', main="con type='s'")
plot(x=x, y=y, type='S', main="con type='S'")
plot(x=x, y=y, type='n', main="con type='n'")
```
### Ejemplo {-}
Como ilustración vamos a crear dos diagramas de dispersión entre el precio de apartamentos usados en la ciudad de Medellín y el área de los apartamentos. El primer diagrama es un gráfico básico mientras que el segundo es un diagrama mejorado.
El código necesario para cargar la base de datos y construir los diagramas de dispersión se muestra a continuación.
```{r ex2plot, fig.cap='Diagrama de dispersión del precio del apartamento versus área del apartamento. A la izquierda el diagrama de dispersión sin editar y a la derecha el diagrama de dispersión mejorado.', fig.height=4, fig.width=8}
url <- 'https://tinyurl.com/hwhb769'
datos <- read.table(file=url, header=T)
par(mfrow=c(1, 2))
plot(x=datos$mt2, y=datos$precio)
plot(x=datos$mt2, y=datos$precio, pch='.',
xlab='Área del apartamento (m2)',
ylab='Precio (millones de pesos)')
```
En la Figura \@ref(fig:ex2plot) se presentan los diagramas de dispersión entre precio y área de los apartamentos. En el panel de la izquierda está el diagrama básico, de este diagrama se observa claramente que a medida que los apartamentos tienen mayor área el precio promedio y la variabilidad del precio aumentan. En la parte inferior izquierda de este diagrama se tiene una zona de alta densidad de puntos y por esa razón se observa una mancha en el diagrama. Para la construcción del diagrama de dispersión mostrado en el panel derecho se usó el parámetro `pch='.'` con el objetivo de obtener pequeños puntos que representen cada apartamento y que no se traslapen debido a que se tienen `r nrow(datos)` observaciones en la base de datos.
## Función `sunflowerplot`
La función `sunflowerplot` sirve para crear gráficos de dispersión en los cuales hay parejas repetidas que se superponen y que por lo tanto no se podrían apreciar.
Si una pareja está una sola vez se representará por un punto; si la pareja se repite dos veces se representará por un punto y dos rayitas rojas (pétalos); si la pareja se repite tres veces se representará por un punto y tres rayitas rojas (pétalos) y así sucesivamente.
La estructura de la función `sunflowerplot` con los argumentos más usuales se muestra a continuación:
```{r, eval=F}
sunflowerplot(x, y, pch, seg.col, seg.lwd, ...)
```
Los argumentos de la función `plot` son:
- `x`: vector numérico con las coordenadas del eje horizontal.
- `y`: vector numérico con las coordenadas del eje vertical.
- `pch`: valor o vector numérico con el tipo de punto a usar, por defecto `pch=1`. Para conocer los diferentes símbolos que se pueden obtener con el parámetro `pch` se recomienda consultar la Figura \@ref(fig:point1).
- `seg.col`: color de los pétalos.
- `seg.lwd`: ancho de los pétalos.
- `...`: otros parámetros gráficos que pueden ser pasados como argumentos para `plot`.
A continuación se presenta un ejemplo en los cuales se usa la función `sunflowerplot` para crear gráficos de dispersión.
### Ejemplo {-}
Suponga que se tiene el punto (1, 1) una sola vez, el punto (2, 3) repetido cuatro veces, el punto (3, 2) repetido seis veces y el punto (4, 5) repetido dos veces. El objetivo es crear dos gráficos de dispersión con los trece puntos, uno con la función `plot` y el otro con la función `sunflowerplot` para comparar los resultados.
A continuación se muestra el código con la creación de los vectores y los dos gráficos de dispersión con `plot` y `sunflowerplot`.
```{r sunflower1, fig.cap='Gráfico de dispersión para datos hipotéticos. En la izquierda el gráfico obtenido con `plot` y a la derecha el obtenido con `sunflowerplot`.', fig.asp=0.5, fig.width=8}
x <- c(1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4)
y <- c(1, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 5, 5)
par(mfrow=c(1, 2))
plot(x, y, main='a) Usando plot')
sunflowerplot(x, y, seg.col='blue', seg.lwd=2, cex=1.5,
main='b) Usando sunflowerplot')
```
En la Figura \@ref(fig:sunflower1) se muestran los dos gráficos de dispersión para los datos. En el panel de la izquierda está el diagrama obtenido con la función `plot` pero sólo se observan 4 puntos cuando en realidad eran 13, esto se debe a que hay puntos repetidos y éstos quedan unos sobre otros. En el panel de la derecha está el diagrama obtenido con la función `sunflowerplot`, en este diagrama se observan cuatro objetos: el punto con coordenadas (1, 1) se representó con un punto ya que él no se repite, el punto (2, 3) está representado por un punto y cuatro pétalos de color azul ya que él se repite cuatro veces, y los puntos (3, 2) y (4, 5) se represetan con seis y dos pétalos porque esas son las veces que ellos se repiten.
### Ejemplo {-}
Como ilustración vamos a crear un diagrama de dispersión con la función `sunflowerplot` para las variables número de alcobas y número de baños de la base de datos de apartamentos usados.
El código necesario para cargar la base de datos y construir el diagrama de dispersión se muestra a continuación. El diagrama de dispersión se construyó excluyendo la información del apartamento 594 porque éste aparece con 14 alcobas.
```{r sunflower2, fig.cap='Diagrama de dispersión para número de baños versus número de alcobas.', fig.height=3.5, fig.width=3.5}
url <- 'https://tinyurl.com/hwhb769'
datos <- read.table(file=url, header=T)
datos <- datos[-594, ] # Sacando el apto 594
sunflowerplot(x=datos$alcobas, y=datos$banos)
```
En la Figura \@ref(fig:sunflower2) se muestra el diagrama de dispersión entre número de baños y número de alcobas. De este diagrama se observa que la mayor parte de los apartamentos de la base de datos tienen 2 o 3 alcobas con 2 o 3 baños, se nota que sólo 8 apartamentos tiene 5 alcobas y que sólo un apatamento tiene seis baños.
## Función `symbols`
La función `symbols` sirve para construir diagramas de dispersión en dos dimensiones incluyendo información adicional de variables cuantitativas.
### Ejemplo {-}
Como ilustración vamos a crear un diagrama de dispersión entre el precio de apartamentos usados en la ciudad de Medellín y el área de los apartamentos pero incluyendo otras variables.
```{r symbols1, fig.cap='Diagrama de dispersión con los símbolos circle y squares para incluir más variables.', fig.asp=0.5, fig.width=8}
url <- 'https://tinyurl.com/hwhb769'
datos <- read.table(url, header=T)
subdat <- subset(datos, ubicacion == 'centro')
par(mfrow=c(1, 2))
with(subdat, symbols(x=mt2, y=precio,
circles=alcobas,
las=1, inches=0.4,
fg='red',
main='Radio = N° alcobas'))
with(subdat, symbols(x=mt2, y=precio,
squares=alcobas,
las=1, inches=0.4,
fg='dodgerblue4', bg='pink',
main='Lado = N° alcobas'))
```
```{r symbols2, fig.cap='Diagrama de dispersión con los símbolos rectangles y stars para incluir más variables.', fig.asp=0.5, fig.width=8}
par(mfrow=c(1, 2))
with(subdat, symbols(x=mt2, y=precio,
rectangles=cbind(estrato, alcobas),
las=1, inches=0.4,
fg='chartreuse4', bg='yellow',
main='Ancho = estrato y Alto = N° alcobas'))
with(subdat, symbols(x=mt2, y=precio,
stars=cbind(estrato, alcobas,
banos),
las=1, inches=0.4,
fg='purple1', bg='tomato',
main='Estrato, alcobas y n° baños'))
```
## Función `pairs`
Las matrices de dispersión obtenidas con la función `pairs` proporcionan un método simple de presentar las relaciones entre pares de variables cuantitativas y son la versión múltiple de la función `plot`. Este gráfico consiste en una matriz donde cada entrada presenta un gráfico de dispersión sencillo. Un inconveniente es que si tenemos muchas variables el tamaño de cada entrada se reduce demasiado impidiendo ver con claridad las relaciones entre los pares de variables. La celda $(i,j)$ de una matriz de dispersión contiene el gráfico de dispersión de la columna $i$ versus la columna $j$ de la matriz de datos.
En la Figura \@ref(fig:ex0pairs) se muestra un ejemplo de una matriz de dispersión para un conjunto de datos, en la diagonal están los nombres de las variables y por fuera de la diagonal están los diagramas de dispersión para cada combinación de variables.
```{r, ex0pairs, echo=F, fig.cap='Ilustración de una matriz de dispersión.', fig.asp=0.8, fig.width=6}
pairs(USJudgeRatings[,c(2:3,6,1,7)])
```
La estructura de la función `pairs` con los argumentos más usuales se muestra a continuación:
```{r, eval=F}
pairs(x, labels, panel = points, ...,
horInd = 1:nc, verInd = 1:nc,
lower.panel = panel, upper.panel = panel,
diag.panel = NULL, text.panel = textPanel,
label.pos = 0.5 + has.diag/3, line.main = 3,
cex.labels = NULL, font.labels = 1,
row1attop = TRUE, gap = 1, log = "")
```
Los argumentos de la función `pairs` son:
- `x`: matriz o marco de datos con la información de las variables cuantitativas a incluir en la matriz de dispersión.
- `labels`: vector opcional con los nombres a colocar en la diagonal, por defecto se usan los nombres de columnas del objeto `x`.
- `panel`: función usual de la forma `function(x,y,...)` a ser usada para determinar el contenido de los páneles. Por defecto es `points`, indicando que se graficarán los puntos de los pares de variables. Es posible utilizar aquí otras funciones diseñadas por el usuario.
- `...`: Indica que es posible agregar otros parámetros gráficos, tales como `pch` y `col`, con los cuales puede especificarse un vector de símbolos y colores a ser usados en los scatterplots.
- `lower.panel, upper.panel`: función usual de la forma `function(x,y,...)` para definir lo que se desea dibujar en los paneles abajo y arriba de la diagonal.
- `diag.panel`: función usual de la forma `function(x,y,...)` para definir lo que se desea dibujar en la diagonal.
- `text.panel`: Es opcional. Permite que una función: `function(x, y, labels, cex, font, ...)` sea aplicada a los paneles de la diagonal.
- `label.pos`: Para especificar la posición $y$ de las etiquetas en el text panel.
- `cex.labels, font.labels`: Parámetros para la expansión de caracteres y fuentes a usar en las etiquetas de las variables.
- `row1attop`: Parámetro lógico con el cual se especifica si el gráfico para especificar si el diseño lucirá como una matriz con su primera fila en la parte superior o como un gráfico con fila uno en la base. Por defecto es lo primero.
### Ejemplo {-}
Dibujar una matriz de dispersión para las variables precio, área, número de alcobas y número de baños de la base de datos sobre apartamentos en Medellín.
A continuación se muestra el código usado para crear el gráfico solicitado. El objeto `datos` corresponde a la base de datos completa mientras que `datos.num` es el marco de datos sólo con las variables de interés precio, área, número de alcobas y número de baños.
```{r ex1pairs, fig.cap='Matriz de dispersión para las variables precio, área, número de alcobas y número de baños de la base de datos sobre apartamentos en Medellín.', fig.asp=0.8, fig.width=6}
url <- 'https://tinyurl.com/hwhb769'
datos <- read.table(file=url, header=T)
datos.num <- datos[, c('precio', 'mt2', 'alcobas', 'banos')]
pairs(datos.num)
```
En la Figura \@ref(fig:ex1pairs) se muestra la matriz de dispersión para las variables del marco de datos `datos.num`.
### Ejemplo {-}
Volver a construir la Figura \@ref(fig:ex1pairs) editando los nombres de las variables, usando cruces azules en lugar de puntos, en escala logaritmica, con marcas horizontales en el eje vertical y eliminando los diagramas de dispersión abajo de la diagonal.
Para obtener la nueva matriz de dispersión con los cambios solicitados se usa el siguiente código. En la Figura \@ref(fig:ex2pairs) se presenta la nueva matriz de dispersión.
```{r ex2pairs, fig.cap='Matriz de dispersión modificando los parámetros adicionales de la función `pairs`.', fig.asp=0.8, fig.width=6}
pairs(datos.num, lower.panel=NULL, cex.labels=1.5, log='xy',
main='Matriz de dispersión', las=1,
labels=c('Precio', 'Área', 'Num alcobas', 'Num baños'),
pch=3, cex=0.6, col='dodgerblue2')
```
### Ejemplo {-}
Construir una matriz de dispersión con las variables precio, área y avaluo para apartamentos que cumplan la condición $100 m^2 < area < 130 m^2$. Adicionalmente, se deben diferenciar los apartamentos sin parqueadero con color rojo y los apartamentos con parqueadero con color verde.
Para crear una matriz de dispersión se puede tambien usar la base de datos original llamada `datos` que contiene todas las variables y usar una fórmula con la ayuda del operador `~` para indicar las variables de interés. La fórmula __NO__ debe contener nada del lado izquierdo mientras que en el lado derecho se colocan todas las variables a considerar en la matriz de dispersión, por esta razón es que en el códido mostrado abajo se inicia con la instrucción `~ precio + mt2 + avaluo`. Para incluir condiciones se usa el parámetro `subset` de la siguiente manera: `subset=mt2 > 100 & mt2 < 130`. A continuación el código completo para construir la matriz de dispersión solicitada.
```{r ex3pairs, fig.cap='Matriz de dispersión con un subconjunto de los datos y con colores para identificar los puntos.', fig.asp=0.8, fig.width=6}
col1 <- ifelse(datos$parqueadero == 'no', 'red', 'green3')
pairs(~ precio + mt2 + avaluo, data=datos,
lower.panel=NULL, col=col1,
subset=mt2 > 100 & mt2 < 130, pch=19, cex=0.8,
main="Matriz de dispersión para aptos con
100 < área < 130 mt2")
```
En la Figura \@ref(fig:ex3pairs) se presenta la matriz de dispersión solicitada, los puntos rojos representan los apartamento sin parqueadero mientras que los puntos verdes son los apartamento que si tienen parqueadero.
### Ejemplo {-}
¿Es posible agregar una leyenda a una matriz de dispersión?
Claro que es posible, se construye la matriz de dispersión y se deja en el lienzo del dibujo un espacio para colocar la leyenda. A continuación se muestra un ejemplo disponible en [Stackoverflow](http://stackoverflow.com/questions/14948852/how-to-use-the-pairs-function-combined-with-layout-in-r). A continuación se muestra el código para el ejemplo y en la Figura \@ref(fig:expairs) se presenta el resultado.
```{r expairs, fig.cap='Matriz de dispersión con leyenda.', fig.asp=0.8, fig.width=6}
pairs(iris[1:4], main="Anderson's Iris Data -- 3 species",
pch=21, bg=c("red", "green3", "blue")[iris$Species],
oma=c(4, 4, 6, 12))
par(xpd=TRUE)
legend(0.85, 0.7, as.vector(unique(iris$Species)), bty='n',
fill=c("red", "green3", "blue"))
```
### Ejemplo {-}
¿Es posible modificar el contenido de los páneles de una matriz de dispersión?
Claro que es posible, para hacer esto se definen funciones que hagan lo que se desea ver tanto en la diagonal como arriba y abajo de la misma.
Como ejemplo vamos a construir una matriz de dispersión que cumpla:
- sobre la diagonal un diagrama de dispersión para las variables involucradas y la recta de regresión ajustada,
- en la diagonal un histograma para la variable,
- debajo de la diagonal el coeficiente de correlación entre las variables involucradas y usando un tamaño de fuente proporcional a la fuerza de correlación.
Para obtener esta matriz de dispersión especial se definen a continuación las funciones `panel.reg`, `panel.hist` y `panel.cor`, a continuación el código utilizado. Luego se usa la función `pairs` y se indica qué función debe actuar en cada uno de los parámetros `upper.panel`, `diag.panel` y `lower.panel`.
```{r exmod1pairs, fig.cap='Matriz de dispersión con páneles modificados.', fig.asp=0.8, fig.width=6}
# Función para dibujar los puntos y agregar la recta de regresión
panel.reg <- function (x, y)
{
points(x, y, pch=20)
abline(lm(y ~ x), lwd=2, col='dodgerblue2')
}
# Función para crear el histograma
panel.hist <- function(x, ...)
{
usr <- par("usr"); on.exit(par(usr))
par(usr = c(usr[1:2], 0, 1.5) )
h <- hist(x, plot = FALSE)
breaks <- h$breaks; nB <- length(breaks)
y <- h$counts; y <- y/max(y)
rect(breaks[-nB], 0, breaks[-1], y, col="dodgerblue2", ...)
}
# Función para obtener la correlación
panel.cor <- function(x, y, digits=2, prefix="", cex.cor)
{
usr <- par("usr"); on.exit(par(usr))
par(usr = c(0, 1, 0, 1))
r <- abs(cor(x, y))
txt <- format(c(r, 0.123456789), digits=digits)[1]
txt <- paste(prefix, txt, sep="")
if(missing(cex.cor)) cex <- 0.8/strwidth(txt)
text(0.5, 0.5, txt, cex = cex * r)
}
pairs(datos.num,
upper.panel = panel.reg,
diag.panel = panel.hist,
lower.panel = panel.cor)
```
En la Figura \@ref(fig:exmod1pairs) se presenta la matriz de dispersión con las modificaciones en cada uno de los páneles. Cualquier usuario puede modificar las funciones `panel.reg`, `panel.hist` y `panel.cor` para personalizar la apariencia de los contenidos.
La función `panel.smooth` está disponible en R para que el usuario pueda incluir arriba o abajo de la diagonal un diagrama de dispersión con una línea resultado de un ajuste suavizado. Abajo se muestra el código de cómo incluir la función `panel.smooth` y en la Figura \@ref(fig:exmod2pairs) se muestra gráfico obtenido.
```{r exmod2pairs, fig.cap='Matriz de dispersión usando la función panel.smooth.', fig.asp=0.8, fig.width=6}
pairs(datos.num,
upper.panel = panel.reg,
diag.panel = panel.hist,
lower.panel = panel.smooth)
```
```{block2, type='rmdtip'}
Al construir un gráfico con `pairs` se recomienda no incluir demasiadas variables porque el gráfico se satura y no se pueden apreciar los patrones con facilidad. Se recomienda máximo 10 variables.
```
## Función `persp`
La función `persp` dibuja superfices en tres dimensiones y es posible rotar la superficie para obtener una perpectiva apropiada. La estructura de la función `persp` con los argumentos más usuales se muestra a continuación:
```{r, eval=F}
persp(x, y, z, main, sub, theta, phi, r, col,
border, box, axes, nticks)
```
Los argumentos de la función `plot` son:
- `x`: vector numérico con los valores de $x$ donde fue evaluada la función o superficie.
- `y`: vector numérico con los valores de $y$ donde fue evaluada la función o superficie.
- `z`: matriz que contiene las alturas $z$ de la supercifie para cada combinación de $x$ e $y$.
- `main`: vector numérico con las coordenadas del eje vertical.
- `sub`: vector numérico con las coordenadas del eje vertical.
- `theta, phi`: ángulo para la visión de la superficie, `theta` para la dirección azimutal y `phi` para latitud. Ver Figura \@ref(fig:globo) para una ilustración de los ángulos.
- `r`: distancia entre el centro de la caja de dibujo al punto de vista.
- `col`: color de la superficie.
- `border`: color para el borde de la superficie.
- `box`: valor lógico para indicar si se quiere dibujar la caja que contiene la superficie, por defecto es `TRUE`.
- `axes`: valor lógico para indicar si se desean marcas en los ejes y nombres de los ejes, por defecto es `TRUE`. Si `box='FALSE'` no aparecen marcas ni nombres de los ejes.
- `expand`: factor de expansión aplicado a los valores en el eje `z`.
- `ticktype`: tipo de marcas a colocar en los ejes, `simple` no dibuja nada y `detailed` coloca números a los ejes.
- `nticks`: número aproximado de marcas en los ejes.
```{r globo, fig.cap='Ilustración de los ángulos theta y phi para la función persp. Figura tomada de https://i-msdn.sec.s-msft.com/dynimg/IC412528.png', echo=F, out.width = '40%', fig.align='center'}
knitr::include_graphics("images/IC412528.png")
```
### Ejemplo {-}
Dibujar la superficie asociada a la función $f(x, y)=sen(x^2+y^2)$ para $-2 \leq x \leq2$ y $-2 \leq y \leq2$. Usar 4 combinaciones de los parámetros `theta` y `phi` para obtener un buen punto de vista de la superficie.
Lo primero que se debe hacer es crear la función $f(x, y)$ la cual se va a llamar `fun`. Luego se definen los vectores `x` e `y` tomando por ejemplo 25 puntos equiespaciados en el intervalo $[-2, 2]$. Luego se usa la función `outer` para crear la rejilla o matriz que contiene los valores de $f(x, y)$ para cada combinación de `x` e `y`, los resultados se almacenan en el objeto `z`. Por último se dibujan 4 perspectivas de la función variando los parámetros `theta` y `phi` de la función `persp`. A continuación el código utilizado.
```{r ex1persp, fig.cap='Superficie generada con `persp` y diferentes valores de theta y phi.', fig.asp=1, fig.width=10}
fun <- function(x, y) sin(x^2 + y^2)
x <- seq(from=-2, to=2, length.out=25)
y <- seq(from=-2, to=2, length.out=25)
z <- outer(x, y, fun)
par(mfrow=c(2, 2), mar=c(1, 1, 2, 1))
persp(x, y, z, zlim=c(-1, 1.5), theta=0, phi=0, col='aquamarine',
main='(A) theta=0, phi=0')
persp(x, y, z, zlim=c(-1, 1.5), theta=15, phi=15, col='lightpink',
main='(B) theta=15, phi=15')
persp(x, y, z, zlim=c(-1, 1.5), theta=45, phi=30, col='yellow1',
main='(c) theta=45, phi=30')
persp(x, y, z, zlim=c(-1, 1.5), theta=60, phi=50, col='lightblue',
main='(D) theta=60, phi=50')
```
En la Figura \@ref(fig:ex1persp) se presentan las 4 perspectivas de la función $f(x, y)=sen(x^2+y^2)$. De los 4 páneles se nota que (C) y (D) muestran mejor la superficie de interés.
Al aumentar el valor del parámetro `length.out` en la creación de los vectores `x` e `y` se obtendrá una rejilla más tupida, se recomienda modificar este valor para obtener una superficie apropiada.
### Ejemplo {-}
Dibujar la superficie de una distribución normal bivariada con vector de medias $\boldsymbol{\mu}=(5, 12)^\top$, varianzas unitarias y covarianza con valor de -0.8. Explorar el efecto de los parámetros `ticktype`, `nticks`, `expand`, `axes` y `box`.
Primero se define el vector de medias y la matriz de varianzas y covarianzas, luego se carga el paquete `mvtnorm` que contiene la función `dmvnorm` que calcula la densidad dado el vector de medias y la matriz de varianzas y covarianzas. Se construye la función `fun` y se vectoriza para luego obtener las alturas de la superficie con la ayuda de `outer`. Por último se dibujan tres perspectivas diferentes para la densidad modificando los parámetros `ticktype`, `nticks`, `expand`, `axes` y `box`, a continuación el código usado.
```{r ex2persp, fig.cap='Distribución normal bivariada.', fig.asp=0.5, fig.width=8, message=FALSE}
media <- c(5, 12)
varianza <- matrix(c(1, -0.8, -0.8, 1), ncol=2)
require(mvtnorm)
fun <- function(x, y) dmvnorm(c(x, y), mean=media, sigma=varianza)
fun <- Vectorize(fun)
x <- seq(from=2, to=8, length.out=30)
y <- seq(from=9, to=15, length.out=30)
z <- outer(x, y, fun)
par(mfrow=c(1, 3), mar=c(1, 1, 2, 1))
persp(x, y, z, theta=30, phi=30, ticktype = "detailed", nticks=4)
persp(x, y, z, theta=30, phi=30, col='salmon1', expand=0.5, axes=FALSE)
persp(x, y, z, theta=30, phi=30, col='springgreen1', expand=0.2, box=FALSE)
```
En la Figura \@ref(fig:ex2persp) se presentan las 3 perspectivas para la densidad. Note los efectos que `ticktype`, `nticks`, `expand`, `axes` y `box` tienen sobre los dibujos de las perspectivas.
## Función `contour`
La función `contour` dibuja gráficos contornos. La estructura de la función `contour` con los argumentos más usuales se muestra a continuación:
```{r, eval=FALSE}
contour(x, y, z,
xlim, ylim, zlim,
levels, nlevels=20, col)
```
Los argumentos de la función son:
- `x, y`: vectores numéricos en los cuales se evaluó la función de interés para construir el objeto `z`. Ambos vectores deben estar ordenados.
- `z`: matriz con las alturas de la función de interés, por lo general creada con la función `outer`.
- `xlim, ylim, zlim`: límites de los ejes x, y e z respectivamente.
- `nlevels`: número aproximado de niveles o cortes en la superficie a representar.
- `col`: color a usar en las líneas de contornos.
La función `contour` tiene otros parámetros adicionales que el lector puede consultar en la ayuda usando `help(contour)`.
### Ejemplo {-}
Generar una muestra aleatoria de 50 observaciones de una distribución normal con parámetros $\mu=170$ y $\sigma^2=25$. Dibujar un gráfico de contornos para la superficie de log-verosimilitud.
La muestra aleatoria se genera con el siguiente código.
```{r}
y <- rnorm(n=50, mean=170, sd=5) # sd es desviación
```
Para dibujar los contornos solicitados se debe primero construir la función de log-verosimilitud llamada `ll`. A continuación el código para crear `ll`, mayores detalles de cómo construir funciones de log-verosimilitud se pueden consultar en @hernandez_usuga.
```{r}
ll <- function(a, b) sum(dnorm(x=y, mean=a, sd=b, log=TRUE))
ll <- Vectorize(ll) # Para vectorizar la función
```
Una vez construída la función `ll` se deben construir los vectores con las coordenadas horizontal y vertical donde se evalua la función `ll`. En el código mostrado abajo se tienen dos vectores `xx` e `yy` obtenidos como secuencias desde el menor valor hasta el mayor valor para cada uno de los parámetros $\mu$ y $\sigma$ de la distribución normal, el valor `by=0.5` indica el tamaño de paso de la secuencia. Luego se construye la matriz `zz` usando la función `outer` evaluando `ll` en `xx` e `yy`. Por último la función `contour` se aplica sobre los elementos `xx`, `yy` e `zz`. En la Figura \@ref(fig:contour1) se muestra el gráfico de contornos con aproximadamente 50 niveles.
```{r contour1, fig.cap='Gráfico de contornos para la función de log-verosimilitud para el ejemplo sobre normal.', fig.height=4, fig.width=7}
xx <- seq(from=160, to=180, by=0.5)
yy <- seq(from=3, to=7, by=0.5)
zz <- outer(X=xx, Y=yy, ll)
contour(x=xx, y=yy, z=zz, nlevels=50,
col=gray(0.3), lwd=2, lty='solid',
xlab=expression(mu), ylab=expression(sigma))
```
## Función `filled.contour`
La función `filled.contour` dibuja gráficos contornos pero usando una paleta de colores, este tipo de representación se denomina gráfico de nivel. La estructura de la función `filled.contour` con los argumentos más usuales se muestra a continuación:
```{r, eval=FALSE}
filled.contour(x, y, z,
xlim, ylim, zlim,
levels, nlevels=20,
color.palette=cm.colors, col)
```
Los argumentos de la función son:
- `x, y`: vectores numéricos en los cuales se evaluó la función de interés para construir el objeto `z`. Ambos vectores deben estar ordenados.
- `z`: matriz con las alturas de la función de interés, por lo general creada con la función `outer`.
- `xlim, ylim, zlim`: límites de los ejes x, y e z respectivamente.
- `nlevels`: número aproximado de niveles o cortes en la superficie a representar.
- `color.palette`: paleta de colores a usar. Por defecto es `cm.colors` pero el usuario puede elegir entre `heat.colors`, `terrain.colors` o `topo.colors`.
La función `filled.contour` tiene otros parámetros adicionales que el lector puede consultar en la ayuda usando `help(filled.contour)`.
### Ejemplo {-}
Abajo se muestra el código para crear un gráfico de nivel usando los datos del ejemplo anterior. Observe que las figuras \@ref(fig:contour1) y \@ref(fig:contour2) son bastante similares.
```{r contour2, fig.cap='Gráfico de nivel para la función de log-verosimilitud para el ejemplo sobre normal.', fig.height=4, fig.width=7}
filled.contour(x=xx, y=yy, z=zz, nlevels=20,
xlab=expression(mu), ylab=expression(sigma),
color = topo.colors)
```
### Ejemplo {-}
¿Es posible crear un gráfico de contornos y de niveles en la misma figura?
Claro que si, abajo se muestra el código para crear primero el gráfico de niveles (en colores) y luego superponer el gráficos de contornos (las lineas). En la Figura \@ref(fig:contour3) se muestra el gráfico resultante.
```{r contour3, fig.cap='Gráfico de nivel y contornos para la función de log-verosimilitud para el ejemplo sobre normal.', fig.height=4, fig.width=7}
filled.contour(x=xx, y=yy, z=zz, nlevels=20,
color.palette = topo.colors,
plot.axes=contour(xx, yy, zz, nlevels=20, add=TRUE))
```
## Función `image`
La función `image` dibuja un gráfico de calor similar al obtenido con la función `filled.contour`. La estructura de la función `image` con los argumentos más usuales se muestra a continuación:
```{r, eval=FALSE}
image(x, y, z)
```
Los argumentos de la función son:
- `x, y`: vectores numéricos en los cuales se evaluó la función de interés para construir el objeto `z`. Ambos vectores deben estar ordenados.
- `z`: matriz con las alturas de la función de interés, por lo general creada con la función `outer`.
### Ejemplo {-}
Para la muestra aleatoria obtenida en el ejemplo anterior, dibujar un gráfico con `image` para la superficie de log-verosimilitud.
Usando los objetos `xx`, `yy` e `zz` creados en el ejemplo anterior se puede construir el gráfico solicitado, a continuación el código utilizado. En la Figura \@ref(fig:image1) se muestra el gráfico.
```{r image1, fig.cap='Gráfico para la función de log-verosimilitud para el ejemplo sobre normal.', fig.asp=0.6, fig.width=9}
image(x=xx, y=yy, z=zz,
xlab=expression(mu), ylab=expression(sigma))
```
## Función `kde2d`
La función `kde2d` pertenece al paquete `MASS` y es utilizada para crear densidades para dos variables cuantitativas. La estructura de la función `kde2d` con los argumentos más usuales se muestra a continuación:
```{r, eval=FALSE}
kde2d(x, y, h, n = 25, lims = c(range(x), range(y)))
```
Los argumentos de la función son:
- `x`: vector con la variable para el eje X.
- `y`: vector con la variable para el eje Y..
- `h`: vector con los anchos de banda en las direcciones X e Y.
- `n`: número de puntos para construir la rejilla.
- `lims`: límites del rectángulo de datos a considerar, debe ser un vector de la forma `c(xl, xu, yl, yu)`. Este parámetro por defecto es `c(range(x), range(y))`.
### Ejemplo {-}
La base de datos medidas del cuerpo cuenta con 6 variables registradas
a un grupo de 36 estudiantes de la universidad, dos de esas variables son la altura y el peso corporal. Se desea construir un gráfico de densidad bivariada para altura y peso.
El código mostrado a continuación hace la lectura de la base de datos y luego se construyen dos densidades, la primera con `n=5` y la segunda con `n=50`, esto para ver el efecto del parámetro `n`.
```{r, eval=TRUE, echo=TRUE, message=FALSE}
url <- 'https://raw.githubusercontent.com/fhernanb/datos/master/medidas_cuerpo'
datos <- read.table(file=url, header=T)
require(MASS) # Se debe cargar este paquete
f1 <- kde2d(x=datos$peso, y=datos$altura, n=5)
f2 <- kde2d(x=datos$peso, y=datos$altura, n=50)
```
En el código mostrado a continuación se dibujan las dos densidades usando un gráfico de calor usando la función `image`.
```{r den2d1, fig.cap='Gráfico de densidad bivariada para el peso corporal y la estatura de un grupo de estudiantes. A la izquierda la densidad con `n=5` y a la derecha con `n=50`.', fig.height=5, fig.width=10}
par(mfrow=c(1, 2))
image(f1, xlab='Peso', ylab='Estatura', main='n=5')
image(f2, xlab='Peso', ylab='Estatura', main='n=50')
```
## Función `interaction.plot`
La función `interaction.plot` dibuja gráficos de interacción. La estructura de la función `interaction.plot` con los argumentos más usuales se muestra a continuación:
```{r, eval=FALSE}
interaction.plot(response, x.factor, trace.factor, fun,
legend, trace.label)
```
Los argumentos de la función son:
- `response`: vector numérico con la variable respuesta.
- `x.factor`: factor 1 a ubicar en el eje horizontal.
- `trace.factor`: factor 2 para diferenciar las líneas.
- `fun`: función a aplicar para a `response` para cada combinación de `x.factor` y `trace.factor`.
- `legend`: valor lógico para incluir o no leyenda.
- `trace.label`: nombre a colocar en la leyenda.
La función `interaction.plot` tiene otros parámetros adicionales que el lector puede consultar en la ayuda usando `help(interaction.plot)`.
### Ejemplo {-}
Se realizó un experimento para determinar cómo influye el material de la batería y la temperatura del medio ambiente sobre la duración en horas de la batería. Se desea construir un gráfico de interacción entre Temperatura y Material para ver el efecto sobre la duración promedio de las baterías. Los datos y el código para generar el gráfico solicitado se muestran a continuación.
```{r intplot1, fig.cap='Gráfico de interacción entre Temperatura y Material sobre la duración promedio de las baterías.', fig.height=5, fig.width=7}
horas <- c(130, 155, 74, 180, 150, 188, 159, 126, 138, 110, 168,
160, 34, 40, 80, 75, 136, 122, 106, 115, 174, 120, 150,
139, 20, 70, 82, 58, 25, 70, 58, 45, 96, 104, 82, 60)
temperatura <- rep(c(15, 70, 125), each=12)
material <- rep(1:3, each=4, times=3)
interaction.plot(x.factor=temperatura, trace.factor=material,
response=horas, trace.label='Material',
xlab='Temperatura',
ylab='Duración promedio (horas)',
col=c('dodgerblue3', 'chartreuse4', 'salmon3'),
fun=mean, lwd=2, las=1, fixed=T)
```
## Gráfico de espagueti
Los gráficos de espagueti son usados para representar la evolución de una variable medida para un grupo de sujetos en diferentes momentos del tiempo. La función `interaction.plot` se puede usar para obtener este tipo de gráficos, a continuación un ejemplo.
### Ejemplo {-}
El ejemplo aquí presentado fue tomado de este [enlace](http://stats.idre.ucla.edu/r/faq/how-can-i-make-spaghetti-plots/). El objetivo es crear un gráfico de espagueti para mostrar la evolución de la variable tolerancia a través del tiempo para cada uno de los 16 individuos estudiados. El código para descargar la base de datos y construir el gráfico se muestran a continuación.
```{r intplot2, fig.cap='Gráfico de espagueti para ver la evolución de la variable tolerancia.', fig.height=5, fig.width=7, message=FALSE}
dt <- read.table("https://stats.idre.ucla.edu/stat/r/faq/tolpp.csv",
sep=",", header=T)
require(gplots) # Paquete especial para crear una paleta
palette(rich.colors(16)) # de 16 colores diferentes y suaves
interaction.plot(response=dt$tolerance,
x.factor=dt$time, col=1:16, lwd=2,
trace.factor=dt$id, las=1, lty=1,
xlab="Tiempo", ylab="Tolerancia", legend=F)
```