Search code examples
rggplot2r-markdown

center bar graph and title with ggplot2


I am trying to center a bar graph and title with ggplot2, for a pdf document with r markdown, the problem is that when the pdf is generated the graph does not allow everything to be seen.

---
title: 
  output:
  pdf_document:
  fig_caption: yes
geometry:
  - top=1.8cm
- left=2cm
- bottom=1.5cm
- right=2cm
- paper=a4paper
header-includes:
  - \usepackage{lscape}
---

  
```{r echo=FALSE}

library(dplyr)
library(ggplot2)


set.seed(456)  
base <- data.frame(
  AÑO = rep(2024, 100),
  ENFERMEDAD = sample(1:6, 100, replace = TRUE)
)


head(base)


base %>%
  filter(AÑO == 2024) %>%
  mutate(ENFERMEDAD = as.character(ENFERMEDAD)) %>%
  mutate(ENFERMEDAD = case_when(
    ENFERMEDAD == "1" ~ "Enfermedades Respiratorias",
    ENFERMEDAD == "2" ~ "Diabetes",
    ENFERMEDAD == "3" ~ "Hipertensión",
    ENFERMEDAD == "4" ~ "Enfermedades Cardiovasculares",
    ENFERMEDAD == "5" ~ "Cáncer",
    ENFERMEDAD == "6" ~ "Enfermedades Infecciosas"
  )) %>%
  count(ENFERMEDAD) %>%
  arrange(desc(n)) %>%
  mutate(PORCENTAJE = paste0(round(n / sum(n) * 100, digits = 0), "%")) %>%
  ggplot(aes(x = reorder(ENFERMEDAD, n), y = n)) +
  geom_bar(stat = "identity", width = 0.7, color = "black", fill = "steelblue") +
  geom_text(aes(label = PORCENTAJE), vjust = 0.5, hjust = -0.1, colour = "black", size = 3) +
  labs(
    title = "Número de Casos Reportados por Tipo de Enfermedad en 2024",
    subtitle = "(Datos simulados para fines de demostración)",
    caption = "",
    x = "",
    y = ""
  ) +
  theme(
    plot.title = element_text(size = 15, face = "plain", hjust = 0),  # Alinear título a la izquierda
    plot.subtitle = element_text(size = 10, face = "plain"),
    panel.background = element_blank(),
    axis.text.y = element_text(size = 8),
    axis.title.y = element_text(size = 8),
    plot.margin = margin(1, 1, 1, 4, "cm")  
  ) +
  geom_vline(xintercept = 0.5, color = "black", linewidth = 0.5) + 
  geom_hline(yintercept = 0, color = "black", linewidth = 0.5) +
  geom_vline(xintercept = 0.5, color = "black", linewidth = 0.5) + 
  geom_hline(yintercept = 0, color = "black", linewidth = 0.5) +
  coord_flip() 

```

Solution

  • If you want to center align your figure then use chunk option fig.align="center". Moreover, one issue with your code is that you already added a left margin of 4cm to your plot (probably to shift the plot to the center?). Hence the barchart and the title will be shifted to the right. Instead I use a margin of 1cm for all four sides. Next, to get more room for the plot remove the axis titles using e.g. x = NULL instead of x="". Third, even with these adjustments the title will still not fit on the page. Besides reducing the font size or adding a line break one option would be to align the title with the plot using theme option plot.title.position="plot". Finally, to avoid the labels from being clipped off I added clip="off" to coord_flip and to add some padding for the labels I switched to geom_label (instead of using the alignment parameter hjust to shift the labels).

    ---
    title: 
    output: 
      pdf_document:
        fig_caption: yes
    geometry:
      - top=1.8cm
      - left=2cm
      - bottom=1.5cm
      - right=2cm
      - paper=a4paper
    header-includes:
      - \usepackage{lscape}
    ---
      
    ```{r echo=FALSE, message=FALSE, fig.align = 'center'}
    library(dplyr)
    library(ggplot2)
    
    set.seed(456)
    base <- data.frame(
      AÑO = rep(2024, 100),
      ENFERMEDAD = sample(1:6, 100, replace = TRUE)
    )
    
    base %>%
      filter(AÑO == 2024) %>%
      mutate(ENFERMEDAD = as.character(ENFERMEDAD)) %>%
      mutate(ENFERMEDAD = case_when(
        ENFERMEDAD == "1" ~ "Enfermedades Respiratorias",
        ENFERMEDAD == "2" ~ "Diabetes",
        ENFERMEDAD == "3" ~ "Hipertensión",
        ENFERMEDAD == "4" ~ "Enfermedades Cardiovasculares",
        ENFERMEDAD == "5" ~ "Cáncer",
        ENFERMEDAD == "6" ~ "Enfermedades Infecciosas"
      )) %>%
      count(ENFERMEDAD) %>%
      arrange(desc(n)) %>%
      mutate(PORCENTAJE = paste0(round(n / sum(n) * 100, digits = 0), "%")) %>%
      ggplot(aes(x = reorder(ENFERMEDAD, n), y = n)) +
      geom_bar(stat = "identity", width = 0.7, color = "black", fill = "steelblue") +
      geom_label(aes(label = PORCENTAJE),
        vjust = 0.5,
        hjust = 0, colour = "black", size = 3,
        label.size = 0, fill = NA
      ) +
      labs(
        title = "Número de Casos Reportados por Tipo de Enfermedad en 2024",
        subtitle = "(Datos simulados para fines de demostración)",
        caption = NULL,
        x = NULL,
        y = NULL
      ) +
      theme(
        plot.title = element_text(size = 15, face = "plain", hjust = 0),
        plot.title.position = "plot",
        plot.subtitle = element_text(size = 10, face = "plain"),
        panel.background = element_blank(),
        axis.text.y = element_text(size = 8),
        axis.title.y = element_text(size = 8),
        plot.margin = margin(1, 1, 1, 1, "cm")
      ) +
      geom_vline(xintercept = 0.5, color = "black", linewidth = 0.5) +
      geom_hline(yintercept = 0, color = "black", linewidth = 0.5) +
      coord_flip(clip = "off")
    ```
    

    enter image description here