Controle de fluxo

O uso de condição é utilizada em diversas linguagens, inclusive o R. Declarando condições podemos economizar tempo e processamento.

Declarações condicionais if e else

Se quisermos que o R execute uma determinada função de acordo com uma determinada condição utilizo o comando if (), caso queremos que ele execute outra função se a condição for falsa executo o comando else (). Vamos considerar o seguinte, vamos criar uma variável e verificar ela com uma determinada condição.

# Forma 01
num <- 12
if(num < 10) {
    print("Menor que 10")
} else("Maior ou igual a 10")
## [1] "Maior ou igual a 10"
# Forma 02
num.1 <- 8
if(num.1 > 8) {
    print("Maior que 8")
} else if(num.1 == 8) {
    print("Igual a 8")
} else {
    print("Menor que 8")
}
## [1] "Igual a 8"
# Forma 03
num.3 <- c(1,3,5,7,9)
ifelse(num.3 > 4, "Maior que 4", "Menor ou igual a 4")
## [1] "Menor ou igual a 4" "Menor ou igual a 4" "Maior que 4"       
## [4] "Maior que 4"        "Maior que 4"

Manipulação de dados

Neste tópico iremos trabalhar com funções dos pacotes “dplyr” e “tidyr”. Tais pacotes são bastante conhecidos pela comunidade que trabalha com R, possuem diversas funções importantes para a manipulação de dataframes e tibbles. Instale-os e carregue-os.

# Instalando pacotes
install.packages("dplyr", dependencies = TRUE)
## Installing package into '/home/jean/R/x86_64-pc-linux-gnu-library/3.5'
## (as 'lib' is unspecified)
## also installing the dependencies 'RMySQL', 'RPostgreSQL'
## Warning in install.packages("dplyr", dependencies = TRUE): installation of
## package 'RMySQL' had non-zero exit status
## Warning in install.packages("dplyr", dependencies = TRUE): installation of
## package 'RPostgreSQL' had non-zero exit status
install.packages("tidyr", dependencies = TRUE)
## Installing package into '/home/jean/R/x86_64-pc-linux-gnu-library/3.5'
## (as 'lib' is unspecified)
# Carregando pacotes
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(tidyr)

Filtrando observações

A primeira função que utilizaremos é a função filter() do pacote “dplyr”. Tal função serve para filtrar observações.

# Vamos criar um dataframe.
alunos <- data.frame(
    nome = c("Maria", "Rebeca", "Gabriela", "Roberto", "Mateus", "Gustavo", "Tatiane", "Isaque"),
    sexo = c("feminino", "feminino", "feminino", "masculino", "masculino", "masculino", "feminino", "masculino"),
    graduacao = c("Farmácia", "Farmácia", "Nutrição", "Química", "Física", "Química", "Biotecnologia", "Biotecnologia"),
    fumante = c(TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE),
    altura = c(1.65, 1.7, 1.65, 1.80, 1.73, 1.75, 1.68, 1.71),
    idade = c(18, 19, 23, 22, 20, 19, 25, 26),
    peso = c(50, 65, 52, 70, 75, 63, 62, 70),
    renda = c(2, 3, 1, 2, 2, 4, 4, NA)
)

Essa função é parecida com a do subset(), porém, com a função filter() podemos usar com outras funções.

# Filtrando as observações com a altura maior que 1.7
filter(alunos, altura > 1.7)
##      nome      sexo     graduacao fumante altura idade peso renda
## 1 Roberto masculino       Química    TRUE   1.80    22   70     2
## 2  Mateus masculino        Física   FALSE   1.73    20   75     2
## 3 Gustavo masculino       Química   FALSE   1.75    19   63     4
## 4  Isaque masculino Biotecnologia    TRUE   1.71    26   70    NA
# Filtrando as observações com altura maior que 1.6 e são do sexo feminino
filter(alunos, altura > 1.6 & sexo == "feminino")
##       nome     sexo     graduacao fumante altura idade peso renda
## 1    Maria feminino      Farmácia    TRUE   1.65    18   50     2
## 2   Rebeca feminino      Farmácia    TRUE   1.70    19   65     3
## 3 Gabriela feminino      Nutrição   FALSE   1.65    23   52     1
## 4  Tatiane feminino Biotecnologia   FALSE   1.68    25   62     4

