library(pacman)
p_load(dplyr, ggplot2, datos)
El presente documento contiene el solucionario a los ejercicios 5.5.2 del libro de R for Data Science de Hadley Wickham y Garrett Grolemund en su versión en español.
Este documento se realiza con fines académicos para el curso de Técnicas de Exploración de Datos de la carrera de Estadística e Informática de la Universidad Nacional Agraria La Molina de Lima, Perú.
Estos ejercicios corresponden al tema de Funciones de creación útiles.
Hay muchas funciones para crear nuevas variables que puedes usar con
mutate(). La propiedad clave es que la función debe ser
vectorizada: debe tomar un vector de valores como input, y devolver un
vector con el mismo número de valores como output. No hay forma de
enumerar todas las posibles funciones que podrías usar, pero aquí hay
una selección de funciones que frecuentemente son útiles:
Operadores aritméticos: +, -,
*,/,^. Todos están vectorizados
usando las llamadas “reglas de reciclaje”. Si un parámetro es más corto
que el otro, se extenderá automáticamente para tener la misma longitud.
Esto es muy útil cuando uno de los argumentos es un solo número:
tiempo_vuelo / 60, horas * 60 + minuto, etc.
Los operadores aritméticos también son útiles junto con las funciones
de agregar que aprenderás más adelante. Por ejemplo,
x / sum(x) calcula la proporción de un total, y
y - mean(y) calcula la diferencia de la media.
Aritmética modular: %/% (división entera) y
%% (resto), donde
x == y * (x %/% y) + (x %% y). La aritmética modular es una
herramienta útil porque te permite dividir enteros en partes. Por
ejemplo, en el conjunto de datos de vuelos, puedes calcular
hora y minutos de horario_salida
con:
transmute(vuelos,
horario_salida,
hora = horario_salida %/% 100,
minuto = horario_salida %% 100
)
## # A tibble: 336,776 × 3
## horario_salida hora minuto
## <int> <dbl> <dbl>
## 1 517 5 17
## 2 533 5 33
## 3 542 5 42
## 4 544 5 44
## 5 554 5 54
## 6 554 5 54
## 7 555 5 55
## 8 557 5 57
## 9 557 5 57
## 10 558 5 58
## # ℹ 336,766 more rows
Logaritmos: log(), log2(),
log10(). Los logaritmos son increíblemente útiles como
transformación para trabajar con datos con múltiples órdenes de
magnitud. También convierten las relaciones multiplicativas en aditivas,
una característica que retomaremos en los capítulos sobre modelos.
En igualdad de condiciones, recomendamos usar log2()
porque es más fácil de interpretar: una diferencia de 1 en la escala de
registro corresponde a la duplicación de la escala original y una
diferencia de -1 corresponde a dividir a la mitad.
Rezagos: lead() y lag() te permiten
referirte a un valor adelante o un valor atrás (con rezago). Esto te
permite calcular las diferencias móviles (por ejemplo,
x - lag(x)) o encontrar cuándo cambian los valores
(x! = lag (x)). Estos comandos son más útiles cuando se
utilizan junto con group_by(), algo que aprenderás en
breve.
(x <- 1:10)
## [1] 1 2 3 4 5 6 7 8 9 10
lag(x)
## [1] NA 1 2 3 4 5 6 7 8 9
lead(x)
## [1] 2 3 4 5 6 7 8 9 10 NA
cumsum(),
cumprod(), cummin(), cummax();
dplyr, por su parte, proporciona cummean()
para las medias acumuladas. Si necesitas calcular agregados móviles (es
decir, una suma calculada en una ventana móvil), prueba el paquete
RcppRoll.x
## [1] 1 2 3 4 5 6 7 8 9 10
cumsum(x)
## [1] 1 3 6 10 15 21 28 36 45 55
cummean(x)
## [1] 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5
Comparaciones lógicas: <, <=,
>, >=, != sobre las cuales
aprendiste antes. Si estás haciendo una secuencia compleja de
operaciones lógicas, es a menudo una buena idea almacenar los valores
provisionales en nuevas variables para que puedas comprobar que cada
paso funciona como se espera.
Ordenamiento: hay una serie de funciones de ordenamiento
(ranking), pero deberías comenzar con min_rank(). Esta
función realiza el tipo más común de ordenamiento (por ejemplo, primero,
segundo, tercero, etc.). El valor predeterminado otorga la menor
posición a los valores más pequeños; usa desc(x) para dar
la menor posición a los valores más grandes.
y <- c (1, 2, 2, NA, 3, 4)
min_rank(y)
## [1] 1 2 2 NA 4 5
min_rank(desc(y))
## [1] 5 3 3 NA 2 1
Si min_rank() no hace lo que necesitas, consulta las
variantes row_number(), dense_rank(),
percent_rank(), cume_dist(),
quantile(). Revisa sus páginas de ayuda para más
detalles.
row_number(y)
## [1] 1 2 3 NA 4 5
dense_rank(y)
## [1] 1 2 2 NA 3 4
percent_rank(y)
## [1] 0.00 0.25 0.25 NA 0.75 1.00
cume_dist(y)
## [1] 0.2 0.6 0.6 NA 0.8 1.0
Las variables horario_salida y
salida_programada tienen un formato conveniente para leer,
pero es difícil realizar cualquier cálculo con ellas porque no son
realmente números continuos. Transfórmalas hacia un formato más
conveniente como número de minutos desde la medianoche.
vuelos |> mutate(min_horario_salida= (horario_salida %/% 100 * 60 + horario_salida %% 100),
min_salida_programada= (salida_programada %/% 100 * 60 + salida_programada %% 100)) -> vuelos
vuelos |> select(horario_salida, min_horario_salida,salida_programada, min_salida_programada)
## # A tibble: 336,776 × 4
## horario_salida min_horario_salida salida_programada min_salida_programada
## <int> <dbl> <int> <dbl>
## 1 517 317 515 315
## 2 533 333 529 329
## 3 542 342 540 340
## 4 544 344 545 345
## 5 554 354 600 360
## 6 554 354 558 358
## 7 555 355 600 360
## 8 557 357 600 360
## 9 557 357 600 360
## 10 558 358 600 360
## # ℹ 336,766 more rows
Compara tiempo_vuelo con
horario_llegada - horario_salida. ¿Qué esperas ver? ¿Qué
ves? ¿Qué necesitas hacer para arreglarlo?
Lo que se espera ver es que tiempo_vuelo =
horario_llegada - horario_salida. Entonces, se crea la
variable llegada_salida =
horario_llegada - horario_salida y se compara la diferencia
entre tiempo_vuelo y llegada_salida.
vuelos |> group_by(tiempo_vuelo) |> reframe(llegada_salida= horario_llegada - horario_salida,
diferencia1 = llegada_salida - tiempo_vuelo)
## # A tibble: 336,776 × 3
## tiempo_vuelo llegada_salida diferencia1
## <dbl> <int> <dbl>
## 1 20 87 67
## 2 20 85 65
## 3 21 99 78
## 4 21 94 73
## 5 21 39 18
## 6 21 88 67
## 7 21 97 76
## 8 21 105 84
## 9 21 77 56
## 10 21 79 58
## # ℹ 336,766 more rows
En tabla anterior se puede observar fácilmente que los valores de
tiempo_vuelo y la resta de
horario_llegada - horario_salida son diferentes. Esto se
debe a que se deben transformar los datos a minutos.
vuelos |> mutate(min_horario_llegada= (horario_llegada %/% 100 * 60 + horario_llegada %% 100) ) -> vuelos
vuelos |> group_by(tiempo_vuelo) |> reframe(min_llegada_salida = min_horario_llegada - min_horario_salida,
diferencia2 = min_llegada_salida - tiempo_vuelo)
## # A tibble: 336,776 × 3
## tiempo_vuelo min_llegada_salida diferencia2
## <dbl> <dbl> <dbl>
## 1 20 47 27
## 2 20 45 25
## 3 21 59 38
## 4 21 54 33
## 5 21 39 18
## 6 21 48 27
## 7 21 57 36
## 8 21 65 44
## 9 21 37 16
## 10 21 39 18
## # ℹ 336,766 more rows
A pesar de que se transformó el horario de llegada a minutos, se
observa que al realizar la resta entre el horario de llegada
(min_horario_llegada) y el horario de salida
(min_horario_salida), los valores resultantes no son
iguales a los de tiempo_vuelo. Esto puede deberse a un
error al registrar los datos.
Compara horario_salida, salida_programada,
y atraso_salida. ¿Cómo esperarías que esos tres números
estén relacionados?
vuelos |> select(horario_salida, salida_programada, atraso_salida)
## # A tibble: 336,776 × 3
## horario_salida salida_programada atraso_salida
## <int> <int> <dbl>
## 1 517 515 2
## 2 533 529 4
## 3 542 540 2
## 4 544 545 -1
## 5 554 600 -6
## 6 554 558 -4
## 7 555 600 -5
## 8 557 600 -3
## 9 557 600 -3
## 10 558 600 -2
## # ℹ 336,766 more rows
La relación entre las variables es: atraso_salida =
horario_salida - salida_programada
vuelos |> mutate(diferencia_salida= min_horario_salida - min_salida_programada) -> vuelos
table(vuelos$atraso_salida == vuelos$diferencia_salida)
##
## FALSE TRUE
## 1207 327314
(vuelos |> filter(diferencia_salida != atraso_salida)|>
select(horario_salida, salida_programada, atraso_salida,
diferencia_salida, min_horario_salida, min_salida_programada) -> P3)
## # A tibble: 1,207 × 6
## horario_salida salida_programada atraso_salida diferencia_salida
## <int> <int> <dbl> <dbl>
## 1 848 1835 853 -587
## 2 42 2359 43 -1397
## 3 126 2250 156 -1284
## 4 32 2359 33 -1407
## 5 50 2145 185 -1255
## 6 235 2359 156 -1284
## 7 25 2359 26 -1414
## 8 106 2245 141 -1299
## 9 14 2359 15 -1425
## 10 37 2230 127 -1313
## # ℹ 1,197 more rows
## # ℹ 2 more variables: min_horario_salida <dbl>, min_salida_programada <dbl>
Se observa que la relación atraso_salida =
horario_salida - salida_programada se cumple cuando se han
transformado las dos últimas variables a minutos. Sin embargo, existen
algunas excepciones que se generan cuando la hora de salida programada
es anterior a las 00:00 y la hora de salida se da al día siguiente, es
entonces que al realizar la resta no se obtiene el resultado adecuado.
Esto se debe a que no se tiene en cuenta el cambio de día, lo que
produce resultados diferentes a los de atraso_salida.
Encuentra los 10 vuelos más retrasados utilizando una función de
ordenamiento. ¿Cómo quieres manejar los empates? Lee atentamente la
documentación de min_rank().
vuelos |> mutate(atraso_min_rank = min_rank(desc(atraso_salida)),
atraso_row_number = row_number(desc(atraso_salida)),
atraso_dense_rank = dense_rank(desc(atraso_salida))) -> P4
P4 |> filter(atraso_min_rank <= 10 & atraso_row_number <= 10 & atraso_dense_rank <= 10) -> P4
P4 |> arrange(atraso_min_rank) -> P4
P4
## # A tibble: 10 × 26
## anio mes dia horario_salida salida_programada atraso_salida
## <int> <int> <int> <int> <int> <dbl>
## 1 2013 1 9 641 900 1301
## 2 2013 6 15 1432 1935 1137
## 3 2013 1 10 1121 1635 1126
## 4 2013 9 20 1139 1845 1014
## 5 2013 7 22 845 1600 1005
## 6 2013 4 10 1100 1900 960
## 7 2013 3 17 2321 810 911
## 8 2013 6 27 959 1900 899
## 9 2013 7 22 2257 759 898
## 10 2013 12 5 756 1700 896
## # ℹ 20 more variables: horario_llegada <int>, llegada_programada <int>,
## # atraso_llegada <dbl>, aerolinea <chr>, vuelo <int>, codigo_cola <chr>,
## # origen <chr>, destino <chr>, tiempo_vuelo <dbl>, distancia <dbl>,
## # hora <dbl>, minuto <dbl>, fecha_hora <dttm>, min_horario_salida <dbl>,
## # min_salida_programada <dbl>, min_horario_llegada <dbl>,
## # diferencia_salida <dbl>, atraso_min_rank <int>, atraso_row_number <int>,
## # atraso_dense_rank <int>
Los empates se manejan utilizando las funciones:
min_rank, row_number y dense_rank
conjuntamente.
¿Qué devuelve 1:3 + 1:10? ¿Por qué?
1:3 + 1:10
## [1] 2 4 6 5 7 9 8 10 12 11
Devuelve la suma de los números del 1 al 3 y los números del 1 al 10, sumando los tres valores (1,2,3) repetidamente a los valores respectivos del (1:10). Esto se da debido a que la longitud de ambos vectores es desigual.
¿Qué funciones trigonométricas proporciona R?
x <- (pi/2)
cos(x)
## [1] 6.123032e-17
sin(x)
## [1] 1
tan(x)
## [1] 1.633124e+16
acos(4/5)
## [1] 0.6435011
asin(3/5)
## [1] 0.6435011
atan(1)
## [1] 0.7853982
atan2(1, 0.5)
## [1] 1.107149
cospi(pi)
## [1] -0.9026854
sinpi(pi)
## [1] -0.4303012
tanpi(pi)
## [1] 0.4766901
Todas las funciones trigonométricas anteriormente mostradas se pueden
hallar con el codigo ?Trig.