11  Gráfico de Barras

Data de Publicação

14 de abril de 2025

Neste tutorial aborda-se a construção de gráficos de barras para uma ou duas variáveis categóricas utilizando os gráficos base do R. Como os gráficos de barras são construídos a partir de tabelas de contingência, a secção inclui a elaboração destas tabelas.

11.1 Introdução

Os dados utilizados estão disponíveis e descritos em OpenIntro. Trata-se de um conjunto de dados sobre imigração obtidos num inquérito realizado no estado da Florida, nos EUA, em 2012.

Vamos começar por ler os dados e fazer uma pequena exploração inicial.

im <- read.csv("https://www.openintro.org/data/csv/immigration.csv")
summary(im)
   response          political        
 Length:910         Length:910        
 Class :character   Class :character  
 Mode  :character   Mode  :character  
head(im)
               response    political
1 Apply for citizenship conservative
2 Apply for citizenship conservative
3 Apply for citizenship conservative
4 Apply for citizenship conservative
5 Apply for citizenship conservative
6 Apply for citizenship conservative

Como se pode verificar, ambas as variáveis foram lidas como texto, sendo uma boa oportunidade para aplicar as técnicas apresentadas em Secção 9.7 para informar o R da natureza categórica das variáveis.

im$response <- factor(im$response)
im$political <- factor(im$political)

Note-se que o mesmo resultado poderia ser obtido especificando stringsAsFactors = TRUE ao ler o ficheiro, tal como no código que se segue.

im <- read.csv(
  "https://www.openintro.org/data/csv/immigration.csv",
  stringsAsFactors = TRUE
)

Podemos agora verificar se os dados estão corretamente codificados:

summary(im)
                  response          political  
 Apply for citizenship:278   conservative:372  
 Guest worker         :262   liberal     :175  
 Leave the country    :350   moderate    :363  
 Not sure             : 20                     

A variável response regista a resposta à questão do inquérito sobre que tratamento dar aos trabalhadores ilegais nos EUA. A variável political indica qual a ideologia política do respondente. Trata-se portanto de duas variáveis nominais (eventualmente poder-se-ia ordenar a ideologia do mais à esquerda para o mais à direita, se tal fosse relevante).

11.2 Tabela de contingência

Tal como é referido no Capítulo 3, o gráfico de barras é o gráfico mais adequado para descrever dados categóricos. Tal como descrito no Capítulo 10, a função plot() produz gráficos de barras quando lhe é passada uma variável categórica. No entanto, para maior flexibilidade, existe a função barplot() que aceita uma tabela de contingência com a informação sobre as barras a representar. Caso essa informação não exista, no caso mais simples, a pode ser obtida através de contagem das observações em cada categoria, ou seja, elaborando uma tabela de contingência com a função table(). Para a variável response:

t_res <- table(im$response)
t_res

Apply for citizenship          Guest worker     Leave the country 
                  278                   262                   350 
             Not sure 
                   20 

Note-se que o objeto t_res é um vetor numérico com nomes atribuídos a cada elemento. Estes nomes serão utilizados para anotar o gráfico.

A função prop.table() pode ser utilizada para calcular proporções a partir das contagens:

pt_res <- prop.table(t_res)
pt_res

Apply for citizenship          Guest worker     Leave the country 
           0.30549451            0.28791209            0.38461538 
             Not sure 
           0.02197802 

11.3 Barras simples

Dispondo agora da informação sobre as barras, podemos invocar a função barplot() que produz a Figura 11.1.

barplot(t_res)
Figura 11.1: Gráfico de barras

O primeiro e principal argumento da função barplot() é height, que deve ser um vetor numérico, como na Figura 11.1, ou uma matriz, no caso de barras sobrepostas ou barras agrupadas (secções 11.4, 11.5 e 11.6). Este vetor deve conter a altura das barras a representar e pode conter valores negativos, o que origina barras abaixo do eixo base.

