%\VignetteEngine{knitr::knitr} %\VignetteIndexEntry{figr-showcase}
require(knitr, quietly=TRUE) opts_chunk$set(message=FALSE, warning=FALSE, tidy=FALSE)
figr
is designed to be a simple figure and table reference manager for markdown documents. The package provides automatic numbering of document elements (figures and tables) and allows you to cite, cross-reference (i.e. link) and label (i.e. caption) these elements. Functionality for inserting figures from external files is also provided.
The package is designed to be used with the knitr
package and uses both markdown syntax and HTML tags to provide cross-referencing and within-document linking to figures and tables. knitr
hooks are defined to allow anchoring and figure captioning via chunk options.
The package is designed to be easily extendable to other distinct types of document elements, e.g. animations, videos or interactive objects (TODO: add referencing functionality for code chunks). This vignette provides a tour of the main features of figr
.
We will first show how figr
tracks figures in a document. First, create a plot as you would normally would in a knitr
document. This is most easily done using the ggplot2
package:
require(ggplot2) p = qplot(rnorm(500),geom="histogram")
Next, we index it using figr
:
require(figr) addFigure('normal', p, caption='500 draws from a normal distribution.') # note that figr makes a copy of the plot object rm(p)
A number has not been assigned to the figure yet. Using addFigure
simply registers the plot with figr
for future use. Registering the plot with figr
allows you to place figures using labels, rather than requiring that you remember the variable name itself. This is analogous to \label{}
in LaTeX.
figr
provides cross-referencing capability using the HTML anchor (<a>
) tag. figr
defines a new knitr
code chunk option, anchor
, to write an anchor element to the document for rendering. A simplified definition of the anchor hook provided by figr
is shown below. figr
defines this hook when it is loaded so you do can immediately use the anchor
option after loading figr.
knitr::knit_hooks$set(anchor = function(before, options, envir) { if (before) paste('<a name="', options$anchor, '"></a>', sep='') })
Note that the anchors are placed above the code chunk because we are using if(before)
to specify that the hook is evaluated before the code chunk itself. (You can redefine the hook to place the anchor below the chunk by using if(!before)
instead). We can automatically generate an anchor that will match a figure object using with anchorFigure(figure name)
.
You can place a figure and assign it a number with placeFigure(figure name)
(as shown below) and simultaneously create an anchor for the plot. Note that the following code chunk includes the option anchor=anchorFigure('normal')
in its header.
placeFigure('normal')
figr
determines figure numbers by ranking them based on the order they are placed or cited in the document. When placeFigure
is called, the referenced object is assigned a rank (if it does not have one already--see next paragraph). We can reference a figure, e.g. r citeFigure("normal")
(I just did!) using citeFigure(figure name)
in an inline code chunk. Note that anchoring also updates a figure rank, so the addFigure
and placeFigure
functions are not technically needed if you will not need to reproduce the figure again later (i.e. in an appendix).
Calling placeFigure()
or citeFigure()
a second time will not change the rankings. This is the result of code that allows a figure to be cited before it is placed. A figure is not ranked until it is placed, cited or anchored, so if for some reason you need to refer to a later figure you must cite or place any intervening figures first. Note that you can cite a figure before placing or even creating the figure:r invisible(citeFigure('lognormal'))
# you can also do this inline! invisible(citeFigure('lognormal'))
Now we can reference the later plot, r citeFigure('gamma')
, before placing the one we just invisibly cited (r citeFigure('lognormal')
).
p2 = qplot(rlnorm(500), geom="histogram") addFigure('lognormal', p2, '500 draws from a lognormal distribution.') placeFigure('lognormal')
And now we'll place r citeFigure('gamma')
:
p3 = qplot(rgamma(500, 3), geom='histogram') addFigure('gamma', p3, '500 draws from a gamma distribution.') placeFigure('gamma')
As you can see, placing, anchoring and referencing figures is straightforward. Note that due to the way knitr
evaluates a document, automatic generation of a list of figures in the front matter of a document is not possible. However, it would be simple to write a function to generate a list of figures at the end of a document, or even write all referenced figures to the end matter of a document. If you are creating a document that requires a list of figures in the front matter of a document, you may want to consider using LaTeX instead of Markdown.
So far we have ignored figure captions. figr
also defines a new knitr
hook for adding captions to a figure. The hook definition is shown below, but you do not need to define this hook yourself as figr
defines it on load.
knit_hooks$set(plot = function(x, options) { paste('<figure><img src="', knitr::opts_knit$get('base.url'), paste(x, collapse = '.'), '"><figcaption>', text=options$fig.cap, '</figcaption></figure>', sep = '') }) opts_knit$set(eval.after='fig.cap')
Note that the hook definition allows the figure caption to be generated within the referenced code chunk thanks to the eval.after
option. The fig.caption
hook will likely be included in a future knitr release (> version 1.6).
A figure caption can be referenced using labelFigure(figure name)
(recall that we defined the caption when we registered the figure using addFigure
). an anchor link is placed within the caption itself; Having the link in the caption is not really useful, but it is nice for labelling consistency. In r citeFigure('chisquared')
below, the chunk options fig.cap=labelFigure('chisquared')
and anchor=anchorFigure('chisquared')
are used.
addFigure('chisquared', qplot(rchisq(500, 3), geom='histogram'), '500 draws from a Chi-squared distribution.') placeFigure('chisquared')
Placing an external image in a markdown document is straightforward from an HTML standpoint, but requires specific formatting to take advantage of the figr
and knitr
packages. Placing an external image as a figure is similar to placing an R plot object, but uses the function ExternalFigure
instead of placeFigure
. Furthermore, it requires that the code chunk results
option is specified 'asis'
. When adding an external image as a Figure using addFigure
, the path to the file is specified instead of an R plot object in the call to addFigure
. figr
automatically copies or downloads this file into knitr
's fig.path
directory. In r citeFigure('external')
below, the chunk options fig.cap=labelFigure('external')
, anchor=anchorFigure('external')
, and results='asis'
are used.
# note that you can place other links in a caption using regular markdown syntax! addFigure('external', 'http://upload.wikimedia.org/wikipedia/commons/5/5f/Pantheon_Rome_miniature_XV.jpg', 'an image from [Wikipedia](http://en.wikipedia.org/wiki/Piazza_della_Rotonda).') ExternalFigure("external", caption=TRUE)
Note that when adding a caption to an external figure, labelFigure
is called internally by placeTable
when caption=TRUE
(rather than being used through a code chunk option). externalFigure
also accepts arguments for figure height
and width
, in inches (same units as knitr
's fig.width
and fig.height
chunk options). If height
or width
are not specified, the knitr
global settings are assumed.
figr
provides identical functionality (e.g. addTable
, citeTable
, etc.) for kable objects, as shown by r citeTable('example')
. Note that tables can have identical names to figures without risk of overwriting. Remember that when printing kable tables, the code chunk results must be specified 'asis'.
# note only the dataframe is passed to addTable d = head(iris[,1:5]) addTable('example', d, caption='The first five rows of the [iris](http://stat.ethz.ch/R-manual/R-patched/library/datasets/html/iris.html) dataset.') placeTable('example', caption=TRUE)
Note that table captioning is handled slightly differently, as the table caption is defined in the call to kable
. A labelTable function is defined for symmetry with labelFigure
but is called internally by placeTable
when caption=TRUE
, rather than being used through a code chunk option (similar to adding captions with externalFigure
).
figr
also enables you to cross-reference and anchor chunks. Chunks can be cited and anchored in the same manner as figures and tables using the citeChunk
and addChunk
functions. However, usershould consider the following when citing chunks:
anchor=paste(anchorFigure('example'), anchorChunk('example'))
). This means that multiple anchors will be indistinguishable. It may be preferable to split example code and outputs into separate chunks for anchoring.labelChunk
function).The third point can create some confusion when a user selectively anchors chunks. For example, r citeChunk('cite-chunk')
below is clearly not the first chunk in the document, but it is the first cited chunk. However, anchored chunks are not visually distinguished from non-anchored chunks, which may make it difficult for users to refer to specific chunks when linking is not available. It may therefore be desirable to format anchored chunks differently from standard chunks. This could perhaps be achieved using some kind of frame, and using the term "blocks" to refer to anchored chunks.
An example of chunk anchoring is shown below. As an additional shortcut, passing the chunk option anchor=TRUE
allows the user to anchor and register a chunk using its label
option.
knit_hooks$set(anchor = function(before, options, envir) { if (before){ if(is.character(options$anchor)) paste('<a name="', options$anchor, '"></a>', sep='') else if(as.logical(options$anchor)) paste('<a name="', anchorChunk(options$label), '"></a>', sep='') } }) opts_chunk$set(anchor=FALSE)
# You can cite chunks even if they are not evaluated # label = 'cite-chunk' paste(opts_current$get('label'), ' ', opts_current$get('anchor'))
Referencing a chunk that references another chunk using the ref.label
chunk option is equivalent to the expected behavior of a placeChunk
function. Chunks that refer to other chunks (like r citeChunk('refer-chunk')
) are given their own rank. Note that r citeChunk('refer-chunk')
uses the options ref.label='cite-chunk'
and anchor=anchorChunk('refer-chunk')
.
Beware that there are no checks for whether an anchored chunk is evaluated or even echoed. Anchoring non-echoed chunks will be cause them to be ranked and an anchor to appear where the code block would be placed if echo=TRUE
. The definition of the anchor hook is shown in r citeChunk('redefine-anchor')
. Note that the chunk shown is actually a reference to a hidden chunk I defined earlier by creating an empty chunk with the same name as the hidden chunk and using anchor=TRUE`.
figr
check that an anchor has not already been created (what happens when you define duplicate anchors in a page?)opts_figr$set("link", FALSE)
)knitr
's figure folder using knitr::fig.path
. Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.