5  Aprendendo a manipular dados

Autor
Afiliação

Programa de Pós-Graduação em Sociologia (USP)

Data de Publicação

3 de fevereiro de 2026

Dentro do R, existem inúmeras formas de se importar um conjunto de dados. Os dados podem ter os mais diversos formatos (extensões):

1 É a forma mais recomendada, ao meu ver, de salvar objetos dentro do R. Um diferencial do .rds é que ele mantém a estrutura do objeto: ou seja, os atributos permanecem os mesmos.

5.1 Importando os pacotes no R

Como vimos, a primeira coisa a se fazer dentro de um script no R é fazer a importação dos pacotes (ou bibliotecas).

Nota

Um pacote é uma “caixa de ferramentas” extra que você instala no R para ganhar novas funcionalidades. Ele reúne códigos, dados e documentação em um único lugar. O termo biblioteca (library) refere-se ao local (a pasta no seu computador) onde esses pacotes ficam guardados.

Geralmente, precisamos, primeiramente, instalar um pacote com a função install.packages e então “carregá-lo” para nosso ambiente, com a função library. Carregar um pacote significa, basicamente, dizer ao R que queremos utilizar um conjunto de ferramentas na nossa sessão. Dito isso:

  1. Sempre instala-se um pacote novo. Este processo só é feito uma vez, ou seja, utiliza-se a função install.packages apenas quando ainda não possuímos o pacote em nossa máquina.
  2. Após a primeira instalação, só é necessário instalar um pacote novamente caso ele tenha sido atualizado (lembra que a comunidade é ativa?). Caso não seja o caso, só é necessário “carregar” nosso pacote para a sessão.
install.packages("tidyverse")
library(tidyverse)

Você pode ter notado que não utilizei as aspas (““) com a função library. Isso é opcional, você pode ou não utilizá-las.

DicaDica 1

O pacote pacman permite que você faça, ao mesmo tempo, a instalação e o carregamento do pacote, com a função p_load. Ao invés de fazer, por exemplo:

install.packages("tidyverse")
library(tidyverse)

você pode fazer apenas:

p_load(tidyverse)

Isso é particularmente útil quando você precisa importar muitos pacotes!

Caso você se esqueça de importar algum pacote, não se preocupe! É possível utilizar uma função de um pacote específico (desde que você tenha ele baixado no seu computador) sem precisar utilizar o library(nome_do_pacote) no começo do seu script. Ao especificar o nome do pacote e utilizar ::, como demonstrado na Figura 5.1, é possível acessar a função desejada:

Figura 5.1: Usando uma função sem carregar o pacote

Agora, basta carregamos os pacaotes de interesse

pacman::p_load(
              tidyverse, # pacotão com vários pacotes core 
              rio,       # pacote que facilita a leitura de qualquer formato
              readxl,    # pacote para ler no formato .xlsx
              janitor    # pacote para limpeza de dados
               )

O script de nossa aula está disponível aqui!

6 Ambientação e importação de pacotes

Feito isso, precisamos importar o conjunto de dados a serem trabalhados no encontro de hoje. Inicialmente, vamos trabalhar com um banco de dados de personagens de starwars. Esse banco está “embutido” no pacote dplyr. São bases de dados para fins didáticos!

dados <- dplyr::starwars

7 Estatística descritiva e manipulação de dados

7.1 Utilizando o R Base

Feita a importação dos dados, podemos visualizá-los com a função head().

head(dados)
# A tibble: 6 × 14
  name      height  mass hair_color skin_color eye_color birth_year sex   gender
  <chr>      <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
1 Luke Sky…    172    77 blond      fair       blue            19   male  mascu…
2 C-3PO        167    75 <NA>       gold       yellow         112   none  mascu…
3 R2-D2         96    32 <NA>       white, bl… red             33   none  mascu…
4 Darth Va…    202   136 none       white      yellow          41.9 male  mascu…
5 Leia Org…    150    49 brown      light      brown           19   fema… femin…
6 Owen Lars    178   120 brown, gr… light      blue            52   male  mascu…
# ℹ 5 more variables: homeworld <chr>, species <chr>, films <list>,
#   vehicles <list>, starships <list>

É possível, também, especificar quantas linhas queremos ver. Por exemplo, as 3 primeiras linhas:

head(dados, 3)
# A tibble: 3 × 14
  name      height  mass hair_color skin_color eye_color birth_year sex   gender
  <chr>      <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
1 Luke Sky…    172    77 blond      fair       blue              19 male  mascu…
2 C-3PO        167    75 <NA>       gold       yellow           112 none  mascu…
3 R2-D2         96    32 <NA>       white, bl… red               33 none  mascu…
# ℹ 5 more variables: homeworld <chr>, species <chr>, films <list>,
#   vehicles <list>, starships <list>

Se eu quiser saber quais são as últimas linhas do meu banco de dados, posso usar a função tail():

tail(dados)
# A tibble: 6 × 14
  name      height  mass hair_color skin_color eye_color birth_year sex   gender
  <chr>      <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
1 Tion Med…    206    80 none       grey       black             NA male  mascu…
2 Finn          NA    NA black      dark       dark              NA male  mascu…
3 Rey           NA    NA brown      light      hazel             NA fema… femin…
4 Poe Dame…     NA    NA brown      light      brown             NA male  mascu…
5 BB8           NA    NA none       none       black             NA none  mascu…
6 Captain …     NA    NA none       none       unknown           NA fema… femin…
# ℹ 5 more variables: homeworld <chr>, species <chr>, films <list>,
#   vehicles <list>, starships <list>

Para acessar alguma coluna dentro do meu objeto dados, basta usar o $. Com o $, posso usar a função mean() para saber a média de alguma variável de interesse:

