0

I'm using knitr withR to build charts showing metrics from various tests I've performed on a piece of software. The data is stored in a SQL server table. These tests produce the same categories of data but in different files so I'm using a loop to build the charts.

Here's my set up:

(SQLConn_remote is a function included in an internally used R package. Just trust me that the db connection is not the issue.)

<<setup, echo=FALSE>>=
db <- SQLConn_remote(DBName = "DATABASE", ServerName = "SERVER")
df <- sqlQuery(db, "select * from TABLE", stringsAsFactors = FALSE)

versions<-unique(df[order(df$Number), ][,2])
df$Version <- factor(df$Version, levels = versions)

files <- unique(df$FileName)
@

Here's the loop:

for (i in 1:6){
g <- ggplot(subset(df, FileName == files[i]), aes(x=Version, y=Value, group=FileName))
g <- g + geom_line(size=.25) + geom_point(aes(shape = Build), size = 1.2, colour = 'red') + 
scale_shape_manual(values=c(1,15)) + ggtitle(files[i]) + 
facet_grid(Category ~ ., scales = "free", space = "fixed", labeller = label_value) + 
ylab("Value") + xlab("Version") + expand_limits(y=0)
g
}

However, when I compile the PDF, no charts are generated. If I take the g at the end and put it on the other side of the final "}" then it does print a single chart for the very last file (as expected).

Any idea or thoughts on why the charts not print inside the for loop?

EXTRAS: I didn't think it was very relevant to include an example of the SQL data but if you think differently, leave a comment and I'll add a basic example.

EDIT: Here's a script to create a table you can use with the chart script.

