Matt
Matt

Reputation: 7413

Graph Sizing for RMarkdown + ggplotly

I am plotting results to several survey questions, and am having trouble finding a way to properly scale the plots once rendered to HTML.

My end result is that all graphs are center-aligned, and have the same widths for each distribution. All facets/panels have a scale of 0 - 100%, so I would like them to be visually identical, with the only difference being the bars/text.

Is there a way to control this, other than seeing width = or height = parameters in the ggplotly call?

Any help is greatly appreciated. I have tried changing aspect.ratio, the rmd chunk options, and the ggplotly height/width arguments, but to no avail.

Here is a .rmd reprex:

---
title: "SO"
author: "Matt"
date: "11/23/2020"
output: html_document
---

```{r setup, include=FALSE}
library(tidyverse)
library(plotly)

knitr::opts_chunk$set(
    echo = FALSE,
    message = FALSE,
    warning = FALSE
)
# Function for plotting
plot_func <- function(data){
  ggplot(data, aes(x = reorder(name, rank_order, max), y = pct, fill = value)) +
  geom_bar(stat = "identity", color = "#2b2b2b", size = 0.5) +
  facet_wrap( ~ value) +
  coord_flip() +
  facet_grid(cols = vars(value)) +
  theme(strip.text = element_text(size = 9, color = "white", hjust = .5),
        strip.background = element_rect( fill = "black", color = NA ),
        strip.placement = "outside",
        panel.background = element_rect( fill = "white", color = NA ),
        panel.grid.major.x = element_blank(),
        panel.grid.minor.x = element_blank(),
        panel.grid.minor.y = element_blank(),
        panel.grid.major.y = element_blank(),
        panel.spacing.x = unit( 0.01, "cm" ),
        panel.spacing.y = unit( 0.01, "cm" ),
        legend.position = "none",
        aspect.ratio = .8, 
        #axis.text.x=element_blank(), 
        axis.ticks.x=element_blank(),
        plot.title = element_text(hjust = 0.5)) + 
  annotate("segment", x=-Inf, xend=Inf, y=-Inf, yend=-Inf) +
  scale_y_continuous(limits = c(0, 100), expand = expansion(mult = c(0, .1))) +
  labs(title = "Activities",
       x = "",
       y = "Percentage of Respondents (each panel = 100%)")
}

# Question 1 Data

q1 <- structure(list(name = c("Go outside", "Go outside, walk the dog, get a coffee, take a nap", 
"Stay inside, don't get a coffee, have lunch, leave everything until tomorrow", 
"Go outside", "Stay inside, don't get a coffee, have lunch, leave everything until tomorrow", 
"Go outside, walk the dog, get a coffee, take a nap", "Stay inside, don't get a coffee, have lunch, leave everything until tomorrow", 
"Go outside", "Go outside, walk the dog, get a coffee, take a nap", 
"Go outside", "Stay inside, don't get a coffee, have lunch, leave everything until tomorrow", 
"Go outside, walk the dog, get a coffee, take a nap", "Go outside, walk the dog, get a coffee, take a nap", 
"Stay inside, don't get a coffee, have lunch, leave everything until tomorrow", 
"Go outside"), value = structure(c(5L, 5L, 5L, 4L, 4L, 4L, 3L, 
3L, 3L, 2L, 2L, 2L, 1L, 1L, 1L), .Label = c("Several times a day", 
"Once a day", "Several times a week", "Once a week", "Once a month or less"
), class = "factor"), n = c(20, 24, 44, 12, 40, 52, 196, 208, 
252, 132, 136, 228, 1188, 1328, 1372), group_count = c(1744, 
1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 
1744, 1744, 1744), pct = c(1.1, 1.4, 2.5, 0.7, 2.3, 3, 11.2, 
11.9, 14.4, 7.6, 7.8, 13.1, 68.1, 76.1, 78.7), rank_order = 1:15), row.names = c(NA, 
-15L), class = c("tbl_df", "tbl", "data.frame"))


# Question 2 Data

q2 <- structure(list(name = c("Do something", "Do something else, go outside, take a walk, go to the store, drive somewhere, come back home, go to sleep", 
"Take a hike, do a dance", "Go shopping", "Do something", "Do something else, go outside, take a walk, go to the store, drive somewhere, come back home, go to sleep", 
"Take a hike, do a dance", "Go shopping", "Do something", "Do something else, go outside, take a walk, go to the store, drive somewhere, come back home, go to sleep", 
"Take a hike, do a dance", "Go shopping", "Do something", "Do something else, go outside, take a walk, go to the store, drive somewhere, come back home, go to sleep", 
"Take a hike, do a dance", "Go shopping", "Do something", "Do something else, go outside, take a walk, go to the store, drive somewhere, come back home, go to sleep", 
"Take a hike, do a dance"), value = c("Once a month or less", 
"Once a month or less", "Once a month or less", "Once a week", 
"Once a week", "Once a week", "Once a week", "Several times a week", 
"Several times a week", "Several times a week", "Several times a week", 
"Once a day", "Once a day", "Once a day", "Once a day", "Several times a day", 
"Several times a day", "Several times a day", "Several times a day"
), n = c(20, 24, 44, 4, 12, 40, 52, 55, 196, 208, 252, 101, 132, 
136, 228, 965, 1188, 1328, 1372), group_count = c(6357, 6357, 
6357, 6357, 6357, 6357, 6357, 6357, 6357, 6357, 6357, 6357, 6357, 
6357, 6357, 6357, 6357, 6357, 6357), pct = c(0.3, 0.4, 0.7, 0.1, 
0.2, 0.6, 0.8, 0.9, 3.1, 3.3, 4, 1.6, 2.1, 2.1, 3.6, 15.2, 18.7, 
20.9, 21.6), rank_order = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 
12, 13, 14, 15, 16, 17, 18, 19)), row.names = c(NA, -19L), groups = structure(list(
    value = c("Once a day", "Once a month or less", "Once a week", 
    "Several times a day", "Several times a week"), .rows = structure(list(
        12:15, 1:3, 4:7, 16:19, 8:11), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), row.names = c(NA, 5L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))
```