Naturalmente, os elementos gráficos do gráfico de barras, como cores, linhas, anotações, etc., podem ser ajustados como necessário. Para além dos parâmetros gráficos comuns a todos os gráficos, a função barplot() pode ser configurada com os parâmetros da tabela Tabela 11.1.

Tabela 11.1: Configuração de gráficos de barras
Argumento Elemento
width = Vetor com a largura das barras. Por omissão, todas iguais a 1 unidade
space = Especifica o espaço entre as barras. Por omissão, 0.2 unidades
horiz = TRUE Para desenhar um gráfico com barras horizontais
col =, border = Para especificar a cor das barras e dos contornos das mesmas
plot = FALSE O gráfico não é desenhado e a função apenas devolve a posição das barras, o que é útil para acrescentar elementos gráficos posteriormente
offset = Distância entre as barras e o eixo base (0 por omissão)
add = TRUE Para desenhar as barras num gráfico já existente

O código que se segue produz a Figura 11.2 e ilustra algumas das configurações que se podem realizar com a função barplot().

par(mar = c(5, 9, 4, 2)) # alargar a margem esquerda

barplot(
  sort(pt_res) * 100,
  main = "Gráfico de Barras", xlab = "percentagem",
  col = "deepskyblue", border = "blue",
  horiz = TRUE, las = 1
)
Figura 11.2: Gráfico de barras com alguns ajuste

11.4 Barras sobrepostas

O gráfico de barras sobrepostas utiliza-se quando se pretende representar as contagens cruzadas de duas variáveis. O processo é em tudo semelhante ao do gráfico de barras simples, mas é necessária uma tabela de contingência de dupla entrada. A tabela de contingência pode ser obtida com a função table(), passando as duas variáveis a cruzar, tal como no código que se segue.

t_res_pol <- table(im$response, im$political)
t_pol_res <- t(t_res_pol) # transposição da tabela
t_res_pol
                       
                        conservative liberal moderate
  Apply for citizenship           57     101      120
  Guest worker                   121      28      113
  Leave the country              179      45      126
  Not sure                        15       1        4

Caso se passe uma tabela de contingência de dupla entrada à função barplot() esta irá devolver um dos gráficos da Figura 11.3, dependendo da ordem das variáveis (cada coluna da tabela de contingência corresponde a uma barra). Note que a função t() transpõe a tabela de contingência. Alternativamente, poderia ser trocada a ordem das variáveis na função table().

barplot(t_res_pol)
barplot(t_pol_res)
(a) Categorias political no eixo
(b) Categorias response no eixo
Figura 11.3: Gráfico de barras sobrepostas

Por norma, este gráfico necessita de uma legenda, o que pode ser especificado com legend.text = TRUE (ou um vetor de entradas para colocar na legenda). Por omissão, a legenda é colocada no topo direito, sobrepondo-se muitas vezes à última barra (ordenar os totais por ordem decrescente pode resolver o problema mas não faz sentido para categorias ordinais, por exemplo), pelo que deve ser configurada utilizando os parâmetros descritos na Secção 10.11.

Para especificar a configuração da legenda há duas alternativas:

  • Fazer o gráfico sem legenda e acrescentar depois uma legenda com legend().
  • Especificar legend.text = TRUE e passar uma lista de configurações no argumento args.legend.

O código que se segue ilustra ambas as técnicas, e os resultados podem ser visualizados na Figura 11.4.

cl <- palette.colors(4, palette = "Set 3") # criar vetor de 4 cores
  
barplot(t_res_pol, col = cl, legend.text = TRUE)

barplot(
  t_res_pol[, order(colSums(t_res_pol), decreasing = TRUE)],
  col = cl, legend.text = TRUE
)

par(mar = c(5, 4, 4, 11))
barplot(
  t_res_pol,
  col = cl,
  legend.text = TRUE,
  args.legend = list(
    x = "right",
    title = "Response",
    fill = cl,
    inset = -0.5
  )
)

