Gráfico de Colunas

Há duas funções para criar gráficos de colunas: o geom_bar() e geom_col().

O gráfico mais simples é o de contagem. A base diamonds traz o preço e alguns atributos de uma amostra de diamantes. Uma das características listadas é a qualidade do corte do diamante: em ordem crescente eles são categorizados em Fair, Good, Very Good, Premium e Ideal. Com o geom_bar pode-se facilmente visualizar a quantidade de observações em cada categoria.

library(ggplot2)
# gráfico de contagem
ggplot(data = diamonds, aes(x = cut))+geom_bar()

Note que a função geom_bar() dispensa o argumento y já que o gráfico faz a contagem do número de casos em cada categoria no eixo-x. Em muitos casos, contudo, pode ser interessante especificar também uma variável no eixo-y. Para fazer este ajuste é necessário especificar o argumento stat = "identity" dentro da função.

# Cria dados artificiais
set.seed(33)
df <- data.frame(cat = c("a", "b", "c", "d", "e"),
                 val = 5 + rnorm(5))

ggplot(df, aes(x = cat, y = val)) +
  geom_bar(stat = "identity")

Por comodidade, costuma ser mais prático usar diretamente a função geom_col(), que assume que uma variável y também deve ser plotada.

ggplot(df, aes(x = cat, y = val)) +
  geom_col()

Invertendo os eixos

Para facilitar a visualização das categorias pode ser interessante inverter os eixos do gráfico. Para isto usa-se o coord_flip(). Vale notar que é possível inverter os eixos de qualquer tipo de gráfico do ggplot.

df <- data.frame(cat = c("Ens. Fundamental", "Ens. Médio", "Ens. Superior", "Pós-graduação"),
                 val = 1000 + 200*seq(1, 4))

ggplot(df, aes(x = cat, y = val)) +
  geom_col() +
  labs(title = "Salário e escolaridade") +
  coord_flip()

Características estéticas

Há três características estéticas básicas num gráfico de colunas: colour, fill e alpha. A primeira define a cor do contorno da coluna, a segunda, a cor da parte interior da coluna; a última é um parâmetro de transparência em que alpha = 0 é “perfeitamente transparente” e alpha = 1 é nada transparente, i.e., o gráfico inalterado.

ggplot(df, aes(x = cat, y = val)) + geom_col(colour = "orange", fill = "lightblue", alpha = 0.75)

Ainda que seja interessante definir as cores do gráfico desta maneira, costuma ser mais útil atribuir cores distintas a categorias distintas. Para melhor exemplificar isto vamos carregar a base SmokeBan.

library(AER)
data(SmokeBan)
smoker ban age education afam hispanic gender
yes yes 41 hs no no female
yes yes 44 some college no no female
no no 19 some college no no female
yes no 29 hs no no female
no yes 28 some college no no female
no no 40 some college no no male

O gráfico abaixo mostra as diferenças entre fumantes e não-fumantes para diferentes níveis de escolaridade.

ggplot(SmokeBan, aes(x = education)) +
  geom_bar(aes(fill = smoker))

Para colocar as colunas lado a lado usa-se position = "dodge"

ggplot(SmokeBan, aes(x = education)) +
  geom_bar(aes(fill = smoker), position = "dodge")

Em geral, é mais interessante visualizar proporções do que valores absolutos. Pode-se fazer isto agregando os dados e usando funções como table e prop.table. A primeira cria uma tabela de frequências e a segunda usa como input uma tabela de frequências para gerar uma tabela de proporções.

cdata <- table(SmokeBan$education, SmokeBan$smoker)
(pdata <- prop.table(cdata))
##               
##                    no    yes
##   hs drop out  0.0569 0.0343
##   hs           0.2240 0.1026
##   some college 0.2113 0.0689
##   college      0.1704 0.0268
##   master       0.0951 0.0097
dados <- as.data.frame(pdata)

ggplot(dados, aes(x = Var1, y = Freq)) +
  geom_col(aes(fill = Var2), position = "dodge") +
  scale_y_continuous(labels = scales::percent)

Note que este não é um tutorial de manipulação de dados, mas pode-se adiantar que, na prática, não se costuma usar as funções base do R para transformar dados. Em geral, usa-se ou o dplyr ou data.table para manipular dados. De qualquer forma, o ggplot tem alguns atalhos para plotar dados tranformados. Em particular, pode-se usar y = (..count..) para somar o número de observações em cada categoria e então dividir este valor por sum(..count..) o número total de observações em todos os casos das categorias em questão.

