R Markdown HTML Number Figures

前端 未结 4 654
[愿得一人]
[愿得一人] 2020-12-01 08:40

Does anyone know how to number the figures in the captions, for HTML format R Markdown script?

For PDF documents, the caption will say something like:

相关标签:
4条回答
  • 2020-12-01 08:59

    So unless someone has a better solution, this is the solution that I came up with, there are some flaws with this approach (for example, if the figure/table number is dependent on the section number etc...), but for the basic html document, it works.

    Somewhere at the top of you document, run this:

    ```{r echo=FALSE}
    #Determine the output format of the document
    outputFormat   = opts_knit$get("rmarkdown.pandoc.to")
    
    #Figure and Table Caption Numbering, for HTML do it manually
    capTabNo = 1; capFigNo = 1;
    
    #Function to add the Table Number
    capTab = function(x){
      if(outputFormat == 'html'){
        x = paste0("Table ",capTabNo,". ",x)
        capTabNo <<- capTabNo + 1
      }; x
    }
    
    #Function to add the Figure Number
    capFig = function(x){
      if(outputFormat == 'html'){
        x = paste0("Figure ",capFigNo,". ",x)
        capFigNo <<- capFigNo + 1
      }; x
    }
    ```
    

    Then during the course of your document, if say you want to plot a figure:

    ```{r figA,fig.cap=capFig("My Figure Caption")
    base = ggplot(data=data.frame(x=0,y=0),aes(x,y)) + geom_point()
    base
    ```
    

    Substitute the capFig to capTab in the above, if you want a table caption.

    0 讨论(0)
  • 2020-12-01 08:59

    We can make use of pandoc-crossref, a filter that allows a cross-referencing of figures, tables, sections, and equations and works for all output format. The easiest way is to cat the figure label (in the form of {#fig:figure_label}) after each plot, although this requires echo=FALSE and results='asis'. Then we can reference a figure as we would a citation : [@fig:figure_label] produces fig. figure_number by default.

    Here is a MWE:

    ---
    output: 
      html_document:
        toc: true
        number_sections: true
        fig_caption: true
        pandoc_args: ["-F","pandoc-crossref"]
    ---
    
    ```{r}
    knitr::opts_chunk$set(echo=FALSE,results='asis')
    
    ```
    
    
    ```{r plot1,fig.cap="This is plot one"}
    x <- 1:10
    y <- rnorm(10)
    plot(x,y)
    cat("{#fig:plot1}")
    
    ```
    
    As we can see in [@fig:plot1]... whereas [@fig:plot2] shows...
    
    ```{r plot2, fig.cap="This is plot two"}
    plot(y,x)
    cat("{#fig:plot2}")
    
    ```
    

    which produces (removing the graphics

    PLOT1

    Figure 1: This is plot one

    As we can see in fig. 1… whereas fig. 2 shows…

    PLOT2

    Figure 2: This is plot two

    See the pandoc-crossref readme for more options and customizations.

    To install pandoc-crossref, assuming you have a haskell installation:

    cabal update
    cabal install pandoc-crossref
    
    0 讨论(0)
  • 2020-12-01 09:06

    I solve cross-referencing using a solution similar to that posted by Nicholas above. I use bookdown for some projects but I find that awkward to use for other projects where I just want simple cross-referencing.

    I use the following when I am writing a paper with rmarkdown and I want it in standard format for submission to a journal. I want a figure legend at the end, then tables, then I'll have the tables and figures. As I am writing, I only have a rough idea of what order the figures will be referenced in the text. I just want to reference them with a text code like fig:foobar and have the number assigned based appearance in the text. When I look at the figure legend list, I'll see what order to put the legends and will move legends around as needed.

    Here's my structure.

    I have an R package where I have things I need for papers, like various bibliographies and helper R functions. In that package, I have the following function which uses some variables defined in the main Rmd environment: .rmdenvir and .rmdctr .

    ref <- function(useName) {
    require(stringr)
    if(!exists(".refctr")) .refctr <- c(`_` = 0)
    if(any(names(.refctr)==useName)) return(.refctr[useName])
    type=str_split(useName,":")[[1]][1]
    nObj <- sum(str_detect(names(.refctr),type))
    useNum <- nObj + 1
    newrefctr <- c(.refctr, useNum)
    names(newrefctr)[length(.refctr) + 1] <- useName
    assign(".refctr", newrefctr, envir=.rmdenvir)
    return(useNum)
    }
    

    It assumes that I name things I want referenced with something like cntname:foo, for example fig:foo. It makes a new counter for each one and I can make up new counters on the fly (while writing) if needed.

    In my main Rmd file, I have some set-up lines:

        ```{r setup_main}
        require(myPackageforPapers)
        # here is where the variables needed by ref() are defined.
        .rmdenvir = environment()
        .refctr <- c(`_` = 0)
        ````
    

    In the text I use the following

        You can see what I am trying to show in Figure `r ref("fig:foo")`
        and you can see it also in Tables `r ref("tab:foo")` 
        and A`r ref("tabappA:foobig")`.
    

    to get "You can see what I am trying to show in Figure 1 and you can see it also in Tables 1 and A1." Although the numbers might not be 1; the number to use will be dynamically determined. I don't have to use a special function for the first time I reference a figure, table or whatever I am counting. ref() figures that out by looking to see if the label exists already. If not it assigns the next number, and returns it. So you don't have to use "label" in one place and "ref" in another.

    In the course of writing, I might decide that appendix A is getting too big, and that I will split off some of the tables into an appendix B. All I need to do is change the above to

        You can see what I am trying to show in Figure `r ref("fig:foo")`
        and you can see it also in Tables `r ref("tab:foo")` 
        and B`r ref("tabappB:foobig")`.
    

    I just specify a new counter name 'tabappB' and the numbers for that are dynamically determined.

    At the end of my Rmd file, I have a figure list that will look like

        # Figure Legends
    
        Figure `r ref("fig:foo")`. This is the legend for this figure.
    
        Figure  `r ref("fig:foo2")`. This is the legend for another figure.
    

    Then my tables appear like so

        ```{r print-tablefoo, echo=FALSE}
        tablefoo=mtcars
        thecap = "Tables appear with a legend while figures do not."
        fullcap = paste("Table ", ref("tab:foo"), ". ", thecap, sep="")
        kable(tablefoo, caption=fullcap)
        ```
    

    and then the figures like so:

        ```{r fig-foo, echo=FALSE, fig.cap=paste("Figure",ref("fig:foo"))}
        plot(1,1)
        ```
    

    Appendix A is an Rmd file that included as a child. It will have tables like

        ```{r print-tableAfoo, echo=FALSE}
        tablefoo=mtcars
        thecap = "This is a legend."
        fullcap = paste("Table A", ref("tabappA:foobig"), ". ", thecap, sep="")
        kable(tablefoo, caption=fullcap)
        ```
    

    I do have to add the "A" to get Table A1, but I find it easier if R doesn't think too much for me in terms of labelling my counters. I just I want it to return the right number.

    The cross-referencing works for html, pdf/latex or word. I'd happily stick with latex solutions, but my co-authors use word so I need a solution that works with pandoc and word. Also sometimes I want html or some other output and I need a solution that works for any output that works with rmarkdown.

    0 讨论(0)
  • 2020-12-01 09:12

    The other answers provided are relatively out of date, and this has since been made very easy using the bookdown package. This package provides a number of improvements which includes the built-in numbering of figures across Word, HTML and PDF.

    To be able to use bookdown, you need to first install the package install.packages("bookdown") and then use one of the output formats. For HTML, this is html_document2. Taking your example:

    ---
    title: "My Title"
    author: "Me"
    date:  "1/1/2016"
    output: bookdown::html_document2
    ---
    
    
    ```{r cars, fig.cap = "An amazing plot"}
    plot(cars)
    ```
    
    
    ```{r cars2, fig.cap = "Another amazing plot"}
    plot(cars)
    ```
    

    These Figures will be numbered Figure 1 and Figure 2. Providing the code chunk is named and has a caption, we can cross reference the output using the the syntax \@ref(fig:foo) where foo is the name of the chunk i.e. \@ref(fig-cars). You can learn more about this behaviour here

    Further Reading

    • R Markdown: The definitive Guide: Chapter 11 provides a great overview of bookdown
    • Authoring books with bookdown provides a comprehensive guide on bookdown, and recommended for more advanced details.
    0 讨论(0)
提交回复
热议问题