Skip to contents

ggposter builds an A1 (or other true-size) conference poster from ggplot2. A poster is declared as a title band plus columns of rounded, tab-headed cards – text, tables, ggplot2 figures, or photo strips – assembled with grid and gtable and rendered at true size with embedded fonts, including CJK (Japanese). Content and layout can be written as an R list or a YAML file; figures, tables, and photos are supplied separately as R objects.

Installation

You can install the development version of ggposter from GitHub with:

# install.packages("remotes")
remotes::install_github("matutosi/ggposter")

Example

The layout below follows a typical conference poster – a full-width title band and a two-column body of rounded, tab-headed cards for introduction/methods/summary on the left and results/conclusions on the right – filled in with the mpg fuel-economy dataset bundled with ggplot2. The title, author, and affiliation are placeholders. It also shows two features for keeping a card’s height tied to what’s actually in it, instead of a fixed proportion of the column: height = "auto" sizes a card to fit its own content, and notes puts a bullet-list description beside a table or figure.

library(ggposter)
library(ggplot2)

tbl_class <- aggregate(cbind(hwy, cty) ~ class, data = mpg, FUN = function(x) round(mean(x), 1))
names(tbl_class) <- c("Class", "Mean hwy", "Mean cty")
class_best  <- tbl_class$Class[which.max(tbl_class$`Mean hwy`)]
class_worst <- tbl_class$Class[which.min(tbl_class$`Mean hwy`)]

tbl_drv <- aggregate(cbind(hwy, cty) ~ drv, data = mpg, FUN = function(x) round(mean(x), 1))
names(tbl_drv) <- c("Drivetrain", "Mean hwy", "Mean cty")
drv_best  <- tbl_drv$Drivetrain[which.max(tbl_drv$`Mean hwy`)]
drv_worst <- tbl_drv$Drivetrain[which.min(tbl_drv$`Mean hwy`)]

fig_facet <- ggplot(mpg, aes(displ, hwy, colour = class)) +
  geom_point() +
  labs(caption = paste(
    "• Highway mileage falls as engine displacement rises.",
    "• Compact and subcompact classes reach the highest mileage.",
    sep = "\n")) +
  theme_bw() +
  theme(legend.position = "inside", legend.position.inside = c(0.85, 0.72),
        legend.background = element_rect(fill = scales::alpha("white", 0.7), colour = NA),
        legend.key.size = unit(0.9, "lines"),
        plot.caption = element_text(hjust = 0, size = rel(1.3), colour = "black"))

fig_scatter <- ggplot(mpg, aes(cty, hwy, colour = drv)) +
  geom_point(alpha = 0.7) +
  theme_bw() +
  theme(legend.position = "inside", legend.position.inside = c(0.75, 0.32),
        legend.background = element_rect(fill = scales::alpha("white", 0.7), colour = NA))

fig_box <- ggplot(mpg, aes(drv, hwy, fill = drv)) +
  geom_boxplot(show.legend = FALSE) +
  labs(x = "Drivetrain", y = "Highway mpg") +
  theme_bw()
drv_med <- aggregate(hwy ~ drv, data = mpg, FUN = median)
drv_box_best <- as.character(drv_med$drv[which.max(drv_med$hwy)])

mpg_heat <- aggregate(hwy ~ class + drv, data = mpg, FUN = function(x) round(mean(x), 1))
fig_heat <- ggplot(mpg_heat, aes(drv, class, fill = hwy)) +
  geom_tile(colour = "white") +
  geom_text(aes(label = hwy), size = 2.6) +
  scale_fill_gradient(low = "#E8F5E9", high = "#2E7D32") +
  labs(x = "Drivetrain", y = "Class", fill = "Mean hwy") +
  theme_minimal() +
  theme(legend.position = "bottom")

img_dir <- system.file("extdata", package = "ggposter")
stock_photos <- c("small.JPG", "tall.jpg", "wide.jpg", "large.JPG")
stock_labels <- c("Photo A", "Photo B", "Photo C", "Photo D")

