{PT} Cowplot!

By Isabella Bicalho Frazeto in Graficos

February 13, 2022

Sobre o pacote

O Cowplot 🐄 é um pacote que foi projetado para ser um add-on do ggplot. As características mais notáveis são os temas, o alinhamento, a organização de figuras em vários painéis gráficos e funções que facilitam a anotação de plotagens ou mesmo mesclar nossos gráficos com outras imagens. Meu objetivo neste tutorial não é usar o pacote extensivamente, mas sim mostrar a você as funções que eu mais uso ao trabalhar com gráficos.

Dados

Neste tutorial, usaremos a Tabela Nutricional do McDonald’s.

## Pacotes ----
library(ggplot2) 
library(cowplot) #<<
library(dplyr)

## Dados ----
menu <- read.csv("menu.csv")

## Visualizar a tabela ----
glimpse(menu)
## Rows: 260
## Columns: 24
## $ Category                      <chr> "Breakfast", "Breakfast", "Breakfast", "~
## $ Item                          <chr> "Egg McMuffin", "Egg White Delight", "Sa~
## $ Serving.Size                  <chr> "4.8 oz (136 g)", "4.8 oz (135 g)", "3.9~
## $ Calories                      <int> 300, 250, 370, 450, 400, 430, 460, 520, ~
## $ Calories.from.Fat             <int> 120, 70, 200, 250, 210, 210, 230, 270, 1~
## $ Total.Fat                     <dbl> 13, 8, 23, 28, 23, 23, 26, 30, 20, 25, 2~
## $ Total.Fat....Daily.Value.     <int> 20, 12, 35, 43, 35, 36, 40, 47, 32, 38, ~
## $ Saturated.Fat                 <dbl> 5, 3, 8, 10, 8, 9, 13, 14, 11, 12, 12, 1~
## $ Saturated.Fat....Daily.Value. <int> 25, 15, 42, 52, 42, 46, 65, 68, 56, 59, ~
## $ Trans.Fat                     <dbl> 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, ~
## $ Cholesterol                   <int> 260, 25, 45, 285, 50, 300, 250, 250, 35,~
## $ Cholesterol....Daily.Value.   <int> 87, 8, 15, 95, 16, 100, 83, 83, 11, 11, ~
## $ Sodium                        <int> 750, 770, 780, 860, 880, 960, 1300, 1410~
## $ Sodium....Daily.Value.        <int> 31, 32, 33, 36, 37, 40, 54, 59, 54, 59, ~
## $ Carbohydrates                 <int> 31, 30, 29, 30, 30, 31, 38, 43, 36, 42, ~
## $ Carbohydrates....Daily.Value. <int> 10, 10, 10, 10, 10, 10, 13, 14, 12, 14, ~
## $ Dietary.Fiber                 <int> 4, 4, 4, 4, 4, 4, 2, 3, 2, 3, 2, 3, 2, 3~
## $ Dietary.Fiber....Daily.Value. <int> 17, 17, 17, 17, 17, 18, 7, 12, 7, 12, 6,~
## $ Sugars                        <int> 3, 3, 2, 2, 2, 3, 3, 4, 3, 4, 2, 3, 2, 3~
## $ Protein                       <int> 17, 18, 14, 21, 21, 26, 19, 19, 20, 20, ~
## $ Vitamin.A....Daily.Value.     <int> 10, 6, 8, 15, 6, 15, 10, 15, 2, 6, 0, 4,~
## $ Vitamin.C....Daily.Value.     <int> 0, 0, 0, 0, 0, 2, 8, 8, 8, 8, 0, 0, 0, 0~
## $ Calcium....Daily.Value.       <int> 25, 25, 25, 30, 25, 30, 15, 20, 15, 15, ~
## $ Iron....Daily.Value.          <int> 15, 8, 10, 15, 10, 20, 15, 20, 10, 15, 1~

Temas e background_grid

Apesar de ter conhecido o cowplot pela aplicabilidade em painéis, sempre acabo utilizando-o em outros tipos de projetos pela facilidade de lembrar os temas que desejo. Por exemplo, quando preciso de um gráfico mais clean, eu uso a função theme_half_open(), que tem um design simples, sem background e um estilo de eixo semiaberto (duas linhas no eixo do quadrantes inferiores esquerdos). Em seguida, vou aplicar esse tema em um gráfico scatter plot entre as variáveis “Total.Fat” e “Calories”:

ggplot(menu, aes(x = Calories, 
                 y = Total.Fat, 
                 color = Category)) + 
            geom_point() + 
            theme_half_open() ## < tema do cowplot

Veja que, com a ajuda do cowplot, rapidamente tivemos um gráfico produzido com um tema clean e que está pronto para ser publicado! O mais legal é que o tema ainda tem a opção de alterar o tamanho do texto no título, no corpo do gráfico e assim por diante. Para obter mais informações sobre essa função, execute o código: ?theme_half_open().

