Adicionando a curva da distribuição normal em um gráfico de distribuição com ggplot2

Tutorial
Visualização de dados
ggplot2
Autor

Beatriz Milz

Data de Publicação

4 de março de 2025

Introdução

Ao trabalhar com análise de dados, um dos gráficos mais comuns que utilizamos é o gráfico de densidade, que nos permite observar a distribuição de uma variável contínua. No entanto, às vezes é útil comparar essa distribuição “real” com uma distribuição normal1, para verificar o quão próximo os dados estão dessa curva teórica.

O objetivo deste post não é fazer uma explicação sobre o que é uma distribuição normal. Caso você não esteja familiarizado com o conceito, esse material pode ajudar.

Neste post, vou mostrar como adicionar uma curva normal simulada sobreposta ao gráfico de densidade de uma variável contínua.

Nota

Esse post foi escrito a partir de uma dúvida que recebi alguns meses atrás! Na época eu respondi, e a resposta ficou guardada em um script. Decidi transformá-la em um post para compartilhar com outras pessoas também. Espero que seja útil!

Passo 1: Carregar os pacotes necessários

Antes de qualquer coisa, vamos garantir que os pacotes necessários estão carregados. Neste caso, utilizaremos os pacotes ggplot2 (que faz parte do tidyverse) e os dados sobre os pinguins de Palmer, que estão disponíveis no pacote dados.

Caso não tenha esses pacotes instalados, você pode instalar executando o código abaixo:

install.packages("dados")
install.packages("tidyverse")

Carregando os pacotes:

dados_pinguins <- dados::pinguins |> 
  mutate(massa_corporal_kg = massa_corporal / 1000) 

Passo 2: Criar o gráfico de densidade

Agora, vamos plotar a distribuição da massa corporal dos pinguins utilizando a função geom_density(), que gera a curva de densidade dos dados.

dados_pinguins |> 
  ggplot() +
  aes(x = massa_corporal_kg) +
  geom_density()
Warning: Removed 2 rows containing non-finite outside the scale range
(`stat_density()`).

Essa visualização já nos fornece uma visão geral da distribuição dos dados de massa corporal. Agora, vamos para o próximo passo: adicionar a curva normal sobre essa distribuição.

Passo 3: Adicionar a curva normal ao gráfico

A função stat_function() permite adicionar uma função estatística ao gráfico. Neste caso, vamos utilizar a função de densidade da distribuição normal (dnorm()) no argumento fun (fun = dnorm), e ajustar a cor da linha para vermelho.

dados_pinguins |>
  ggplot() +
  aes(x = massa_corporal_kg) +
  geom_density() +
  stat_function(fun = dnorm,
                color = "red",
                linetype = "dashed")
Warning: Removed 2 rows containing non-finite outside the scale range
(`stat_density()`).

Perceba que a curva que foi criada está “transladada”. Ela não está ajustada aos dados, pois não informamos os parâmetros da distribuição normal (média e desvio padrão), e a função dnorm() foi executada utilizando os valores padrão (média = 0 e desvio padrão = 1).

Portanto, precisamos calcular esses valores a partir dos dados e utilizá-los para simular a curva normal.

media <- mean(dados_pinguins$massa_corporal_kg, na.rm = TRUE)

desvio_padrao <- sd(dados_pinguins$massa_corporal_kg, na.rm = TRUE)

Agora, vamos adicionar a curva normal ao gráfico, informando os parâmetros da distribuição normal. O código abaixo pode parecer estranho pois usamos o ~ para indicar que estamos passando uma função anônima para o argumento fun da stat_function().

dados_pinguins |>
  ggplot() +
  aes(x = massa_corporal_kg) +
  geom_density() +
  stat_function(
    fun = ~ dnorm(x = .x, mean = media, sd = desvio_padrao),
    color = "red",
    linetype = "dashed"
  )
Warning: Removed 2 rows containing non-finite outside the scale range
(`stat_density()`).

Aqui está! Agora temos um gráfico de densidade da massa corporal dos pinguins com a curva normal sobreposta. Isso nos permite visualizar a distribuição real dos dados e compará-la com a distribuição normal.

Conclusão

Neste post, mostrei como adicionar uma curva normal simulada sobreposta a um gráfico de densidade de uma variável contínua. Você conhece outras formas de fazer isso? Compartilhe nos comentários!

Gostaria de agradecer ao Julio Trecenti por me fazer sugestões para melhorar o post!

Se você gostou deste post, você pode me acompanhar nas seguintes plataformas:

Notas de rodapé

  1. Conhecida também como “curva com forma de sino”, “curva normal”, “gaussiana”.↩︎