Descritivas no R

Intro
Estatística
Descritivas
Estatística descritiva númerica no R. Como sumariar os dados no seu todo e em função de outras variáveis
Autores
Afiliações

João O. Santos

ISPA

Cristina Mendonça

ISPA; WJCR

Vitória Melita

FP-UL

Mariona Pascual Peñas

UIB

João Raposo

ISPA

Marta Barros

FP-UL

0 Estatística Descritiva

  • A estatística descritiva, como o nome indica, ajuda-nos a descrever os dados

  • É uma forma de apresentarmos um ou mais sumários dos dados

  • Como qualquer sumário tem como objectivo facilitar a leitura, mas implica perda de informação

1 Palmer Penguins

Ao longo deste tutorial vamos usar o dataset penguins do pacote palmerpenguins.

Instalar o Pacote

Importante

Como sempre, para podermos usar um pacote temos primeiro do instalar, mas só o temos do fazer uma vez (por computador). Não precisamos de instalar o pacote cada vez que o queremos invocar.

install.packages("palmerpenguins")

Importar os Dados

Para termos acesso à base de dados basta importarmos o pacote palmerpenguins e a partir daí conseguiremos aceder à variável penguins que contém os nossos dados. Para facilitar a escrita do código, tornando-o mais genérico e simulando a importação de dados dum ficheiro, vamos criar uma variável ds (abreviatura de dataset) com os dados e depois trabalharemos com essa variável.

Importante

Todos os exemplos deste tutorial assumem que já instalou o pacote palmerpenguins e que executou as linhas de código abaixo.

library(palmerpenguins)

ds <- penguins

2 Tendência Central

Média

A média é calculada com a função mean(). Passamos-lhe como argumento o vector com os valores que queremos sumariar.

# Computa a média da massa corporal dos pinguins
mean(ds$body_mass_g)
[1] NA
Aviso

Como podemos ver acima, se a variável tiver valores em falta (NA), a função mean() retorna NA.

Para ignorarmos os valores em falta, temos de especificar o argumento na.rm = TRUE.

# Computa a média ignorando valores em falta
mean(ds$body_mass_g, na.rm = TRUE)
[1] 4201.754

Mediana

A mediana é calculada com a função median(). Tal como a mean(), passamos-lhe o vector de valores e, se necessário, o argumento na.rm = TRUE.

# Computa a mediana da massa corporal dos pinguins
median(ds$body_mass_g, na.rm = TRUE)
[1] 4050

Moda

O R base não tem uma função dedicada para calcular a moda estatística.

AvisoCuidado com a função mode()!

Ao contrário do que o nome sugere, a função mode() no R não calcula a moda estatística. No R, esta função é utilizada para identificar o tipo de armazenamento do objeto (e.g., numeric, character, logical).

Para encontrar a moda (o valor mais frequente), podemos usar a função table() para contar as frequências e identificar o valor máximo.

# Frequências da variável espécie
table(ds$species)

   Adelie Chinstrap    Gentoo 
      152        68       124 
# Para obter apenas o nome do valor mais frequente (a moda)
names(which.max(table(ds$species)))
[1] "Adelie"

Para variáveis contínuas, a moda não é tão informativa. Normalmente só faz sentido para variáveis categóricas ou discretas.

3 Dispersão

Amplitude Total

A amplitude total é a diferença entre o máximo e o mínimo.

# Calcula amplitude total da massa corporal
max(ds$body_mass_g, na.rm = TRUE) - min(ds$body_mass_g, na.rm = TRUE)
[1] 3600

Podemos também usar a função range() para obter o mínimo e máximo de uma só vez.

# Retorna o mínimo e máximo
range(ds$body_mass_g, na.rm = TRUE)
[1] 2700 6300

Amplitude Inter-Quartil (AIQ)

A AIQ é calculada com a função IQR().

# Calcula a AIQ da massa corporal
IQR(ds$body_mass_g, na.rm = TRUE)
[1] 1200

Podemos também calcular os quartis com a função quantile().

# Calcula os quartis (0%, 25%, 50%, 75%, 100%)
quantile(ds$body_mass_g, na.rm = TRUE)
  0%  25%  50%  75% 100% 
2700 3550 4050 4750 6300 
# Calcula Q1 e Q3 especificamente
quantile(ds$body_mass_g, probs = c(0.25, 0.75), na.rm = TRUE)
 25%  75% 
3550 4750 

Variância

A variância é calculada com a função var().

# Calcula a variância da massa corporal
var(ds$body_mass_g, na.rm = TRUE)
[1] 643131.1

