Crear funciones para reducir líneas de código
Descubre cómo utilizar funciones para simplificar y optimizar tu código, ahorrando tiempo y reduciendo la complejidad.
A medida que voy mejorando mis habilidades de programación, voy enfrentándome a nuevos desafíos. Mi postura en cualquier área que tenga que ver con aprender algo es siempre la misma: concentrémonos primero en el panorama general, después habrá tiempo para precisar detalles.
Y uno de esos “detalles” en los que nunca profundicé fue la creación de funciones. Es decir, sé que se puede hacer, hice algunos ejercicios en algunos tutoriales, pero siempre fueron funciones muy básicas como “calcular la media de un número” o convertir temperaturas Celsius a Fahrenheit y etc. Siempre me dije “vamos a dejar este tema para más adelante”, y creo que ese más adelante ya llegó.
Me di cuenta de eso porque cada vez que leía o escuchaba la idea de que hacer nuestras propias funciones nos evita reproducir un mismo código muchas veces, me acordaba de este post donde para crear cada uno de los gráficos repetí el mismo código 23 veces (pésima idea, lo sé). Así que hoy llegó el día: acompáñenme a entender cómo hacer mi propia función.
La lógica de las funciones
Lo primero que tenemos que tener en cuenta es que una función es una operación que se va a ejecutar sobre uno o más elementos, con una serie de especificaciones que funcionan como parámetros. Todo esto se incorpora a la función en forma de argumentos.
En este caso, el código que se repite 23 veces es el siguiente:
##
## Downloading file 1 of 2: `drought.csv`
## Downloading file 2 of 2: `drought-fips.csv`
# 2000
a2000 <- county.map.drought %>%
filter(date == "2000-01-04" & !STATE %in% c("02", "15")) %>%
ggplot(aes(long, lat, group=group)) +
geom_polygon(aes(fill = value))+
scale_fill_viridis_c(option = "plasma",
limits = c(0, 500))+
labs(title = "2000",
x = "", y = "")+
theme_void()+
theme(legend.position = "none",
plot.title = element_text(size = 12, hjust = 0.5,
family="Times"))
Básicamente es un código que toma un dataframe que es siempre el mismo (county.map.drought
), filtra por una fecha específica y luego grafica, especificando el título de cada fecha. Por lo tanto, la función solo necesita tomar como argumento el valor de la fecha que se quiere graficar; a partir de ese valor podemos segmentarlo para luego utilizar el valor del año como título del gráfico.
drought_graph <- function(date){
titulo <- str_sub(fecha, end = 4)
county.map.drought %>%
filter(date == fecha & !STATE %in% c("02", "15")) %>%
ggplot(aes(long, lat, group=group)) +
geom_polygon(aes(fill = value))+
scale_fill_viridis_c(option = "plasma",
limits = c(0, 500))+
labs(title = titulo,
x = "", y = "")+
theme_void()+
theme(legend.position = "none",
plot.title = element_text(size = 12, hjust = 0.5))
}
Para simplificar aún más, podemos crear un vector con las fechas específicas, una por cada año (en este caso, la primera medición de enero de cada año) y luego, con un for loop
, recorremos esas fechas para crear el gráfico correspondiente a cada año, lo almacenamos en una lista y finalmente agrupamos esos gráficos en uno solo (este paso ya estaba de esta misma forma en el post anterior).
fechas <- c("2000-01-04", "2001-01-02", "2002-01-01", "2003-01-07", "2004-01-06",
"2005-01-04", "2006-01-03", "2007-01-02", "2008-01-01", "2009-01-06",
"2010-01-05", "2011-01-04", "2012-01-03", "2013-01-01", "2014-01-07",
"2015-01-06", "2016-01-05", "2017-01-03", "2018-01-02", "2019-01-01",
"2020-01-07", "2021-01-05", "2022-01-04")
graficos <- list()
for (fecha in fechas){
graf <- drought_graph(fecha)
graficos[[fecha]] <- ggplotGrob(graf)
}
grid.arrange(grobs = graficos[c("2000-01-04", "2001-01-02", "2002-01-01", "2003-01-07", "2004-01-06",
"2005-01-04", "2006-01-03", "2007-01-02", "2008-01-01", "2009-01-06",
"2010-01-05", "2011-01-04", "2012-01-03", "2013-01-01", "2014-01-07",
"2015-01-06", "2016-01-05", "2017-01-03", "2018-01-02", "2019-01-01",
"2020-01-07", "2021-01-05", "2022-01-04")],
top = grid::textGrob("Índice de Gravedad y Alcance de la sequía (DSCI) \nmedido la primera semana de enero"),
nrow = 5, ncol = 6)
Hay muchas cosas que se pueden seguir mejorando en este código: por ejemplo, la función podría tomar solamente el año y segmentar automáticamente la cadena de fecha. Sin embargo, eso sorpresivamente me trajo muchos problemas: no solamente porque la primera medición no siempre se hizo en el mismo día de enero (que podría resolverse con row_number()
), sino porque los distintos tipos de agrupaciones que podrían realizarse para resolver eso afectan de formas que no termino de entender a los valores necesarios para realizar el gráfico espacial.
Más allá de eso, estoy bastante satisfecha con el resultado. Algo que no contemplé a la hora de comenzar este proyecto fue que los objetos, al contar con la información de 22 años de todos los estados de EEUU, eran muy, muy pesados, y cada cambio que tenía que realizar implicaba volver a levantar archivos de varios megas (ni hablar del objeto final con los 23 mapas). La próxima vez, voy a intentar jugar con tablas más pequeñas.
Como siempre, recordá que podés suscribirte a mi blog para no perderte ninguna actualización, y si te quedó alguna consulta no dudes en contactarme. Y, si te gusta lo que hago, podés invitarme un cafecito desde Argentina o un kofi.