Miksmith
Miksmith

Reputation: 159

R ggplot2 for loop plots same data

I have put together a simple for loop to generate a series of plots and then use grid.arrange to plot them. I have two problems:

  1. The axes of the plots change correctly to the column names, but the same data is plotted on each graph. Having put in a breakpoint and stepped through the code it appears to be incrementing correctly so I'm not sure why.

  2. I have set the plot aesthetic to group on year, however this produces intermediate .5 years that appear in the legend. This hasn't happened to me before.

Should all be reproducible using mtcars.

library(ggplot2)
library(gridExtra)

result <- mtcars

for(i in 1:2) {
  nam <- paste("p", i, sep = "")
  assign(
    nam, ggplot(result, aes(x = disp, y = results[i+4], group = gear, color = gear)) +
      geom_line() +
      geom_point() +
      scale_colour_distiller(palette = "Dark2", direction = -1, guide = "legend") +
      scale_y_continuous(name = colnames(results[i+4])) +
      scale_x_continuous(name = "x")
  )
}


plist <- mget(paste0("p", 1:2))
do.call(grid.arrange, plist)

Upvotes: 1

Views: 2418

Answers (4)

CPak
CPak

Reputation: 13581

You should take full advantage of ggplot::facet_wrap

This means tidying your data to a single data frame that's interpretable to ggplot

Data

temp <- mtcars

Tidy data

library(purrr)
library(dplyr)
Names <- map_chr(1:2, ~names(temp)[.x+4])
# "drat" "wt"

data <- map_df(1:2, ~temp[,c("cyl", names(temp)[.x+4])] %>% setNames(c("cyl", "value")), .id="iteration") %>%
          mutate(iteration = Names[as.numeric(iteration)])

plot with facet_wrap

ggplot(data=data, aes(x=cyl, y=value, label=iteration)) +
  geom_line() +
  geom_point() +
  facet_wrap(~iteration)

Upvotes: 0

Eric Watt
Eric Watt

Reputation: 3230

The problem is that the plot is generated in the for loop, but evaluated in the do.call. Since i has changed in the for loop, both are evaluated with i = 2. You can confirm this with:

i <- 3
do.call(grid.arrange, plist)

A small adjustment to your code fixes the issue:

for(i in 1:2) {
  nam <- paste("p", i, sep = "")
  coln <- colnames(result[i+4])
  assign(
    nam, ggplot(result,aes_(x=~disp,y=as.name(coln), group=~gear, color=~gear)) +
      geom_line() +
      geom_point() +
      scale_colour_distiller(palette = "Dark2", direction=-1, guide="legend") +
      scale_y_continuous(name=coln) +
      scale_x_continuous(name="x")
  )
}


plist <- mget(paste0("p", 1:2))
do.call(grid.arrange, plist)

Upvotes: 0

Andre Elrico
Andre Elrico

Reputation: 11480

Your using results and result. And you should use aes_string and then refer to the variables by string name:

You should also avoid to make tons of assignments. Just put it all into a list()

library(ggplot2)
library(gridExtra)

result<-mtcars

for(i in 1:2) {
    nam <- paste("p", i, sep = "")
    assign(
        nam, ggplot(result,aes_string(x="disp",y=names(result)[i+4], group="gear", color="gear")) +
            geom_line() +
            geom_point() +
            scale_colour_distiller(palette = "Dark2", direction=-1, guide="legend") +
            scale_y_continuous(name=colnames(result[i+4])) +
            scale_x_continuous(name="x")
    )
}


plist <- mget(paste0("p", 1:2))
do.call(grid.arrange, plist)

Upvotes: 0

Christoph Wolk
Christoph Wolk

Reputation: 1758

I think trying to access the columns by their number in the aes mapping is confusing ggplot. This works:

for(i in 1:2) {
  nam <- paste("p", i, sep = "")
  assign(
    nam, ggplot(result,aes_string(x="disp",y=colnames(result)[i+4], group="gear", color="gear")) +
      geom_line() +
      geom_point() +
      scale_colour_distiller(palette = "Dark2", direction=-1, guide="legend") +
      scale_y_continuous(name=colnames(result[i+4])) +
      scale_x_continuous(name="x")
  )
}

I would suggest iterating over the names though; this makes the code much clearer. Here's a version that does this and skips the detour around the environment:

plots <- lapply(c("drat", "wt"), function(column) {
  ggplot(result,aes_string(x="disp",y=column, group="gear", color="gear")) +
    geom_line() + geom_point() +
    scale_colour_distiller(palette = "Dark2", direction=-1, guide="legend") +
    scale_y_continuous(name=column) +
    scale_x_continuous(name="x")}) %>% 
  do.call(grid.arrange, .)
do.call(grid.arrange, plots)

Upvotes: 2

Related Questions