rmacey
rmacey

Reputation: 657

How to control output order from an rmarkdown / knitr file (or how to prevent the float)

I'm having a problem similar to the issue raised in 'R, knitr doesn't respect order of chunks and text'. In my code I have a text heading followed by a chunk which uses four knitr::kable function calls to show four tables. Strangely, Tables 1 and Table 2 appear above the heading and Tables 3 and 4 below in output to a PDF. It appears this has to do with knitr allowing objects to float. Can I turn that off preferably in the knitr::kable function or in the chunk options? Here is my code:

---
title: "Reproducible Error"
author: "Rex Macey"
date: "February 14, 2017"
output: pdf_document
header-includes: 
- \usepackage{placeins}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

\newpage  

# Section 1  
```{r CompTables, echo=FALSE, warning=FALSE, results='asis', out.extra='FloatBarrier'}
comptables1<-matrix(rep(c(100,200,300,400,500),3),nrow=5,ncol=3)
colnames(comptables1)<-c("Conservative","Moderate","Aggressive")
row.names(comptables1)<-c("5th %-tile","25th %-tile","50th %-tile","75th %-tile","95th %-tile")
comptables2<-matrix(0,nrow=6,ncol=3)
comptables2[1,]<-comptables1[1,]
for (i in 2:5){
    comptables2[i,]<-comptables1[i,]-comptables1[i-1,]
}
comptables<-list()
comptables[[1]]<-list(comptables1,comptables2)
comptables[[2]]<-list(comptables1,comptables2)
comptables[[3]]<-list(comptables1,comptables2)
comptables[[4]]<-list(comptables1,comptables2)

knitr::kable(comptables[[1]][1],
         caption="Table of Forecast Wealth Values: Suggested One Year",
        format.args=list(big.mark=",",floating=FALSE))

knitr::kable(comptables[[2]][1],
         caption="Table of Forecast Wealth Values: Suggested Three Years",
        format.args=list(big.mark=",",floating=FALSE))

knitr::kable(comptables[[3]][1],
         caption="Table of Forecast Wealth Values: Suggested Five Years",
        format.args=list(big.mark=",",floating=FALSE))

knitr::kable(comptables[[4]][1],
         caption="Table of Forecast Wealth Values: Suggested Ten Years",
        format.args=list(big.mark=",",floating=FALSE))
```


```{r CompChart, echo=FALSE, warning=FALSE, fig.height=4, fig.show='hold', results='asis'}
horizons <- c(1,3,5,10)
par(mfrow=c(1,2))
minv<-min(unlist(comptables[[1]][1]),unlist(comptables[[2]][1]),
          unlist(comptables[[3]][1]),unlist(comptables[[4]][1]))
maxv<-max(unlist(comptables[[1]][1]),unlist(comptables[[2]][1]),
          unlist(comptables[[3]][1]),unlist(comptables[[4]][1]))
for (h in 1:length(horizons)){
    wealth.pl.comp<-matrix(unlist(comptables[[h]][2],use.names = FALSE),ncol=3,byrow=FALSE)
    colnames(wealth.pl.comp)<-c("Cons.","Mod.","Aggr.")
    barplot(wealth.pl.comp,col=c("white","red","yellow","green","blue"),border=NA,
        main=paste("Forecast A/T Values -",horizons[h],"Years"),
        ylim=c(minv/2,maxv+minv/2))
    abline(h=250,col="darkgray")
}
par(mfrow=c(1,1))
```


\newpage    

#Section 2

I have experimented with the floating = FALSE option in the kable function and the fig.show and results parameters (including results='hold') in the chunk options. The newpage before Section 1 is out of order as well. Note I did check out this seemingly similar question too.

Here is an image of the output. The text from within the single chunk shown is out of order because two of the tables are above the text header "Section 1". The chart between tables is from a subsequent chunk.

Image of Output

Upvotes: 5

Views: 9357

Answers (2)

Rob Smith
Rob Smith

Reputation: 561

Bit of a late response, but I have just been working on this. Loading the kableExtra package and including some restrictions in the kable_styling options seems to do the trick. Particularly latex_options = c("hold_position")

---
title: "Reproducible Error"
author: "Rex Macey"
date: "February 14, 2017"
output: pdf_document
header-includes: 
    - \usepackage{placeins}
---

```{r setup, include=FALSE}
library("knitr")
library("tidyverse")
library("kableExtra")

knitr::opts_chunk$set(echo = TRUE)
```

\newpage  

