我想使用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,那么这是一个问题。 有什么帮助吗?
答案 0 :(得分:36)
您只需使用aes_string
代替aes
,就像这样:
ggplot(data=t, aes_string(x = "w", y = i)) + geom_line()
请注意,w
也需要指定为字符串。
答案 1 :(得分:6)
ggplot2 v3.0.0
支持整洁的评估,例如undefined
内部的!!
(爆炸)。因此,我们可以执行以下操作:
构建一个将x-和y-列名称作为输入的函数。请注意使用aes()
和rlang::sym
。
然后使用!!
遍历每一列。
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) {
# 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)
}
编辑:上述功能也可以不使用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)
和sym
!!
或者在将数据帧从宽格式转换为长格式(facet_grid
/facet_wrap
)之后,我们可以只使用tidyr::gather
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)
}
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
答案 2 :(得分:2)
问题是如何访问数据框t
。您可能知道,有几种方法可以这样做但不幸的是,在ggplot
中使用角色显然不是其中之一。
可行的一种方法是使用示例中列的数字位置,例如,您可以尝试i <- 2
。但是,如果这个作品依赖于我从未使用的ggplot(但我知道Hadley的其他作品,我想它应该有用)
绕过这种情况的另一种方法是每次调用ggplot时创建一个新的临时数据帧。 e.g:
tmp <- data.frame(a = t[['w']], b = t[[i]])
ggplot(data=tmp, aes(a, b)) + geom_line()
答案 3 :(得分:0)
根据您要执行的操作,我发现facet_wrap
或facet_grid
可以很好地创建具有相同基本结构的多个绘图。这样的事情可以让你进入正确的球场:
t.m = melt(t, id="w")
ggplot(t.m, aes(w, value)) + facet_wrap(~ variable) + geom_line()