mean(dados$height)
[1] NA

Recebemos uma resposta estranha: NA. Existem 03 classes especiais de objetos:: NA, NULL e NaN. NULL significa que eu estou tentando acessar um elemento que não existe, logo, ele é nulo. NaN significa “Not a Number”, que é autoexplicativo2. Já o NA significa “Not Available”, ou seja, não está disponível. O NA geralmente acontece quando fazemos medidas descritivas, como a média, e o nosso conjunto de dados tem algum valor faltante. Para contornar esse problema, usamos a seguinte opção dentro da função mean:

2 Se eu tento dividir 0 por 0, por exemplo, o resultado é NaN.

mean(dados$height, na.rm = TRUE)
[1] 174.6049

na.rm significa, basicamente, “na remove”. Ou seja, remover os valores ausentes. Assim, consigo ver a média da altura dos personagens de Star Wars.

Também posso analisar o desvio padrão da altura dos personagens. O desvio padrão é uma medida de dispersão que mostra, em média, quanto os valores se distanciam da média de uma variável.

sd(dados$height, na.rm = TRUE)
[1] 34.77416

7.2 Operadores lógicos

Operadores lógicos no R
Operador Operação
! Negação (não)
& E (avalia elemento a elemento)
| Ou (avalia elemento a elemento)
< Menor
<= Menor ou igual
> Maior
>= Maior ou igual
!= Diferente
&& E (avalia apenas o 1º elemento)
|| Ou (avalia apenas o 1º elemento)

Operadores lógicos no R são símbolos usados para fazer comparações e testar condições, retornando valores TRUE ou FALSE. É muito comum utilizarmos eles em filtros. Às vezes, queremos filtrar resultados dado uma condição específica. Veremos isso mais à frente.

7.3 Encadeando funções com o operador pipe |>

René Magritte tem uma pintura icônica, que inspirou um pacote no R. O pacote é chamado de {magrittr} e ele basicamente nos apresenta um conceito fantástico: o operador pipe. Basicamente, o pipe pega o lado esquerdo do seu código e alimenta o lado direito, encadeando as funções que você for utilizar.

La trahison des images

Esse conceito ficará mais claro adiante, mas é importante saber da existência dele. Sempre que virmos um |> no nosso código, leremos ele como um “e então”. Pode ser que o pipe apareça para você como %>%, mas isso não faz muita diferença agora. O atalho para o operador pipe é CTRL + SHIFT + M.

7.4 Conhecendo o pacote {dplyr}

O {dplyr} é um dos principais pacotes do {tidyverse}, e é nele que passaremos a maior parte do tempo. Isso porque, quando trabalhamos com dados, a maior parte da energia que gastamos é em “limpar” os dados. O {dplyr} tem alguns “verbos” que são os mais utilizados. Vamos conhecê-los.

Se quiser, por exemplo, verificar a média da altura dos personagens de Star Wars por sexo, podemos fazer da seguinte forma:

dados |> 
  group_by(sex) |> 
  summarise(media_altura = mean(height, na.rm = TRUE))
# A tibble: 5 × 2
  sex            media_altura
  <chr>                 <dbl>
1 female                 172.
2 hermaphroditic         175 
3 male                   179.
4 none                   131.
5 <NA>                   175 

Lemos essa operação da seguinte forma: “pegue o objeto dados, e então agrupe-o por sexo, e então calcule a média para cada subgrupo, omitindo os valores ausentes”.

Sem o operador |>, teríamos de escrever o código da seguinte forma:

summarise(group_by(dados, sex), mean(height, na.rm = TRUE))
# A tibble: 5 × 2
  sex            `mean(height, na.rm = TRUE)`
  <chr>                                 <dbl>
1 female                                 172.
2 hermaphroditic                         175 
3 male                                   179.
4 none                                   131.
5 <NA>                                   175 

Concordamos que o |> é uma mão na roda, né?

Ainda, é possível filtrar informações de interesse primeiro. Por exemplo, se eu quero filtrar a altura de personagens cujo gênero é “masculine”, basta inserirmos a função filter().

dados |> 
  filter(gender == "masculine") |> 
  group_by(sex) |> 
  summarise(media_altura = mean(height, na.rm = TRUE))
# A tibble: 3 × 2
  sex            media_altura
  <chr>                 <dbl>
1 hermaphroditic         175 
2 male                   179.
3 none                   140 

Lemos essa operação da seguinte forma: “pegue o objeto dados, e então filtre as ocorrências cuja variável gender seja igual a”masculine”, e então agrupe-o por sexo, e então calcule a média para cada subgrupo, omitindo os valores ausentes”.

Se precisarmos de mais medidas para além da média da altura, podemos adicionar várias funções conforme precisarmos:

tabela_descritiva <- dados |> 
  group_by(sex) |> 
  summarise(media_altura = mean(height, na.rm = TRUE),
            variancia_altura = var(height, na.rm = TRUE),
            desvio_altura = sd(height, na.rm = TRUE),
            n_obs = n()) # número de observações

tabela_descritiva
# A tibble: 5 × 5
  sex            media_altura variancia_altura desvio_altura n_obs
  <chr>                 <dbl>            <dbl>         <dbl> <int>
1 female                 172.             253.          15.9    16
2 hermaphroditic         175               NA           NA       1
3 male                   179.            1297.          36.0    60
4 none                   131.            2416.          49.1     6
5 <NA>                   175              153.          12.4     4

A função var() me dá a variância da altura e a função n() me retorna o número de observações. Na nossa tabela descritiva, vimos que temos um grupo com apenas 01 indivíduo. Se quisermos, por exemplo, analisar os sexos que tem mais de um indivíduo, podemos filtrar:

