Search code examples
rggplot2plot

Totals of gglikert plot adjustments in R


I have a data frame and ggplot2 graph that reproduce the following graph:

library(dplyr, warn = FALSE)
library(ggplot2)
library(ggstats)
library(purrr)
library(scales)

likert_levels <- c(
 "Strongly disagree",
 "Disagree",
 "Neither agree nor disagree",
 "Agree",
 "Strongly agree"
)

df <-
 tibble(
   "there is an argument sort_prop_include_center that could be set up to TRUE in order to include half of the centered level when sorting data" = sample(likert_levels, 150, replace = TRUE),
   "Similarly, the argument totals_include_center allows you to include half of the centered level into the left and the right totals" = sample(likert_levels, 150, replace = TRUE, prob = 5:1),
   "Here is one possible option which uses reorder and an ifelse to reorder the variable mapped on y using the counts (aka the sum) of Strictly disagree " = sample(likert_levels, 150, replace = TRUE, prob = 1:5),
   "and disagree answers. Under the hood ggstats::gglikert reshape the data to long where the question id's are stored in a column named .question and the answers in a column named .answer:" = sample(likert_levels, 150, replace = TRUE, prob = 1:5),
   "They used sampling data and create a data frame called df. I am using the same as given in the link. (the df not the df_dk). Ok, if i run in R the following code :" = sample(c(likert_levels, NA), 150, replace = TRUE),
   "proportion of answers higher than the centered level. I want the plot to be sorted according to very left proportions that are the combination (sum) of the two lower levels. (i.e. Respectively the percentages on the very right in the sum of the two lower categories. )" = sample(
     likert_levels,
     150,
     replace = TRUE,
     prob = c(1, 0, 1, 1, 0)
   )
 ) %>%
 mutate(across(everything(), ~ factor(.x, levels = likert_levels)))
anno <-
 partial(
   annotate,
   "text",
   x = -1,
   angle = 90,
   size = 3,
   fontface = "bold"
 )
gg <- gglikert(
 df, 
 labels_size = 2, 
 y_label_wrap = 68,
 totals_hjust = 0.5
) +
 aes(y = reorder(
   .question,
   ifelse(.answer %in% c("Strongly disagree", "Disagree"),
          1, 0),
   FUN = sum,
   decreasing = TRUE
 )) +
 theme(axis.text.y = element_text(size = 8)) +
 geom_hline(
   yintercept = c(1.5, 5.5),
   linetype = "dashed",
   colour = "grey20"
 ) +
 anno(y = 1,
      label = "warning\nzone",
      color = "#A6611A") +
 anno(y = 3.5,
      label = "so-so",
      color = "black") +
 anno(y = 6,
      label = "no warning\nzone",
      color = "#018571") +
 labs(y = NULL)

gg +
 theme(
   # set to "inside" to enable use of `legend.position.inside`
   legend.position = "inside",
   # move legend to the left and down a smidge
   legend.position.inside = c(0, -0.1), 
   # maintain horizontal direction
   legend.direction = "horizontal",
   # remove gridlines
   panel.grid = element_blank(),
   # add some margin to prevent clipping
   plot.margin = margin(
     t = 1,
     r = 1,
     b = 25,
     l = 1
   )
 )

When I try to render it to html via Rmarkdown the totals in the right side disappear and the and the left side totals remain in the middle.I want to have them near the vertical borders.What adjustments have to be made in order to get the wanted result?


Solution

  • If I knit the .Rmd per below, I get an html figure that looks okay as shown.

    Could you update your question with your full Rmd script (between a pair of 4 ticks) and include your html figure?

    ---
    title: "test"
    output: html_document
    date: "2024-04-28"
    ---
    
    ```{r}
    
    library(dplyr, warn = FALSE)
    library(ggplot2)
    library(ggstats)
    library(purrr)
    library(scales)
    
    likert_levels <- c(
     "Strongly disagree",
     "Disagree",
     "Neither agree nor disagree",
     "Agree",
     "Strongly agree"
    )
    
    df <-
     tibble(
       "there is an argument sort_prop_include_center that could be set up to TRUE in order to include half of the centered level when sorting data" = sample(likert_levels, 150, replace = TRUE),
       "Similarly, the argument totals_include_center allows you to include half of the centered level into the left and the right totals" = sample(likert_levels, 150, replace = TRUE, prob = 5:1),
       "Here is one possible option which uses reorder and an ifelse to reorder the variable mapped on y using the counts (aka the sum) of Strictly disagree " = sample(likert_levels, 150, replace = TRUE, prob = 1:5),
       "and disagree answers. Under the hood ggstats::gglikert reshape the data to long where the question id's are stored in a column named .question and the answers in a column named .answer:" = sample(likert_levels, 150, replace = TRUE, prob = 1:5),
       "They used sampling data and create a data frame called df. I am using the same as given in the link. (the df not the df_dk). Ok, if i run in R the following code :" = sample(c(likert_levels, NA), 150, replace = TRUE),
       "proportion of answers higher than the centered level. I want the plot to be sorted according to very left proportions that are the combination (sum) of the two lower levels. (i.e. Respectively the percentages on the very right in the sum of the two lower categories. )" = sample(
         likert_levels,
         150,
         replace = TRUE,
         prob = c(1, 0, 1, 1, 0)
       )
     ) %>%
     mutate(across(everything(), ~ factor(.x, levels = likert_levels)))
    anno <-
     partial(
       annotate,
       "text",
       x = -1,
       angle = 90,
       size = 3,
       fontface = "bold"
     )
    gg <- gglikert(
     df, 
     labels_size = 2, 
     y_label_wrap = 68,
     totals_hjust = 0.5
    ) +
     aes(y = reorder(
       .question,
       ifelse(.answer %in% c("Strongly disagree", "Disagree"),
              1, 0),
       FUN = sum,
       decreasing = TRUE
     )) +
     theme(axis.text.y = element_text(size = 8)) +
     geom_hline(
       yintercept = c(1.5, 5.5),
       linetype = "dashed",
       colour = "grey20"
     ) +
     anno(y = 1,
          label = "warning\nzone",
          color = "#A6611A") +
     anno(y = 3.5,
          label = "so-so",
          color = "black") +
     anno(y = 6,
          label = "no warning\nzone",
          color = "#018571") +
     labs(y = NULL)
    
    gg +
     theme(
       # set to "inside" to enable use of `legend.position.inside`
       legend.position = "inside",
       # move legend to the left and down a smidge
       legend.position.inside = c(0, -0.1), 
       # maintain horizontal direction
       legend.direction = "horizontal",
       # remove gridlines
       panel.grid = element_blank(),
       # add some margin to prevent clipping
       plot.margin = margin(
         t = 1,
         r = 1,
         b = 25,
         l = 1
       )
     )
    
    ```
    

    enter image description here