What is preferred way to specify graphics size?

1,230 views
Skip to first unread message

Frank

unread,
Feb 8, 2012, 1:01:24 PM2/8/12
to knitr
I frequently produce graphics whose size I control using for example
pdf(..., width=4, height=3) (sizes are in inches). I see from knitr
documentation how to tell LaTeX what size to use for \includegraphics,
but how do we pass through other arguments to the graphics device
(e.g;., pdf()) that knitr automatically calls?
Thanks
Frank Harrell

Carl Boettiger

unread,
Feb 8, 2012, 1:07:20 PM2/8/12
to Frank, knitr
You can set the R device options globally (in \SweaveOpts) or for any chunk.  e.g. for your example:

\begin{figure}
<<fig=TRUE, dev=pdf, fig.width=4, fig.heigth=3>>=
plot(...)
@
\end{figure}

--
Carl Boettiger
UC Davis
http://www.carlboettiger.info/

Frank

unread,
Feb 8, 2012, 1:11:25 PM2/8/12
to knitr
Super. So do you just prefix any options the device expects with
"fig.", e.g. can you specify fig.ps=13 to change the pointsize for
pdf?

I've enhanced the default knitr plot hook to automatically generate
\begin and \end{figure} if you specify for example <<chunkname,
caption=some caption>>. You don't need fig=TRUE at any rate. I could
not figure out how to get knitr to allow a comma in the caption - it
doesn't allow caption=". . ." or {. . .} or "<. . .>". Unless someone
has a better idea I'll intercept ;; inside caption= and change it to a
comma, inside the hook.

Frank


On Feb 8, 12:07 pm, Carl Boettiger <cboet...@gmail.com> wrote:
> You can set the R device options globally (in \SweaveOpts) or for any
> chunk.  e.g. for your example:
>
> \begin{figure}
> <<fig=TRUE, dev=pdf, fig.width=4, fig.heigth=3>>=
> plot(...)
> @
> \end{figure}
>

Carl Boettiger

unread,
Feb 8, 2012, 1:21:12 PM2/8/12
to Frank, knitr
Good question, I've only seen supported options: http://yihui.name/knitr/options#chunk_options



On Wed, Feb 8, 2012 at 10:11 AM, Frank <harr...@gmail.com> wrote:
Super.  So do you just prefix any options the device expects with
"fig.", e.g. can you specify fig.ps=13 to change the pointsize for
pdf?

I've enhanced the default knitr plot hook to automatically generate
\begin and \end{figure} if you specify for example <<chunkname,
caption=some caption>>.  You don't need fig=TRUE at any rate.  I could
not figure out how to get knitr to allow a comma in the caption - it
doesn't allow caption=". . ." or {. . .} or "<. . .>".  Unless someone
has a better idea I'll intercept ;; inside caption= and change it to a
comma, inside the hook.

interesting.  Is this just to avoid writing the \begin{figure} commands?  seems like it might loose some of the flexibility of the latex figure environment.  Why not add captions with something like
\begin{figure}[ht]
<<chunk dev=pdf fig.width=3>>=
# some plotting code 
@
 \caption{ plotting some stuff}
\label{fig:stuff}
\end{figure}

-C

Frank


On Feb 8, 12:07 pm, Carl Boettiger <cboet...@gmail.com> wrote:
> You can set the R device options globally (in \SweaveOpts) or for any
> chunk.  e.g. for your example:
>
> \begin{figure}
> <<fig=TRUE, dev=pdf, fig.width=4, fig.heigth=3>>=
> plot(...)
> @
> \end{figure}
>
> On Wed, Feb 8, 2012 at 10:01 AM, Frank <harre...@gmail.com> wrote:
> > I frequently produce graphics whose size I control using for example
> > pdf(..., width=4, height=3) (sizes are in inches).  I see from knitr
> > documentation how to tell LaTeX what size to use for \includegraphics,
> > but how do we pass through other arguments to the graphics device
> > (e.g;., pdf()) that knitr automatically calls?
> > Thanks
> > Frank Harrell
>
> --
> Carl Boettiger
> UC Davishttp://www.carlboettiger.info/

Frank

unread,
Feb 8, 2012, 2:17:43 PM2/8/12
to knitr
Hi Carl,

Yes I'm doing this to save \begin{figure} ... \end{figure} but also to
auto-generate \label{fig:chunk label}.

I tried <<.... fig.ps or fig.pointsize>> to no avail. fig.width and
fig.height work fine.

Frank


On Feb 8, 12:21 pm, Carl Boettiger <cboet...@gmail.com> wrote:
> Good question, I've only seen supported options:http://yihui.name/knitr/options#chunk_options
>