ggplot(SmokeBan, aes(x = education)) +
  geom_bar(aes(fill = smoker, 
               y = (..count..)/sum(..count..)), position = "dodge") +
  scale_y_continuous(labels = scales::percent)

ggplot(SmokeBan, aes(x = education))+
  geom_bar(aes(fill = smoker, 
               y = (..count..)/sum(..count..)), position = "fill")+
  scale_y_continuous(labels = scales::percent)

library(AER)
data(OECDGas)
country year gas income price cars
Austria 1960 4.173244 -6.474277 -0.3345476 -9.766840
Austria 1961 4.100989 -6.426006 -0.3513276 -9.608622
Austria 1962 4.073177 -6.407308 -0.3795177 -9.457257
Austria 1963 4.059509 -6.370679 -0.4142514 -9.343155
Austria 1964 4.037689 -6.322247 -0.4453354 -9.237739
Austria 1965 4.033983 -6.294668 -0.4970607 -9.123904
Austria 1966 4.047537 -6.252546 -0.4668377 -9.019822
Austria 1967 4.052911 -6.234581 -0.5058834 -8.934402
Austria 1968 4.045507 -6.206894 -0.5224125 -8.847967
Austria 1969 4.046355 -6.153140 -0.5591105 -8.788686
Austria 1970 4.080888 -6.081712 -0.5965612 -8.728200
Austria 1971 4.106720 -6.043626 -0.6544591 -8.635898
Austria 1972 4.128018 -5.981052 -0.5963318 -8.538338
Austria 1973 4.199381 -5.895153 -0.5944468 -8.487289
Austria 1974 4.018495 -5.852381 -0.4660269 -8.430404
selecao <- OECDGas[OECDGas$country %in% c("Austria", "Belgium", "Canada", "Japan", "USA"), ]
ggplot(selecao, aes(x = year, y = gas))+geom_col(aes(fill = country))

Um pacote útil para escolher boas cores de forma automática é o RColorBrewer. Para saber mais visite o site do pacote. Escolhe-se cores diferentes variando o argumento palette. Para diferentes tipos de dados deve-se ajustar o argumento type. Para dados divergentes: type = "div"; para dados em sequência: type = "seq"; para dados categóricos em geral: type = "qual".

library(RColorBrewer) 
ggplot(selecao, aes(x = year, y = gas)) +
  geom_col(aes(fill = country)) +
  scale_fill_brewer(palette = 2, type = "seq")

Dicas gerais

Sempre comece um gráfico de colunas no zero. Caso contrário, a diferença entre as coluns fica inflada.

Fazendo um zoom nos dados parece haver uma diferença substancial nos dados.

ggplot(OECDGas, aes(x = year, y = gas)) +
  geom_col() +
  # Redefine os limites do eixo-y
  coord_cartesian(ylim = c(71, 82))

Mas começando o gráfico no zero vemos que aquela diferença é muito menor do que parecia.

ggplot(OECDGas, aes(x = year, y = gas)) +
  geom_col()

Evite usar cores diferentes para colunas que representam a mesma varíavel

O gráfico abaixo representa o consumo de gasolina para um conjunto de 18 países.

ggplot(OECDGas, aes(x = year, y = gas)) +
  geom_col(aes(fill = year))

Como a variável de interesse é a mesma para todos os anos (i.e. consumo de gasolina), um gráfico simples - sem diferenciação por cores - é mais adequado.

ggplot(OECDGas, aes(x = year, y = gas)) +
  geom_col()

Use um degradê de cores

Degradês facilitam a comparação de classes diferentes. Cores diferentes podem ser uma opção, mas tenha muito cuidado com o contraste para não dificultar a interpretação dos dados.

ggplot(diamonds, aes(x = color)) +
  geom_bar(aes(fill = cut), position = "dodge") +
  scale_fill_brewer(palette = 3, type = "qual")+
  theme_dark()

Note como degradês facilitam a comparação e são uma solução elegante.

ggplot(diamonds, aes(x = color)) +
  geom_bar(aes(fill = cut), position = "dodge") +
  scale_fill_brewer(palette = 1) +
  theme_dark()

Gráficos horizontais em ordem

Gráficos horizontais desordenados podem ser muito confusos.

