#r #ggplot2
#r #ggplot2
Вопрос:
Я хочу создать матрицу диаграммы рассеяния, используя вложенные циклы for, ggplot2 и grid.arrange. Циклы повторяются по столбцам для создания различных подзаголовков. Это, очевидно, работает, потому что лаборатории подзаголовков различны для каждого участка. Однако ось графика и панель одинаковы для каждого подзаголовка. Теперь становится интересно: используемые столбцы относятся к случаю i = j = 4, который даже находится в другой ветви if-else .
Моей первой попыткой было принудительно выполнить глубокое копирование с помощью функции duplicate() rlang.
Единственный другой намек, который я нашел, состоял в том, чтобы явно использовать print() для отображения графика. смотрите: https://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-do-lattice_002ftrellis-graphics-not-work_003f
Ни один из вариантов ничего не изменил в конечном графике.
Удаление элемента if-else, чтобы всегда генерировать ветвь i<j, создает «тот же» график. Создание 16 графиков вручную (жестко запрограммированных, без циклов) приводит к желаемому поведению.
Пример кода:
library(tidyverse)
library(rlang)
library(egg)
#species is in last column
n = ncol(iris) - 1
plot_list = list()
for (i in 1:n) {
for (j in 1:n) {
#diagonal
if (i==j) {
new_plot = ggplot() annotate("text", x = 4, y = 25, size = 5, label = colnames(iris)[i]) theme_void()
}
#upper triangle
else if (i < j) {
#assign to new plot nested into a print(), doesn't help
new_plot = print(
ggplot()
geom_point(aes(x = iris[,j], y = iris[,i], colour=iris[,5]), shape=18, size=3.5)
labs(x = colnames(iris)[j], y = colnames(iris)[i])
theme_light()
theme(legend.position="none")
)
}
#lower triangle
else {
new_plot = ggplot() annotate("text", x = 4, y = 25, size = 5, label = "lower triangle") theme_void()
}
#this doesn't help
print(new_plot)
#this doesn't help either
plot_buffer = duplicate(new_plot, shallow=FALSE)
#append new plot to plot list
plot_list = append(plot_list, list(plot_buffer))
}
}
grid.arrange(grobs = plot_list, top = "grand title")
Вот неисправный график. Лепесток.Ширина используется в качестве столбца значений x и y everythyme:
PS: Я использую R только для визуализации своих данных, поэтому мое внимание сосредоточено на ggplot2. Этот код выполняется внутри узла R view в KNIME.
Ответ №1:
Вы можете использовать aes_string
так:
ggplot(iris)
geom_point(aes_string(colnames(iris)[j], colnames(iris)[i], color = "Species"), shape=18, size=3.5)
theme_light()
theme(legend.position="none")
Это также гарантирует, что вам больше не придется использовать labs()
.
Это дает
Комментарии:
1. Потрясающе, спасибо. У вас также есть объяснение, почему это работает? В документации указано, что aes() не вычисляется немедленно, в то время как aes_string() выполняется. Правильно ли я это понимаю? 🙂
2. Обычно вы используете
ggplot(iris) geom_point(aes(Sepal.Width, Sepal.Height))
. Если вы хотите сделать это программно, как вы делаете, вместоSepal.Width
у вас есть переменная, содержащая строку, скажемx <- "Sepal.Width"
. Чтобы иметь возможность использовать это, вам нужноaes_string(x)
, посколькуaes(x)
будет искать столбец с именемx
, которого не существует. Почему ваш код не работает, я не совсем уверен.3. Этого не может быть, потому что минимальное изменение, необходимое для работы моего кода, — это заменить «aes» на «aes_string». Я по-прежнему передаю весь столбец с помощью x = iris[,i], потому что в реальном наборе данных в именах столбцов есть пробелы (иначе это не сработает, «x =» является необязательным). Однако в будущем мне, вероятно, следует ссылаться на столбцы по их имени.
4. Да, если вы посмотрите
plot_list[[2]]$layers[[1]]$mapping
после запуска любой из двух версий, вы можете увидеть, что в одной из них была оцененаx
иy
, а в другой — нет, поэтому на заключительном этапе она заменитi
иj
, которые в этот момент равны 4, так что «Лепесток. Ширина».