spec <- list(
  title = list(
    title = "Example Poster: Fuel Economy Patterns in the mpg Dataset",
    authors = "*Jane Doe (Example University), John Smith (Example Institute)",
    funding = "This is a demonstration poster for the ggposter package; it does not describe real research."
  ),
  layout = list(
    left  = c("objectives", "background", "methods", "summary_table", "fig_box", "fig_heat"),
    right = c("conclusions", "results_table", "fig_facet", "fig_scatter", "photos_2")
  ),
  sections = list(
    objectives = list(header = "OBJECTIVES", height = "auto", body = list(type = "text", md = c(
      "- Demonstrate the ggposter package.",
      "- Use the mpg fuel-economy dataset as example content.",
      "- Combine text, tables, figures, and photos in one poster."
    ))),
    background = list(header = "BACKGROUND", height = "auto", body = list(type = "text", md = c(
      "- Conference posters often mix text, tables, and figures.",
      "- ggposter arranges these as rounded, tab-headed cards.",
      "- Layout and content can be declared as an R list or a YAML file."
    ))),
    methods = list(header = "METHODS", height = "auto", body = list(type = "text", md = c(
      "- Data: the mpg dataset (234 vehicles, model years 1999-2008).",
      "- Figures: highway/city mileage by class and drivetrain.",
      "- Photos: generic stock images bundled with ggposter."
    ))),
    summary_table = list(header = "SUMMARY by class", height = "auto", body = list(
      type = "table", object = "tbl_class", title = "Mean mileage by vehicle class",
      notes = c(
        sprintf("- **%s** has the best highway mileage of all vehicle classes in this dataset.", class_best),
        sprintf("- **%s** has the worst, largely due to its greater size and weight.", class_worst),
        "- Compact and subcompact classes have nearly identical mean highway mileage.",
        "- Midsize vehicles average close to the compact/subcompact classes.",
        "- Pickup and SUV classes have the two lowest highway mileages, both under 19 mpg.",
        "- City mileage tracks highway mileage closely across all seven classes."
      )
    )),
    fig_box = list(header = "Mileage spread by drivetrain", height = "auto", body = list(
      type = "figure", object = "fig_box", notes_width = 0.4, height = 117,
      notes = c(
        "- Boxes show the full spread of highway mileage, not just the mean.",
        sprintf("- **%s**-wheel drive has the highest median highway mileage.", drv_box_best)
      )
    )),
    fig_heat = list(header = "Mean mileage: class x drivetrain", height = "auto", body = list(
      type = "figure", object = "fig_heat", notes_width = 0.4, height = 137,
      notes = c(
        "- Colour shows mean highway mpg for each class/drivetrain combination.",
        "- Blank cells are combinations that don't occur in the data."
      )
    )),
    conclusions = list(header = "CONCLUSIONS", height = "auto", body = list(type = "text", md = c(
      "- Compact and subcompact cars get the best highway mileage.",
      "- SUVs and pickups get the lowest.",
      "- ggposter can lay out this kind of summary automatically."
    ))),
    results_table = list(header = "SUMMARY by drivetrain", height = "auto", body = list(
      type = "table", object = "tbl_drv", title = "Mean mileage by drivetrain",
      notes = c(
        sprintf("- **%s**-wheel drive has the best highway mileage among the three drivetrain types.", drv_best),
        sprintf("- **%s**-wheel drive has the worst, mainly due to the added weight of the drivetrain.", drv_worst),
        "- The gap between front- and four-wheel drive is nearly 9 mpg highway."
      )
    )),
    fig_facet = list(header = "Mileage by class", height = "auto",
      body = list(type = "figure", object = "fig_facet", height = 280)),
    fig_scatter = list(header = "Highway vs. city mileage", height = "auto", body = list(
      type = "figure", object = "fig_scatter", notes_width = 0.45, height = 102,
      notes = c(
        "- Highway and city mileage are closely correlated.",
        "- 4-wheel drive vehicles cluster at the low-mileage end.",
        "- Front-wheel drive vehicles cluster at the high-mileage end."
      )
    )),
    photos_2 = list(header = "More sample photos", height = "auto", body = list(
      type = "image", files = stock_photos, labels = stock_labels,
      width = 230
    ))
  )
)

p <- poster(
  spec,
  objects = list(tbl_class = tbl_class, tbl_drv = tbl_drv,
                 fig_facet = fig_facet, fig_scatter = fig_scatter,
                 fig_box = fig_box, fig_heat = fig_heat),
  theme = theme_green(base_size = 24),
  base_dir = img_dir
)