Yihui Xie

unread,
Feb 8, 2012, 2:27:30 PM2/8/12
to Frank, knitr
The built-in graphical devices only support three key arguments: width
(fig.width), height (fig.height) and dpi (dpi). I thought these three
were enough... If you want other arguments, you have to write a new
device function, e.g.

my_pdf = function(file, width, height) {
pdf(file, width = width, height = height, pointsize =
opts_current$get('pointsize'))
}

The object opts_current gives you the chunk options for the current
chunk, so you can use any custom options in your hooks or device
functions, e.g.

<<pdf-with-pointsize, dev=my_pdf, width=5, height=4, pointsize=10>>=
plot(1)
@

For the caption problem, I have been thinking on how to deal with
commas as well. You can use other characters to replace commas when
writing the captions, and replace them back to commas in the hook to
get the real captions. For example, use ;; as , and I guess a neater
solution is to be able to escape the comma like \,. I will see what I
can do.

Regards,
Yihui
--
Yihui Xie <xiey...@gmail.com>
Phone: 515-294-2465 Web: http://yihui.name
Department of Statistics, Iowa State University
2215 Snedecor Hall, Ames, IA

Frank

unread,
Feb 8, 2012, 4:04:42 PM2/8/12
to knitr
Great. Just shows how good design pays off!

Can I override the builtin knitr pdf device by giving the function a
special name?

Thanks for working on the comma problem. Something like
<<caption={. . .}>> may be a good syntax. However there are also
occasions where the caption needs to have calculated components. I
just implemented <<caption=@name>> where the contents of R object
"name" is used instead of the literal @name.

Frank


On Feb 8, 1:27 pm, Yihui Xie <xieyi...@gmail.com> wrote:
> The built-in graphical devices only support three key arguments: width
> (fig.width), height (fig.height) and dpi (dpi). I thought these three
> were enough... If you want other arguments, you have to write a new
> device function, e.g.
>
> my_pdf = function(file, width, height) {
>   pdf(file, width = width, height = height, pointsize =
> opts_current$get('pointsize'))
>
> }
>
> The object opts_current gives you the chunk options for the current
> chunk, so you can use any custom options in your hooks or device
> functions, e.g.
>
> <<pdf-with-pointsize, dev=my_pdf, width=5, height=4, pointsize=10>>=
> plot(1)
> @
>
> For the caption problem, I have been thinking on how to deal with
> commas as well. You can use other characters to replace commas when
> writing the captions, and replace them back to commas in the hook to
> get the real captions. For example, use ;; as , and I guess a neater
> solution is to be able to escape the comma like \,. I will see what I
> can do.
>
> Regards,
> Yihui
> --
> Yihui Xie <xieyi...@gmail.com>
> Phone:515-294-2465Web:http://yihui.name

Yihui Xie

unread,
Feb 8, 2012, 4:40:34 PM2/8/12
to Frank, knitr
You can override the default device by setting a global option like
\SweaveOpts{dev=your_dev_name}.

In fact you may not need to evaluate 'name' in @name; there is an
alternative way to do that. You can set

opts_knit$set(eval.opts = c('eval', 'echo', 'caption')) # see
http://yihui.name/knitr/options#package_options

then use

<<>>=
.fig.caption = 'a long long caption here'
<<my-caption, caption=.fig.caption>>=
@

In this case, the caption will be evaluated to the real character string.

Regards,
Yihui
--
Yihui Xie <xiey...@gmail.com>
Phone: 515-294-2465 Web: http://yihui.name


Department of Statistics, Iowa State University
2215 Snedecor Hall, Ames, IA

Frank

unread,
Feb 9, 2012, 9:39:42 AM2/9/12
to knitr
Hi Yihui,

This kind of extensibility is impressive. I did run into a problem
with dev=my customized function:

knit_hooks$set(plot=function (x, options) {
if (!options$include)
return("")
cap <- options$caption # FH
...
})

mpdf <- function(file, width, height) {
g <- function(n, default=NULL, aslist=FALSE) {
w <- opts_current$get(n)
w <- if(length(w)) w else default
if(aslist) structure(list(w), names=n) else w
}
pdf(file, width = width, height = height, pointsize = g('pointsize',
12))
z <- c(g('mfrow', aslist=TRUE), g('bty', 'l', aslist=TRUE),
g('mgp',aslist=TRUE))
if(length(z)) do.call('spar', z) else spar()
}
opts_knit$set(eval.opts = c('eval', 'echo', 'caption')) # allows
symbolic captions
## see http://yihui.name/knitr/options#package_options
options(replace.assign=TRUE)
@