tabela_descritiva2 <- tabela_descritiva |> 
  filter(n_obs > 1)

tabela_descritiva2
# A tibble: 4 × 5
  sex    media_altura variancia_altura desvio_altura n_obs
  <chr>         <dbl>            <dbl>         <dbl> <int>
1 female         172.             253.          15.9    16
2 male           179.            1297.          36.0    60
3 none           131.            2416.          49.1     6
4 <NA>           175              153.          12.4     4

7.4.1 Filtrando NAs

É um pouco cansativo ficar utilizando o argumento na.rm = TRUE o tempo todo para filtrar os NAs a cada operação. Antes de eliminarmos quaisquer valores ausentes, é preciso conhecer nosso banco de dados para tomar esta decisão. Isso porque, como alguns cientistas sociais dizem, um não dado também é dado! Muitos valores ausentes podem indicar, por exemplo, como as pessoas estão registrando (no caso, deixando de registrar) as ocorrências. Muitos NAs pode ser sinal de mal preenchimento de informações.

Voltando para nosso conjunto de dados, vamos ver quantas linhas temos na coluna sex que são NA:

dados |> 
  filter(is.na(sex))
# A tibble: 4 × 14
  name      height  mass hair_color skin_color eye_color birth_year sex   gender
  <chr>      <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
1 Jek Tono…    180   110 brown      fair       blue              NA <NA>  <NA>  
2 Gregar T…    185    85 black      dark       brown             NA <NA>  <NA>  
3 Cordé        157    NA brown      light      brown             NA <NA>  <NA>  
4 Sly Moore    178    48 none       pale       white             NA <NA>  <NA>  
# ℹ 5 more variables: homeworld <chr>, species <chr>, films <list>,
#   vehicles <list>, starships <list>

São apenas 04 linhas. Podemos ignorálas. Refazendo a análise da primeira tabela descritiva:

dados |> 
  filter(!is.na(sex)) |> 
  group_by(sex) |> 
  summarise(media_altura = mean(height, na.rm = TRUE),
            variancia_altura = var(height, na.rm = TRUE),
            desvio_altura = sd(height, na.rm = TRUE),
            n_obs = n()) |> 
  filter(n_obs > 1)
# A tibble: 3 × 5
  sex    media_altura variancia_altura desvio_altura n_obs
  <chr>         <dbl>            <dbl>         <dbl> <int>
1 female         172.             253.          15.9    16
2 male           179.            1297.          36.0    60
3 none           131.            2416.          49.1     6

E se quisermos adicionar outra variável ao nosso grupo?

dados |> 
  filter(!is.na(sex)) |> 
  group_by(sex, eye_color) |> 
  summarise(media_altura = mean(height, na.rm = TRUE),
            variancia_altura = var(height, na.rm = TRUE),
            desvio_altura = sd(height, na.rm = TRUE),
            n_obs = n()) |> 
  filter(n_obs > 1)
`summarise()` has grouped output by 'sex'. You can override using the `.groups`
argument.
# A tibble: 12 × 6
# Groups:   sex [3]
   sex    eye_color media_altura variancia_altura desvio_altura n_obs
   <chr>  <chr>            <dbl>            <dbl>         <dbl> <int>
 1 female black             196.            612.         24.7       2
 2 female blue              167             118.         10.9       6
 3 female brown             166.            209.         14.5       4
 4 female hazel             178              NA          NA         2
 5 male   black             182            1197          34.6       7
 6 male   blue              190             429.         20.7      12
 7 male   brown             167.           1657.         40.7      15
 8 male   orange            181.           1306.         36.1       7
 9 male   red               190.              0.5         0.707     2
10 male   unknown           136            6498          80.6       2
11 male   yellow            180.           2196.         46.9       9
12 none   red               131            3571          59.8       3

Para essa primeira parte, está suficiente. Conhecemos as funções filter(), group_by() e summarise() do pacote {dplyr}.

8 Usando o dataset Gasoline

Primeiro, precisamos instalar o pacote plm.

install.packages("plm")

Agora, vamos carregar os dados que estão dentro do pacote:

data(Gasoline, package = "plm")

Este conjunto de dados nos dá informações sobre consumo de gasolina para 18 países, entre 1960 e 1978. As variáveis são:

Variável Descrição
country Fator com 18 níveis (países)
year Ano
lgaspcar Logaritmo do consumo de gasolina por carro
lincomep Logaritmo da renda real per capita
lrpmg Logaritmo do preço real da gasolina
lcarpcap Logaritmo do estoque de carros per capita

Quando carregamos este conjunto de dados, ele pertence à uma classe chamada data.frame. O R possui uma classe diferente e especial para conjunto de dados, que apresenta um melhor “print” no console, chamada tibble. Para convertemos este conjunto de dados (no formato data.frame) para tibble, executamos a seguinte operação:

gasoline <- as_tibble(Gasoline)

O tibble no R é uma versão moderna e aprimorada do data.frame tradicional, projetada para facilitar a manipulação e visualização de dados dentro do ecossistema Tidyverse. Ele é conhecido por não alterar tipos de dados automaticamente, imprimir apenas as primeiras 10 linhas e colunas ajustadas à tela, tornando a exploração de conjuntos de dados grandes mais eficiente e organizada.

Adicionalmente, quero deixar todas os países da coluna country com letras minúsculas. Para isso:

gasoline <- gasoline |> 
  mutate(country = tolower(country))

E se eu quiser filtrar os dados somente para o ano de 1972? Muito simples com a função filter(), sem utilizar o |>.

