37
votes

In knitr, one can specify the size of plot by simply specifying it in the chunk options.

For example:

```{r, fig.width=9,fig.height=3}
plot(x)
```

I would like to be able to dynamically adjust the figure height and width on the basis of variables in x. Let's say that x is a data.frame:

x <- data.frame(x=factor(letters[1:3]),y=rnorm(3))

For example's sake lets say I would like to adjust fig.height to be equal to length(unique(x$x))

3

3 Answers

31
votes

You can for example define the width in another chunk, then use it

```{r,echo=FALSE}
x <- data.frame(x=factor(letters[1:3]),y=rnorm(3))
len = length(unique(x$x))
```


```{r fig.width=len, fig.height=6}

plot(cars)
```
12
votes

I just found a great blog post about this.

Read more at Michael J Williams' blog - I've shamelessly pilfered the code, so more detail there. Remember to set chunk options to results = "asis".

Say you want to output a bunch of plots using a loop but you want them to each have different sizes. Define the following function (again, I'm just copy-pasting here):

subchunkify <- function(g, fig_height=7, fig_width=5) {
  g_deparsed <- paste0(deparse(
    function() {g}
  ), collapse = '')

  sub_chunk <- paste0("
  `","``{r sub_chunk_", floor(runif(1) * 10000), ", fig.height=",
   fig_height, ", fig.width=", fig_width, ", echo=FALSE}",
  "\n(", 
    g_deparsed
    , ")()",
  "\n`","``
  ")

  cat(knitr::knit(text = knitr::knit_expand(text = sub_chunk), quiet = TRUE))
}

And use the function like this, defining your own figure sizes:

```{r echo=FALSE, results='asis'}
g <- ggplot(economics, aes(date, unemploy)) + 
  geom_line()
subchunkify(g, 10, 3)
subchunkify(g, 7, 7)
```

Or let the data define the sizes:

```{r echo=FALSE, results='asis'}
g <- ggplot(economics, aes(date, unemploy)) + 
  geom_line()
for (i in seq(2, 5)) {
  subchunkify(g, i / 2, i)
}
```

In the post Michael warns that you must be careful:

Since we’re using results='asis', if we want to output text or headings or anything else from the chunk, we must use raw HTML, not Markdown, and we must use cat() to do this, not print(). For instance:

g <- ggplot(economics, aes(date, unemploy)) + 
  geom_line()

cat('<h2>A Small Square Plot</h2>')
subchunkify(g, 3, 3)

Again, not my work... head on over to that lovely blog post for more details. Hope this works for you.

0
votes

One workaround this problem, especially if you want to change figure parameter within a loop,

  1. Define another chunk, a function which executes the loop
  2. Separately define the figure details in the following chunks

    ```{r, echo=FALSE}
    testFunction <- function (parameter) {
        x <- data.frame(x=c(1:parameter), y=rnorm(parameter))
        g1 <- ggplot(data=x, aes(x=x, y=y)) + geom_point()
        print(g1)
    }
    ```
    
    
    ```{r fig.width=10, fig.height=6}
    testFunction(10)
    ```
    
    
    ```{r fig.width=5, fig.height=4}
    testFunction(4)
    ```