Создание нескольких графиков в ggplot с разными значениями оси Y с использованием цикла
Я пытаюсь создать несколько графиков графика разброса в ggplot, которые имеют одинаковую структуру, но с другим значением Y. Мне нужно, чтобы они были отдельными (и, следовательно, не использовали facet_wrap), потому что на более позднем этапе я использую grid_arrange для размещения различных комбинаций графиков на одном макете.
Из-за этого мне нужно создать новые имена для каждого графика, которые отражают отображаемое значение y. Ниже приведен пример кода, где month - это переменная на оси x, и я хочу три отдельных графика месяца против трех дополнительных переменных (lag1_var, lag3_var и lag9_var).
df <- data.frame (month= c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
lag1_var= c (10, 20, 30, 40, 10, 40, 30, 50, 70, 90, 100, 100),
lag3_var= c(90, 70, 50, 40, 70, 50, 20, 50, 70, 90, 10, 10),
lag9_var = c(50, 20,90, 100, 90, 10, 40, 90, 100, 20, 30, 70))
Мой подход заключался в создании списка значений, которые отличаются между значениями y и циклом над этим списком, как показано ниже:
loop.list <- c("1", "3", "9")
for (val in loop.list) {
yval<- paste0("lag", val, "_var")
ptitle <-paste0("graph plot lag", val, "_Var")
assign(paste0("plot", val), ggplot(data=df, aes(x=month, y=get(yval)))
+geom_point(color="red", size=2) + ggtitle(ptitle))
}
когда я это делаю, я получаю три сюжета с тремя разными именами (plot1, plot3, plot9) и правильными заголовками (так что сюжет 1 имеет заголовок "график графика lag1", а график 3 имеет заголовок "graph plot lag3", и т.д.), но все они одинаковые. Таким образом, цикл работает для названия сюжета и названия сюжета, но не для значения y. Он просто выводит значения из последнего цикла (для переменной lag9_var).
Я не могу понять, почему это происходит, и почему это происходит только с Y-значением, а не с названием или названием. Я всегда программировал в SAS и новичок в R, поэтому я думаю, что приближаюсь к этому из перспективы SAS, вместо того, чтобы думать об этом по-разному.
Примечание: в приведенном выше коде я создаю объекты "yval" и "ptitle" вне инструкции ggplot, но только для устранения неполадок. то же самое происходит, если я включаю их в инструкцию ggplot, как показано ниже:
for (val in loop.list) {
assign(paste0("plot", val), ggplot(data=df,aes(x=month,y=get(paste0("lag", val, "_var")))) +
geom_point(color="red", size=2) +
ggtitle(paste0("graph plot lag", val, "_Var")))
}
Спасибо за помощь!
Ответы
Ответ 1
Я думаю, что проблема, с которой вы столкнулись, может быть ggplot, пытаясь перестроить каждый сюжет при вызове, чтобы показать его, и он извлекает данные из приведенной последней ссылки, а не ссылку, данную при создании каждого сюжета. Я не совсем понимаю это, поэтому было бы здорово, если бы кто-то еще мог осветить этот вопрос.
В любом случае, следуя этим рассуждениям, я попытался разделить данные для каждого графика на свой собственный фрейм данных и, похоже, получил его работу:
library(data.table)
library(ggplot2)
loop.list <- c("1", "3", "9")
for (val in loop.list) {
col <- grep( paste0("lag", val, "_var"), colnames(df) )
yval <- df[,c(1,col)]
setnames( yval, c( "month", "var" ) )
frameval <- paste0("frame", val)
assign( paste0("frame", val), yval )
ptitle <-paste0("graph plot lag", val, "_Var")
plotval <- ggplot( data = get(frameval), aes(x=month,y=var) ) +
geom_point( color="red", size=2) +
ggtitle(ptitle)
assign( paste0("plot",val), plotval )
}
Обратите внимание, что вызов grep
находит номер столбца, который будет использоваться для этого графика, а затем отделяет этот столбец от остального как своего собственного фрейма данных.
Я не могу объяснить, почему ggplot не работает с методом, который вы использовали, но это похоже на обходной путь, поэтому я надеюсь, что это поможет.
Ответ 2
Код выше работает с одним изменением, которое я использовал
names(yval)<-c("month", "var")
вместо setNames. По какой-то причине setNames не работал, поэтому оператор ggplot не имел значения y для построения графика, потому что имя переменной в каждом кадре все еще было lag3_var, lag6_var и lag9_var. Спасибо!
library(data.table)
library(ggplot2)
loop.list <- c("1", "3", "9")
for (val in loop.list) {
col <- grep( paste0("lag", val, "_var"), colnames(df) )
yval <- df[,c(1,col)]
**names(yval)<- c( "month", "var")**
frameval <- paste0("frame", val)
assign( paste0("frame", val), yval )
ptitle <-paste0("graph plot lag", val, "_Var")
plotval <- ggplot( data = get(frameval), aes(x=month,y=var) ) +
geom_point( color="red", size=2) +
ggtitle(ptitle)
assign( paste0("plot",val), plotval )
}
Ответ 3
В приведенном ниже коде показано, как это сделать, используя функцию 'multipot()', источник которой приведен здесь: http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2):
plotAllCounts <- function (dt){
plots <- list();
for(i in 1:ncol(dt)) {
strX = names(dt)[i]
print(sprintf("%i: strX = %s", i, strX))
plots[[i]] <- ggplot(dt) + xlab(strX) +
geom_point(aes_string(strX),stat="count")
}
columnsToPlot <- floor(sqrt(ncol(dt)))
multiplot(plotlist = plots, cols = columnsToPlot)
}
Теперь запустите функцию - чтобы получить Count для всех переменных, напечатанных с помощью ggplot на одной странице:
dt = ggplot2::diamonds
plotAllCounts(dt)
Это один из первых шагов, которые я всегда делаю при анализе нового набора данных.
Надеюсь, вы сочтете это полезным.
Следует отметить, что: используя aes(get(strX))
, который вы обычно используете в циклах при работе с ggplot
, в приведенном выше коде вместо aes_string(strX)
НЕ будет рисовать нужные графики. Вместо этого он будет строить последний график много раз. Я не понял, почему, возможно, придется делать aes
и aes_string
, вызываемые в ggplot
.