A função filter() também se encontra no pacote stats (pacote básico do R), assim, certifique-se que esteja carregando o pacote certo ou utilize a sintaxe dplyr::filter() para ter certeza de que está usando a função certa.

# Pacote::função
dplyr::filter(alunos, altura > 1.6 & sexo == "feminino")
##       nome     sexo     graduacao fumante altura idade peso renda
## 1    Maria feminino      Farmácia    TRUE   1.65    18   50     2
## 2   Rebeca feminino      Farmácia    TRUE   1.70    19   65     3
## 3 Gabriela feminino      Nutrição   FALSE   1.65    23   52     1
## 4  Tatiane feminino Biotecnologia   FALSE   1.68    25   62     4

Selecionando variáveis

A função select() que também está no pacote “dplyr” é utilizada para selecionar variáveis do nosso objeto.

# Selecionando variáveis.
select(alunos, nome, altura, peso)
##       nome altura peso
## 1    Maria   1.65   50
## 2   Rebeca   1.70   65
## 3 Gabriela   1.65   52
## 4  Roberto   1.80   70
## 5   Mateus   1.73   75
## 6  Gustavo   1.75   63
## 7  Tatiane   1.68   62
## 8   Isaque   1.71   70
# Selecionando variáveis que terminam com "e".
select(alunos, ends_with("e"))
##       nome fumante idade
## 1    Maria    TRUE    18
## 2   Rebeca    TRUE    19
## 3 Gabriela   FALSE    23
## 4  Roberto    TRUE    22
## 5   Mateus   FALSE    20
## 6  Gustavo   FALSE    19
## 7  Tatiane   FALSE    25
## 8   Isaque    TRUE    26
# Selecionando variáveis que contêm "da".
select(alunos, contains("da"))
##   idade renda
## 1    18     2
## 2    19     3
## 3    23     1
## 4    22     2
## 5    20     2
## 6    19     4
## 7    25     4
## 8    26    NA
# Selecionando da quinta coluna até a oitava coluna
select(alunos, c(5:8))
##   altura idade peso renda
## 1   1.65    18   50     2
## 2   1.70    19   65     3
## 3   1.65    23   52     1
## 4   1.80    22   70     2
## 5   1.73    20   75     2
## 6   1.75    19   63     4
## 7   1.68    25   62     4
## 8   1.71    26   70    NA

Modificando dados

Diversas vezes queremos criar uma nova variável em que essa tal variável envolve outras variáveis.

alunos.2 <- mutate(alunos, imc = (peso/(altura)^2))

Renomeando variáveis

Que tal renomearmos o nome de alguma variável? Podemos renomear nossas variáveis utilizando a função rename() que também é do pacote “dplyr”

rename(alunos,
       altura.m = altura,
       peso.kg = peso,
       renda.sm = renda
       )
##       nome      sexo     graduacao fumante altura.m idade peso.kg renda.sm
## 1    Maria  feminino      Farmácia    TRUE     1.65    18      50        2
## 2   Rebeca  feminino      Farmácia    TRUE     1.70    19      65        3
## 3 Gabriela  feminino      Nutrição   FALSE     1.65    23      52        1
## 4  Roberto masculino       Química    TRUE     1.80    22      70        2
## 5   Mateus masculino        Física   FALSE     1.73    20      75        2
## 6  Gustavo masculino       Química   FALSE     1.75    19      63        4
## 7  Tatiane  feminino Biotecnologia   FALSE     1.68    25      62        4
## 8   Isaque masculino Biotecnologia    TRUE     1.71    26      70       NA

Utilizando pipes

Utilizamos o pipe (%>%) quando queremos fazer operações múltiplas em sequências. Para uso do pipes é necessário carregar o pacote “magrittr”. Supondo que precisamos fazer várias operações (selecionar, cumarizar, filtrar, …) para que o código não fique confuso podemos utilizar pipes, fica mais fácil para entendeermos o que estamos fazendo.

# Sem pipes
select(filter(alunos.2, imc >= 25), nome, graduacao, imc)
##     nome graduacao      imc
## 1 Mateus    Física 25.05931
# Com pipes
alunos.2 %>%
    filter(imc >= 25) %>%
    select(nome, graduacao, imc)