par(mar = c(7.5, 7, 4, 2))
barplot(t_res_pol, col = cl, horiz = TRUE, las = 1)
legend(
  "bottom",
  row.names(t_res_pol),
  title = "Response",
  fill = cl,
  ncol = 2,
  inset = - 0.5,
  xpd = TRUE
)
(a) Sem configurações adicionais
(b) Ordenação das colunas
(c) Com configurações via args.legend
(d) Com legenda especificada autonomamente
Figura 11.4: Gráfico de barras sobrepostas com legenda

Na Figura 11.4 (a) não se fizeram quaisquer configurações, resultando numa legenda sobreposta com uma das barras o que é inaceitável.

Na Figura 11.4 (b) apenas se ordenaram as barras por ordem decrescente dos totais da colunas da tabela de contingência. Como a última barra é mais pequena, a legenda já não sobrepõe com a barra.

Na Figura 11.4 (c) configurou-se a legenda utilizando o argumento args.legend. Tal como referido na Secção 10.11, é necessário aumentar a margem onde se coloca a legenda.

Por fim, na Figura 11.4 (d), a legenda foi colocada com a função legend(). Neste caso, como as barras estão na horizontal, faz mais sentido colocar a legenda ao fundo ou no topo.

11.5 Barras sobrepostas normalizadas

Para elaborar um gráfico de barras sobrepostas normalizadas, é necessário acrescentar um passo intermédio ao procedimento descrito na Secção 11.4: calcular as proporções normalizadas.

As proporções normalizadas não são mais do que a frequência de uma determinada célula dividida pela frequência da coluna e podem ser obtidas facilmente com a função prop.table, como se ilustra no código abaixo.

npt_res_pol <- prop.table(t_res_pol, margin = 2)
npt_res_pol
                       
                        conservative     liberal    moderate
  Apply for citizenship  0.153225806 0.577142857 0.330578512
  Guest worker           0.325268817 0.160000000 0.311294766
  Leave the country      0.481182796 0.257142857 0.347107438
  Not sure               0.040322581 0.005714286 0.011019284

Ao especificar margin = 2, estamos a indicar que as proporções devem ser calculadas sobre o total das colunas.

Nota

Na função prop.table(), o argumento margin tem o seguinte significado:

  • margin = 1: calcula proporções sobre os totais das linhas.
  • margin = 2: calcula proporções sobre os totais das colunas, sendo o que se pretende no caso dos gráficos de barras sobrepostas normalizadas.
  • margin = NULL, por omissão: calcula proporções sobre o total da tabela.

Efetuado este passo adicional, estamos em condições de fazer o gráfico com a função barplot(). Na Figura 11.5 pode visualizar-se a versão normalizada da Figura 11.4 (c), produzida com o código que se segue.

par(mar = c(5, 4, 4, 11))
barplot(
  npt_res_pol,
  col = cl,
  legend.text = TRUE,
  args.legend = list(
    x = "right",
    title = "Response",
    fill = cl,
    inset = -0.5
  )
)
Figura 11.5: Gráfico de barras sobrepostas normalizadas

11.6 Barras agrupadas

Em vez de sobrepor as barras, estas podem ser agrupadas e colocadas lado a lado. Para obter um gráfico deste tipo, basta passar o argumento beside = TRUE à função barplot(), sendo tudo o resto idêntico.

O código que se segue produz a versão agrupada da Figura 11.4 (c) e o resultado pode ser visualizado na Figura 11.6.

par(mar = c(5, 4, 4, 11))
barplot(
  t_res_pol,
  col = cl,
  beside = TRUE,
  legend.text = TRUE,
  args.legend = list(
    x = "right",
    title = "Response",
    fill = cl,
    inset = -0.5
  )
)
Figura 11.6: Gráfico de barras agrupadas