FileName <- c('File1', 'File1', 'File1', 'File2', 'File2', 'File2', 'File1', 'File1', 'File1', 'File2', 'File2', 'File2', 'File1', 'File1', 'File1', 'File2', 'File2', 'File2', 'File1', 'File1', 'File1', 'File2', 'File2', 'File2')
Version <- c('1.0.1', '1.0.12', '1.0.12', '1.0.1', '1.0.1', '1.0.1', '1.0.15', '1.0.15', '1.0.15', '1.0.15', '1.0.15', '1.0.15', '1.0.17', '1.0.17', '1.0.17', '1.0.17', '1.0.17', '1.0.17', '1.0.15', '1.0.15', '1.0.15', '1.0.15', '1.0.21', '1.0.21')
Category <- c('Category1', 'Category2', 'Category3', 'Category1', 'Category2', 'Category3',  'Category1', 'Category2', 'Category3', 'Category1', 'Category2', 'Category3', 'Category1', 'Category2', 'Category3', 'Category1', 'Category2', 'Category3', 'Category1', 'Category2', 'Category3', 'Category1', 'Category2', 'Category3')
Value <- c(10, 11, 12, 18, 19, 20, 12, 11, 10, 20, 18, 19, 10, 11, 12, 18, 19, 20, 12, 11, 10, 20, 18, 19)
Date <- c('2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00')
Number <- c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4)
Build <- c('Release', 'Release', 'Release', 'Release', 'Release', 'Release', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration')
df <- data.frame(FileName, Version, Category, Value, Date, Number, Build)

Here's the chunk

opts_chuck$set(fig.path='figure/minimal-',fig.align='center', fig.show='hold',fig.width=10,fig.height=5.5)
options(replace.assign=TRUE,width=90)
JohnN
  • 968
  • 4
  • 13
  • 35
  • 6
    Try `print(g)`. See [here](http://stackoverflow.com/q/15678261/324364), or [here](http://stackoverflow.com/q/4811106/324364), or [here](http://stackoverflow.com/q/2547306/324364)...? – joran Oct 10 '16 at 17:31
  • I'm happy to wait for your confirmation that that fixes the problem before closing this question... – joran Oct 10 '16 at 17:34
  • @joran I tried `print(g)`. It didn't work. – JohnN Oct 10 '16 at 17:42
  • Then you might need to provide some more info, maybe with a more complete example. – joran Oct 10 '16 at 17:44
  • @joran What other information would be helpful? The only information I could include would be some examples of the SQL data. – JohnN Oct 10 '16 at 17:45
  • What would be relevant would be a reproducible example using built-in data that anyone could run instead of your SQL call that only you can run. It would also be useful to see the chunk and chunk options you have for the plotting code. – Gregor Thomas Oct 10 '16 at 17:46
  • Barring that, reproducibly sharing some data would be good, that is using `dput()` so that we can see the structure of the data. [Please see here](http://stackoverflow.com/q/5963269/903061) for tips on making a good reproducible example. – Gregor Thomas Oct 10 '16 at 17:49
  • 2
    As-is, I can't reproduce your problem. I knitted a document with single code chunk with the default chunk options: `library(ggplot2); for (i in unique(mtcars$cyl)) { g = ggplot(mtcars[mtcars$cyl == i, ], aes(x = disp, y = mpg)) + geom_point(); print(g) }` It worked fine, I got 3 plots. – Gregor Thomas Oct 10 '16 at 17:51
  • @Gregor I'm putting together an example now – JohnN Oct 10 '16 at 17:58
  • @Gregor see the edit – JohnN Oct 10 '16 at 18:47
  • 1
    Well, you've got some typos. Two `c`s missing in your data definitions (for `Number` and `Build`), `chuck` should be `chunk`. After fixing those and changing your loop to `i in seq_along(files)` it knitted just fine, I got two plots. Still can't replicate your problem. Have you tried this in a fresh document? – Gregor Thomas Oct 10 '16 at 18:59
  • Also note that I used `print(g)` rather than `g` as the last line in your for loop. – Gregor Thomas Oct 10 '16 at 23:46
  • @Gregor, I ended up mostly figuring it out. I did have to use `print(g)` but I also found that `theme(axis.title.x = element_text(vjust = -0.1)) +` was responsible somehow. When I commented it out, the charts were produced (except now I'm working on keeping them from being all on one page and being cut off.) I didn't include that in the original because I assumed (you know what they say about assumptions) that it couldn't have been responsible for the problems. – JohnN Oct 12 '16 at 14:07
  • ..hence the high value of making (and verifying!) a minimal, reproducible example. – Gregor Thomas Oct 12 '16 at 16:18

1 Answers1

0

Use dplyr and lazyeval to subset the data and build a list of ggplot objects which can be easily plotted.

Here is an example .Rmd file that will be knite to .pdf

---
title: ggplot2 charts
---

We'll use the `mpg` data from the `ggplot2` package.

```{r}
library(ggplot2) 
library(dplyr)
library(lazyeval)
mpg 
```

Let's have `r n_distinct(mpg$manufacturer)` graphics, on for each manufacturer.

```{r}
graphics <-
  lapply(unique(mpg$manufacturer),
         function(m) {
           dat <- dplyr::filter_(mpg, lazyeval::interp(~ manufacturer == mm, mm = m)) 
           ggplot2::ggplot(dat) + ggplot2::aes_string(x = "model", y = "cty") + ggplot2::geom_boxplot()
         })
```

To print _all_ the graphics just call for the `graphics` object in a chunk.

```{r, fig.width = 3, fig.height = 3}
graphics
```



With your data

```{r}
FileName <- c('File1', 'File1', 'File1', 'File2', 'File2', 'File2', 'File1', 'File1', 'File1', 'File2', 'File2', 'File2', 'File1', 'File1', 'File1', 'File2', 'File2', 'File2', 'File1', 'File1', 'File1', 'File2', 'File2', 'File2')
Version <- c('1.0.1', '1.0.12', '1.0.12', '1.0.1', '1.0.1', '1.0.1', '1.0.15', '1.0.15', '1.0.15', '1.0.15', '1.0.15', '1.0.15', '1.0.17', '1.0.17', '1.0.17', '1.0.17', '1.0.17', '1.0.17', '1.0.15', '1.0.15', '1.0.15', '1.0.15', '1.0.21', '1.0.21')
Category <- c('Category1', 'Category2', 'Category3', 'Category1', 'Category2', 'Category3',  'Category1', 'Category2', 'Category3', 'Category1', 'Category2', 'Category3', 'Category1', 'Category2', 'Category3', 'Category1', 'Category2', 'Category3', 'Category1', 'Category2', 'Category3', 'Category1', 'Category2', 'Category3')
Value <- c(10, 11, 12, 18, 19, 20, 12, 11, 10, 20, 18, 19, 10, 11, 12, 18, 19, 20, 12, 11, 10, 20, 18, 19)
Date <- c('2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00', '2016-05-19 10:00:00')
Number <- c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4)
Build <- c('Release', 'Release', 'Release', 'Release', 'Release', 'Release', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration', 'Iteration')
df <- data.frame(FileName, Version, Category, Value, Date, Number, Build)
```

```{r}
graphics <-
  lapply(unique(df$FileName),
         function(m) {
           dat <- dplyr::filter_(df, lazyeval::interp(~ FileName == mm, mm = m)) 

           ggplot2::ggplot(dat) +
             ggplot2::aes_string(x = "Version", y = "Value", group = "FileName") +
             ggplot2::geom_line(size = 0.25) +
             ggplot2::geom_point(mapping = ggplot2::aes_string(shape = "Build"), size = 1.2, colour = 'red') +
             scale_shape_manual(values=c(1,15)) +
             ggtitle(m) + 
             facet_grid(Category ~ ., scales = "free", space = "fixed", labeller = label_value) + 
             ylab("Value") + xlab("Version") + expand_limits(y=0)
         })
```

```{r}
graphics
```

The resulting pdf file, a small screen shot with the thumbnails is provided, shows that all the graphics have been printed to the page. enter image description here

Peter
  • 7,460
  • 2
  • 47
  • 68