The same layout, theme, title, and section text can live in a YAML file instead of an inline R list, keeping the declarative content separate from the R code. Only the figures and tables stay in R, passed in via objects (reusing the same objects built above); image paths in the spec resolve relative to the YAML file’s own directory. p_yml below is identical to p above:

yml_path <- system.file("extdata", "poster_readme_example.yml", package = "ggposter")

p_yml <- poster(
  yml_path,
  objects = list(tbl_class = tbl_class, tbl_drv = tbl_drv,
                 fig_facet = fig_facet, fig_scatter = fig_scatter,
                 fig_box = fig_box, fig_heat = fig_heat)
)

Rendering a poster at true size makes font sizes and spacing come out correctly proportioned; previewing it at an arbitrary plot size (as this README does) does not, so we render a scaled-down preview PNG instead of printing p directly:

render_poster(p, "man/figures/README-poster-preview.png", scale = 0.3, dpi = 150)
knitr::include_graphics("man/figures/README-poster-preview.png")

An example poster built from the mpg dataset, with a placeholder title and authors, showing a full-width title band and a two-column body of tab-headed cards for text, tables, figures, and photos.

Seeing each card’s plot area

Passing show_plot_area = TRUE to render_poster() outlines every card’s header tab and body – the area its text, table, figure, or photo strip actually occupies – with a dashed border, on top of the content. A table/figure paired with a bullet-list description gets two separate borders, one for each side, rather than one around the pair. It’s an output option, so the same poster p renders both the normal version above and the outlined version below – useful for checking exactly how much of a card each of its parts fills:

render_poster(p, "man/figures/README-poster-preview-plot-area.png",
              scale = 0.3, dpi = 150, show_plot_area = TRUE)
knitr::include_graphics("man/figures/README-poster-preview-plot-area.png")

The same example poster, with a dashed magenta border drawn around each card's header tab and body area -- and, for tables and figures with notes, a separate border around the notes column -- to show exactly how much space each part occupies.

Save it at true size, with fonts embedded:

render_poster(p, "poster.pdf")                            # true A1 size
render_poster(p, "preview.png", scale = 0.25, dpi = 150)   # A4-ish preview

See vignette("ggposter") for the full spec schema, theming, and a reproduction of a real conference poster.

How to make an academic poster

The poster below is a quick tour of ggposter’s card types rather than a real research example: the left column has one card of each kind – a bullet list, a figure, a figure with a caption below it, a table with notes beside it, a photo strip, and finally how the title and layout parts of the spec themselves are written – the center column shows the YAML spec for the matching card on the left, and the right column shows the equivalent R code.

howto_fig <- ggplot(mpg, aes(displ, hwy)) +
  geom_point(colour = "#2E7D32") +
  theme_bw()

howto_fig_notes <- ggplot(mpg, aes(class, hwy)) +
  geom_boxplot(fill = "#A5D6A7") +
  labs(x = "Class", y = "Highway mpg") +
  theme_bw()

howto_tbl_notes <- data.frame(Drivetrain = c("f", "4", "r"),
                               `Mean highway mpg` = c(28.2, 19.2, 21.0),
                               check.names = FALSE)

