14

Hi I would like to change chunk options, mid chunk, without having to create a new chunk..

running the following code I would expect to get two very different size outputs, but for some reason this does not seem to be the case.

Also the second plot doesn't plot at all...(it does when you change it to plot(2:1000)...but either way the second output is the same size as the first. both fig.width=7. What am I doing wrong?

Pls note the importance of 'mid chunk' the reason for this is that I would like to change the chunk options several times when running a function to get different outputs of different sizes.

```{r}
sessionInfo()

opts_chunk$set(fig.width=3)

plot(1:1000)

opts_chunk$set(fig.width=10)

plot(1:1000)

```

the sessionInfo output is as follows:

## R version 2.15.1 (2012-06-22)
## Platform: i386-pc-mingw32/i386 (32-bit)
## 
## locale:
## [1] LC_COLLATE=English_United Kingdom.1252 
## [2] LC_CTYPE=English_United Kingdom.1252   
## [3] LC_MONETARY=English_United Kingdom.1252
## [4] LC_NUMERIC=C                           
## [5] LC_TIME=English_United Kingdom.1252    
## 
## attached base packages:
## [1] stats     graphics  grDevices datasets  utils     methods   base     
## 
## other attached packages:
## [1] knitr_0.7
## 
## loaded via a namespace (and not attached):
## [1] digest_0.5.2   evaluate_0.4.2 formatR_0.5    parser_0.0-16 
## [5] plyr_1.7.1     Rcpp_0.9.13    stringr_0.6    tools_2.15.1  

html preview

Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
h.l.m
  • 13,015
  • 22
  • 82
  • 169
  • 1
    in theory I could allow you to use `fig.width=c(3, 10)` and save the two plots in 3 and 10 inches respectively, but the problem is when I record the plots, I can only use one size per chunk, so your plots may not look right if the the recording size and the drawing size are different (see the [graphics manual](https://github.com/downloads/yihui/knitr/knitr-graphics.pdf) for details) – Yihui Xie Jul 26 '12 at 14:33
  • http://stackoverflow.com/q/11653573/559676 should be a good example to show you how to construct code chunks in a programmable fashion and knit them; it can be more complicated than that case, but you can do it anyway – Yihui Xie Jul 26 '12 at 15:05

2 Answers2

9

This works for me, based on hints from Yui on github.

\documentclass{article}

\begin{document}
<<setup,echo=FALSE>>=
opts_knit$set(progress = F, verbose = F)
opts_chunk$set(comment=NA, warning=FALSE,message=FALSE,fig.width=6, echo=F)
kexpand=function(){
  cat(knit(
  text=knit_expand(text=
                     "<<yfig-{{cap}}-,fig.cap='{{cap}}',results='markup',echo=FALSE,fig.height={{figheight}},out.height={{outheight}}>>=\n
                   .q\n
                   @"
  )
))}
@

<<results='asis'>>=
library(ggplot2)
.q=qplot(1:10);cap="first caption";figheight=9;outheight=90
kexpand()
.q=qplot(1:20);cap="second caption";figheight=12;outheight=160
kexpand()

@
\end{document}

So one key thing is to set progress and verbose to F otherwise they destroy the output. Then the little function kexpand expands an inline template which is typed as text as part of the function. Then you can define your plot as .q and your caption as cap, and your heights etc. You could adapt the function to control other options. Strangely, .q and the caption don't have to be parameters for the function, you can just set them in the current environment and they get picked up by the function anyway. Don't know if this is good practice or why it works but it does.

Steve Powell
  • 1,646
  • 16
  • 26
  • For some reason, this only works for me if I follow your example exactly. If I have plots other than ggplot, (base R, metafor forest plot) it doesn't work. Even weirder, if I have the heights in a vector and loop through the vector creating figures, it does not work either. Do you have any idea if your method can be changed to work for my case? http://stackoverflow.com/questions/37998364 – rumtscho Jun 23 '16 at 19:24
5

Two questions: When you want both figures to be keep, use

```{r fig.keep='all'}

Default only keeps the unique plots (because your two plots are identical, the second one is removed; see the knitr graphics manual for details).

Global chunk options are active when the next chunk(s) open:

```{r}
opts_chunk$set(fig.width=10)
```


```{r}
opts_chunk$set(fig.width=2)
# Our figure is 10 wide, not 2
plot(1:1000)
```

```{r}
# Our figure is 2 wide, not 10
opts_chunk$set(fig.width=10)
plot(1:1000)
```
Yihui Xie
  • 28,913
  • 23
  • 193
  • 419
Dieter Menne
  • 10,076
  • 44
  • 67
  • Agreed on the `fig.keep='all'` part. Thanks for that, I appreciate it...but the whole point of the main part of the question was NOT to break up the code into separate chunks...as I mentioned, I am running a single function that produces different size output images to be created and setting the `fig.width` for the whole chunk to be ok for some images makes others either too small or too big, thus I wanted to edit the code to put a `opts_current$set(fig.width=x)` in between the plots in the function. – h.l.m Jul 26 '12 at 14:03
  • @h.l.m the short answer is no, it is not possible to use `opts_current` in that way. – Yihui Xie Jul 26 '12 at 15:00
  • @Yihui the lack of ability to change chunk options mid chunk...is that likely to change or is that going to remain? Is it possible to request it as an enhancement for the future...? – h.l.m Jul 27 '12 at 02:03
  • @h.l.m at best I can support `fig.width=a_numeric_vector`, but that will not be an ideal solution; it gives you the correct output size but not the original recording size; figures may look ugly in that way. If that is acceptable, a github issue is fine – Yihui Xie Jul 27 '12 at 04:40