2

The following knitr thingy produces multiple plots via lapply. Their number and content therefore varies depending on the preceding R code.

Is there a way to set the plot height individually for each plot using a variable (like the height of the highest bar in a given bar chart)?

---
title: "Variable plot height"
output: word_document
---

Plots:

```{r, echo=FALSE, fig.height = 2}
library(ggplot2)
library(tidyr)

data(mtcars)
mtcars$car = row.names(mtcars)

cars = gather(mtcars[1:5, ], variable, value, 
              -c(car, mpg, disp, hp, qsec))

lapply(unique(cars$car), function(x) {

  ggplot(cars[cars$car == x, ], aes(variable, value)) + 
      geom_bar(stat = "identity")

})
```
jakub
  • 4,774
  • 4
  • 29
  • 46
  • See [this related question](http://stackoverflow.com/questions/33701038/print-a-list-of-dynamically-sized-plots-in-knitr/33723600#33723600) on how to use different `fig.height` values within "one" chunk. – CL. Dec 04 '15 at 10:31
  • Another option would to be create figures (i.e. using `ggsave`) and include them into the document. – Roman Luštrik Dec 04 '15 at 10:36
  • Thanks for the suggestion, @RomanLuštrik - this looks really intuitive. Can you give me a hint: The resulting number and names of figures saved by `ggsave` is variable. How to loop over them to include them all in the document? – jakub Dec 04 '15 at 11:40

2 Answers2

2

One way would be to create each image and include it into the document as an external image. You can employ the power of "asis". Here's a small example.

---
title: "Untitled"
author: "Neznani partizan"
date: "04. december 2015"
output: html_document
---

```{r, echo=FALSE, fig.height = 2}
library(ggplot2)
library(tidyr)

data(mtcars)
mtcars$car = row.names(mtcars)

cars = gather(mtcars[1:5, ], variable, value, 
              -c(car, mpg, disp, hp, qsec))

suppressMessages(invisible(lapply(unique(cars$car), function(x) {

  ggplot(cars[cars$car == x, ], aes(variable, value)) + 
      geom_bar(stat = "identity")
  ggsave(sprintf("%s.png", x))

})))
```

```{r results = "asis", echo = FALSE}
cat(sprintf("<img src='%s' alt='' style='width:350px;height:228px;'> <br />", 
            list.files(pattern = ".png", full.name = TRUE)))
```

Image sizes can be adjusted on-the-fly using appropriate arguments in ggsave and/or in printing HTML code.

Roman Luštrik
  • 69,533
  • 24
  • 154
  • 197
  • `asis` to the rescue! And I can store the plot height in a variable, then call it from within the `asis` chunk using `paste` combined with `sprintf` to set the plot width in the document. Only thing: It works for html, but not word - the pictures are missing in the word file - any idea why? @RomanLuštrik – jakub Dec 04 '15 at 14:42
  • @jakub sorry, I'm not familiar with how images are inserted into word. Probably not by reference but hardcoded. If that's the case, this solution may not work out of the box. – Roman Luštrik Dec 06 '15 at 11:35
  • As far as I know, images are correctly inserted into word if `knitr` has control over them. By inserting hardcoded HTML this mechanism gets broken. – CL. Dec 07 '15 at 09:37
  • What if you import them back using one of packages for handling raster data (`png`)? :> – Roman Luštrik Dec 07 '15 at 13:26
  • Interesting. I have to research how to do that. – jakub Dec 09 '15 at 22:44
  • [This answer](http://stackoverflow.com/a/34227856/2706569) made me aware of a brand-new feature that could solve the problem: Generate the PNG as @RomanLuštrik suggested but then use `knitr::include_graphics` to embed it. Not tested yet, but I think this should work. – CL. Dec 11 '15 at 16:40
0

The fig.width and fig.height chunk options can take in multiple values. In your example, there are five plots, so by setting a numeric vector of length five for the widths and heights, and saving the list of ggplot objects, you can have one chunk produce five graphics of different sizes in the final document. An example .Rmd file is below.

---
title: "Variable plot height"
output: word_document
---

Plots:

```{r, echo=FALSE}
library(ggplot2)
library(tidyr) 
data(mtcars)
mtcars$car = row.names(mtcars)
cars = gather(mtcars[1:5, ], variable, value, -c(car, mpg, disp, hp, qsec))

plots <- 
  lapply(unique(cars$car), function(x) { 
           ggplot(cars[cars$car == x, ], aes(variable, value)) + 
                 geom_bar(stat = "identity") 
                              })
widths  <- c(3, 4, 5, 3, 6)
heights <- c(3, 3, 3, 4, 3)
```

```{r show_plots, fig.width = widths, fig.height = heights}
plots
```
Peter
  • 7,460
  • 2
  • 47
  • 68