howto_spec <- list(
  title = list(
    title = "How to Make an Academic Poster",
    authors = "*A guide to the ggposter card types",
    funding = "Each left-column card demonstrates one card type; the matching center-column card shows the YAML spec for it; the matching right-column card shows the equivalent R code."
  ),
  layout = list(
    align_rows = TRUE,
    left   = c(
               "howto_title", "howto_layout",
               "howto_bullets", "howto_table_notes", 
               "howto_figure", "howto_figure_notes",
               "howto_photo"),
    center = c(
               "yml_title", "yml_layout",
               "yml_bullets", "yml_table_notes",
               "yml_figure", "yml_figure_notes", 
               "yml_photo"),
    right  = c(
               "code_title", "code_layout",
               "code_bullets", "code_table_notes",
               "code_figure", "code_figure_notes",
               "code_photo")
  ),
  sections = list(
    howto_title = list(header = "The title band", height = "auto", body = list(
      type = "text", md = c(
        "- `title` is written once, not per column.",
        "- `title`, `authors`, `funding` stack top to bottom.",
        "- It spans the full poster width, above every column."
      )
    )),
    howto_layout = list(header = "The layout", height = "auto", body = list(
      type = "text", md = c(
        "- `layout` assigns section names to columns.",
        "- Column names are free-form -- not just left/right.",
        "- `align_rows: true` lines up each row to the tallest card at that row."
      )
    )),
    howto_bullets = list(header = "Bullet list only", height = "auto", body = list(
      type = "text", md = c(
        "- Bullet points summarize key facts.",
        "- Each line starts with a dash.",
        "- Long lines wrap to fit the card."
      )
    )),
    howto_figure = list(header = "Figure only", height = "auto", body = list(
      type = "figure", object = "howto_fig", height = 100
    )),
    howto_figure_notes = list(header = "Figure + bullets (below)", height = "auto", body = list(
      type = "figure", object = "howto_fig_notes", height = 110,
      caption = paste(
        "- A figure's caption= adds bullets below it.",
        "- Great for calling out key takeaways.",
        sep = "\n"
      )
    )),
    howto_table_notes = list(header = "Table + bullets (right)", height = "auto", body = list(
      type = "table", object = "howto_tbl_notes", notes_width = 0.4,
      notes = c(
        "- A table's notes= sits beside it.",
        "- Good for a short note."
      )
    )),
    howto_photo = list(header = "Photo strip", height = "auto", body = list(
      type = "image", files = c("small.JPG", "tall.jpg", "wide.jpg"),
      labels = c("Photo 1", "Photo 2", "Photo 3"), width = 200
    )),

    yml_title = list(header = "YAML: title", height = "auto", body = list(
      type = "text", md = c(
        "title:",
        "  title: \"How to Make an Academic Poster\"",
        "  authors: \"*A guide to the ggposter card types\"",
        "  funding: \"...\""
      )
    )),
    yml_layout = list(header = "YAML: layout", height = "auto", body = list(
      type = "text", md = c(
        "layout:",
        "  align_rows: true",
        "  left: howto_bullets, ...",
        "  center: yml_bullets, ...",
        "  right: code_bullets, ..."
      )
    )),
    yml_bullets = list(header = "YAML: bullet list", height = "auto", body = list(
      type = "text", md = c(
        "howto_bullets:",
        "  header: \"Bullet list only\"",
        "  height: \"auto\"",
        "  body:",
        "    type: text",
        "    md:",
        "      \\- \"- Bullet points summarize key facts.\"",
        "      \\- \"- Each line starts with a dash.\"",
        "      \\- \"- Long lines wrap to fit the card.\""
      )
    )),
    yml_figure = list(header = "YAML: figure only", height = "auto", body = list(
      type = "text", md = c(
        "howto_figure:",
        "  header: \"Figure only\"",
        "  height: \"auto\"",
        "  body:",
        "    type: figure",
        "    object: howto_fig",
        "    height: 80"
      )
    )),
    yml_figure_notes = list(header = "YAML: figure + bullets", height = "auto", body = list(
      type = "text", md = c(
        "howto_figure_notes:",
        "  header: \"Figure + bullets (below)\"",
        "  height: \"auto\"",
        "  body:",
        "    type: figure",
        "    object: howto_fig_notes",
        "    height: 110",
        "    caption: |-",
        "      \\- A figure's caption= adds bullets below it.",
        "      \\- Great for calling out key takeaways."
      )
    )),
    yml_table_notes = list(header = "YAML: table + bullets", height = "auto", body = list(
      type = "text", md = c(
        "howto_table_notes:",
        "  header: \"Table + bullets (right)\"",
        "  height: \"auto\"",
        "  body:",
        "    type: table",
        "    object: howto_tbl_notes",
        "    notes_width: 0.4",
        "    notes:",
        "      \\- \"- A table's notes= sits beside it.\"",
        "      \\- \"- Good for a short note.\""
      )
    )),
    yml_photo = list(header = "YAML: photo strip", height = "auto", body = list(
      type = "text", md = c(
        "howto_photo:",
        "  header: \"Photo strip\"",
        "  height: \"auto\"",
        "  body:",
        "    type: image",
        "    files:",
        "      \\- small.JPG",
        "      \\- tall.jpg",
        "      \\- wide.jpg",
        "    labels:",
        "      \\- \"Photo 1\"",
        "      \\- \"Photo 2\"",
        "      \\- \"Photo 3\"",
        "    width: 200"
      )
    )),

    code_title = list(header = "Code: title", height = "auto", body = list(
      type = "text", md = c(
        "title = list(",
        "  title = \"How to Make an Academic Poster\",",
        "  authors = \"*A guide to the ggposter card types\",",
        "  funding = \"...\"",
        ")"
      )
    )),
    code_layout = list(header = "Code: layout", height = "auto", body = list(
      type = "text", md = c(
        "layout = list(",
        "  align_rows = TRUE,",
        "  left   = c(\"howto_bullets\", ...),",
        "  center = c(\"yml_bullets\", ...),",
        "  right  = c(\"code_bullets\", ...)",
        ")"
      )
    )),
    code_bullets = list(header = "Code: bullet list", height = "auto", body = list(
      type = "text", md = c(
        "list(",
        "  header = \"Bullet list only\",",
        "  body = list(",
        "    type = \"text\",",
        "    md = c(",
        "      \"- Bullet points summarize key facts.\",",
        "      \"- Each line starts with a dash.\",",
        "      \"- Long lines wrap to fit the card.\"",
        "    )",
        "  )",
        ")"
      )
    )),
    code_figure = list(header = "Code: figure only", height = "auto", body = list(
      type = "text", md = c(
        "list(",
        "  header = \"Figure only\",",
        "  body = list(",
        "    type = \"figure\",",
        "    object = \"howto_fig\",",
        "    height = 80",
        "  )",
        ")"
      )
    )),
    code_figure_notes = list(header = "Code: figure + bullets", height = "auto", body = list(
      type = "text", md = c(
        "list(",
        "  header = \"Figure + bullets (below)\",",
        "  body = list(",
        "    type = \"figure\",",
        "    object = \"howto_fig_notes\",",
        "    height = 80,",
        "    caption = paste(",
        "      \"- A figure's caption= adds bullets below it.\",",
        "      \"- Great for calling out key takeaways.\",",
        "      sep = \"\\n\"",
        "    )",
        "  )",
        ")"
      )
    )),
    code_table_notes = list(header = "Code: table + bullets", height = "auto", body = list(
      type = "text", md = c(
        "list(",
        "  header = \"Table + bullets (right)\",",
        "  body = list(",
        "    type = \"table\",",
        "    object = \"howto_tbl_notes\",",
        "    notes_width = 0.4,",
        "    notes = c(",
        "      \"- A table's notes= sits beside it.\",",
        "      \"- Good for a short note.\"",
        "    )",
        "  )",
        ")"
      )
    )),
    code_photo = list(header = "Code: photo strip", height = "auto", body = list(
      type = "text", md = c(
        "list(",
        "  header = \"Photo strip\",",
        "  body = list(",
        "    type = \"image\",",
        "    files = c(\"small.JPG\", \"tall.jpg\", \"wide.jpg\"),",
        "    labels = c(\"Photo 1\", \"Photo 2\", \"Photo 3\"),",
        "    width = 200",
        "  )",
        ")"
      )
    ))
  )
)

p_howto <- poster(
  howto_spec,
  objects = list(howto_fig = howto_fig, howto_fig_notes = howto_fig_notes,
                 howto_tbl_notes = howto_tbl_notes),
  theme = theme_green(base_size = 18),
  base_dir = img_dir
)

The same layout, theme, title, and section text can live in a YAML file instead of an inline R list; only the figures and tables stay in R, passed in via objects. p_howto_yml below is identical to p_howto above:

howto_yml_path <- system.file("extdata", "poster_sample_howto.yml", package = "ggposter")

p_howto_yml <- poster(
  howto_yml_path,
  objects = list(howto_fig = howto_fig, howto_fig_notes = howto_fig_notes,
                 howto_tbl_notes = howto_tbl_notes)
)

render_poster(p_howto, "man/figures/README-howto-poster.png", scale = 0.3, dpi = 150)
knitr::include_graphics("man/figures/README-howto-poster.png")

A tutorial poster titled 'How to Make an Academic Poster', with a left column showing one example of each ggposter card type (bullet list, figure, figure with bullets below, table with bullets to the right, a photo strip, and explanations of the title band and layout config), a center column showing the YAML spec for each matching card, and a right column showing the R code that built each matching card.