filter(gasoline, year == 1972)
# A tibble: 18 × 6
   country   year lgaspcar lincomep  lrpmg lcarpcap
   <chr>    <int>    <dbl>    <dbl>  <dbl>    <dbl>
 1 austria   1972     4.13    -5.98 -0.596    -8.54
 2 belgium   1972     3.91    -5.71 -0.311    -8.36
 3 canada    1972     4.89    -5.44 -1.10     -7.99
 4 denmark   1972     4.08    -5.65 -0.499    -8.33
 5 france    1972     3.85    -5.70 -0.408    -8.22
 6 germany   1972     3.93    -5.72 -0.718    -8.24
 7 greece    1972     4.80    -6.35 -0.120   -10.3 
 8 ireland   1972     4.27    -6.31 -0.424    -8.82
 9 italy     1972     3.63    -6.21 -0.215    -8.38
10 japan     1972     4.22    -5.93 -0.521    -9.05
11 netherla  1972     3.92    -5.79 -0.319    -8.38
12 norway    1972     4.08    -5.66 -0.260    -8.51
13 spain     1972     3.89    -5.46  0.537    -9.27
14 sweden    1972     3.98    -7.74 -2.77     -8.10
15 switzerl  1972     4.26    -5.81 -0.940    -8.30
16 turkey    1972     5.58    -7.08 -0.546   -12.2 
17 u.k.      1972     3.99    -5.97 -0.528    -8.36
18 u.s.a.    1972     4.85    -5.35 -1.33     -7.68

Mas, é bom nos acostumarmos com o operador pipe, portanto:

gasoline |> 
  filter(year == 1972)
# A tibble: 18 × 6
   country   year lgaspcar lincomep  lrpmg lcarpcap
   <chr>    <int>    <dbl>    <dbl>  <dbl>    <dbl>
 1 austria   1972     4.13    -5.98 -0.596    -8.54
 2 belgium   1972     3.91    -5.71 -0.311    -8.36
 3 canada    1972     4.89    -5.44 -1.10     -7.99
 4 denmark   1972     4.08    -5.65 -0.499    -8.33
 5 france    1972     3.85    -5.70 -0.408    -8.22
 6 germany   1972     3.93    -5.72 -0.718    -8.24
 7 greece    1972     4.80    -6.35 -0.120   -10.3 
 8 ireland   1972     4.27    -6.31 -0.424    -8.82
 9 italy     1972     3.63    -6.21 -0.215    -8.38
10 japan     1972     4.22    -5.93 -0.521    -9.05
11 netherla  1972     3.92    -5.79 -0.319    -8.38
12 norway    1972     4.08    -5.66 -0.260    -8.51
13 spain     1972     3.89    -5.46  0.537    -9.27
14 sweden    1972     3.98    -7.74 -2.77     -8.10
15 switzerl  1972     4.26    -5.81 -0.940    -8.30
16 turkey    1972     5.58    -7.08 -0.546   -12.2 
17 u.k.      1972     3.99    -5.97 -0.528    -8.36
18 u.s.a.    1972     4.85    -5.35 -1.33     -7.68

Também é possível filtrar mais de uma condição. Para isso, podemos usar o operador %in%:

gasoline %>%
  filter(year %in% seq(1969, 1973)) # sequência de anos entre 1969 a 1973
# A tibble: 90 × 6
   country  year lgaspcar lincomep  lrpmg lcarpcap
   <chr>   <int>    <dbl>    <dbl>  <dbl>    <dbl>
 1 austria  1969     4.05    -6.15 -0.559    -8.79
 2 austria  1970     4.08    -6.08 -0.597    -8.73
 3 austria  1971     4.11    -6.04 -0.654    -8.64
 4 austria  1972     4.13    -5.98 -0.596    -8.54
 5 austria  1973     4.20    -5.90 -0.594    -8.49
 6 belgium  1969     3.85    -5.86 -0.355    -8.52
 7 belgium  1970     3.87    -5.80 -0.378    -8.45
 8 belgium  1971     3.87    -5.76 -0.399    -8.41
 9 belgium  1972     3.91    -5.71 -0.311    -8.36
10 belgium  1973     3.90    -5.64 -0.373    -8.31
# ℹ 80 more rows

Ou

gasoline %>%
  filter(year %in% 1969:1973) # sem a função seq()
# A tibble: 90 × 6
   country  year lgaspcar lincomep  lrpmg lcarpcap
   <chr>   <int>    <dbl>    <dbl>  <dbl>    <dbl>
 1 austria  1969     4.05    -6.15 -0.559    -8.79
 2 austria  1970     4.08    -6.08 -0.597    -8.73
 3 austria  1971     4.11    -6.04 -0.654    -8.64
 4 austria  1972     4.13    -5.98 -0.596    -8.54
 5 austria  1973     4.20    -5.90 -0.594    -8.49
 6 belgium  1969     3.85    -5.86 -0.355    -8.52
 7 belgium  1970     3.87    -5.80 -0.378    -8.45
 8 belgium  1971     3.87    -5.76 -0.399    -8.41
 9 belgium  1972     3.91    -5.71 -0.311    -8.36
10 belgium  1973     3.90    -5.64 -0.373    -8.31
# ℹ 80 more rows

Ainda, é possível utilizar a função auxiliadora3 between():

3 Como o nome sugere, funções auxiliadores ajudam as funções principais. É importante notar que é possível usar funções dentro de funções.

gasoline %>%
  filter(between(year, 1969, 1973))