background_grid também é uma das minhas funções preferidas porque, bem 😅, é a função da qual me lembro quando quero colocar um plano de fundo (background 👌) no meu gráfico. Vamos executar dois exemplos com essa função:

## Gordura total vs. caloria
g_fat <- ggplot(menu, aes(x=Calories, y=Total.Fat, color = Category)) + 
            geom_point() +
            theme_half_open() +
            background_grid() # <<

g_fat

## Proteína vs. caloria
g_protein <- ggplot(menu, aes(x = Calories, y = Protein, color = Category)) + 
              geom_point() +
              theme_half_open() +
              background_grid() # <<


g_protein

Outro tema que eu costumo usar com frequência é o theme_minimal. De novo, o pacote me ganha pela usabilidade, logo que este tema possui “duas variantes”: theme_minimal_hgrid, que adiciona linhas na horizontal, e o theme_minimal_vgrid, que adiciona linhas na vertical. Por último, outro add-on que considero muito prático é o panel_border, que adicionar bordas ao panéis.

# Histograma para os dados de gordura total
## Com o theme_minimal_hgrid
hist_fat <- ggplot(menu, aes(x = Total.Fat, fill = Category)) + 
              geom_histogram() +
              facet_grid(vars(Category),  labeller = as_labeller(NULL)) +
              theme_minimal_hgrid() + #<<
              panel_border(color='black') + #<<,
              theme(strip.text.y  = element_blank()) 

hist_fat

# Histograma para os dados de proteína
## Com o theme_minimal_vgrid
hist_protein <- ggplot(menu, aes(x = Protein, fill = Category)) + 
                  geom_histogram() +
                  facet_grid(vars(Category)) +
                  theme_minimal_vgrid() + #<<
                  panel_border(color='black') + #<<
                  theme(strip.text.y  = element_blank()) 

hist_protein

Painéis

Por último, o cowplot tem um função semelhante ao par(mfrow) do base. A partir dela, você é capaz de gerar painéis com vários gráficos em uma única figura.

Vamos fazer três panéis: O primeiro para combinar os dois gráficos de dispersão (p_1), o segundo para combinar os dois gráficos de histograma (p_2) e o terceiro vai combinar o p_1 e o p_2 (p_3).

Painel I

Primeiro, observe que se usarmos apenas a função plot_grid() sem levar a legenda em consideração, ela ficará assim:

plot_grid(g_fat, g_protein, labels = c("A", "B"), label_size = 12)

Obviamente, o painel não é muito bom, pois os dois gráficos compartilham a mesma legenda (🤕). A solução então é a seguinde:

1. Fazer uma figura apenas com os gráficos e sem nenhuma legenda (prow).

prow <- plot_grid(
  g_fat + theme(legend.position="none"),
  g_protein + theme(legend.position="none"),
  align = 'vh',
  labels = c("A", "B"),
  hjust = -1,
  nrow = 1, 
  label_size = 12
)

2. Extrair a legenda usando get_legend (também do cowplot).

legend <- get_legend(
  g_protein + theme()
)

3. Combinar num novo grid prow e a legenda.

p1 <- plot_grid(prow, legend)
p1

Painel II

Vamos repetir os mesmo passos realizados no Painel I, agora com os histogramas:

## Unir os gráficos
prow2 <- plot_grid(
  hist_fat + theme(legend.position="none"),
  hist_protein + theme(legend.position="none"),
  align = 'vh',
  labels = c("C", "D"),
  hjust = -1,
  nrow = 1, 
  label_size = 12
)

## Criar um objeto para a legenda
legend2 <- get_legend(
  hist_protein + theme(legend.position = c(0, 0.55))
)

## Criar o gráfico
p2 <- plot_grid(prow2, legend2, nrow = 1)
p2

Painel III

Finalmente, o último painel 🤙! Nele incluiremos os quatro gráficos criados, no entanto, precisamos ter apenas uma legenda. Para tal, usaremos somente as combinações de gráficos sem legenda (prow e prow2) e a legenda criada para combinação com os histogramas (legend2). Faremos uma pequena edição na legenda 2 para ajeitar

plot_grid(prow, legend2, prow2, nrow = 2)

Para finalizar, precisamos arrumar as proporções dos gráficos no painel. Para isso, vamos utilizar as funções rel_heights = c(t1, t2)) e rel_widths = c(t1, t2), que alteram a altura e a largura, respectivamente. Os argumentos da função correspondem ao tamanho que queremos para cada figura. Os tamanhos devem ser inseridos na ordem em que são incluídas os gráficos na função plot_grid().

p3 <- plot_grid(prow, legend2, prow2, nrow = 2, 
                rel_heights = c(8, 20, 6), 
                rel_widths = c(3, 3, 2)) 
p3

E fim 🥳!

Revisão por Marília Melo Favalesso.