Medidas-resumo no tidyverse

Hoje estava fazendo uma análise exploratória e precisava estudar os quartis de uma variável contínua. A solução usando o tidyverse é tão elegante que valeu um post no blog.

Usaremos os pacotes tibble, dplyr, tidyr e purrr. Caso você não tenha qualquer um deles instalado, basta rodar os códigos abaixo.

install.packages(tibble)
install.packages(dplyr)
install.packages(tidyr)
install.packages(purrr)

Nesse exemplo, usamos a famosa base mtcars:

tab <- mtcars |> 
  dplyr::group_by(am, vs) |> 
  tidyr::nest() |> 
  dplyr::mutate(
    quartis = purrr::map(data, ~ tibble::enframe(quantile(.x$mpg, 1:4 / 4)))
  ) |> 
  tidyr::unnest(quartis) |>
  tidyr::pivot_wider(
    names_from = name,
    values_from = value
  ) |> 
  dplyr::select(-data)

tab
## # A tibble: 4 × 6
## # Groups:   am, vs [4]
##      vs    am `25%` `50%` `75%` `100%`
##   <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>
## 1     0     1  16.8  20.4  21     26  
## 2     1     1  25.0  30.4  31.4   33.9
## 3     1     0  18.6  21.4  22.2   24.4
## 4     0     0  14.0  15.2  16.6   19.2
  • A função dplyr::group_by() faz um grupo para cada combinação de am e vs.
  • A função tidyr::nest() guarda os dados de cada grupo numa list-column chamada data.
  • A função purrr::map() aplica elegantemente a função quantile() para cada grupo de datas, sendo ajudada pela função tibble::enframe(), que coloca o resultado de quantile() em uma tibble.
  • A função tidyr::unnest() coloca os resultados de volta em colunas-vetores.
  • Terminamos com tidyr::pivot_wider() para espalhar os quartis nas colunas e a função dplyr::select() para remover a list-column data que não precisamos mais.

O resultado pode ser jogado diretamente numa tabela:

knitr::kable(tab) |>
  kableExtra::kable_styling()
vs am 25% 50% 75% 100%
0 1 16.775 20.35 21.000 26.0
1 1 25.050 30.40 31.400 33.9
1 0 18.650 21.40 22.150 24.4
0 0 14.050 15.20 16.625 19.2

É possível mudar esse código para ter outras medidas-resumo, por exemplo. Para isso, podemos usar a função summary(), por exemplo, ou criar nossa própria função.

mtcars |>
  dplyr::group_by(am, vs) |>
  tidyr::nest() |>
  dplyr::mutate(
    s = purrr::map(data, ~tibble::enframe(summary(.x$mpg))),
    s = purrr::map(s, ~ .x |> dplyr::mutate(value = as.numeric(value)))
  ) |>
  dplyr::select(vs, am, s) |>
  tidyr::unnest(s) |>
  tidyr::pivot_wider(names_from = name, values_from = value) |>
  knitr::kable() |>
  kableExtra::kable_styling()
vs am Min. 1st Qu. Median Mean 3rd Qu. Max.
0 1 15.0 16.775 20.35 19.75000 21.000 26.0
1 1 21.4 25.050 30.40 28.37143 31.400 33.9
1 0 17.8 18.650 21.40 20.74286 22.150 24.4
0 0 10.4 14.050 15.20 15.05000 16.625 19.2

Como você resolveria essa task? Escreva nos comentários!

comments powered by Disqus