## Question 1
```{r}
plot_func(q1) %>% ggplotly(., width = 1000, height = 300)
```

## Question 2
```{r}
plot_func(q2) %>% ggplotly(., width = 1000, height = 500)
```

Misaligned plots:

enter image description here

Upvotes: 2

Views: 897

Answers (1)

Klaus
Klaus

Reputation: 504

Try to use the layout:

---
title: "SO"
author: "Matt"
date: "11/23/2020"
output: html_document
---

```{r setup, include=FALSE}
library(tidyverse)
library(plotly)

knitr::opts_chunk$set(
    echo = FALSE,
    message = FALSE,
    warning = FALSE
)
# Function for plotting
plot_func <- function(data){
  ggplot(data, aes(x = reorder(gsub(', ', ', \n',name), rank_order, max), y = pct, fill = value)) +
  geom_bar(stat = "identity", color = "#2b2b2b", size = 0.5) +
  facet_wrap( ~ value) +
  coord_flip() +
  facet_grid(cols = vars(value)) +
  theme(strip.text = element_text(size = 9, color = "white", hjust = .5),
        strip.background = element_rect( fill = "black", color = NA ),
        strip.placement = "outside",
        panel.background = element_rect( fill = "white", color = NA ),
        panel.grid.major.x = element_blank(),
        panel.grid.minor.x = element_blank(),
        panel.grid.minor.y = element_blank(),
        panel.grid.major.y = element_blank(),
        panel.spacing.x = unit( 0.01, "cm" ),
        panel.spacing.y = unit( 0.01, "cm" ),
        legend.position = "none",
        aspect.ratio = .8, 
        #axis.text.x=element_blank(), 
        axis.ticks.x=element_blank(),
        plot.title = element_text(hjust = 0.5)) + 
  annotate("segment", x=-Inf, xend=Inf, y=-Inf, yend=-Inf) +
  scale_y_continuous(limits = c(0, 100), expand = expansion(mult = c(0, .1))) +
  labs(title = "Activities",
       x = "",
       y = "Percentage of Respondents (each panel = 100%)")
}


# Question 1 Data

q1 <- structure(list(name = c("Go outside", "Go outside, walk the dog, get a coffee, take a nap", 
"Stay inside, don't get a coffee, have lunch, leave everything until tomorrow", 
"Go outside", "Stay inside, don't get a coffee, have lunch, leave everything until tomorrow", 
"Go outside, walk the dog, get a coffee, take a nap", "Stay inside, don't get a coffee, have lunch, leave everything until tomorrow", 
"Go outside", "Go outside, walk the dog, get a coffee, take a nap", 
"Go outside", "Stay inside, don't get a coffee, have lunch, leave everything until tomorrow", 
"Go outside, walk the dog, get a coffee, take a nap", "Go outside, walk the dog, get a coffee, take a nap", 
"Stay inside, don't get a coffee, have lunch, leave everything until tomorrow", 
"Go outside"), value = structure(c(5L, 5L, 5L, 4L, 4L, 4L, 3L, 
3L, 3L, 2L, 2L, 2L, 1L, 1L, 1L), .Label = c("Several times a day", 
"Once a day", "Several times a week", "Once a week", "Once a month or less"
), class = "factor"), n = c(20, 24, 44, 12, 40, 52, 196, 208, 
252, 132, 136, 228, 1188, 1328, 1372), group_count = c(1744, 
1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 1744, 
1744, 1744, 1744), pct = c(1.1, 1.4, 2.5, 0.7, 2.3, 3, 11.2, 
11.9, 14.4, 7.6, 7.8, 13.1, 68.1, 76.1, 78.7), rank_order = 1:15), row.names = c(NA, 
-15L), class = c("tbl_df", "tbl", "data.frame"))


# Question 2 Data

q2 <- structure(list(name = c("Do something", "Do something else, go outside, take a walk, go to the store, drive somewhere, come back home, go to sleep", 
"Take a hike, do a dance", "Go shopping", "Do something", "Do something else, go outside, take a walk, go to the store, drive somewhere, come back home, go to sleep", 
"Take a hike, do a dance", "Go shopping", "Do something", "Do something else, go outside, take a walk, go to the store, drive somewhere, come back home, go to sleep", 
"Take a hike, do a dance", "Go shopping", "Do something", "Do something else, go outside, take a walk, go to the store, drive somewhere, come back home, go to sleep", 
"Take a hike, do a dance", "Go shopping", "Do something", "Do something else, go outside, take a walk, go to the store, drive somewhere, come back home, go to sleep", 
"Take a hike, do a dance"), value = c("Once a month or less", 
"Once a month or less", "Once a month or less", "Once a week", 
"Once a week", "Once a week", "Once a week", "Several times a week", 
"Several times a week", "Several times a week", "Several times a week", 
"Once a day", "Once a day", "Once a day", "Once a day", "Several times a day", 
"Several times a day", "Several times a day", "Several times a day"
), n = c(20, 24, 44, 4, 12, 40, 52, 55, 196, 208, 252, 101, 132, 
136, 228, 965, 1188, 1328, 1372), group_count = c(6357, 6357, 
6357, 6357, 6357, 6357, 6357, 6357, 6357, 6357, 6357, 6357, 6357, 
6357, 6357, 6357, 6357, 6357, 6357), pct = c(0.3, 0.4, 0.7, 0.1, 
0.2, 0.6, 0.8, 0.9, 3.1, 3.3, 4, 1.6, 2.1, 2.1, 3.6, 15.2, 18.7, 
20.9, 21.6), rank_order = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 
12, 13, 14, 15, 16, 17, 18, 19)), row.names = c(NA, -19L), groups = structure(list(
    value = c("Once a day", "Once a month or less", "Once a week", 
    "Several times a day", "Several times a week"), .rows = structure(list(
        12:15, 1:3, 4:7, 16:19, 8:11), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), row.names = c(NA, 5L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))
```

## Question 1


```{r echo=FALSE, fig.align="center", warning=FALSE}
m <- list(
    l = 50,
    r = 50,
    b = 100,
    t = 100,
    pad = 0.5
)

plot_func(q1) %>% 
  ggplotly(.) %>%
  layout(autosize = F, width = 1000, height = 500, margin = m)

```


## Question 2

```{r, fig.align="center", warning=FALSE}
m <- list(
    l = 50,
    r = 50,
    b = 100,
    t = 100,
    pad = 0.5
)

plot_func(q2) %>% 
  ggplotly(.) %>%
  layout(autosize = F, width = 1000, height = 600, margin = m)
```

Upvotes: 1

Related Questions