# A tibble: 90 × 6
   country  year lgaspcar lincomep  lrpmg lcarpcap
   <chr>   <int>    <dbl>    <dbl>  <dbl>    <dbl>
 1 austria  1969     4.05    -6.15 -0.559    -8.79
 2 austria  1970     4.08    -6.08 -0.597    -8.73
 3 austria  1971     4.11    -6.04 -0.654    -8.64
 4 austria  1972     4.13    -5.98 -0.596    -8.54
 5 austria  1973     4.20    -5.90 -0.594    -8.49
 6 belgium  1969     3.85    -5.86 -0.355    -8.52
 7 belgium  1970     3.87    -5.80 -0.378    -8.45
 8 belgium  1971     3.87    -5.76 -0.399    -8.41
 9 belgium  1972     3.91    -5.71 -0.311    -8.36
10 belgium  1973     3.90    -5.64 -0.373    -8.31
# ℹ 80 more rows

Também é possível selecionar anos não consecutivos:

gasoline %>%
  filter(year %in% c(1969, 1973, 1977))
# A tibble: 54 × 6
   country  year lgaspcar lincomep  lrpmg lcarpcap
   <chr>   <int>    <dbl>    <dbl>  <dbl>    <dbl>
 1 austria  1969     4.05    -6.15 -0.559    -8.79
 2 austria  1973     4.20    -5.90 -0.594    -8.49
 3 austria  1977     3.93    -5.83 -0.422    -8.25
 4 belgium  1969     3.85    -5.86 -0.355    -8.52
 5 belgium  1973     3.90    -5.64 -0.373    -8.31
 6 belgium  1977     3.85    -5.56 -0.432    -8.14
 7 canada   1969     4.86    -5.56 -1.04     -8.10
 8 canada   1973     4.90    -5.41 -1.13     -7.94
 9 canada   1977     4.81    -5.34 -1.07     -7.77
10 denmark  1969     4.17    -5.72 -0.407    -8.47
# ℹ 44 more rows

8.1 Usando a função select()

Enquanto a função filter() é utilizada para manter ou descartar as linhas do nosso conjunto de dados, a função select() nos permite selecionar colunas inteiras.

Para manter colunas, podemos utilizar:

gasoline %>%
  select(country, year, lrpmg)
# A tibble: 342 × 3
   country  year  lrpmg
   <chr>   <int>  <dbl>
 1 austria  1960 -0.335
 2 austria  1961 -0.351
 3 austria  1962 -0.380
 4 austria  1963 -0.414
 5 austria  1964 -0.445
 6 austria  1965 -0.497
 7 austria  1966 -0.467
 8 austria  1967 -0.506
 9 austria  1968 -0.522
10 austria  1969 -0.559
# ℹ 332 more rows

Para descartálas, utilizamos:

gasoline %>%
  select(-country, -year, -lrpmg)
# A tibble: 342 × 3
   lgaspcar lincomep lcarpcap
      <dbl>    <dbl>    <dbl>
 1     4.17    -6.47    -9.77
 2     4.10    -6.43    -9.61
 3     4.07    -6.41    -9.46
 4     4.06    -6.37    -9.34
 5     4.04    -6.32    -9.24
 6     4.03    -6.29    -9.12
 7     4.05    -6.25    -9.02
 8     4.05    -6.23    -8.93
 9     4.05    -6.21    -8.85
10     4.05    -6.15    -8.79
# ℹ 332 more rows

Ainda, é possível renomeá-las diretamente com a função select():

gasoline %>%
  select(country, date = year, lrpmg)
# A tibble: 342 × 3
   country  date  lrpmg
   <chr>   <int>  <dbl>
 1 austria  1960 -0.335
 2 austria  1961 -0.351
 3 austria  1962 -0.380
 4 austria  1963 -0.414
 5 austria  1964 -0.445
 6 austria  1965 -0.497
 7 austria  1966 -0.467
 8 austria  1967 -0.506
 9 austria  1968 -0.522
10 austria  1969 -0.559
# ℹ 332 more rows

A função rename() faz exatamente a mesma coisa. Entretanto, ele não faz nenhum tipo de seleção, apenas renomea a coluna de interesse.

gasoline %>%
  rename(date = year)
# A tibble: 342 × 6
   country  date lgaspcar lincomep  lrpmg lcarpcap
   <chr>   <int>    <dbl>    <dbl>  <dbl>    <dbl>
 1 austria  1960     4.17    -6.47 -0.335    -9.77
 2 austria  1961     4.10    -6.43 -0.351    -9.61
 3 austria  1962     4.07    -6.41 -0.380    -9.46
 4 austria  1963     4.06    -6.37 -0.414    -9.34
 5 austria  1964     4.04    -6.32 -0.445    -9.24
 6 austria  1965     4.03    -6.29 -0.497    -9.12
 7 austria  1966     4.05    -6.25 -0.467    -9.02
 8 austria  1967     4.05    -6.23 -0.506    -8.93
 9 austria  1968     4.05    -6.21 -0.522    -8.85
10 austria  1969     4.05    -6.15 -0.559    -8.79
# ℹ 332 more rows

É possível utilizar a função select() para reordenar as colunas. Eu quero, por exemplo, que minhas três primeiras colunas do conjunto de dados sejam year, country e lrpmg, nesta ordem:

gasoline %>%
  select(year, country, lrpmg, everything())
# A tibble: 342 × 6
    year country  lrpmg lgaspcar lincomep lcarpcap
   <int> <chr>    <dbl>    <dbl>    <dbl>    <dbl>
 1  1960 austria -0.335     4.17    -6.47    -9.77
 2  1961 austria -0.351     4.10    -6.43    -9.61
 3  1962 austria -0.380     4.07    -6.41    -9.46
 4  1963 austria -0.414     4.06    -6.37    -9.34
 5  1964 austria -0.445     4.04    -6.32    -9.24
 6  1965 austria -0.497     4.03    -6.29    -9.12
 7  1966 austria -0.467     4.05    -6.25    -9.02
 8  1967 austria -0.506     4.05    -6.23    -8.93
 9  1968 austria -0.522     4.05    -6.21    -8.85
