R_Multiple plots on same figure using a for loop

13,571

Solution 1

It is unclear what you are trying to do. Do you want 2 plots, one for mydf1 and one for mydf2 or all on one figure? If two panels, you should change to mfrow=c(2,1) instead of c(2,2) which is currently making 4 panels?

If you want them all on a single plot, then remove the par(mfrow... line.

Then within the plots, you are plotting the first series from mydf1 and the other two series from mydf2. Is that actually what you want?

Using base graphics, you should move your plot line outside the loop so it is done once, change the loop to start at 3, and then keep the points statements inside the loop. Alternatively, you could put an if statement inside the loop to see if it is the first time.

You also have a typo in the plot statement with mydf (no number).

And move your dev.off() outside the loop so it only closes the figure once.

Here is some code that generates a single-panel plot, and you should be able to modify it to work for your desired output...

jpeg("myplot.jpg")
    for (i in 2:4) { 
        ymin<-min(mydf1[,i],mydf2[,i])
        ymax<-max(mydf1[,i],mydf2[,i])
        if (i==2){
            plot(mydf1[,1],mydf1[,i],ylim=c(ymin,ymax),xlab="id",ylab=colnames(mydf1)[i])
            legend("topright",c("mydf1","mydf2"),pch=c(1,2))     
            }
        else{
            points(mydf2[,1],mydf2[,i],pch=2)
        }  
    }
dev.off()

EDIT: After your clarified question, I think the only problem is that dev.off() should be outside the loop. (I recommend PNG or PDF instead of JPEG for any plot worth presenting....)

png("myplot.png")
par(mfrow=c(2,2))
    for (i in 2:4) { 
        ymin<-min(mydf1[,i],mydf2[,i])
        ymax<-max(mydf1[,i],mydf2[,i])
            plot(mydf1[,1],mydf1[,i],ylim=c(ymin,ymax),xlab="id",ylab=colnames(mydf1)[i])
            legend("topright",c("mydf1","mydf2"),pch=c(1,2))     
            points(mydf2[,1],mydf2[,i],pch=2)
    }
dev.off()

enter image description here

Solution 2

I'd do something like

mydf1$g <- 1
mydf2$g <- 2
d3 <- rbind(mydf1, mydf2)
library(reshape2)
d3 <- melt(d3, id.vars = c('id', 'g'))
library(ggplot2)
ggplot(d3, aes(x=id, y=value)) + 
  geom_point(aes(colour = as.factor(g), shape = variable))

ggplot example

or using facets

ggplot(d3, aes(x=id, y=value)) + 
  geom_point(aes(colour = as.factor(g))) +
  facet_wrap(~variable)

ggplot with faceting

to finally export it

ggsave(file = paste0(tempdir(), 'myplot.png'),
last_plot()
)
Share:
13,571
rm167
Author by

rm167

Updated on July 16, 2022

Comments

  • rm167
    rm167 almost 2 years

    I have 2 data frames, mydf1 and mydf2

    > mydf1
      id a  b  c
    1  1 2 10  2
    2  2 3 11  4
    3  3 5 12  6
    4  4 7 13  8
    5  5 8 14 10
    > mydf2
      id  a  b  c
    1  1  4 20  4
    2  2  6 22  8
    3  3 10 24 12
    4  4 14 26 16
    5  5 16 28 20
    

    I would like to plot variables a,b & c against id (sample graphs is given below). I want similar graphs for variables b and c too and I want to do it in a loop and then export it to a local folder. So, I am using the following code

    for (i in 2:4) {
        jpeg(paste("C:/Data/myplot",i,".jpg"))
             ymin<-min(mydf1[,i],mydf2[,i])
             ymax<-max(mydf1[,i],mydf2[,i])
             plot(mydf1[,1],mydf1[,i],ylim=c(ymin,ymax),xlab="id",ylab=colnames(mydf)[i])
             points(mydf2[,1],mydf2[,i],pch=2)
             legend("topright",c("mydf1","mydf2"),pch=c(1,2))     
             dev.off()
    }
    

    My problem is that I would like to get all three different graphs, (id vs a (mydf1 and mydf2) , id vs b(mydf1 and mydf2), id vs c(mydf1 and mydf2) in one figure.(something like 2 along the first row of the figure and the third one in the second row with legend) I tried the following

    jpeg("C:/Data/myplot.jpg")
        par(mfrow=c(2,2))
    for (i in 2:4) { 
        ymin<-min(mydf1[,i],mydf2[,i])
        ymax<-max(mydf1[,i],mydf2[,i])
        plot(mydf1[,1],mydf1[,i],ylim=c(ymin,ymax),xlab="id",ylab=colnames(mydf)[i])
        points(mydf2[,1],mydf2[,i],pch=2)
        legend("topright",c("mydf1","mydf2"),pch=c(1,2))     
        dev.off()
    }
    

    But it didn't work. Any suggestion to do this? p.s: This is the simplified version of my task. Actually I have hundreds of columns, that's why I am using a loop operation

    enter image description here Sample plot id vs a (mydf1 and mydf2) plotted on the same graph

  • rm167
    rm167 about 10 years
    Thanks @beroe. Sorry for the unclear question. I have edited it now. I hope my problem is clear now
  • rm167
    rm167 about 10 years
    Thanks @Paulo Cardoso. The last one is what I want and it looks nice too. But can't I do it without any package, using the base functions of r? Even a simple plot would be ok for me.
  • Paulo E. Cardoso
    Paulo E. Cardoso about 10 years
    I'm afraind not. This looks like this exactly because ggplot renders this output. Why this should be a problem?
  • rm167
    rm167 about 10 years
    No problem @Paulo Cardoso. I just wondered if there is a way to do it using the base functions. Anyway Thanks.
  • beroe
    beroe about 10 years
    In that case, you might just have to move your dev.off outside the loop. I would recommend PDF or at least PNG for this graph. JPG will generate artifacts for that many plots...