\SweaveOpts{highlight=FALSE, fig.path=figure/graphics-,
fig.align=center, fig.width=4, fig.height=3, fig.show=hold,
comment=NA, dev=mpdf}
. . .

<<>>=
plot(1:10)
@

Error: device name 'mpdf' not supported yet; please go to
https://github.com/yihui/knitr/issues to report this issue
Execution halted

Thanks for your continued help.
Frank



On Feb 8, 3:40 pm, Yihui Xie <xieyi...@gmail.com> wrote:
> You can override the default device by setting a global option like
> \SweaveOpts{dev=your_dev_name}.
>
> In fact you may not need to evaluate 'name' in @name; there is an
> alternative way to do that. You can set
>
> opts_knit$set(eval.opts = c('eval', 'echo', 'caption')) # seehttp://yihui.name/knitr/options#package_options
>
> then use
>
> <<>>=
> .fig.caption = 'a long long caption here'
> <<my-caption, caption=.fig.caption>>=
> @
>
> In this case, the caption will be evaluated to the real character string.
>
> Regards,
> Yihui
> --
> Yihui Xie <xieyi...@gmail.com>
> Phone:515-294-2465Web:http://yihui.name

Yihui Xie

unread,
Feb 9, 2012, 12:30:33 PM2/9/12
to Frank, knitr
Oh, I meant to update the online documentation on how to use a
customized device yesterday but did not manage to do it. Basically you
just define a function, but one important thing to do is to provide
the chunk option fig.ext (file extension of the figure) because I
cannot guess it automatically from a custom device. In your case, you
can use fig.ext=pdf.

Regards,
Yihui
--
Yihui Xie <xiey...@gmail.com>
Phone: 515-294-2465 Web: http://yihui.name


Department of Statistics, Iowa State University
2215 Snedecor Hall, Ames, IA

Frank

unread,
Feb 9, 2012, 1:08:24 PM2/9/12
to knitr
That did the trick!

I could not get symbolic captions to work though:

<<>>=
opts_knit$set(eval.opts = c('eval', 'echo', 'caption')) # allows
symbolic captions
## see http://yihui.name/knitr/options#package_options
options(replace.assign=TRUE)
@

<<>>=
.fig.caption = 'a long long caption here'
@
<<caption=.fig.caption>>=
.fig.caption = 'a long long caption here' # tried doing this
assignment twice
hist(rnorm(1000), nclass=20)
@

The caption still comes out as ".fig.caption"

Frank


On Feb 9, 11:30 am, Yihui Xie <xieyi...@gmail.com> wrote:
> Oh, I meant to update the online documentation on how to use a
> customized device yesterday but did not manage to do it. Basically you
> just define a function, but one important thing to do is to provide
> the chunk option fig.ext (file extension of the figure) because I
> cannot guess it automatically from a custom device. In your case, you
> can use fig.ext=pdf.
>
> Regards,
> Yihui
> --
> Yihui Xie <xieyi...@gmail.com>
> Phone:515-294-2465Web:http://yihui.name
> Department of Statistics, Iowa State University
> 2215 Snedecor Hall, Ames, IA
>
>
>
>
>
>
>
> On Thu, Feb 9, 2012 at 8:39 AM, Frank <harre...@gmail.com> wrote:
> > Hi Yihui,
>
> > This kind of extensibility is impressive.  I did run into a problem
> > with dev=my customized function:
>
> > knit_hooks$set(plot=function (x, options) {
> >  if (!options$include)
> >    return("")
> >  cap <- options$caption   # FH
> > ...
> > })
>
> > mpdf <- function(file, width, height) {
> >  g <- function(n, default=NULL, aslist=FALSE) {
> >    w <- opts_current$get(n)
> >    w <- if(length(w)) w else default
> >    if(aslist) structure(list(w), names=n) else w
> >  }
> >  pdf(file, width = width, height = height, pointsize = g('pointsize',
> > 12))
> >  z <- c(g('mfrow', aslist=TRUE), g('bty', 'l', aslist=TRUE),
> > g('mgp',aslist=TRUE))
> >  if(length(z)) do.call('spar', z) else spar()
> > }
> > opts_knit$set(eval.opts = c('eval', 'echo', 'caption')) # allows
> > symbolic captions
> > ## seehttp://yihui.name/knitr/options#package_options
> > options(replace.assign=TRUE)
> > @
>
> > \SweaveOpts{highlight=FALSE, fig.path=figure/graphics-,
> > fig.align=center, fig.width=4, fig.height=3, fig.show=hold,
> > comment=NA, dev=mpdf}
> > . . .
>
> > <<>>=
> > plot(1:10)
> > @
>
> > Error: device name 'mpdf' not supported yet; please go to
> >https://github.com/yihui/knitr/issuesto report this issue