##     nome graduacao      imc
## 1 Mateus    Física 25.05931
# Indicamos o objeto que queremos usar a função filter() depois, sobre o resultado aplicamos a função select().

Resumindo e agrupando dados

Se por exemplo desejo saber a média do peso do grupo feminino e masulino.

alunos %>% 
    group_by(sexo) %>% 
    summarise(media = mean(peso))
## # A tibble: 2 x 2
##   sexo      media
##   <fct>     <dbl>
## 1 feminino   57.2
## 2 masculino  69.5
# Vamos colocar uma variável indicando o desvio padrão e outra indicando a quantidade de observações por sexo.
alunos %>% 
    group_by(sexo) %>% 
    summarise(media = mean(peso), d.peso = sd(peso), total = n())
## # A tibble: 2 x 4
##   sexo      media d.peso total
##   <fct>     <dbl>  <dbl> <int>
## 1 feminino   57.2   7.37     4
## 2 masculino  69.5   4.93     4

Muitas vezes nos deparamos com valores faltantes, então, informamos à função para não levar em consideração esses valores (NA).

alunos %>% 
    group_by(sexo) %>% 
    summarise(media.p = mean(peso),
              media.a = mean(altura),
              media.r = mean(renda, na.rm = TRUE),
              total = n()
              )
## # A tibble: 2 x 5
##   sexo      media.p media.a media.r total
##   <fct>       <dbl>   <dbl>   <dbl> <int>
## 1 feminino     57.2    1.67    2.5      4
## 2 masculino    69.5    1.75    2.67     4

Ordenando dados

Diversas vezes precisamos ordenar nossos dados, para isso vamos utilizar a função arrange () do pacote “dplyr”.

# Ordenando de forma decrescente o objeto "alunos" através da variável idade. 
alunos %>% 
    arrange(desc(idade))
##       nome      sexo     graduacao fumante altura idade peso renda
## 1   Isaque masculino Biotecnologia    TRUE   1.71    26   70    NA
## 2  Tatiane  feminino Biotecnologia   FALSE   1.68    25   62     4
## 3 Gabriela  feminino      Nutrição   FALSE   1.65    23   52     1
## 4  Roberto masculino       Química    TRUE   1.80    22   70     2
## 5   Mateus masculino        Física   FALSE   1.73    20   75     2
## 6   Rebeca  feminino      Farmácia    TRUE   1.70    19   65     3
## 7  Gustavo masculino       Química   FALSE   1.75    19   63     4
## 8    Maria  feminino      Farmácia    TRUE   1.65    18   50     2
# Agrupando por sexo e ordenando pela idade.
alunos %>% 
    group_by(sexo) %>% 
    arrange(desc(idade), .by_group = TRUE)
## # A tibble: 8 x 8
## # Groups:   sexo [2]
##   nome     sexo      graduacao     fumante altura idade  peso renda
##   <fct>    <fct>     <fct>         <lgl>    <dbl> <dbl> <dbl> <dbl>
## 1 Tatiane  feminino  Biotecnologia FALSE     1.68    25    62     4
## 2 Gabriela feminino  Nutrição      FALSE     1.65    23    52     1
## 3 Rebeca   feminino  Farmácia      TRUE      1.7     19    65     3
## 4 Maria    feminino  Farmácia      TRUE      1.65    18    50     2
## 5 Isaque   masculino Biotecnologia TRUE      1.71    26    70    NA
## 6 Roberto  masculino Química       TRUE      1.8     22    70     2
## 7 Mateus   masculino Física        FALSE     1.73    20    75     2
## 8 Gustavo  masculino Química       FALSE     1.75    19    63     4
# Note que informei ".by_grupo = TRUE" para poder ordenar primeiro o "feminino" para depois o "masculino"

Combinando variáveis

Muitas vezes precisamos combinar variáveis. Para tal, utilizaremos a função bind_cols().

# De início crio outro dataframe com o mesmo número de linhas.
complemento <- data.frame(
    nome = c("Maria", "Rebeca", "Gabriela", "Roberto", "Mateus", "Gustavo", "Tatiane", "Isaque"),
    tipo.sang = c("A+", "A+", "B-", "B+", "B+", "AB", "O+", "B-")
)