10  1969 austria -0.559     4.05    -6.15    -8.79
# ℹ 332 more rows

A função everything() é uma função auxiliadora, como notamos. Ainda, existem outras funções, como por exemplo starts_with e ends_with. Se eu quiser, por exemplo, selecionar apenas as colunas cujo nome começam com “l”?

gasoline %>%
  select(starts_with("l"))
# A tibble: 342 × 4
   lgaspcar lincomep  lrpmg lcarpcap
      <dbl>    <dbl>  <dbl>    <dbl>
 1     4.17    -6.47 -0.335    -9.77
 2     4.10    -6.43 -0.351    -9.61
 3     4.07    -6.41 -0.380    -9.46
 4     4.06    -6.37 -0.414    -9.34
 5     4.04    -6.32 -0.445    -9.24
 6     4.03    -6.29 -0.497    -9.12
 7     4.05    -6.25 -0.467    -9.02
 8     4.05    -6.23 -0.506    -8.93
 9     4.05    -6.21 -0.522    -8.85
10     4.05    -6.15 -0.559    -8.79
# ℹ 332 more rows

ends_with funciona de maneira similar, dá para pegar a ideia. Outra função auxiliadora interessante é a contains():

gasoline %>%
  select(country, year, contains("car"))
# A tibble: 342 × 4
   country  year lgaspcar lcarpcap
   <chr>   <int>    <dbl>    <dbl>
 1 austria  1960     4.17    -9.77
 2 austria  1961     4.10    -9.61
 3 austria  1962     4.07    -9.46
 4 austria  1963     4.06    -9.34
 5 austria  1964     4.04    -9.24
 6 austria  1965     4.03    -9.12
 7 austria  1966     4.05    -9.02
 8 austria  1967     4.05    -8.93
 9 austria  1968     4.05    -8.85
10 austria  1969     4.05    -8.79
# ℹ 332 more rows

É possível encontrar uma lista de funções auxiliadoras na documentação do pacote. A documentação é uma espécie de manual, onde os desenvolvedores dos pacotes apresentam as principais funções, argumentos e exemplos de uso. Basta pesquisar por nome do pacote + R no Google que você acha as informações oficiais com bastante facilidade. A documentação do pacote {dplyr} é facilmente encontrada. ]

Outro verbo/função similar ao select() é o pull(). Como o nome sugere, ele puxa as informações de uma coluna específica. Comparativamente:

gasoline %>%
  select(lrpmg)
# A tibble: 342 × 1
    lrpmg
    <dbl>
 1 -0.335
 2 -0.351
 3 -0.380
 4 -0.414
 5 -0.445
 6 -0.497
 7 -0.467
 8 -0.506
 9 -0.522
10 -0.559
# ℹ 332 more rows
gasoline %>%
  pull(lrpmg) %>%
  head() # usando o head() porque temos muitos elementos neste conjunto de daods
[1] -0.3345476 -0.3513276 -0.3795177 -0.4142514 -0.4453354 -0.4970607

8.2 Agrupando informações com group_by()

A função group_by() facilita a computação de estatísticas descritivas por grupos. Agrupando os dados por país:

gasoline %>%
  group_by(country)
# A tibble: 342 × 6
# Groups:   country [18]
   country  year lgaspcar lincomep  lrpmg lcarpcap
   <chr>   <int>    <dbl>    <dbl>  <dbl>    <dbl>
 1 austria  1960     4.17    -6.47 -0.335    -9.77
 2 austria  1961     4.10    -6.43 -0.351    -9.61
 3 austria  1962     4.07    -6.41 -0.380    -9.46
 4 austria  1963     4.06    -6.37 -0.414    -9.34
 5 austria  1964     4.04    -6.32 -0.445    -9.24
 6 austria  1965     4.03    -6.29 -0.497    -9.12
 7 austria  1966     4.05    -6.25 -0.467    -9.02
 8 austria  1967     4.05    -6.23 -0.506    -8.93
 9 austria  1968     4.05    -6.21 -0.522    -8.85
10 austria  1969     4.05    -6.15 -0.559    -8.79
# ℹ 332 more rows

Não parece que mudou muita coisa, mas, se observamos a segunda linha do output, veremos que:

## # Groups:   country [18]

Isso significa que toda análise levará estes grupos em conta. Como vimos anteriormente com o starwars, é possível agrupar por mais de uma variável:

gasoline %>%
  group_by(country, year)
# A tibble: 342 × 6
# Groups:   country, year [342]
   country  year lgaspcar lincomep  lrpmg lcarpcap
   <chr>   <int>    <dbl>    <dbl>  <dbl>    <dbl>
 1 austria  1960     4.17    -6.47 -0.335    -9.77
 2 austria  1961     4.10    -6.43 -0.351    -9.61
 3 austria  1962     4.07    -6.41 -0.380    -9.46
 4 austria  1963     4.06    -6.37 -0.414    -9.34
 5 austria  1964     4.04    -6.32 -0.445    -9.24
 6 austria  1965     4.03    -6.29 -0.497    -9.12
 7 austria  1966     4.05    -6.25 -0.467    -9.02
 8 austria  1967     4.05    -6.23 -0.506    -8.93
 9 austria  1968     4.05    -6.21 -0.522    -8.85
10 austria  1969     4.05    -6.15 -0.559    -8.79
# ℹ 332 more rows

E também é possível desagrupar, com a função ungroup(). Basicamente, o group_by “marca” a tabela para que os cálculos sejam feitos por grupo, e o ungroup() volta para que você trabalhe com a tabela como um todo.

gasoline %>%
  group_by(country, year) %>%
  ungroup()
