Создание нескольких графиков в 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.