Maciej B.
Maciej B.

Reputation: 383

one or more loops - multiple ggplot plots r

I did ask some questions last days about loops last days and it helped me a lot, and many thanks to you guys! This time I met, I think, more complex issue. I skipped the labels and some details in plot code, but it works perfectly.

In general I would like to produce lots of plot using loop. I learned how to deal with simple plot like this, but with ggplot and aes I found it more complicated.

Here are the data as .csv on dropbox.

Some preparation:

data <- select(baza,strefa,v1,v2,v3,v4,v5,v6,v7,v8) # with dplyr package
strefa <- data$strefa
data$strefa <- NULL
data <- data.frame(apply(data, 2, function(x) {x <- recode(x, "9=NA"); x})) #with car package

Some summarize for aes: a <- data$v1 df <- data.frame(cbind(a,strefa))

srednie <- aggregate(a ~ strefa, data = df, FUN = mean)
GD.mean <- round(mean(a, na.rm = TRUE), digits = 2)
srednie <- rbind(srednie, c(13,GD.mean))

And ggplot code:

 jpeg(paste0("plot_",names(data)[i],".jpg"),
         width = 166, height = 120, units = "mm", pointsize = 12,
         res = 300, quality = 90)
     ggplot(srednie, aes(x=factor(strefa), y=a, label=round(srednie$a, digits = 2))) +
          geom_bar(position=position_dodge(), stat="identity", fill="#fff68f", colour="darkgrey", width = 0.5) +
          theme(axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.ticks.y = element_blank()) +
          geom_text(size = 4, hjust = 1.2) +
          coord_flip(ylim = c(1,6))              
     dev.off()

How to bind it into for loop? Should it be in one loop or maybe some more?

for (i in 1:length(names(data))) {

    df <- data.frame(cbind(i,strefa))
    srednie <- aggregate(i ~ strefa, data = df, FUN = mean)
    GD.mean <- round(mean(i, na.rm = TRUE), digits = 2)
    srednie <- rbind(srednie, c(13,GD.mean))

jpeg(paste0("plot_",names(data)[i],".jpg"),
                 width = 166, height = 120, units = "mm", pointsize = 12,
                 res = 300, quality = 90)
      ggplot(srednie, aes(x=factor(strefa), y=i, label=round(srednie$i, digits = 2))) +
            geom_bar(position=position_dodge(), stat="identity", fill="#fff68f", colour="darkgrey", width = 0.5) +
            theme(axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.ticks.y = element_blank()) +
            geom_text(size = 4, hjust = 1.2) +
            coord_flip(ylim = c(1,6))

 dev.off()
    }

Upvotes: 0

Views: 377

Answers (1)

Bishops_Guest
Bishops_Guest

Reputation: 1472

You don't really have a question since your code appears to work as intended. This is just a suggestion on other methods to try out.

If you are going to use dplyr then go all the way. There are a bunch of different ways to loop in R. Personally I tend to steer away from for loops and use either apply (apply, lapply',sapply') functions or dplyr.

I don't have a drop box account and am not going to make one, so I cannot use your data. However here is an example that you should be able to adapt.

Packages:

library(ggplot2)
library(dplyr)
library(tidyr)

Data Generation: Random data, I am just going to make some simple barplots.

Data <- data.frame(Groups=LETTERS[1:5],
                   Var1 = rchisq(5,1),
                   Var2 = rchisq(5,1),
                   Var3 = rchisq(5,1))

Plotting 'Loop':

First, create a function for the plot:

plt.fnc <- function(frm){
  PLT <- ggplot(frm,aes(x=Groups,y=Value)) +
    geom_bar(stat='identity') +
    xlab(frm$Variable[1])

  ggsave(PLT,file=paste0('PLOT_',frm$Variable[1],'.jpeg'),width=10,height=7.5)

  return(PLT)
}

This is the workhorse of the plotting. Note the use of ggsave rather than jpeg/dev.off. The functionality is the same, but ggsave tends make the code a lot cleaner. This function is both generating the plot and saving it. Putting the contents of your loop into a function can be a good practice when your code starts getting messy since it lets you keep a much cleaner flow.

Next up, rather than using a loop I use dplyr.

Plots <- Data %>%
  gather(Variable,Value,Var1:Var3) %>% # this is equivilent to melt.
  group_by(Variable) %>%               # itterates over values of variable
  do(Plot = plt.fnc(.))                # Calls our plotting function.

The main issue with this method is that you have to figure out how to get all of the information you want in the plot into one dataframe. When that is not possible, then often an apply function or for loop will be better.

Upvotes: 1

Related Questions