Desvio-Padrão

O desvio-padrão é calculado com a função sd().

# Calcula o desvio-padrão da massa corporal
sd(ds$body_mass_g, na.rm = TRUE)
[1] 801.9545
Nota

Notem que sd() é a raiz quadrada de var():

sqrt(var(ds$body_mass_g, na.rm = TRUE))
[1] 801.9545

4 Múltiplas Descritivas de Forma Eficiente

R base vs Tidyverse

  • R base = funções nativas que já vêm instaladas no R (não requer instalação de pacotes extra).

  • Vantagens: Sempre disponível, mais leve, familiar para utilizadores de longa data.

  • Desvantagens: Sintaxe menos consistente, funções com comportamentos heterogéneos.

  • Tidyverse = conjunto de pacotes modernos (dplyr, tidyr, etc.) com uma gramática consistente

  • Vantagens: Sintaxe legível (summarise() vs aggregate()), melhor para projetos colaborativos, mais intuitivo.

  • Desvantagens: Requer instalação, dependência externa.

Importante

Tentem ser consistentes dentro do mesmo script/projeto

  • Se começarem com dplyr, usem-no em todo o lado
  • Se usarem apenas R base, não usem dplyr sem haver necessidade

Haverá excepções, mas no geral tentem escolher uma abordagem que faça com que o vosso código pareça escrito pela mesma pessoa e tenha o mesmo estilo (assim como na escrita científica tentamos que cada artigo seja consistente no estilo e “voz” que adopta).

Com R Base

A função summary() calcula várias descritivas de uma só vez.

      species          island    bill_length_mm  bill_depth_mm  
 Adelie   :152   Biscoe   :168   Min.   :32.10   Min.   :13.10  
 Chinstrap: 68   Dream    :124   1st Qu.:39.23   1st Qu.:15.60  
 Gentoo   :124   Torgersen: 52   Median :44.45   Median :17.30  
                                 Mean   :43.92   Mean   :17.15  
                                 3rd Qu.:48.50   3rd Qu.:18.70  
                                 Max.   :59.60   Max.   :21.50  
                                 NAs    :2       NAs    :2      
 flipper_length_mm  body_mass_g       sex           year     
 Min.   :172.0     Min.   :2700   female:165   Min.   :2007  
 1st Qu.:190.0     1st Qu.:3550   male  :168   1st Qu.:2007  
 Median :197.0     Median :4050   NAs   : 11   Median :2008  
 Mean   :200.9     Mean   :4202                Mean   :2008  
 3rd Qu.:213.0     3rd Qu.:4750                3rd Qu.:2009  
 Max.   :231.0     Max.   :6300                Max.   :2009  
 NAs    :2         NAs    :2                                 
Dica

Para variáveis numéricas, summary() retorna: mínimo, Q1, mediana, média, Q3, máximo, e o número de NAs.

A Função aggregate()

A função aggregate() permite calcular descritivas por grupos.

Média da massa corporal por espécie:

aggregate(body_mass_g ~ species, data = ds, FUN = mean, na.rm = TRUE)
species body_mass_g
Adelie 3700.662
Chinstrap 3733.088
Gentoo 5076.016

A Função ave()

A função ave() calcula a média por grupo, mas retorna um vector com o mesmo comprimento que o original (repetindo o valor da média para cada observação do grupo).

Isto é útil quando queremos adicionar uma coluna à base de dados com a média do grupo a que cada observação pertence.

# Adiciona coluna com a média da espécie a que cada pinguim pertence
ds$mean_mass_species <- ave(ds$body_mass_g, ds$species, 
                              FUN = function(x) mean(x, na.rm = TRUE))

# Visualiza as primeiras linhas
head(ds[, c("species", "body_mass_g", "mean_mass_species")])
species body_mass_g mean_mass_species
Adelie 3750 3700.662
Adelie 3800 3700.662
Adelie 3250 3700.662
Adelie NA 3700.662
Adelie 3450 3700.662
Adelie 3650 3700.662

O Pacote dplyr

Instalar o Pacote

Importante

Como sempre, para podermos usar um pacote temos primeiro do instalar, mas só o temos do fazer uma vez (por computador). Não precisamos de instalar o pacote cada vez que o queremos invocar.

Importar o Pacote

Importante

Muitos dos exemplos que se seguem assumem que já instalou e carregou o pacote dplyr (i.e., executou a linha de código acima e a linha de código abaixo deste aviso).

A Função summarise

