1

I have a list (eulerr.list) that contains data frames that can plot Euler diagrams with eulerr. I want to plot and save Euler diagrams for each data frame in the list. To this end I wrote the following code:

for (j in 1: length(eulerr.list)) {
        
        pdf(file=paste0("output/","triple_","eulerr_",names(eulerr.list[j]),".pdf"))
        plot(eulerr.list[[j]],
             fills = c("red", "forestgreen", "mediumorchid"),
             quantities = TRUE,
             alpha = 0.5,
             labels = c("A", 
                        "B", 
                        names(eulerr.list[j])),
             adjust_labels = TRUE)
        dev.off()
        
}

When I run the loop (RStudio Version 1.3.959), I get the files that I expect, but all the file are damaged (cannot be opened by Preview on my Mac (OSX 10.12.6)). When the loop is finished there are no error messages and Rstudio return an empty prompt. When I assign a value of 1 to j manually and run the code inside the loop:

pdf(file=paste0("output/","triple_","eulerr_",names(eulerr.list[j]),".pdf"))
        plot(eulerr.list[[j]],
             fills = c("red", "forestgreen", "mediumorchid"),
             quantities = TRUE,
             alpha = 0.5,
             labels = c("A", 
                        "B", 
                        names(eulerr.list[j])),
             adjust_labels = TRUE)
        dev.off()

then the file is generated properly (can be viewed in Preview) and RStudio returns this:

> dev.off()
RStudioGD 
        2

Why does the for loop generate damaged PDF files?

zx8754
  • 52,746
  • 12
  • 114
  • 209
justinian482
  • 845
  • 2
  • 10
  • 18
  • Are you sure it shouldn't be `names(eulerr.list)[j]`? – Roland Jun 23 '20 at 13:53
  • When I try that, I still have the same issue – justinian482 Jun 23 '20 at 13:57
  • 2
    I think you need to provide a minimal reproducible example. – Roland Jun 23 '20 at 14:01
  • This works: `for (i in 2:3) { pdf(file=paste0(i, ".pdf")); plot(mtcars[[i]], main=names(mtcars)[i]); dev.off(); }`, so it must be something with your data. Are there any non-base packages being used? (I *infer* [`eulerr`](https://cran.r-project.org/web/packages/eulerr/index.html), please be explicit about any/all you're using for questions on SO.) Have you tried expanding the dimensions of the `pdf` with `width=`/`height=`? Perhaps it's a plot-size thing. – r2evans Jun 23 '20 at 14:10
  • Does `eulerr` use base or grid graphics for its `plot` method? – Roland Jun 23 '20 at 14:15
  • @Roland, it imports `grid` (https://cran.r-project.org/web/packages/eulerr/index.html). – r2evans Jun 23 '20 at 14:19
  • 2
    @r2evans I saw that. I could check for the `plot` method but (a) I don't feel like installing the package and (b) without a reproducible example I can't be sure which method is actually called. – Roland Jun 23 '20 at 14:22
  • Absolutely true, my apologies, I see the question was more a prod to improve the question with sample data and such. (I know you're well aware of how to determine a package's imports.) – r2evans Jun 23 '20 at 14:31
  • According to the `eulerr` package info it uses `grid::Grid()graphics` – justinian482 Jun 23 '20 at 15:55
  • I am not sure how to provide a minimal reproducible examples as there is a lot of code and underlying data to get to this point – justinian482 Jun 23 '20 at 15:56
  • @r2evans, I have these other packages active: `VennDiagram`,`ggplot2`,`reshape2`, `plyr` and `dplyr`. Why would it be something with the data if I can basically run one cycle of the `for` loop without any issues? – justinian482 Jun 23 '20 at 19:00
  • Unfortunately, `plot` may not be `plot` ... by that, I mean: since `plot` can be overridden for a particular object class (via S3 methods), we don't know from `plot` alone what is going on. The fact that it is likely an `eulerr` model helps, but I don't have one handy. If a package does something peculiar within `plot` that does not take iteration well (idk, guessing), then ... who knows. It'll take a good reproducible example to be able to route this one out. – r2evans Jun 23 '20 at 19:57
  • I have saved `eulerr.list` with `rlist` as `eulerr.list.rdata'. It can be accessed here: http://sendanywhe.re/4TTETD6L . It should now be possible to reproduce the error with the above code? – justinian482 Jun 24 '20 at 08:23

1 Answers1

3

What's happening here is that the plot.euler() returns an "eulergram" object. To then actually draw this plot on the current device, the print.eulergram() (or plot.eulergram()) method has to be invoked, but it's not because the call is inside a for loop. When you call plot() interactively, the object that is returned actually has its print() method called implicitly. This is exactly the same issue that people have with ggplot or lattice.

What you need to do is to save the object from plot() and invoke print() (or plot()) on it, like so:

for (j in 1: length(eulerr.list)) {  
  pdf(file=paste0("output/","triple_","eulerr_",names(eulerr.list[j]),".pdf"))
  p <- plot(eulerr.list[[j]],
            fills = c("red", "forestgreen", "mediumorchid"),
            quantities = TRUE,
            alpha = 0.5,
            labels = c("A", 
                       "B", 
                       names(eulerr.list[j])),
            adjust_labels = TRUE)
  print(p)
  dev.off()
}

Johan Larsson
  • 3,496
  • 18
  • 34