Продолжаю свои поиски работы с функциями и ggplot:
Я разобрал основные способы использования lapply и ggplot для циклического просмотра списка y_columns для создания отдельных графиков:
require(ggplot2)
# using lapply with ggplot
df <- data.frame(x=c("a", "b", "c"), col1=c(1, 2, 3), col2=c(3, 2, 1), col3=c(4, 2, 3))
cols <- colnames(df[2:4])
myplots <- vector('list', 3)
plot_function <- function(y_column, data) {
ggplot(data, aes_string(x = "x", y=y_column, fill = "x")) +
geom_col() +
labs(title=paste("lapply:", y_column))
}
myplots <- lapply(cols, plot_function, df)
myplots[[3]])
Я знаю, что ввести вторую переменную, которую я буду использовать для выбора строк. В моем минимальном примере я пропускаю выбор и просто повторно использую те же графики и dfs, что и раньше, я просто добавляю 3 итерации. Поэтому я хотел бы создать те же три графика, что и выше, но теперь помеченные как итерация A, B и C.
Мне потребовалось некоторое время, чтобы разобраться с синтаксисом, но теперь я понимаю, что mapply нужны векторы одинаковой длины, которые передаются функции в виде совпадающих пар. Поэтому я использую expand.grid
для генерации всех пар переменных 1 и 2 для создания фрейма данных, а затем передаю первый и второй столбец через mapply
. Следующая проблема, которую нужно решить, заключалась в том, что мне нужно передать фрейм данных в виде списка MoreArgs =
. Так что вроде бы все должно быть хорошо. Я использую тот же синтаксис для aes_string()
, что и выше, в моем примере lapply
.
Однако по какой-то причине теперь он не оценивает y_column должным образом, а просто принимает его как значение для построения, а не как индикатор для обозначения значений, содержащихся в df$col1
.
ПОМОЩЬ!
require(ggplot2)
# using mapply with ggplot
df <- data.frame(x=c("a", "b", "c"), col1=c(1, 2, 3), col2=c(3, 2, 1), col3=c(4, 2, 3))
cols <- colnames(df[2:4])
iteration <- c("Iteration A", "Iteration B", "Iteration C")
multi_plot_function <- function(y_column, iteration, data) {
plot <- ggplot(data, aes_string(x = "x", y=y_column, fill = "x")) +
geom_col() +
labs(title=paste("mapply:", y_column, "___", iteration))
}
# mapply call
combo <- expand.grid(cols=cols, iteration=iteration)
myplots <- mapply(multi_plot_function, combo[[1]], combo[[2]], MoreArgs = list(df), SIMPLIFY = F)
myplots[[3]]
Извините, я просто смотрел на проблему с кодом ранее
Здесь нам может понадобиться использовать rowwise
out <- lapply(asplit(combo, 1), function(x)
multi_plot_function(x[1], x[2], df))
В коде ОП единственная проблема заключается в том, что столбцы factor
для «комбо», поэтому они анализируются неправильно. Если мы изменим его на character
, это сработает.
out2 <- mapply(multi_plot_function, as.character(combo[[1]]),
as.character(combo[[2]]), MoreArgs = list(df), SIMPLIFY = FALSE)
-тестирование
out2[[1]]
Потрясающий. Спасибо за оба решения. Приятно узнать об опции asplit
(которая кажется проще, чем использование mapply), и спасибо, что нашли ошибку. Непонимание точной природы того, что передается, на данный момент является моей проблемой кодирования номер один.
@MarioNiepel Я думаю, что это основано на expand.grid
, который по какой-то причине по умолчанию возвращает stringsAsFactors
как ИСТИНА
Да, это так часто моя проблема. Здесь я не уловил этого, потому что, когда я проверял эту проблему, я просто печатал значения, которые не говорят мне, правильный ли это тип. Я все больше и больше осознаю это, но это процесс обучения. Так же, как мне потребовалась наша жизнь, чтобы понять, что сначала мне нужно было обернуть df в список. :D
@MarioNiepel Обычно я делаю это str
, прежде чем что-либо делать, потому что это может дать признаки жизни
Да, это имеет большой смысл. Мне нужно понять, что «видение значения» менее важно, чем понимание типа/класса.
Что ты имеешь в виду? В ваших руках код выдает другой сюжет для версии mapply, чем мой? Или это то же самое, что и с моей функцией lapply (т. е. отображение значений 4, 2, 3 для a, b, c соответственно)?