Yihui Xie

unread,
Feb 9, 2012, 2:09:20 PM2/9/12
to Frank, knitr
Sorry this is a bug in the object opts_current. It should have been
created _after_ the options have been evaluated. I have fixed it in
the development version: https://github.com/yihui/knitr Now you should
be able to use opts_current$get('caption') to get the real caption
string.

Or alternatively, you can use the argument 'options' in the hook
function; it is always the evaluated version.

knit_hooks$set(caption = function(before, options, envir) {
if (!before) paste('\\caption{', options$caption, '}')
})

Theoretically 'options' in the hook function should be identical to
opts_current$get(), but due to that bug, they are not. The fix will
appear in v0.3 on CRAN about two weeks later.

Regards,
Yihui
--
Yihui Xie <xiey...@gmail.com>
Phone: 515-294-2465 Web: http://yihui.name


Department of Statistics, Iowa State University
2215 Snedecor Hall, Ames, IA

Frank

unread,
Feb 10, 2012, 9:08:21 AM2/10/12
to knitr
Thanks Yihui,

It took me a while to figure out how to install the beta version:

sudo apt-get install libcurl3-dev
install.packages('devtools', repos = "http://cran.case.edu", lib =
"/usr/local/lib/R/site-library",dependencies=TRUE)
require(devtools); install_github('knitr', 'yihui')

But the new version has a new bug, I think:

<<>>=
opts_knit$set(eval.opts = c('eval', 'echo', 'caption')) # allows
symbolic captions
@

<<caption=A B>>=
plot(1:5)
@

Error in parse(text = x) : 1:3: unexpected symbol
1: A B

Frank

On Feb 9, 1:09 pm, Yihui Xie <xieyi...@gmail.com> wrote:
> Sorry this is a bug in the object opts_current. It should have been
> created _after_ the options have been evaluated. I have fixed it in
> the development version:https://github.com/yihui/knitrNow you should
> be able to use opts_current$get('caption') to get the real caption
> string.
>
> Or alternatively, you can use the argument 'options' in the hook
> function; it is always the evaluated version.
>
> knit_hooks$set(caption = function(before, options, envir) {
>   if (!before) paste('\\caption{', options$caption, '}')
>
> })
>
> Theoretically 'options' in the hook function should be identical to
> opts_current$get(), but due to that bug, they are not. The fix will
> appear in v0.3 on CRAN about two weeks later.
>
> Regards,
> Yihui
> --
> Yihui Xie <xieyi...@gmail.com>
> Phone:515-294-2465Web:http://yihui.name
> Department of Statistics, Iowa State University
> 2215 Snedecor Hall, Ames, IA
>
>
>
>
>
>
>
> On Thu, Feb 9, 2012 at 12:08 PM, Frank <harre...@gmail.com> wrote:
> > That did the trick!
>
> > I could not get symbolic captions to work though:
>
> > <<>>=
> > opts_knit$set(eval.opts = c('eval', 'echo', 'caption')) # allows
> > symbolic captions
> > ## seehttp://yihui.name/knitr/options#package_options

Yihui Xie

unread,
Feb 10, 2012, 12:44:30 PM2/10/12
to Frank, knitr
devtools depends on RCurl which depends on libcurl; I will suggest
Hadley consider dropping this dependency because all devtools needs
from RCurl is to be able to download files from the https protocol.

An alternative way to install the beta version is to download the tar
ball and run R CMD INSTALL:
https://github.com/yihui/knitr/tarball/master Perhaps this is not
clear enough in https://github.com/yihui/knitr#readme

'A B' is not a legal R expression, so parse() cannot parse it; I'm not
sure if this should be considered as a bug, because 'eval.opts' means
the option will be evaluated like an R expression. What do you expect
knitr to behave in this case?

Regards,
Yihui
--
Yihui Xie <xiey...@gmail.com>
Phone: 515-294-2465 Web: http://yihui.name


Department of Statistics, Iowa State University
2215 Snedecor Hall, Ames, IA

Frank

unread,
Feb 10, 2012, 12:52:13 PM2/10/12
to knitr
Thanks - the tarball install is simpler but devtools is working too.

