Saltar al contenido

Bucle sobre variables en ggplot

Esta es la contestación más acertada que encomtrarás brindar, pero primero estúdiala detenidamente y analiza si se adapta a tu proyecto.

Solución:

Solo necesitas usar aes_string en vez de aescomo esto:

ggplot(data=t, aes_string(x = "w", y = i)) + geom_line() 

Tenga en cuenta que w entonces debe especificarse como stringtambién.

ggplot2 v3.0.0 lanzado en julio de 2018 admite una evaluación ordenada como !! (bang bang) dentro aes(). Entonces podemos hacer lo siguiente:

  • Cree una función que tome los nombres de las columnas x e y como entradas. Nótese el uso de rlang::sym & !!.

  • Luego recorra cada columna usando purrr::map.

library(rlang)
library(tidyverse)

dt <- data.frame(
  w = c(1, 2, 3, 4), x = c(23, 45, 23, 34),
  y = c(23, 34, 54, 23), z = c(23, 12, 54, 32)
)

Definir una función que acepte cadenas como entrada

plot_for_loop <- function(df, .x_var, .y_var) 

  # convert strings to variable
  x_var <- sym(.x_var)
  y_var <- sym(.y_var)

  # unquote variables using !! 
  ggplot(df, aes(x = !! x_var, y = !! y_var)) + 
    geom_point() + 
    geom_line() +
    labs(x = x_var, y = y_var) +
    theme_classic(base_size = 12)

Bucle a través de cada columna

plot_list <- colnames(dt)[-1] %>% 
  map( ~ plot_for_loop(dt, colnames(dt)[1], .x))

# view all plots individually (not shown)
plot_list

# Combine all plots
library(cowplot)
plot_grid(plotlist = plot_list,
          ncol = 3)

Editar: la función anterior también se puede escribir sin sym y !! usando .data[[]] pronombre

plot_for_loop2 <- function(df, x_var, y_var) 

  ggplot(df, aes(x = .data[[x_var]], y = .data[[y_var]])) + 
    geom_point() + 
    geom_line() +
    labs(x = x_var, y = y_var) +
    theme_classic(base_size = 12)

O simplemente podemos usar facet_grid/facet_wrap después de convertir el marco de datos de formato ancho a largo (tidyr::gather)

dt_long <- dt %>% 
  tidyr::gather(key, value, -w)
dt_long
#>    w key value
#> 1  1   x    23
#> 2  2   x    45
#> 3  3   x    23
#> 4  4   x    34
#> 5  1   y    23
#> 6  2   y    34
#> 7  3   y    54
#> 8  4   y    23
#> 9  1   z    23
#> 10 2   z    12
#> 11 3   z    54
#> 12 4   z    32

### facet_grid
ggp1 <- ggplot(dt_long, 
       aes(x = w, y = value, color = key, group = key)) +
  facet_grid(. ~ key, scales = "free", space = "free") +
  geom_point() + 
  geom_line() +
  theme_bw(base_size = 14)
ggp1

### facet_wrap
ggp2 <- ggplot(dt_long, 
       aes(x = w, y = value, color = key, group = key)) +
  facet_wrap(. ~ key, nrow = 2, ncol = 2) +
  geom_point() + 
  geom_line() +
  theme_bw(base_size = 14)
ggp2

### bonus: reposition legend
# https://cran.r-project.org/web/packages/lemon/vignettes/legends.html
library(lemon)
reposition_legend(ggp2 + theme(legend.direction = 'horizontal'), 
                  'center', panel = 'panel-2-2')

El problema es cómo accedes al marco de datos. t. Como probablemente sepa, hay varias formas de hacerlo, pero desafortunadamente usar un personaje obviamente no es una de ellas en ggplot.

Una forma que podría funcionar es usar la posición numérica de la columna en su ejemplo, por ejemplo, podría intentar i <- 2. Sin embargo, si esto funciona, se basa en ggplot, que nunca he usado (pero conozco otros trabajos de Hadley y supongo que debería funcionar)

Otra forma de eludir esto es creando un nuevo marco de datos temporal cada vez que llama a ggplot. p.ej:

tmp <- data.frame(a = t[['w']], b = t[[i]])
ggplot(data=tmp, aes(a, b)) + geom_line()

Si te ha resultado provechoso este artículo, sería de mucha ayuda si lo compartieras con el resto juniors y nos ayudes a extender nuestro contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *