O R tem um conjunto de operadores igual ao de muitas outras linguagens:
1 == 2 # FALSE
1 != 2 # TRUE
1 < 2 # TRUE
1 > 2 # FALSE
1 <= 2 # TRUE
1 >= 2 # FALSE
A forma básica de um if-then-else é:
if (x > 10) {
y <- "big"
} else if (x > 2) {
y <- "medium"
} else {
y <- "tiny"
}
Nesse caso, os parênteses ( ) em volta do boolean e as chaves { } em volta do corpo são obrigatórios.
Uma condicional if simples pode ser encurtada:
if (x == 0) return("success")
Adiantando um pouco o conceito de vector-filtering: a cláusula condicional entre parênteses () precisa resultar em um único TRUE/FALSE.
Incluir vetores na comparação geralmente produz um vetor de boolean, então vai ser preciso envolvê-lo em uma função de agregação como all() (todos os valores são TRUE?) ou any() (pelo menos um valor é TRUE).
numbers <- c(4,5,7,9,10,11)
numbers %% 3 == 0 # gives vector of booleans
#> [1] FALSE FALSE FALSE TRUE FALSE FALSE
# use any() to get a single TRUE/FALSE
if (any(numbers %% 3 == 0)) print("1 or more numbers are divisible by 3")
#> [1] "1 or more numbers are divisible by 3"
ifelse
Uma forma alternativa de if-else pode ser útil, desde que haja apenas um resultado verdadeiro/falso.
y <- ifelse(x > 8, "big", "small")
# Don't mix result types:
z <- ifelse(x > 100, 100, "small") # numeric or string result? Expect problems!
ifelse() recebe exatamente três parâmetros:
TRUE
FALSE.Entradas na forma de vetor são aceitáveis, e nesse caso a saída também é um vetor.
Nesse caso, certifique-se de que os dois blocos resultem no mesmo tipo de dado: numérico, caractere, lógico, etc.
Isso será abordado no conceito de vector-functions.
Os dois resultados ("big", "small" no exemplo acima) devem ser valores únicos.
Infelizmente, passar um vetor mais longo aqui provavelmente fará o R fazer algo confuso e inesperado, sem emitir nenhuma mensagem de aviso.
if_else
Os mantenedores da linguagem R têm a política de evitar, na medida do possível, mudanças que quebrem a compatibilidade. Isso ajuda a manter o vasto número de pacotes de terceiros disponíveis no CRAN, mas limita a capacidade de atualizar o R base com conceitos modernos de programação.
Nos últimos anos, vários pacotes foram lançados que estendem e às vezes substituem funcionalidades do R, com base em décadas de experiência sobre os pontos fortes e fracos do design original do R.
Esses pacotes formam a coleção tidyverse.
Eles foram adicionados ao test runner do Exercism em 2023 e estão disponíveis para você usar nos exercícios.
Nossa track de R é vários anos anterior à adição do tidyverse, então você pode notar que muitas soluções da comunidade ficam com a linguagem base.
dplyr
O dplyr serve principalmente para manipular dataframes (assunto que será abordado mais adiante no curso).
Adicione-o com library(dplyr) no início do seu código, ou com library(tidyverse) para adicionar a coleção inteira.
Você pode ver mensagens de aviso sobre nomes mascarados, mas isso raramente é um problema.
Para o conceito atual, vale mencionar a função if_else.
Ela é bastante parecida com a ifelse do R base.
library(dplyr) # warnings not shown
x <- 10
if_else(x > 8, "big", "small")
#> [1] "big"
A principal diferença é que if_else pode receber um quarto argumento opcional, para valores ausentes que são representados no R por NA.
xs <- c(3, NA, 10, NA, 4) # a 5-element vector
xs
#> [1] 3 NA 10 NA 4
if_else(xs > 8, "big", "small", "missing")
#> [1] "small" "missing" "big" "missing" "small"
# contrast:
ifelse(xs > 8, "big", "small")
#> [1] "small" NA "big" NA "small"
Você também pode achar que o if_else tem mensagens de erro muito melhores que o ifelse mais antigo.
Depois de carregar a biblioteca dplyr, você também terá acesso à função between().
O R não permite encadear comparações, então 1 <= x <= 5 vai gerar uma mensagem de erro.
Com o dplyr carregado, between(x, 1, 5) é equivalente a x >= 1 & x <= 5, e talvez seja mais legível.
Tanto o limite inferior quanto o superior são inclusivos.