Before I updated to the beta version I could specify <<. . . .,
caption=A long caption with many words>> and everything worked fine as
long as the caption did not contain comma. Now I can't do that, so
something must have changed just in the beta version. Or maybe fixing
the bug where the caption symbol wasn't evaluated early enough caused
this problem. If I just enclose the caption in single or double
quotes now it works, but a comma is not allowed inside the string.

Frank


On Feb 10, 11:44 am, Yihui Xie <xieyi...@gmail.com> wrote:
> devtools depends on RCurl which depends on libcurl; I will suggest
> Hadley consider dropping this dependency because all devtools needs
> from RCurl is to be able to download files from the https protocol.
>
> An alternative way to install the beta version is to download the tar
> ball and run R CMD INSTALL:https://github.com/yihui/knitr/tarball/masterPerhaps this is not
> clear enough inhttps://github.com/yihui/knitr#readme
>
> 'A B' is not a legal R expression, so parse() cannot parse it; I'm not
> sure if this should be considered as a bug, because 'eval.opts' means
> the option will be evaluated like an R expression. What do you expect
> knitr to behave in this case?
>
> Regards,
> Yihui
> --
> Yihui Xie <xieyi...@gmail.com>
> Phone:515-294-2465Web:http://yihui.name

Yihui Xie

unread,
Feb 10, 2012, 12:56:49 PM2/10/12
to Frank, knitr
Hmm... Writing the caption in quotes is actually a simple and smart
trick that I did not think of :)

Commas will be allowed soon but they have to be escaped. I'm working
on it: https://github.com/yihui/knitr/issues/128

Regards,
Yihui
--
Yihui Xie <xiey...@gmail.com>
Phone: 515-294-2465 Web: http://yihui.name


Department of Statistics, Iowa State University
2215 Snedecor Hall, Ames, IA

Frank Harrell

unread,
Feb 10, 2012, 1:01:26 PM2/10/12
to knitr
Great. In other contexts you can put commas inside quoted strings
without escaping them. I hope that can be accomplished someday.

Best regards and keep up the fantastic work,
Frank


On Feb 10, 11:56 am, Yihui Xie <xieyi...@gmail.com> wrote:
> Hmm... Writing the caption in quotes is actually a simple and smart
> trick that I did not think of :)
>
> Commas will be allowed soon but they have to be escaped. I'm working
> on it:https://github.com/yihui/knitr/issues/128
>
> Regards,
> Yihui
> --
> Yihui Xie <xieyi...@gmail.com>
> Phone:515-294-2465Web:http://yihui.name

Yihui Xie

unread,
Feb 11, 2012, 5:45:21 PM2/11/12
to Frank Harrell, knitr
Literal commas can be written as \, now in the devel version.

It is entirely possible to implement your idea (use commas in quoted
strings), but I'd like to keep the syntax consistent -- whenever a
comma has its literal meaning, it must be escaped. Otherwise we have
to remember when to escape it and when not to.

I hope this is an acceptable solution.

Regards,
Yihui
--
Yihui Xie <xiey...@gmail.com>
Phone: 515-294-2465 Web: http://yihui.name


Department of Statistics, Iowa State University
2215 Snedecor Hall, Ames, IA

Jack Tanner

unread,
Feb 11, 2012, 6:15:05 PM2/11/12
to kn...@googlegroups.com
On 2/11/2012 5:45 PM, Yihui Xie wrote:
> Literal commas can be written as \, now in the devel version.
>
> It is entirely possible to implement your idea (use commas in quoted
> strings), but I'd like to keep the syntax consistent -- whenever a
> comma has its literal meaning, it must be escaped. Otherwise we have
> to remember when to escape it and when not to.
>
> I hope this is an acceptable solution.

It would be consistent with R syntax to evaluate "naked" identifiers,
and require strings to be quoted. But that's probably too invasive a
change to knitr at this point.

Frank Harrell

unread,
Feb 11, 2012, 11:39:10 PM2/11/12
to knitr
Yes it's better than my kluge of translating ;; to ,

If you later find an easy way to allow unquoted commas in quoted
strings, even better, but your solution is fine with me.

Best,
Frank


On Feb 11, 4:45 pm, Yihui Xie <xieyi...@gmail.com> wrote:
> Literal commas can be written as \, now in the devel version.
>
> It is entirely possible to implement your idea (use commas in quoted
> strings), but I'd like to keep the syntax consistent -- whenever a
> comma has its literal meaning, it must be escaped. Otherwise we have
> to remember when to escape it and when not to.
>
> I hope this is an acceptable solution.
>
> Regards,
> Yihui
> --
> Yihui Xie <xieyi...@gmail.com>
> Phone:515-294-2465Web:http://yihui.name
Reply all
Reply to author
Forward
0 new messages