summarise(ds,
          N = n(),
          Min = min(body_mass_g, na.rm = TRUE),
          Max = max(body_mass_g, na.rm = TRUE),
          M = mean(body_mass_g, na.rm = TRUE),
          SD = sd(body_mass_g, na.rm = TRUE))
N Min Max M SD
344 2700 6300 4201.754 801.9545

5 Tabelas de Frequências

A Função table()

Espécie.

table(ds$species)

   Adelie Chinstrap    Gentoo 
      152        68       124 

Ilha.

table(ds$island)

   Biscoe     Dream Torgersen 
      168       124        52 

Espécie por sexo.

table(ds$species, ds$sex)
           
            female male
  Adelie        73   73
  Chinstrap     34   34
  Gentoo        58   61

Espécie por ilha

table(ds$species, ds$island)
           
            Biscoe Dream Torgersen
  Adelie        44    56        52
  Chinstrap      0    68         0
  Gentoo       124     0         0

Espécie por sexo e ilha

table(ds$species, ds$sex, ds$island)
, ,  = Biscoe

           
            female male
  Adelie        22   22
  Chinstrap      0    0
  Gentoo        58   61

, ,  = Dream

           
            female male
  Adelie        27   28
  Chinstrap     34   34
  Gentoo         0    0

, ,  = Torgersen

           
            female male
  Adelie        24   23
  Chinstrap      0    0
  Gentoo         0    0

Com o Pacote dplyr

Espécie.

count(ds, species)
species n
Adelie 152
Chinstrap 68
Gentoo 124

Ilha.

count(ds, island)
island n
Biscoe 168
Dream 124
Torgersen 52

Espécie por sexo.

count(ds, species, sex)
species sex n
Adelie female 73
Adelie male 73
Adelie NA 6
Chinstrap female 34
Chinstrap male 34
Gentoo female 58
Gentoo male 61
Gentoo NA 5

Espécie por ilha

count(ds, species, island)
species island n
Adelie Biscoe 44
Adelie Dream 56
Adelie Torgersen 52
Chinstrap Dream 68
Gentoo Biscoe 124

Espécie por sexo e ilha

count(ds, species, sex, island)
species sex island n
Adelie female Biscoe 22
Adelie female Dream 27
Adelie female Torgersen 24
Adelie male Biscoe 22
Adelie male Dream 28
Adelie male Torgersen 23
Adelie NA Dream 1
Adelie NA Torgersen 5
Chinstrap female Dream 34
Chinstrap male Dream 34
Gentoo female Biscoe 58
Gentoo male Biscoe 61
Gentoo NA Biscoe 5

Tabela de Frequência Tradicional (n_i, f_i, N_i, F_i)

Nota

De acordo com alguns autores (e.g., Marôco) a frequência absoluta acumulada e a relativa acumulada só devem ser calculadas para variáveis ordinais por implicarem ordenação das linhas pela ordem dos níveis dessa variável. Para efeitos de demonstração o código abaixo computa todos os tipos de frequência da tabela de frequências tradicionais, apesar da variável “ilha” ser nominal. Tal não significa uma posição teórica sobre se essas frequências devem ou não ser calculadas para variáveis nominais.

freq_table <- summarise(group_by(ds, island),
                        n_i = n(),
                        f_i = n_i / nrow(ds))

freq_table$N_i <- cumsum(freq_table$n_i)
freq_table$F_i <- cumsum(freq_table$f_i)

print(freq_table)
# A tibble: 3 × 5
  island      n_i   f_i   N_i   F_i
  <fct>     <int> <dbl> <int> <dbl>
1 Biscoe      168 0.488   168 0.488
2 Dream       124 0.360   292 0.849
3 Torgersen    52 0.151   344 1    

6 Sumariar em Função de Outras Variáveis

Com R Base

Tal como visto anteriormente, podemos usar aggregate() para calcular descritivas por grupos.

Média da massa corporal por sexo:

aggregate(body_mass_g ~ sex, data = ds, FUN = mean, na.rm = TRUE)
sex body_mass_g
female 3862.273
male 4545.685

Média da massa corporal por espécie:

aggregate(body_mass_g ~ species, data = ds, FUN = mean, na.rm = TRUE)
species body_mass_g
Adelie 3700.662
Chinstrap 3733.088
Gentoo 5076.016

Com o Pacote dplyr

Descritivas por sexo.

summarise(group_by(ds, sex),
          N = n(),
          M = mean(body_mass_g, na.rm = TRUE),
          SD = sd(body_mass_g, na.rm = TRUE))
