Ответ 1
Вам просто нужно использовать aes_string
вместо aes
, например:
ggplot(data=t, aes_string(x = "w", y = i)) + geom_line()
Обратите внимание, что w
тогда также нужно указать как строку.
Я хочу использовать ggplot для перебора нескольких столбцов для создания нескольких графиков, но использование placeholder в цикле 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. Любая помощь?
Вам просто нужно использовать aes_string
вместо aes
, например:
ggplot(data=t, aes_string(x = "w", y = i)) + geom_line()
Обратите внимание, что w
тогда также нужно указать как строку.
ggplot2 v3.0.0
выпущенный в июле 2018 года, поддерживает аккуратную оценку, например !!
(взрыв) внутри aes()
. Таким образом, мы можем сделать следующее:
Создайте функцию, которая принимает имена столбцов x- и y- в качестве входных данных. Обратите внимание на использование rlang::sym
& !!
,
Затем purrr::map
каждый столбец с помощью 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
и !!
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)
}
Или мы можем просто использовать facet_grid
/facet_wrap
после преобразования кадра данных из широкоформатного формата в длинный ( 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')
Проблема заключается в доступе к фрейму данных t
. Как вы, наверное, знаете, существует несколько способов сделать это, но, к сожалению, использование символа, очевидно, не является одним из них в ggplot
.
Один из способов, который может работать, - использовать численное положение столбца в вашем примере, например, вы можете попробовать i <- 2
. Однако, если это работает на ggplot, который я никогда не использовал (но я знаю другую работу Хэдли, и я думаю, она должна работать)
Другим способом обхода этого является создание нового временного кадра данных каждый раз, когда вы вызываете ggplot. например:.
tmp <- data.frame(a = t[['w']], b = t[[i]])
ggplot(data=tmp, aes(a, b)) + geom_line()
В зависимости от того, что вы пытаетесь сделать, я нахожу facet_wrap
или facet_grid
, чтобы хорошо работать для создания нескольких графиков с одинаковой базовой структурой. Что-то вроде этого должно помочь вам в правильном шаге:
t.m = melt(t, id="w")
ggplot(t.m, aes(w, value)) + facet_wrap(~ variable) + geom_line()