# Combinando objetos
bind_cols(alunos, complemento)
##       nome      sexo     graduacao fumante altura idade peso renda
## 1    Maria  feminino      Farmácia    TRUE   1.65    18   50     2
## 2   Rebeca  feminino      Farmácia    TRUE   1.70    19   65     3
## 3 Gabriela  feminino      Nutrição   FALSE   1.65    23   52     1
## 4  Roberto masculino       Química    TRUE   1.80    22   70     2
## 5   Mateus masculino        Física   FALSE   1.73    20   75     2
## 6  Gustavo masculino       Química   FALSE   1.75    19   63     4
## 7  Tatiane  feminino Biotecnologia   FALSE   1.68    25   62     4
## 8   Isaque masculino Biotecnologia    TRUE   1.71    26   70    NA
##      nome1 tipo.sang
## 1    Maria        A+
## 2   Rebeca        A+
## 3 Gabriela        B-
## 4  Roberto        B+
## 5   Mateus        B+
## 6  Gustavo        AB
## 7  Tatiane        O+
## 8   Isaque        B-

Porém apareceu uma ariável com “nome1” (evitando duplicidade).

Unindo variáveis à esquerda (left join)

Nesse caso não é necerssário ter o mesmo número de observações porque serão unidos somente objetos com a mesma chave.

# Criando um novo data.frame
complementos.1 <- data.frame(
    nome = c("Maria", "Mateus"),
    estado = c("PR", "SC")
)

# Unindo-os
left_join(alunos, complementos.1)
## Joining, by = "nome"
## Warning: Column `nome` joining factors with different levels, coercing to
## character vector
##       nome      sexo     graduacao fumante altura idade peso renda estado
## 1    Maria  feminino      Farmácia    TRUE   1.65    18   50     2     PR
## 2   Rebeca  feminino      Farmácia    TRUE   1.70    19   65     3   <NA>
## 3 Gabriela  feminino      Nutrição   FALSE   1.65    23   52     1   <NA>
## 4  Roberto masculino       Química    TRUE   1.80    22   70     2   <NA>
## 5   Mateus masculino        Física   FALSE   1.73    20   75     2     SC
## 6  Gustavo masculino       Química   FALSE   1.75    19   63     4   <NA>
## 7  Tatiane  feminino Biotecnologia   FALSE   1.68    25   62     4   <NA>
## 8   Isaque masculino Biotecnologia    TRUE   1.71    26   70    NA   <NA>

Unindo variáveis à direita (right join)

Iremos unir observações que correspondem à objetos a esquerda. Para unir objetos cujo a variável de um seja diferente da variável do outro basta informar ao comando.

# Criando um novo dataframe
alunos.3 <- data.frame(
    aluno = c("Maria", "Rebeca", "Gustavo"),
    cid.natal = c("Umuarama-PR", "Curitiba-PR", "Maringá-PR" )
)

# Unindo o objeto da direita ao da esquerda de forma a considerar que as variáveis nome e aluno é a mesma.
right_join(alunos.3, alunos, by = c("aluno" = "nome"))
## Warning: Column `aluno`/`nome` joining factors with different levels,
## coercing to character vector
##      aluno   cid.natal      sexo     graduacao fumante altura idade peso
## 1    Maria Umuarama-PR  feminino      Farmácia    TRUE   1.65    18   50
## 2   Rebeca Curitiba-PR  feminino      Farmácia    TRUE   1.70    19   65
## 3 Gabriela        <NA>  feminino      Nutrição   FALSE   1.65    23   52
## 4  Roberto        <NA> masculino       Química    TRUE   1.80    22   70
## 5   Mateus        <NA> masculino        Física   FALSE   1.73    20   75
## 6  Gustavo  Maringá-PR masculino       Química   FALSE   1.75    19   63
## 7  Tatiane        <NA>  feminino Biotecnologia   FALSE   1.68    25   62
## 8   Isaque        <NA> masculino Biotecnologia    TRUE   1.71    26   70
##   renda
## 1     2
## 2     3
## 3     1
## 4     2
## 5     2
## 6     4
## 7     4
## 8    NA

