3

I've written a for loop which goes through the columns of a dataframe and produces a graph for each column using ggplot. The problem is the graphs that are output are all the same - they're all graphs of the final column.

The code I've used is:

library(gridExtra)
library(ggplot2)
test1 <- c("Person1","Person2","Person3","Person4","Person5")
test2 <- as.data.frame(c(1,2,3,4,5))
test3 <- as.data.frame(c(2,2,2,2,2))
test4 <- as.data.frame(c(1,3,5,3,1))
test5 <- as.data.frame(c(5,4,3,2,1))
test <- cbind(test1,test2,test3,test4,test5)
rm(test1,test2,test3,test4,test5)
colnames(test) <- c("Person","var1","var2","var3","var4")

for(i in 2:5){
  nam <- paste0("graph", i-1)
  graph_temp <- ggplot(test, aes(Person, test[,i])) + geom_bar(stat = "identity")
  assign(nam, graph_temp)
}
grid.arrange(graph1, graph2, graph3, graph4, ncol=2)

What I'm aiming for is the plot from this code:

library(gridExtra)
library(ggplot2)
test1 <- c("Person1","Person2","Person3","Person4","Person5")
test2 <- as.data.frame(c(1,2,3,4,5))
test3 <- as.data.frame(c(2,2,2,2,2))
test4 <- as.data.frame(c(1,3,5,3,1))
test5 <- as.data.frame(c(5,4,3,2,1))
test <- cbind(test1,test2,test3,test4,test5)
rm(test1,test2,test3,test4,test5)
colnames(test) <- c("Person","var1","var2","var3","var4")

graph1 <- ggplot(test, aes(Person, test[,2])) + geom_bar(stat = "identity")
graph2 <- ggplot(test, aes(Person, test[,3])) + geom_bar(stat = "identity")
graph3 <- ggplot(test, aes(Person, test[,4])) + geom_bar(stat = "identity")
graph4 <- ggplot(test, aes(Person, test[,5])) + geom_bar(stat = "identity")
grid.arrange(graph1, graph2, graph3, graph4, ncol=2)

I know there's a similar question on saving ggplots in a for loop, but I've not managed to get that one to work for this problem.

Community
  • 1
  • 1
tktk234
  • 426
  • 3
  • 12
  • You are overwriting `graph_temp` and so only the last one gets plotted. Learn to use lists. If you can you should avoid for-loops, although `lapply` is just a for-loop in disguise. At least it protects you from this typical newbie-error. – IRTFM Jan 15 '17 at 21:58
  • Thanks, although are you `graph_temp` was the problem? I thought it wrote it out to another object in each iteration of the for loop (e.g. `graph_temp` to `graph1`, `graph_temp` to `graph2`, etc.). Also, just for future reference, on a site which is about building a communities' skills, statements like 'learn to use lists' with no elaboration and 'typical newbie-error' aren't overly helpful. I refer you to your peer's answer below for the same things said in a constructive manner. I think this is a general issue on Stack Overflow, relative 'newbies' can be scared into not asking questions. – tktk234 Jan 16 '17 at 17:28
  • You need to understand lazy evaluation. It wasn't a problem with that function but rather a problem with using a for-loop. We were all newbies once. The answer you preferred did not explain the cause of your error nor give you advice about what strategy to use in the future. – IRTFM Jan 16 '17 at 20:26

1 Answers1

4

Here's a more concise way to produce your example:

df <- data.frame(
  Person = paste0("Person", 1:5),
  var1 = c(1,2,3,4,5),
  var2 = c(2,2,2,2,2),
  var3 = c(1,3,5,3,1),
  var4 = c(5,4,3,2,1)
)

Now, about your plots.

Best solution

Reshape the data frame to 'long' format, and then use facets:

library(ggplot2)
library(tidyr)
gather(df, var, value, -Person) %>%
  ggplot(aes(Person, value)) +
    geom_bar(stat = "identity") +
    facet_wrap(~ var)

enter image description here

Otherwise…

If you gotta stick with a data structure that looks like what you posted, then use aes_string:

library(ggplot2)
library(gridExtra)

g <- lapply(1:4, function(i) {

  ggplot(df, aes_string("Person", paste0("var", i))) +
    geom_bar(stat = "identity")

})
grid.arrange(grobs = g, ncol = 2)

enter image description here

Fr.
  • 2,865
  • 2
  • 24
  • 44