R语言 在ggplot中循环变量

gzszwxb4  于 2023-05-26  发布在  其他
关注(0)|答案(5)|浏览(148)

我想使用ggplot循环几列来创建多个图,但是在for循环中使用占位符会改变ggplot的行为。
如果我有这个:

t <- 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))

这工作得很好:

ggplot(data=t, aes(w, x)) + geom_line()

但这并不:

i <- 'x'
ggplot(data=t, aes(w, i)) + geom_line()

这是一个问题,如果我想最终循环x,y和z。有什么帮助吗?

gcxthw6b

gcxthw6b1#

你只需要使用aes_string而不是aes,就像这样:

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

请注意,w也需要指定为字符串。

mjqavswn

mjqavswn2#

ggplot2 > 3.0.0支持整洁的求值代词.data。我们可以这样做:

  • 构建一个函数,将x- & y-列名作为输入。注意.data[[]]的使用。
  • 然后使用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)
)

定义一个接受字符串作为输入的函数

plot_for_loop <- 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)
}

循环遍历每列

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)

编辑:上述函数也可以写成w/rlang::sym & !!(bang bang)。

plot_for_loop2 <- 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)
}

或者,我们可以在将 Dataframe 从宽格式转换为长格式(tidyr::gather)后使用facet_grid / facet_wrap

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')

qfe3c7zg

qfe3c7zg3#

问题是如何访问 Dataframe t。您可能知道,有几种方法可以做到这一点,但不幸的是,在ggplot中使用字符显然不是其中之一。
一种可行的方法是在示例中使用列的数字位置,例如,您可以尝试i <- 2。然而,如果这个作品依赖于我从未使用过的ggplot(但我知道哈德利的其他作品,我猜它应该会起作用)
另一种方法是在每次调用ggplot时创建一个新的临时 Dataframe 。例如:

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

8fsztsew4#

根据您尝试做的事情,我发现facet_wrapfacet_grid可以很好地创建具有相同基本结构的多个图。像这样的东西应该让你在正确的球场:

t.m = melt(t, id="w")
ggplot(t.m, aes(w, value)) + facet_wrap(~ variable) + geom_line()
tyg4sfes

tyg4sfes5#

aes_string()在ggplot 2> 3.0.0中被弃用,但可以使用.data。这个答案的灵感来自Matt和Tung的答案。
ggplot(data=t, aes(x = w, y = .data[[i]])) + geom_line()

相关问题