Unindo variáveis internamente (inner join)

Diversas vezes queremos construir bancos de dados completo, assim, podemos utilizar a função inner join (), ela irá desconsiderar as observações que não possui todas as variáveis completas.

inner_join(alunos.3, alunos, by = c("aluno" = "nome"))
## Warning: Column `aluno`/`nome` joining factors with different levels,
## coercing to character vector
##     aluno   cid.natal      sexo graduacao fumante altura idade peso renda
## 1   Maria Umuarama-PR  feminino  Farmácia    TRUE   1.65    18   50     2
## 2  Rebeca Curitiba-PR  feminino  Farmácia    TRUE   1.70    19   65     3
## 3 Gustavo  Maringá-PR masculino   Química   FALSE   1.75    19   63     4

Unindo todas as observações dos objetos (full join)

Se desejamos unir todas as observações de dois objetos podemos utilizar a função full_join().

full_join(alunos.3, alunos, by = c("aluno" = "nome"))
## Warning: Column `aluno`/`nome` joining factors with different levels,
## coercing to character vector
##      aluno   cid.natal      sexo     graduacao fumante altura idade peso
## 1    Maria Umuarama-PR  feminino      Farmácia    TRUE   1.65    18   50
## 2   Rebeca Curitiba-PR  feminino      Farmácia    TRUE   1.70    19   65
## 3  Gustavo  Maringá-PR masculino       Química   FALSE   1.75    19   63
## 4 Gabriela        <NA>  feminino      Nutrição   FALSE   1.65    23   52
## 5  Roberto        <NA> masculino       Química    TRUE   1.80    22   70
## 6   Mateus        <NA> masculino        Física   FALSE   1.73    20   75
## 7  Tatiane        <NA>  feminino Biotecnologia   FALSE   1.68    25   62
## 8   Isaque        <NA> masculino Biotecnologia    TRUE   1.71    26   70
##   renda
## 1     2
## 2     3
## 3     4
## 4     1
## 5     2
## 6     2
## 7     4
## 8    NA

Semi join e anti join

Se desejamos saber quais observações de um objeto possuem correspondências em outro objeto podemos fazer uso da função semi_join().

# Criando um novo dataframe.
alunos.4 <- left_join(complementos.1, alunos)
## Joining, by = "nome"
## Warning: Column `nome` joining factors with different levels, coercing to
## character vector
# Verifiando observações do "alunos" que possuem correspondências com observações com "alunos.4".
semi_join(alunos, alunos.4)
## Joining, by = c("nome", "sexo", "graduacao", "fumante", "altura", "idade", "peso", "renda")
## Warning: Column `nome` joining factor and character vector, coercing into
## character vector
##     nome      sexo graduacao fumante altura idade peso renda
## 1  Maria  feminino  Farmácia    TRUE   1.65    18   50     2
## 2 Mateus masculino    Física   FALSE   1.73    20   75     2

Porém, se desejamos saber quais observações não possuem correspondências em outro objeto podemos fazer uso da função anti_join().

# Verificando observações do "alunos" que não possuem correspondências com observações com "alunos.4".
anti_join(alunos, alunos.4)
## Joining, by = c("nome", "sexo", "graduacao", "fumante", "altura", "idade", "peso", "renda")
## Warning: Column `nome` joining factor and character vector, coercing into
## character vector
##       nome      sexo     graduacao fumante altura idade peso renda
## 1   Rebeca  feminino      Farmácia    TRUE   1.70    19   65     3
## 2 Gabriela  feminino      Nutrição   FALSE   1.65    23   52     1
## 3  Roberto masculino       Química    TRUE   1.80    22   70     2
## 4  Gustavo masculino       Química   FALSE   1.75    19   63     4
## 5  Tatiane  feminino Biotecnologia   FALSE   1.68    25   62     4
## 6   Isaque masculino Biotecnologia    TRUE   1.71    26   70    NA

se quisermos distinguir os dados, quais observações é de um determinado grupo podemos criar uma lista com os objetos, nomear cada um dos elementos da lista e em seguida unir com a função bind_rows() definindo o argumento “.id”.