# A tibble: 342 × 6
   country  year lgaspcar lincomep  lrpmg lcarpcap
   <chr>   <int>    <dbl>    <dbl>  <dbl>    <dbl>
 1 austria  1960     4.17    -6.47 -0.335    -9.77
 2 austria  1961     4.10    -6.43 -0.351    -9.61
 3 austria  1962     4.07    -6.41 -0.380    -9.46
 4 austria  1963     4.06    -6.37 -0.414    -9.34
 5 austria  1964     4.04    -6.32 -0.445    -9.24
 6 austria  1965     4.03    -6.29 -0.497    -9.12
 7 austria  1966     4.05    -6.25 -0.467    -9.02
 8 austria  1967     4.05    -6.23 -0.506    -8.93
 9 austria  1968     4.05    -6.21 -0.522    -8.85
10 austria  1969     4.05    -6.15 -0.559    -8.79
# ℹ 332 more rows

8.3 Resumir estatísticas com summarise()

Passado o básico, vamos avançar. Se eu quero computar o consume médio de gasolina por cada país, para todo o período, fazemos:

gasoline %>%
  group_by(country) %>%
  summarise(mean(lgaspcar))
# A tibble: 18 × 2
   country  `mean(lgaspcar)`
   <chr>               <dbl>
 1 austria              4.06
 2 belgium              3.92
 3 canada               4.86
 4 denmark              4.19
 5 france               3.82
 6 germany              3.89
 7 greece               4.88
 8 ireland              4.23
 9 italy                3.73
10 japan                4.70
11 netherla             4.08
12 norway               4.11
13 spain                4.06
14 sweden               4.01
15 switzerl             4.24
16 turkey               5.77
17 u.k.                 3.98
18 u.s.a.               4.82

Como vimos com o starwars, é possível renomear o nome da coluna da média que apareceu anteriormente. Para isso:

gasoline %>%
  group_by(country) %>%
  summarise(mean_gaspcar = mean(lgaspcar))
# A tibble: 18 × 2
   country  mean_gaspcar
   <chr>           <dbl>
 1 austria          4.06
 2 belgium          3.92
 3 canada           4.86
 4 denmark          4.19
 5 france           3.82
 6 germany          3.89
 7 greece           4.88
 8 ireland          4.23
 9 italy            3.73
10 japan            4.70
11 netherla         4.08
12 norway           4.11
13 spain            4.06
14 sweden           4.01
15 switzerl         4.24
16 turkey           5.77
17 u.k.             3.98
18 u.s.a.           4.82

Além disso, podemos filtrar as ocorrências para um país de interesse:

gasoline %>%
  group_by(country) %>%
  summarise(mean_gaspcar = mean(lgaspcar)) %>%
  filter(country == "france")
# A tibble: 1 × 2
  country mean_gaspcar
  <chr>          <dbl>
1 france          3.82

Com a função summarise(), posso computar várias estatísticas de uma vez:

gasoline %>%
  group_by(country) %>%
  summarise(mean_gaspcar = mean(lgaspcar),
            sd_gaspcar = sd(lgaspcar),
            max_gaspcar = max(lgaspcar),
            min_gaspcar = min(lgaspcar))
# A tibble: 18 × 5
   country  mean_gaspcar sd_gaspcar max_gaspcar min_gaspcar
   <chr>           <dbl>      <dbl>       <dbl>       <dbl>
 1 austria          4.06     0.0693        4.20        3.92
 2 belgium          3.92     0.103         4.16        3.82
 3 canada           4.86     0.0262        4.90        4.81
 4 denmark          4.19     0.158         4.50        4.00
 5 france           3.82     0.0499        3.91        3.75
 6 germany          3.89     0.0239        3.93        3.85
 7 greece           4.88     0.255         5.38        4.48
 8 ireland          4.23     0.0437        4.33        4.16
 9 italy            3.73     0.220         4.05        3.38
10 japan            4.70     0.684         6.00        3.95
11 netherla         4.08     0.286         4.65        3.71
12 norway           4.11     0.123         4.44        3.96
13 spain            4.06     0.317         4.75        3.62
14 sweden           4.01     0.0364        4.07        3.91
15 switzerl         4.24     0.102         4.44        4.05
16 turkey           5.77     0.329         6.16        5.14
17 u.k.             3.98     0.0479        4.10        3.91
18 u.s.a.           4.82     0.0219        4.86        4.79

E se quisermos “salvar” essas operações, basta atribuir a um objeto4:

4 Lembrando que o sinal de atribuição mais apropriado é o <-. Para fazê-lo, o atalho é ALT - (alt menos)

desc_gasoline <- gasoline %>%
  group_by(country) %>%
  summarise(mean_gaspcar = mean(lgaspcar),
            sd_gaspcar = sd(lgaspcar),
            max_gaspcar = max(lgaspcar),
            min_gaspcar = min(lgaspcar))

Questão: qual país tem o maior consumo médio de gasolina?

desc_gasoline %>%
  filter(max(mean_gaspcar) == mean_gaspcar)
# A tibble: 1 × 5
  country mean_gaspcar sd_gaspcar max_gaspcar min_gaspcar
  <chr>          <dbl>      <dbl>       <dbl>       <dbl>
1 turkey          5.77      0.329        6.16        5.14

A função max(mean_gaspcar) calcula o maior valor da média de consumo de gasolina. Depois, fazemos uma comparação lógica para verificar se o valor naquela linha é igual ao valor máximo da coluna. Eu, particularmente, acho assim mais complicado de entender. Alternativametne, podemos usar:

desc_gasoline %>% 
  slice_max(mean_gaspcar) # mais direto e reto!
