kfigr
provides cross-referencing functionality for Rmarkdown documents by creating HTML anchor tags for code chunks. kfigr
is designed to provide a simple and flexible indexing system integrated seamlessly with knitr
.
kfigr
provides just one function and one hook (code chunk option) to anchor a chunk. Any chunk can be anchored regardless of the output. Chunk labels are used for indexing, so there is no way to get confused about what you are referencing. Defining anchors as a chunk option forces users to write distinct chunks for any referenced output, which improves readability of the source document. Users have complete flexibility to define numbering groups for distinguishing between e.g. figures and tables.
kfigr
defines a custom hook, anchor
, which is used to decide how to track the chunk. We use this hook to define a “type” for the chunk. For instance, if I create a plot and want to refer it later I can pass the chunk option anchor="figure"
. kfigr
uses the chunk label to generate an HTML anchor tag above the chunk and assigns a number to the chunk based on its type. As an example, consider the following chunk.
require(ggplot2)
qplot(rnorm(100), geom="histogram")
I named the chunk “first-chunk” and used the chunk option anchor="figure"
. Now, I will use the function figr('first-chunk')
in an inline chunk to reference the chunk here: 1. The figr
function returns the number of the referenced chunk as a markdown link, e.g. [1](#first-chunk)
. kfigr
keeps track of reference numbers by tracking the chunk placement sequence separately for each “type”. Note that the value of the anchor
option is case sensitive, so “Figure” is different from “figure”.
If you need to, you can reference a chunk before you define it. You must specify the “type” when referencing a later chunk, and it is up to you to ensure every chunk you reference is defined. Furthermore, if you want to refer to e.g. the sixth “figure” chunk, you must first reference chunks 1-5 of type “figure”. This can be done inline using invisible(figr(...))
. This limitation is due to the way markdown documents are rendered; if you need smarter referencing capabilities, consider using LaTeX (Rnw) instead of markdown (Rmd).
You can pass prefix=TRUE
or change the global options to get a full label, e.g. figure 2.
qplot(runif(100), geom="density")
You can reference any kind of chunk output, and specify any “type” of chunk. For example, look at table 1:
kable(head(iris, 6))
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa |
4.9 | 3.0 | 1.4 | 0.2 | setosa |
4.7 | 3.2 | 1.3 | 0.2 | setosa |
4.6 | 3.1 | 1.5 | 0.2 | setosa |
5.0 | 3.6 | 1.4 | 0.2 | setosa |
5.4 | 3.9 | 1.7 | 0.4 | setosa |
Anchoring even works for chunks that use the ref.label
option. For instance, consider the following code:
x = 1:20
y = x + rnorm(20)
lm(y~x)
I have not anchored the above chunk and the code was not evaluated because I used the chunk option eval=FALSE
. If I had used echo=FALSE
you would have no idea that the chunk even existed! But I can reproduce the chunk by creating an empty chunk with the same name (see the knitr
documentation for more details) and anchor the empty chunk, as shown in block 1.
x = 1:20
y = x + rnorm(20)
lm(y~x)
##
## Call:
## lm(formula = y ~ x)
##
## Coefficients:
## (Intercept) x
## 0.1616 1.0013
If you want to reference both the code and the output of a chunk separately you can use the chunk option ref.label
and specify an anchor for each referring chunk. Below, I create a hidden chunk and reference it using eval=FALSE to produce the code block. I then reference the hidden chunk a second time using echo=FALSE to produce only the output.
df <- data.frame(x=x, y=y)
ggplot(df, aes(x=x, y=y)) + geom_smooth(method="lm") +
geom_point(pch=21, color="black", fill="red")
You can verify that block 2 and figure 3 are distinct.
kfigr
tracks references internally. If you want to get a list of indexed chunks, you can use anchors()
to return a structure that lists the labels by type, a reference history, and an index, as shown in block 3. The history
attribute can be helpful for troubleshooting problems with document references.
anchors("index")
## label type number
## 1 first-chunk figure 1
## 2 second-chunk figure 2
## 3 third-chunk table 1
## 4 fourth-chunk block 1
## 5 fifth-code block 2
## 6 fifth-plot figure 3
## 7 last-chunk block 3
anchors("history")
## label type number referenced.by
## 1 first-chunk figure 1 hook_anchor
## 2 first-chunk figure 1 figr
## 3 second-chunk figure 2 figr
## 4 second-chunk figure 2 hook_anchor
## 5 third-chunk table 1 figr
## 6 third-chunk table 1 hook_anchor
## 7 fourth-chunk block 1 figr
## 8 fourth-chunk block 1 hook_anchor
## 9 fifth-code block 2 hook_anchor
## 10 fifth-plot figure 3 hook_anchor
## 11 fifth-code block 2 figr
## 12 fifth-plot figure 3 figr
## 13 last-chunk block 3 figr
## 14 last-chunk block 3 hook_anchor
kfigr
uses knitr
options to maintain global default settings. kfigr
option names are identified by the prefix “kfigr”. Two options are available: kfigr.link
to display a link to the anchor in citations; and kfigr.prefix
to include the prefix when referencing. These options can be changed using opts_knit$get
and opts_knit$set
. Any global options set within a chunk will not be available in that particular chunk (see the knitr
documentation for more details).
An important limitation of tangle
is that inline code chunks are not evaluated. Under most circumstances the tangled code should produce the same reference numbers as the knitted document, but discrepancies will appear if you have forgotten to invisibly reference intermediate chunks, or have anchored chunks in a different order than referenced.
Take a look at the .Rmd source file for this vignette and all should become clear.