循环遍历ggplot中的变量

发布于 2024-10-15 02:33:43 字数 421 浏览 5 评论 0原文

我想使用 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,这就是一个问题。 有什么帮助吗?

I want to use ggplot to loop over several columns to create multiple plots, but using the placeholder in the for loop changes the behavior of ggplot.

If I have this:

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

This works fine:

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

But this does not:

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

Which is a problem if I want to eventually loop over x, y and z.
Any help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

呢古 2024-10-22 02:33:43

您只需使用 aes_string 而不是 aes,如下所示:

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

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

You just need to use aes_string instead of aes, like this:

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

Note that w then needs to be specified as a string, too.

静赏你的温柔 2024-10-22 02:33:43

ggplot2 > 3.0.0 支持整洁的评估代词 。数据。因此我们可以执行以下操作:

  • 构建一个采用 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 & !!(砰砰)。

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

或者我们可以使用 facet_grid/facet_wrap< /a> 将数据帧从宽格式转换为长格式后 (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')

ggplot2 > 3.0.0 supports tidy evaluation pronoun .data. So we can do the following:

  • Build a function that takes x- & y- column names as inputs. Note the use of .data[[]].

  • Then loop through every column using 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)
)

Define a function that accept strings as input

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

Loop through every column

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)

Edit: the above function can also be written 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)
}

Or we can just use facet_grid/facet_wrap after convert the data frame from wide to long format (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')

风吹过旳痕迹 2024-10-22 02:33:43

问题在于如何访问数据框t。您可能知道,有多种方法可以做到这一点,但不幸的是,使用字符显然不是 ggplot 中的其中一种。

一种可行的方法是使用示例中列的数字位置,例如,您可以尝试 i <- 2。然而,如果这个工作依赖于我从未使用过的 ggplot(但我知道 Hadley 的其他工作,我想它应该可以工作),

另一种规避方法是在每次调用 ggplot 时创建一个新的临时数据框。例如:

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

The problem is how you access the data frame t. As you probably know, there are several ways of doing so but unfortunately using a character is obviously not one of them in ggplot.

One way that could work is using the numerical position of the column in your example, e.g., you could try i <- 2. However, if this works rests on ggplot which I have never used (but I know other work by Hadley and I guess it should work)

Another way of circumventing this is by creating a new temporary data frame every time you call ggplot. e.g.:

tmp <- data.frame(a = t[['w']], b = t[[i]])
ggplot(data=tmp, aes(a, b)) + geom_line()
涙—继续流 2024-10-22 02:33:43

aes_string() 在 ggplot2 中已弃用 > 3.0.0,但可以使用.data[[]]。这个答案的灵感来自于 Matt 和 Tung 的答案。

ggplot(data=t, aes(x = w, y = .data[[i]])) + geom_line()

aes_string() was deprecated in ggplot2 > 3.0.0 but .data[[]] can be used. This answer was inspired from the answers from Matt and Tung.

ggplot(data=t, aes(x = w, y = .data[[i]])) + geom_line()

且行且努力 2024-10-22 02:33:43

根据您想要执行的操作,我发现 facet_wrapfacet_grid 可以很好地创建具有相同基本结构的多个绘图。像这样的事情应该让你处于正确的位置:

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

Depending on what you are trying to do, I find facet_wrap or facet_grid to work well for creating multiple plots with the same basic structure. Something like this should get you in the right ballpark:

t.m = melt(t, id="w")
ggplot(t.m, aes(w, value)) + facet_wrap(~ variable) + geom_line()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文