# A tibble: 1 × 5
  country mean_gaspcar sd_gaspcar max_gaspcar min_gaspcar
  <chr>          <dbl>      <dbl>       <dbl>       <dbl>
1 turkey          5.77      0.329        6.16        5.14

Ou, também:

desc_gasoline %>% 
  slice(which.max(mean_gaspcar))
# A tibble: 1 × 5
  country mean_gaspcar sd_gaspcar max_gaspcar min_gaspcar
  <chr>          <dbl>      <dbl>       <dbl>       <dbl>
1 turkey          5.77      0.329        6.16        5.14

A Túrquia tem o maior consumo médio de gasolina. E o valor mínimo?

desc_gasoline %>% 
  slice_min(mean_gaspcar) # mais direto e reto!
# A tibble: 1 × 5
  country mean_gaspcar sd_gaspcar max_gaspcar min_gaspcar
  <chr>          <dbl>      <dbl>       <dbl>       <dbl>
1 italy           3.73      0.220        4.05        3.38

8.4 Adicionando colunas com o mutate() e transmute()

A função mutate() adiciona ou transforma uma coluna num conjunto de dados. Por exemplo:

gasoline %>%
  group_by(country) %>%
  mutate(n())
# A tibble: 342 × 7
# Groups:   country [18]
   country  year lgaspcar lincomep  lrpmg lcarpcap `n()`
   <chr>   <int>    <dbl>    <dbl>  <dbl>    <dbl> <int>
 1 austria  1960     4.17    -6.47 -0.335    -9.77    19
 2 austria  1961     4.10    -6.43 -0.351    -9.61    19
 3 austria  1962     4.07    -6.41 -0.380    -9.46    19
 4 austria  1963     4.06    -6.37 -0.414    -9.34    19
 5 austria  1964     4.04    -6.32 -0.445    -9.24    19
 6 austria  1965     4.03    -6.29 -0.497    -9.12    19
 7 austria  1966     4.05    -6.25 -0.467    -9.02    19
 8 austria  1967     4.05    -6.23 -0.506    -8.93    19
 9 austria  1968     4.05    -6.21 -0.522    -8.85    19
10 austria  1969     4.05    -6.15 -0.559    -8.79    19
# ℹ 332 more rows

Também é possível renomear a variável dentro da função mutate():

gasoline %>%
  group_by(country) %>%
  mutate(count = n())
# A tibble: 342 × 7
# Groups:   country [18]
   country  year lgaspcar lincomep  lrpmg lcarpcap count
   <chr>   <int>    <dbl>    <dbl>  <dbl>    <dbl> <int>
 1 austria  1960     4.17    -6.47 -0.335    -9.77    19
 2 austria  1961     4.10    -6.43 -0.351    -9.61    19
 3 austria  1962     4.07    -6.41 -0.380    -9.46    19
 4 austria  1963     4.06    -6.37 -0.414    -9.34    19
 5 austria  1964     4.04    -6.32 -0.445    -9.24    19
 6 austria  1965     4.03    -6.29 -0.497    -9.12    19
 7 austria  1966     4.05    -6.25 -0.467    -9.02    19
 8 austria  1967     4.05    -6.23 -0.506    -8.93    19
 9 austria  1968     4.05    -6.21 -0.522    -8.85    19
10 austria  1969     4.05    -6.15 -0.559    -8.79    19
# ℹ 332 more rows

Ainda, é possível fazer qualquer outra operação:

gasoline |> 
  group_by(country) |> 
  mutate(consumo_renda = lgaspcar / lincomep)
# A tibble: 342 × 7
# Groups:   country [18]
   country  year lgaspcar lincomep  lrpmg lcarpcap consumo_renda
   <chr>   <int>    <dbl>    <dbl>  <dbl>    <dbl>         <dbl>
 1 austria  1960     4.17    -6.47 -0.335    -9.77        -0.645
 2 austria  1961     4.10    -6.43 -0.351    -9.61        -0.638
 3 austria  1962     4.07    -6.41 -0.380    -9.46        -0.636
 4 austria  1963     4.06    -6.37 -0.414    -9.34        -0.637
 5 austria  1964     4.04    -6.32 -0.445    -9.24        -0.639
 6 austria  1965     4.03    -6.29 -0.497    -9.12        -0.641
 7 austria  1966     4.05    -6.25 -0.467    -9.02        -0.647
 8 austria  1967     4.05    -6.23 -0.506    -8.93        -0.650
 9 austria  1968     4.05    -6.21 -0.522    -8.85        -0.652
10 austria  1969     4.05    -6.15 -0.559    -8.79        -0.658
# ℹ 332 more rows

A função transmute() opera da mesma forma que o mutate, mas retorna apenas a variável criada:

gasoline |> 
  group_by(country) |> 
  transmute(consumo_renda = lgaspcar / lincomep)
# A tibble: 342 × 2
# Groups:   country [18]
   country consumo_renda
   <chr>           <dbl>
 1 austria        -0.645
 2 austria        -0.638
 3 austria        -0.636
 4 austria        -0.637
 5 austria        -0.639
 6 austria        -0.641
 7 austria        -0.647
 8 austria        -0.650
 9 austria        -0.652
10 austria        -0.658
# ℹ 332 more rows

Exemplo gráfico:

library(dplyr)
library(ggplot2)

gasoline %>% 
  ggplot(aes(x = year, y = lgaspcar, color = country, group = country)) +
  geom_line() +
  labs(
    title = "Consumo de Gasolina por Carro (log) ao longo do tempo",
    x = "Ano",
    y = "Log do consumo de gasolina por carro",
    color = "País"
  ) +
  theme_classic() +
  theme(
    legend.position = "right",
    legend.title = element_text(face = "bold"),
    panel.grid.minor = element_blank()
  )