sex N M SD
female 165 3862.273 666.1720
male 168 4545.685 787.6289
NA 11 4005.556 679.3584

Descritivas por espécie.

summarise(group_by(ds, species),
          N = n(),
          M = mean(body_mass_g, na.rm = TRUE),
          SD = sd(body_mass_g, na.rm = TRUE))
species N M SD
Adelie 152 3700.662 458.5661
Chinstrap 68 3733.088 384.3351
Gentoo 124 5076.016 504.1162

Descritivas por espécie e sexo.

summarise(group_by(ds, species, sex),
          N = n(),
          M = mean(body_mass_g, na.rm = TRUE),
          SD = sd(body_mass_g, na.rm = TRUE))
species sex N M SD
Adelie female 73 3368.836 269.3801
Adelie male 73 4043.493 346.8116
Adelie NA 6 3540.000 477.1661
Chinstrap female 34 3527.206 285.3339
Chinstrap male 34 3938.971 362.1376
Gentoo female 58 4679.741 281.5783
Gentoo male 61 5484.836 313.1586
Gentoo NA 5 4587.500 338.1937

Ainda mais descritivas por espécie e sexo.

summarise(group_by(ds, species, sex),
          N = n(),
          Min = min(body_mass_g, na.rm = TRUE),
          Max = max(body_mass_g, na.rm = TRUE),
          M = mean(body_mass_g, na.rm = TRUE),
          SD = sd(body_mass_g, na.rm = TRUE))
species sex N Min Max M SD
Adelie female 73 2850 3900 3368.836 269.3801
Adelie male 73 3325 4775 4043.493 346.8116
Adelie NA 6 2975 4250 3540.000 477.1661
Chinstrap female 34 2700 4150 3527.206 285.3339
Chinstrap male 34 3250 4800 3938.971 362.1376
Gentoo female 58 3950 5200 4679.741 281.5783
Gentoo male 61 4750 6300 5484.836 313.1586
Gentoo NA 5 4100 4875 4587.500 338.1937

7 Exercícios

Exercício 1 - summary() (R base)

Utilize summary() para obter um sumário completo da variável flipper_length_mm (comprimento da barbatana).

Exercício 2 - aggregate() (R base)

Utilize aggregate() para calcular a média e o desvio-padrão do comprimento do bico (bill_length_mm) por espécie.

Exercício 3 - summarise() (dplyr)

Utilize summarise() para criar uma tabela com o número de casos (N), média (M) e desvio-padrão (SD) da massa corporal (body_mass_g) por sexo e ilha.

Exercício 4 - Tabelas de Frequência

  1. Crie uma tabela de frequências com table() entre espécie e sexo.
  2. Use count() do dplyr para criar a mesma tabela.
  3. Qual das espécies tem mais fêmeas? E mais machos?

Exercício 1:

summary(ds$flipper_length_mm)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.     NAs 
  172.0   190.0   197.0   200.9   213.0   231.0       2 

Exercício 2:

aggregate(bill_length_mm ~ species, ds, mean, na.rm = TRUE)
species bill_length_mm
Adelie 38.79139
Chinstrap 48.83382
Gentoo 47.50488
aggregate(bill_length_mm ~ species, ds, sd, na.rm = TRUE)
species bill_length_mm
Adelie 2.663405
Chinstrap 3.339256
Gentoo 3.081857

Exercício 3:

summarise(group_by(ds, sex, island),
          N = n(),
          M = mean(body_mass_g, na.rm = TRUE),
          SD = sd(body_mass_g, na.rm = TRUE))
sex island N M SD
female Biscoe 80 4319.375 659.7489
female Dream 61 3446.311 269.5226
female Torgersen 24 3395.833 259.1444
male Biscoe 83 5104.518 714.1977
male Dream 62 3987.097 349.5237
male Torgersen 23 4034.783 372.4717
NA Biscoe 5 4587.500 338.1937
NA Dream 1 2975.000 NA
NA Torgersen 5 3681.250 413.0047

Exercício 4:

# table()
table(ds$species, ds$sex)
           
            female male
  Adelie        73   73
  Chinstrap     34   34
  Gentoo        58   61
# count()
count(ds, species, sex)
species sex n
Adelie female 73
Adelie male 73
Adelie NA 6
Chinstrap female 34
Chinstrap male 34
Gentoo female 58
Gentoo male 61
Gentoo NA 5

Conclusão: Adelie tem mais machos e fêmeas, Gentoo tem mais machos, Chinstrap tem números equilibrados.