-
Notifications
You must be signed in to change notification settings - Fork 12
/
25-model-many.Rmd
221 lines (173 loc) · 5.7 KB
/
25-model-many.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
# Muchos modelos
```{r, include=FALSE}
library(dplyr)
library(tidyr)
library(purrr)
library(modelr)
library(ggplot2)
library(ggbeeswarm)
library(stringr)
library(datos)
```
## 25.2 gapminder{-#gapminder}
### 25.2.5 Ejercicios{-#ejercicios-2525}
1. Una tendencia lineal parece ser demasiado simple para la tendencia general.
¿Puedes hacerlo mejor con un polinomio cuadrático? ¿Cómo puedes interpretar
el coeficiente del término cuadrático? (Pista: puedes querer transformar
`year` para que tenga media cero.)
<div class="solucion">
<h3>Solución</h3>
El siguiente código replica el análisis que se hizo en el libro pero cambia l
función `modelo_pais()` para incluir una regresión que incluye el año al
cuadrado.
```{r}
modelo_pais_2 <- function(df) {
lm(esperanza_de_vida ~ poly(anio - median(anio), 2), data = df)
}
por_pais <- paises %>%
group_by(pais, continente) %>%
nest()
por_pais <- por_pais %>%
mutate(modelo = map(data, modelo_pais_2))
```
```{r}
por_pais <- por_pais %>%
mutate(
residuo = map2(data, modelo, add_residuals)
)
por_pais
```
```{r}
unnest(por_pais, residuo) %>%
ggplot(aes(anio, resid)) +
geom_line(aes(group = pais), alpha = 1 / 3) +
geom_smooth(se = FALSE)
```
```{r}
por_pais %>%
mutate(estadistica = map(modelo, broom::glance)) %>%
unnest(estadistica, .drop = TRUE) %>%
ggplot(aes(continente, r.squared)) +
geom_jitter(width = 0.5)
```
</div>
2. Explora otros métodos para visualizar la distribución del $R^2$ por
continente. Puedes querer probar el paquete __ggbeeswarm__, que provee
métodos similares para evitar superposiciones como jitter, pero usa métodos
determinísticos.
<div class="solucion">
<h3>Solución</h3>
El paquete `gbeeswarm` se usó en el capítulo de análisis exploratorio.
```{r}
por_pais %>%
mutate(estadistica = map(modelo, broom::glance)) %>%
unnest(estadistica, .drop = TRUE) %>%
ggplot(aes(continente, r.squared)) +
geom_beeswarm()
```
</div>
3. Para crear el último gráfico (mostrando los datos para los países con los
peores ajustes del modelo), precisamos dos pasos: creamos un _data frame_ con
una fila por país y después hicimos un _semi-join_ (del inglés _semi juntar_) (TODO: deberíamos aclarar algo?) al conjunto de datos original.
Es posible evitar este _join_ si usamos `unnest()` en lugar de
`unnest(.drop = TRUE)`. ¿Cómo?
<div class="solucion">
<h3>Solución</h3>
```{r}
paises %>%
group_by(pais, continente) %>%
nest() %>%
mutate(modelo = map(data, ~lm(esperanza_de_vida ~ anio, .))) %>%
mutate(estadistica = map(modelo, broom::glance)) %>%
unnest(estadistica) %>%
unnest(data) %>%
filter(r.squared < 0.25) %>%
ggplot(aes(anio, esperanza_de_vida)) +
geom_line(aes(color = pais))
```
</div>
## 25.4 Creando columnas-lista{-#columnas-lista}
### 25.4.5 Ejercicios{-#ejercicios-2545}
1. Lista todas las funciones en las que puedas pensar que tomen como _input_ un vector atómico y
retornen una lista.
<div class="solucion">
<h3>Solución</h3>
Muchas funciones del paquete `stringr` cumplen con el criterio.
```{r}
str_split(sentences[1:3], " ")
str_match_all(c("paul", "john", "george", "ringo"), "a+")
```
En el caso del paquete `purrr`, la función `map()` también cumple el criterio.
```{r}
map(1:3, runif)
```
</div>
2. Piensa en funciones de resumen útiles que, como `quantile()`, retornen
múltiples valores.
<div class="solucion">
<h3>Solución</h3>
Algunos ejemplos de funciones básicas de R que cumplen con el criterio.
```{r}
range(mtcars$mpg)
fivenum(mtcars$mpg)
boxplot.stats(mtcars$mpg)
```
</div>
3. ¿Qué es lo que falta en el siguiente _data frame_? ¿Cómo `quantile()` retorna
eso que falta? ¿Por qué eso no es tan útil aquí?
```{r}
mtautos %>%
group_by(cilindros) %>%
summarise(q = list(quantile(millas))) %>%
unnest()
```
<div class="solucion">
<h3>Solución</h3>
No se muestran los cuartiles correspondientes. Esto se debe a que la función
`quantile()` entrega los valores `0%`, `25%`, `50%`, `75%`, `100%` como nombres
del vector resultante y `unnest()` descarta los nombres del vector.
```{r}
quantile(mtcars$mpg)
```
</div>
4. ¿Qué hace este código? ¿Por qué podría ser útil?
```{r, eval = FALSE}
mtautos %>%
group_by(cilindros) %>%
summarise_each(funs(list))
```
<div class="solucion">
<h3>Solución</h3>
Crea un cuadro de datos en el que cada fila corresponde a un valor unico de
`cilindros` y cada observación fuera de la primera columna es un vector.
La utilidad es que reune las observaciones para cada variable y las agrupa,
lo que puede simplificar algunos análisis particulares en los que se quiera
analizar todas las observaciones agrupando por número de cilindros.
</div>
## 25.5 Simplificando columnas-lista{-#simplificando}
### 25.5.3 Ejercicios{-#ejercicios-2553}
1. ¿Por qué podría ser útil la función `lengths()` para crear columnas de
vectores atómicos a partir de columnas-lista?
<div class="solucion">
<h3>Solución</h3>
La función `lengths()` entreg el largo de cada elemento en una lista.
Proporciona un atajo a `map_int(x, length)` y `sapply(x, length)`.
Es útil para verificar si acaso los elementos de una columna de tipo lista son
todos del mismo largo. Otra posibilidad es calcular el máximo largo dentro de
la columna y así sabremos cuántas columnas debo crear para transformar en varias
columnas atómicas.
</div>
2. Lista los tipos de vectores más comúnes que se encuentran en un _data frame_.
¿Qué hace que las
listas sean diferentes?
<div class="solucion">
<h3>Solución</h3>
Los tipos más comunes de vectores en un cuadro de datos son:
- `logical`
- `numeric`
- `integer`
- `character`
- `factor`
Todos estos tipos son atómicos. Las listas no son atómicas ya que pueden
contener otras listas o vectores.
</div>