#- pedro.j.perez@uv.es [revisado: 2025-27-05]
#- pequeño tutorial sobre loops y purrr. Basado en: https://www.mango-solutions.com/blog/to-purrr-or-not-to-purrr  que a su vez se basa en R4DS
library(tidyverse)

#- Let's talk about loops
# Motivación/Ejemplo: queremos obtener la media de las columnas(o variables) del dataset mtcars
# Hay varias formas de conseguir ese vector con las medias: a mano/ con loops/ apply/ dplyr/ purrrr

#- 1) The long repetitive way --------------------------------------------------
mtcars <- mtcars

mean_vec <- c(mean(mtcars$mpg), mean(mtcars$cyl), mean(mtcars$disp), mean(mtcars$hp),
              mean(mtcars$drat), mean(mtcars$wt), mean(mtcars$qsec), mean(mtcars$vs),
              mean(mtcars$am), mean(mtcars$gear), mean(mtcars$carb))
mean_vec

#- 2) con un for loop ----------------------------------------------------------
mean_vec_loop <- vector("double", ncol(mtcars)) #- primero creamos el vector para almacenar las medias

for (i in 1:ncol(mtcars)) {
  mean_vec_loop[[i]] <- mean(mtcars[[i]])
}

mean_vec_loop

#- MEJORA!!!: con un for loop es mejor hacer con hacerlo con seq_along() xq gestiona mejor casos especiales como p.ej. si ncol() fuese cero: https://campus.datacamp.com/courses/writing-functions-in-r/a-quick-refresher?ex=14#skiponboarding

mean_vec_loop <- vector("double", ncol(mtcars)) #- primero creamos el vector para almacenar las medias

for (i in seq_along(mtcars)) {
  print(i)
  mean_vec_loop[[i]] <- mean(mtcars[[i]])
}

mean_vec_loop

#- 3) con la familia de funciones *apply's -----------------------------------

#- con lapply()
mean_vec_apply <- lapply(mtcars, mean) %>% as.data.frame()   #- el output de lapply es una lista, la paso a df
mean_vec_apply
#- con sapply()
mean_vec_apply <- sapply(mtcars, mean) #- el output de sapply es un vector
mean_vec_apply

#- 4) con el pkg dplyr ---------------------------------------------------------
mean_vec_dplyr <- mtcars %>% summarise_all( mean )                    #- superseded
mean_vec_dplyr
#- con la nueva sintaxis
mean_vec_dplyr <- mtcars %>% summarise(across(everything(), mean) )   #- new sintax
mean_vec_dplyr
#- lo pasamos a vectores
mean_vec_dplyr2 <- mean_vec_dplyr %>% slice(1) %>% as.numeric()
mean_vec_dplyr3 <- mean_vec_dplyr[1,] %>%  as.numeric()


#- 5) con purrr ----------------------------------------------------------------
mean_vec_purrr <- mtcars %>% map(mean) %>% as.data.frame()

mean_vec_purrr <- mtcars %>% map_dbl(mean)                   #- map_dbl() lo pasa directamente a vector numerico)

#- BONUS -----------------------------------------------------------------------
#- BONUS: crear una funcion que nos permita seleccionar q. dataframe y q función queremos usar:

# Create a function that returns a computational value (such as mean or variance)
# for a given dataset

my_fun <- function(df, fun) {
  output <- vector("double", length(df))
  for (i in seq_along(df)) {
    output[[i]] <- fun(df[[i]])
  }
  output
}
my_fun(mtcars, mean)
my_fun(mtcars, var)

#- aunque la verdad, ya que nos ponemos lo hacemos con purr
my_fun.2 <- function(df,fun) {
  output <- map(df, fun) %>% as.data.frame()
  output
}

my_fun.2(mtcars, mean)
my_fun.2(mtcars, var)

#- que en realidad no nos hacia falta xq eso es justo lo que hace purrrr::map() , aplicar una función a los elementos de una lista
mtcars %>% map_dbl(var)