# Section 1  
```{r CompTables, echo=FALSE, warning=FALSE, results='asis', out.extra='FloatBarrier'}
comptables1<-matrix(rep(c(100,200,300,400,500),3),nrow=5,ncol=3)
colnames(comptables1)<-c("Conservative","Moderate","Aggressive")
row.names(comptables1)<-c("5th %-tile","25th %-tile","50th %-tile","75th %-tile","95th %-tile")
comptables2<-matrix(0,nrow=6,ncol=3)
comptables2[1,]<-comptables1[1,]
for (i in 2:5){
    comptables2[i,]<-comptables1[i,]-comptables1[i-1,]
}
comptables<-list()
comptables[[1]]<-list(comptables1,comptables2)
comptables[[2]]<-list(comptables1,comptables2)
comptables[[3]]<-list(comptables1,comptables2)
comptables[[4]]<-list(comptables1,comptables2)

knitr::kable(comptables[[1]][1],
             caption="Table of Forecast Wealth Values: Suggested One Year",
             format.args=list(big.mark=",",floating=FALSE)) %>%
   kable_styling(c("bordered","condensed"),
                latex_options = c("hold_position"), 
                font_size = 10,
                full_width = F)


knitr::kable(comptables[[2]][1],
             caption="Table of Forecast Wealth Values: Suggested Three Years",
             format.args=list(big.mark=",",floating=FALSE))%>%
   kable_styling(c("bordered","condensed"),
                latex_options = c("hold_position"), 
                font_size = 10,
                full_width = F)

knitr::kable(comptables[[3]][1],
             caption="Table of Forecast Wealth Values: Suggested Five Years",
             format.args=list(big.mark=",",floating=FALSE))%>%
   kable_styling(c("bordered","condensed"),
                latex_options = c("hold_position"), 
                font_size = 10,
                full_width = F)

knitr::kable(comptables[[4]][1],
             caption="Table of Forecast Wealth Values: Suggested Ten Years",
             format.args=list(big.mark=",",floating=FALSE))%>%
   kable_styling(c("bordered","condensed"),
                latex_options = c("hold_position"), 
                font_size = 10,
                full_width = F)
```


```{r CompChart, echo=FALSE, warning=FALSE, fig.height=4, fig.show='hold', results='asis'}
horizons <- c(1,3,5,10)
par(mfrow=c(1,2))
minv<-min(unlist(comptables[[1]][1]),unlist(comptables[[2]][1]),
          unlist(comptables[[3]][1]),unlist(comptables[[4]][1]))
maxv<-max(unlist(comptables[[1]][1]),unlist(comptables[[2]][1]),
          unlist(comptables[[3]][1]),unlist(comptables[[4]][1]))
for (h in 1:length(horizons)){
    wealth.pl.comp<-matrix(unlist(comptables[[h]][2],use.names = FALSE),ncol=3,byrow=FALSE)
    colnames(wealth.pl.comp)<-c("Cons.","Mod.","Aggr.")
    barplot(wealth.pl.comp,col=c("white","red","yellow","green","blue"),border=NA,
            main=paste("Forecast A/T Values -",horizons[h],"Years"),
            ylim=c(minv/2,maxv+minv/2))
    abline(h=250,col="darkgray")
}
par(mfrow=c(1,1))
```


\newpage    

#Section 2

This produces the following (screengrab from PDF)

Page 2 after title page

Page 3 after title page

Upvotes: 2

Benjamin
Benjamin

Reputation: 17369

Based on the documentation, out.extra provides "extra options for figures."

When I place the \FloatBarrier above the chunk instead of using out.extra, I get something more like what I believe you are wanting.

---
title: "Reproducible Error"
author: "Rex Macey"
date: "February 14, 2017"
output: pdf_document
header-includes: 
- \usepackage{placeins}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

\newpage  

\FloatBarrier

# Section 1  
```{r CompTables, echo=FALSE, warning=FALSE, results='asis'}
comptables1<-matrix(rep(c(100,200,300,400,500),3),nrow=5,ncol=3)
colnames(comptables1)<-c("Conservative","Moderate","Aggressive")
row.names(comptables1)<-c("5th %-tile","25th %-tile","50th %-tile","75th %-tile","95th %-tile")
comptables2<-matrix(0,nrow=6,ncol=3)
comptables2[1,]<-comptables1[1,]
for (i in 2:5){
    comptables2[i,]<-comptables1[i,]-comptables1[i-1,]
}
comptables<-list()
comptables[[1]]<-list(comptables1,comptables2)
comptables[[2]]<-list(comptables1,comptables2)
comptables[[3]]<-list(comptables1,comptables2)
comptables[[4]]<-list(comptables1,comptables2)

knitr::kable(comptables[[1]][1],
         caption="Table of Forecast Wealth Values: Suggested One Year",
        format.args=list(big.mark=",",floating=FALSE))

knitr::kable(comptables[[2]][1],
         caption="Table of Forecast Wealth Values: Suggested Three Years",
        format.args=list(big.mark=",",floating=FALSE))

knitr::kable(comptables[[3]][1],
         caption="Table of Forecast Wealth Values: Suggested Five Years",
        format.args=list(big.mark=",",floating=FALSE))

knitr::kable(comptables[[4]][1],
         caption="Table of Forecast Wealth Values: Suggested Ten Years",
        format.args=list(big.mark=",",floating=FALSE))
```


```{r CompChart, echo=FALSE, warning=FALSE, fig.height=4, fig.show='hold', results='asis'}
horizons <- c(1,3,5,10)
par(mfrow=c(1,2))
minv<-min(unlist(comptables[[1]][1]),unlist(comptables[[2]][1]),
          unlist(comptables[[3]][1]),unlist(comptables[[4]][1]))
maxv<-max(unlist(comptables[[1]][1]),unlist(comptables[[2]][1]),
          unlist(comptables[[3]][1]),unlist(comptables[[4]][1]))
for (h in 1:length(horizons)){
    wealth.pl.comp<-matrix(unlist(comptables[[h]][2],use.names = FALSE),ncol=3,byrow=FALSE)
    colnames(wealth.pl.comp)<-c("Cons.","Mod.","Aggr.")
    barplot(wealth.pl.comp,col=c("white","red","yellow","green","blue"),border=NA,
        main=paste("Forecast A/T Values -",horizons[h],"Years"),
        ylim=c(minv/2,maxv+minv/2))
    abline(h=250,col="darkgray")
}
par(mfrow=c(1,1))
```


\newpage    

#Section 2

Upvotes: 3

Related Questions