Создание нескольких графиков в ggplot с различными значениями оси Y с использованием цикла

Я пытаюсь создать несколько графиков рассеяния в ggplot, которые имеют одинаковую структуру, но с другим значением Y. Мне нужно, чтобы они были отдельными (и, следовательно, не использовали facet_wrap), потому что на следующем шаге я использую grid_arrange, чтобы расположить различные комбинации графиков в одном макете.

Из-за этого мне нужно создавать новые имена для каждого графика, которые отражают построенное значение y. Ниже приведен пример кода, где месяц - это переменная на оси 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 имеет заголовок "graph plot lag1", а участок 3 имеет заголовок "graph plot lag3" и т. д.).), но все они одинаковые участки. Таким образом, цикл работает для имени графика и заголовка графика, но не для значения y. Он просто выводит значения из последнего цикла (для переменной lag9_var).

Я не могу понять, почему это происходит, и почему это происходит только с Y-значением, а не с названием или сюжетом. Я всегда программировал на SAS и плохо знаком с R, поэтому я думаю, что подхожу к этому с точки зрения SAS, а не думаю об этом "R".

Примечание: в приведенном выше коде я создаю объекты "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")))

        }

Спасибо за любую помощь!

3 ответа

Решение

Я думаю, что ваша проблема может заключаться в том, что 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 call находит номер столбца, который будет использоваться для этого графика, а затем отделяет этот столбец от остальных в качестве своего собственного фрейма данных.

Я не могу объяснить, почему ggplot не работает с методом, который вы использовали, но это обходной путь, поэтому я надеюсь, что это поможет.

Приведенный выше код работает с одним изменением, которое я использовал 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 )
}

В приведенном ниже коде показано, как это сделать с помощью функции multiplot(), источник которой приведен здесь: 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,

Другие вопросы по тегам