lista.1 <- list(alunos.4, alunos)
names(lista.1) <- c("A", "B")
lista.1
## $A
##     nome estado      sexo graduacao fumante altura idade peso renda
## 1  Maria     PR  feminino  Farmácia    TRUE   1.65    18   50     2
## 2 Mateus     SC masculino    Física   FALSE   1.73    20   75     2
## 
## $B
##       nome      sexo     graduacao fumante altura idade peso renda
## 1    Maria  feminino      Farmácia    TRUE   1.65    18   50     2
## 2   Rebeca  feminino      Farmácia    TRUE   1.70    19   65     3
## 3 Gabriela  feminino      Nutrição   FALSE   1.65    23   52     1
## 4  Roberto masculino       Química    TRUE   1.80    22   70     2
## 5   Mateus masculino        Física   FALSE   1.73    20   75     2
## 6  Gustavo masculino       Química   FALSE   1.75    19   63     4
## 7  Tatiane  feminino Biotecnologia   FALSE   1.68    25   62     4
## 8   Isaque masculino Biotecnologia    TRUE   1.71    26   70    NA
bind_rows(lista.1, .id = "turma")
## Warning in bind_rows_(x, .id): binding character and factor vector,
## coercing into character vector
##    turma     nome estado      sexo     graduacao fumante altura idade peso
## 1      A    Maria     PR  feminino      Farmácia    TRUE   1.65    18   50
## 2      A   Mateus     SC masculino        Física   FALSE   1.73    20   75
## 3      B    Maria   <NA>  feminino      Farmácia    TRUE   1.65    18   50
## 4      B   Rebeca   <NA>  feminino      Farmácia    TRUE   1.70    19   65
## 5      B Gabriela   <NA>  feminino      Nutrição   FALSE   1.65    23   52
## 6      B  Roberto   <NA> masculino       Química    TRUE   1.80    22   70
## 7      B   Mateus   <NA> masculino        Física   FALSE   1.73    20   75
## 8      B  Gustavo   <NA> masculino       Química   FALSE   1.75    19   63
## 9      B  Tatiane   <NA>  feminino Biotecnologia   FALSE   1.68    25   62
## 10     B   Isaque   <NA> masculino Biotecnologia    TRUE   1.71    26   70
##    renda
## 1      2
## 2      2
## 3      2
## 4      3
## 5      1
## 6      2
## 7      2
## 8      4
## 9      4
## 10    NA

Trabalhando com valores ausentes

Vamos utilizar funções do pacote “tidyr”.

library(tidyr)

No nosso dataframe “alunos” a oitava observação está com um valor ausente na variável “renda”, se quisermos exibir nosso dataframe sem as observações que contêm valores faltantes fazemos o seguinte:

drop_na(alunos)
##       nome      sexo     graduacao fumante altura idade peso renda
## 1    Maria  feminino      Farmácia    TRUE   1.65    18   50     2
## 2   Rebeca  feminino      Farmácia    TRUE   1.70    19   65     3
## 3 Gabriela  feminino      Nutrição   FALSE   1.65    23   52     1
## 4  Roberto masculino       Química    TRUE   1.80    22   70     2
## 5   Mateus masculino        Física   FALSE   1.73    20   75     2
## 6  Gustavo masculino       Química   FALSE   1.75    19   63     4
## 7  Tatiane  feminino Biotecnologia   FALSE   1.68    25   62     4

Se desejarmos substituir os valores ausentes por outro valor utilizaremos outra função.

replace_na(alunos, list(renda = 1))
##       nome      sexo     graduacao fumante altura idade peso renda
## 1    Maria  feminino      Farmácia    TRUE   1.65    18   50     2
## 2   Rebeca  feminino      Farmácia    TRUE   1.70    19   65     3
## 3 Gabriela  feminino      Nutrição   FALSE   1.65    23   52     1
## 4  Roberto masculino       Química    TRUE   1.80    22   70     2
## 5   Mateus masculino        Física   FALSE   1.73    20   75     2
## 6  Gustavo masculino       Química   FALSE   1.75    19   63     4
## 7  Tatiane  feminino Biotecnologia   FALSE   1.68    25   62     4
## 8   Isaque masculino Biotecnologia    TRUE   1.71    26   70     1