No R, como em qualquer boa linguagem de programação, existem ferramentas de controle de fluxo essenciais para manipular dados de maneira eficiente, que podem ser divididas em duas categorias: condicionantes e iteradores. Neste exercício mostraremos como funcionam os famosos if, else, for e while, de modo a tornar seus scripts de R mais eficientes e menos repetitivos.
Provavelmente você já se deparou com estas estruturas em algum código ou precisou usá-las em alguma rotina, mas no primeiro contato a experiência costuma ser traumatizante para iniciantes da linguagem. Para evitar a frustração, comece aprendendo elementos mais básicos sobre as ferramentas que você está utilizando.
Ou seja, inicie se familiarizando com as principais estruturas de dados existentes (veja aqui um post sobre) e tenha sempre em mãos um resumo dos principais operadores lógicos que você precisará usar no dia a dia. A seguir iremos abordar brevemente os operadores e testes lógicos para usá-los nas estruturas de controle de fluxo.
Testes e operadores lógicos
Antes de explorar os controles de fluxo, é importante você entender e estar familiarizado com os principais operadores lógicos no R, possibilitando a construção de operações lógicas em seu código. Uma operação lógica nada mais é do que um teste que retorna um resultado verdadeiro (TRUE) ou falso (FALSE). Por exemplo, suponha que você precise testar se um valor é igual ao outro. Para isso use o operador == (igual):
# Com números 2 == 4 # [1] FALSE # Com textos "fernando" == "fernando" # [1] TRUE
Bem simples, não? Não doeu!
Tabela de operadores lógicos
Existem diversos operadores lógicos no R, aqui resumimos os mais utilizados:
Condicionantes: if e else
Os condicionantes if e else permitem que você execute códigos dependendo da condição (teste lógico) a ser satisfeita.
A sintaxe básica de uma instrução if no R é a seguinte:
if (condicao) acao_verdadeira if (condicao) acao_verdadeira else acao_falsa
A leitura do código é praticamente literal: se a condicao for verdadeira (TRUE), acao_verdadeira será avaliada (executada); se a condicao for falsa (FALSE), a acao_falsa (opcional) será avaliada.
Em resumo, estamos dizendo para o R testar algo e fazer alguma coisa se a condição do teste for satisfeita, e, opcionalmente, fazer outra coisa se a condição do teste não for satisfeita. Caso o else não seja declarado, o R retornará invisivelmente o valor NULL.
Geralmente, as ações são declaradas dentro das chaves {}, conforme os exemplos abaixo. No primeiro exemplo, o R só irá calcular o log de x se o valor deste objeto for maior que 0 (condição TRUE). Caso contrário, no segundo exemplo, o R calculará o exponencial do valor de x (condição FALSE).
x <- 2 if (x > 0) { # condição lógica log(x) # ação se a condição é verdadeira } # [1] 0.6931472 x <- -1 if (x > 0) { # condição lógica log(x) # ação se a condição é verdadeira } else exp(x) # ação se a condição é falsa # [1] 0.3678794
Seguindo essa lógica, podemos trabalhar com estas estruturas encadeando-as, atribuindo/salvando os resultados em objetos, especificando mais de uma condição, aumentando a complexidade com outras estruturas de controle, etc. O céu é o limite (ou não)!
Iteradores: for
A segunda categoria de controles de fluxo são os iteradores ou loopings, que servem para quando precisamos executar uma tarefa repetidas vezes utilizando um conjunto de valores diferentes. Se você trabalha intensivamente com dados no R, é provável que você já tenha usado os iteradores, mesmo que implicitamente através de alguma função.
O for é usado para iterar (repetir) uma determinada ação/tarefa sobre os elementos de um vetor. Para sair da abstração, primeiro vamos entender a sintaxe básica de uma instrução for:
for (elemento in vetor) executar_acao
Lemos o código da seguinte forma: para cada elemento no vetor, executar_acao é chamado uma vez, atualizando o valor do elemento a cada vez.
Alguns conceitos básicos:
- Iteração: é cada repetição da tarefa (executar_acao)
- Iterador: o vetor que muda de valor a cada iteração
Um dos exemplos mais básicos da vida real que podemos explorar é o cálculo da mediana de uma série de variáveis de um conjunto de dados. Imagine que temos o seguinte data.frame:
dados <- data.frame( a = rnorm(10), b = rnorm(10), c = rnorm(10) )
Queremos calcular a mediana de cada coluna, que poderia ser feito da seguinte forma (manual e repetitiva):
median(dados$a) # [1] 0.2477374 median(dados$b) # [1] -0.1486918 median(dados$c) # [1] 0.1975281
Repetir uma mesma tarefa (cálculo da mediana) copiando e colando o código mais do que duas vezes não é recomendável, por isso podemos usar o for:
for (i in 1:ncol(dados)) { # iterador print(median(dados[[i]])) # iteração } # [1] 0.2477374 # [1] -0.1486918 # [1] 0.1975281
Neste exemplo, para cada posição das colunas do objeto data.frame (vetor com sequência de 1 até 3, ditado pelo ncol), calculamos a mediana e imprimimos o resultado no Console. Neste caso, o valor de i é 1 na primeira iteração, 2 na segunda iteração e, por fim, 3 na última iteração.
Iteradores: while
Iteradores for são úteis se você souber com antecedência o conjunto de valores sobre o qual deseja repetir uma ação. Caso não saiba, o iterador while é mais flexível, possuindo apenas dois componentes: a condição (teste lógico) e a iteração (tarefa), conforme abaixo.
while(condicao) executar_acao
Essa instrução diz para o R avaliar executar_acao enquanto a condicao for verdadeira (TRUE).
Vamos a um exemplo: o código a seguir irá exibir na tela o valor de i enquanto o valor deste objeto for menor ou igual a 10. No momento em que esta condição não for mais verdadeira, o processo é interrompido.
i <- 7 while (i <= 10) { # condição print(i) # iteração i <- i + 1 # atualiza valor de i, evitando um loop infinito } # [1] 7 # [1] 8 # [1] 9 # [1] 10
O exemplo acima apenas demonstra a sintaxe básica a ser seguida. O iterador while é mais usado para simulações, por exemplo: descobrir quantas vezes é necessário jogar uma moeda para obter 3 caras seguidas.
Saiba mais
Para se aprofundar sobre os tópicos abordados, confira estes posts no blog da Análise Macro:
E também o ótimo livro de Hadley Wickham intitulado “Advanced R”, especificamente o capítulo 5.