0

I have a melted dataset:

 ID variable        mean          sd         sem
1 0001      1 0.000000000 0.000000000 0.000000000
2 0001      2 0.000000000 0.000000000 0.000000000
3 0001      3 1.374013050 0.083787761 0.001524927
4 0001      4 1.622939744 0.232510250 0.004231658
5 0001      5 0.004092427 0.004076841 0.000074198

There are 120 variables for each of 50 unique IDs.

[Edited based on comments]

I would like to create a single plot for each variable, showing the mean & sem for each ID. I would like the means to be ordered

First: I would like to create a plot for one variable:

  ggplot(subset(dataset, variable=="1"), aes(x = ID, y = mean)) +
    geom_bar(position = position_dodge(), stat = "identity") + 
    geom_errorbar(aes(ymin=mean-sem, ymax=mean+sem))  +
    theme(axis.title.x = element_text(face="bold",size=16),
          axis.text.x = element_text(angle=90, colour = "black", vjust=1, hjust        = 1, size=14),
          axis.text.y = element_text(colour = "black", size=14),
          axis.title.y = element_text(face="bold", size=16),
          plot.title = element_text(size = 18),
          legend.title = element_text(size=14),
          legend.text = element_text(size = 13),
          legend.position="right",
          strip.text.x = element_text(size=12, face="bold"),
          strip.text.y = element_text(size=12, face="bold"),
          strip.background = element_rect(colour="black")) + ylab("Mean") + xlab("ID") 

Now, I would like to do the same thing for all 120 variables. How do I initialize a for statement to create a plot for each variable?

I tried:

for(i in 1:120)
{unique <- unique(test$variable)
ggplot(unique[i], aes(x = KGID, y = mean))

But that doesn't work. I want ggplot() to take each unique ID and make the plot.

user3795577
  • 187
  • 1
  • 18
  • I don't see this calling itself, is there recursion I'm missing? I think your call to `png` is premature. `png` will just write a single `png` file, that is an image of whatever the plotting window would show if you hadn't called `png`. Creating many plots inside one `png` won't work. Get the plot to look how you want, then just call `png` and you'll be fine. – Gregor Thomas Aug 06 '15 at 17:27
  • I'm super-confused about whether you want a single plot with multiple bars, a single plot with multiple barplot facets, or multiple separate plots. I'm also not sure if you want multiple png files or a single png file as output. – Gregor Thomas Aug 06 '15 at 17:29
  • @Gregor. I'm sorry I wasn't as clear as I intended. I would like one plot per variable, with each plot showing the mean and sem per ID. – user3795577 Aug 06 '15 at 17:35
  • `png` will save one plot. (And `ggsave()` is usually recommended as being better for ggplots anyway). One of the big benefits of ggplots is that they are objects. I would recommend creating a list of all the ggplots you want to make, and then saving them rather than trying to mash the two steps (creating and saving) together. – Gregor Thomas Aug 06 '15 at 17:38

3 Answers3

2

I'd recommend creating all your plots, then saving them.

# par() works for base graphics, it does nothing for ggplot
# par(mfrow=c(3, 4)) #just try to plot 12 variables right now

Creating the plots:

# initialize a list to put the plots in
my_plots = list()

u <- unique(dataset$variable) #Get all unique values for variable

for(i in 1:length(u)) {
    # I just put your data subset inside the plot
    my_plots[[i]] = ggplot(test[dataset$variable==u[i], ],
                           aes(x = ID, y = mean)) +  
        geom_bar(position = position_dodge(), stat = "identity") + 
        geom_errorbar(aes(ymin=mean-sem, ymax=mean+sem))  +
          # I deleted all your theme stuff to keep this minimal and 
          # easy to understand, you can add it back in
        ylab("Mean") + xlab("ID") 
}

Now you can print them in your R session, check them, make sure they look good

print(my_plots[[1]])
print(my_plots[[8]])

Save them in a for loop: (you could also use lapply)

for (i in 1:length(my_plots)) {
    ggsave(filename = paste0("plot_", i, ".png"),
           # you can specify height, width, cairodevice, etc.
           plot = my_plots[[i]])
}

Though, if I were you, I think faceting might work much better:

ggplot(dat, aes(x = ID, y = mean)) +  
    geom_bar(position = position_dodge(), stat = "identity") + 
    geom_errorbar(aes(ymin=mean-sem, ymax=mean+sem))  +
    ylab("Mean") + xlab("ID") +
    facet_wrap(~ variable)
Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
  • For some reason it doesn't subset appropriately. It looks like this plots every variable on the same plot. I tried `subset(test,test$variable==u)`, but that didn't work, either. – user3795577 Aug 06 '15 at 17:55
  • Looking closely, I think it might be a naming problem. You seem to call the data both `dataset` and `test` in that one line. (Both of which, I would say, are poor names for a dataset. `fortunes::fortune("dog")`) – Gregor Thomas Aug 06 '15 at 17:58
  • Oh, and the subsetting was incorrect. `u` is constant throughout the loop, you want `u[i]`, see edits. – Gregor Thomas Aug 06 '15 at 18:01
  • That was it. I'm sorry you had to deal with teaching me and troubleshooting at the same time. Take care. – user3795577 Aug 06 '15 at 18:03
  • No problem. Do check out the last edit I added, a facet version. – Gregor Thomas Aug 06 '15 at 18:04
1

a lazy option would be (using mtcars as an example)

p = ggplot(mtcars, aes(x = hp, y = drat)) + geom_point()

png("plot%03d.png")
plyr::d_ply(mtcars, "carb", "%+%", e1 = p, .print=TRUE)
dev.off()

or, in two steps,

pl = plyr::dlply(mtcars, "carb", "%+%", e1 = p)
ggsave("plot%03d.png", gridExtra::marrangeGrob(pl, nrow=1, ncol=1))
baptiste
  • 75,767
  • 19
  • 198
  • 294
0

Try adding a print statement around your ggplot calls as ggplot just returns the ggplot object within a loop and does not print the plot. Also I don't think ggplot listens to par(mfrow(. The standard for a grid of ggplots is grid.arrange as you can see in this post. You can also just lapply over your variables to store the ggplot objects in a list and print with arrange.grid via a do.call command as in this post. Hope this helps!

Community
  • 1
  • 1
cr1msonB1ade
  • 1,716
  • 9
  • 14