Search code examples
latexquartogt

Why is gt table putting the table in the wrong location in Quarto PDF output?


I'm writing a short presentation about different output options for dynamic vs static content using Quarto rendering to PDF. When using the gt table package, I have the code chunk for the table AFTER the section heading text and description. However, rendering to a PDF, the table incorrectly prints BEFORE the section heading text. In the source code, the section heading is before the table code. I cannot figure out why the gt table continues to print in the wrong location.

Below is a short sample to reproduce the problem. In the sample, the section ### Population Table should be printing BEFORE the gt table but it is not. I have had this problem across several other Quarto projects as well.

---
title: "gt table testing"
format: 
  pdf:
    geometry: # sets page margins for PDF
      - top=2.0cm
      - left=1.27cm
      - right=1.27cm
      - bottom=2.5cm
execute:
  echo: false
  message: false
  warning: false
  include: true
editor_options: 
  chunk_output_type: console
---


```{r}
#| label: Setup

pacman::p_load(
  gt, # table package
  sf, # for working with geospatial data
  spData, # contains the nz dataset for making maps
  tidyverse, # data analysis metapackage containing other packages
  tmap # mapping package
)

# Eliminate scientific notation
options(scipen = 999)
```

## Static Map - PDF  

Static maps present useful information but lack interactivity like a dynamic map. Check it out!  
```{r}
#| label: Static map
#| fig-height: 6

# Set map to static plot mode
tmap_mode("plot")

# View map
tm_shape(nz) +
  tm_polygons(
    col = 'Population', # color by population count
    alpha = 0.8, # change transparency of colors
    breaks = seq(0, 2000000, by = 250000) # set breakpoints for population count
    ) +
  tm_layout(
    main.title = "Static Map of New Zealand's Population",
    main.title.size = 1
  ) +
  tm_text("Name", size = 0.6, col = "black")
```

### Population Table  

Dynamic maps can contain popups that users can click to see more information. With a static map that cannot have dynamic popups, adding a table with more information can help make the static map more understandable.   

```{r}
#| label: gt table of population

nz %>% 
  st_drop_geometry() %>% 
  select(Name, Island, Population) %>% 
  arrange(desc(Population)) %>% 
  gt(
    groupname_col = "Island",
    rowname_col = "Name"
    ) %>% 
  tab_header(
    title = "Population of New Zealand by Region",
    subtitle = "Grouped by Island (North/South)"
  ) %>% 
   tab_style(
     style = list(
       cell_fill("royalblue2"),
       cell_text("white")
       ),
     locations = cells_row_groups()
     ) %>% 
  fmt_number(columns = "Population", decimals = 0)
```

## New Section Topic  

Anything after the table change things?  

Session and version info: platform x86_64-w64-mingw32
arch x86_64
os mingw32
crt ucrt
system x86_64, mingw32
status
major 4
minor 4.2
year 2024
month 10
day 31
svn rev 87279
language R
version.string R version 4.4.2 (2024-10-31 ucrt) nickname Pile of Leaves

Quarto version: 1.6.39


Solution

  • This is because the table gets the default floating option, which locates it at the top of the page. The docs suggest one solution (from ?gt::tab_options):

    latex.tbl.pos Specify latex floating position

    The latex position indicator for a floating environment (e.g., "!t", "H"). It should be specified without square brackets. Quarto users should instead set the floating position within the code chunk argument tbl-pos. The output table will only float if latex.use_longtable = FALSE.

    However, as recently discussed within quarto-dev/quarto-cli#4849, tbl-pos additionally requires using layout. Hence, you could wrap your code chunk inside a div using something along these lines and the table will be put "here":

    ::: {#tbl-t1 tbl-pos="h" layout-ncol="1"}
    
    ```{r}
    #| label: gt table of population
    nz %>% 
      st_drop_geometry() %>% 
      ...
    ```
    
    :::
    

    enter image description here

    ---
    title: "gt table testing"
    format: 
      pdf:
        geometry: # sets page margins for PDF
          - top=2.0cm
          - left=1.27cm
          - right=1.27cm
          - bottom=2.5cm
    execute:
      echo: false
      message: false
      warning: false
      include: true
    editor_options: 
      chunk_output_type: console
    keep-tex: true
    ---
    
    
    ```{r}
    #| label: Setup
    
    pacman::p_load(
      gt, # table package
      sf, # for working with geospatial data
      spData, # contains the nz dataset for making maps
      tidyverse, # data analysis metapackage containing other packages
      tmap # mapping package
    )
    
    # Eliminate scientific notation
    options(scipen = 999)
    ```
    
    ## Static Map - PDF  
    
    Static maps present useful information but lack interactivity like a dynamic map. Check it out!  
    ```{r}
    #| label: Static map
    #| fig-height: 6
    
    # Set map to static plot mode
    tmap_mode("plot")
    
    # View map
    tm_shape(nz) +
      tm_polygons(
        col = 'Population', # color by population count
        alpha = 0.8, # change transparency of colors
        breaks = seq(0, 2000000, by = 250000) # set breakpoints for population count
        ) +
      tm_layout(
        main.title = "Static Map of New Zealand's Population",
        main.title.size = 1
      ) +
      tm_text("Name", size = 0.6, col = "black")
    ```
    
    ### Population Table  
    
    Dynamic maps can contain popups that users can click to see more information. With a static map that cannot have dynamic popups, adding a table with more information can help make the static map more understandable.   
    
    ::: {#tbl-t1 tbl-pos="h" layout-ncol="1"}
    
    ```{r}
    #| label: gt table of population
    nz %>% 
      st_drop_geometry() %>% 
      select(Name, Island, Population) %>% 
      arrange(desc(Population)) %>% 
      gt(
        groupname_col = "Island",
        rowname_col = "Name"
        ) %>% 
      tab_header(
        title = "Population of New Zealand by Region",
        subtitle = "Grouped by Island (North/South)"
      ) %>% 
       tab_style(
         style = list(
           cell_fill("royalblue2"),
           cell_text("white")
           ),
         locations = cells_row_groups()
         ) %>% 
      fmt_number(columns = "Population", decimals = 0)
    ```
    
    :::
    
    ## New Section Topic  
    
    Anything after the table change things?