# Seleciona somente os dados do ano de 1978
selecao <- OECDGas[OECDGas$year == 1978, ]
# Gráfico de barras sem ordem
ggplot(selecao, aes(x = country, y = gas)) +
  geom_col() +
  coord_flip()

Quase sempre é preferível ordená-los em ordem decrescente. Uma exceção é quando, por exemplo, a ordem alfabética das categorias é mais importante.

# Ordena os países segundo o consumo de gasolina
selecao$country <- factor(as.character(selecao$country), levels = selecao$country[order(selecao$gas)])
# Gráfico de barras ordenado
ggplot(selecao, aes(x = country, y = gas)) +
  geom_col() +
  coord_flip()

Acrescente números às colunas para facilitar a interpretação

Gráficos horizontais podem ser uma opção interessante para destacar o nome das categorias, mas costumam dificultar a comparação das magnitudes representadas. Plotar o valor das colunas costuma facilitar a comapração.

ggplot(selecao, aes(x = country, y = gas)) +
  geom_col() +
  # Acrescenta números ao gráfico
  geom_text(aes(label = round(gas, 1)), hjust = -.5) +
  coord_flip(ylim = c(0, 5.5))

Linhas horizontais para agrupar muitas categorias

Linhas horizontais ou verticais podem facilitar a visualização quando há muitas colunas no gráfico. Tente escolher as linhas de maneira a agrupar os dados em grupos similares.

ggplot(selecao, aes(x = country, y = gas)) +
  geom_col(fill = "gray50", width = .65) +
  geom_text(aes(label = round(gas, 2)), hjust = -.5) +
  coord_flip(ylim = c(0, 5.5)) +
  # Define linhas horizontais no gráfico
  geom_vline(xintercept = 8.5, size = 1) +
  geom_vline(xintercept = 13.5, size = 1)

Destaque informações usando cores fortes (e contraste)

Uma forma de destacar uma particular observação é contrastando cores.

# Cria uma variável dummy para destacar os USA
selecao$highlight <- ifelse(selecao$country == "USA", "sim", "não")
ggplot(selecao, aes(x = country, y = gas)) +
  geom_col(aes(fill = highlight)) +
  geom_text(aes(label = round(gas, 1)), hjust = -1) +
  coord_flip() +
  # Para suprimir a legenda
  guides(fill = FALSE) +
  # Para escolher as core manualmente
  scale_fill_manual(values = c("gray80", "gray15"))

Quando plotando dados positivos e negativos é comum distinguir os valores usando cores diferentes. Lembre-se de usar cores intuitivas (cores fortes como vermelho para valores negativos). Primeiro um exemplo que não faz esta distinção.

# Carrega a base de dados USMacroSWQ do pacote AER
data(USMacroSWQ)
# Selciona a série do PIB trimestral
pib <- USMacroSWQ[, 1]
# Calcula a variação trimestre contre trimestre do ano anterior
var_pib <- (pib - lag(pib, -4))/lag(pib, -4)
# Selciona uma janela específica (anos 1970)
var_pib_1970 <- window(var_pib, start = c(1970, 1), end = c(1979, 4))
# Junta os dados num data.frame
dados <- data.frame(tempo = time(var_pib_1970),
                  y = var_pib_1970)
# Gráfico dos dados
ggplot(dados, aes(tempo, y)) + 
  geom_col()+
  labs(title = "Variação trimestral do PIB")

Agora o mesmo gráfico com cores e também com uma linha horizontal para ressaltar o eixo-x.

# Cria uma dummy para indicar os anos em que houve crescimento
dados$crescimento = as.factor(ifelse(dados$y > 0, yes = 1, no = 0))
# Gráfico dos dados
ggplot(dados, aes(tempo, y)) + 
  geom_col(aes(fill = crescimento)) +
  geom_hline(yintercept = 0) +
  guides(fill = FALSE) +
  scale_fill_manual(values = c("firebrick", "dodgerblue4"))

Evite gráficos em três dimensões

Gráficos de barras em três dimensões são considerados bastante inapropriados. Não só a terceira dimensão é dispensável, pois ela costuma não representar uma variável, ela adiciona considerável ruído na apresentação dos dados. Em geral, um gráfico em duas dimensões é muito mais claro. Este tipo de gráfico, atualmente, é tão pouco popular que o pacote ggplot2 não oferece uma função para gerá-lo.