Todas as linguagens de programação usam ifs, fors e whiles, que sempre fazem a mesma coisa em linhas gerais. Este capítulo trata deles. Cada seção vai tratar de cada um deles, e todas serão estruturadas da seguinte maneira: primeiramente, só apresentamos a sintaxe dos comandos no R. A seguir, temos uma discussão sobre o que cada estrutura faz. Desta maneira, aqueles que já conhecem essas estruturas de outras linguagens podem simplesmente ler a sintaxe e pular toda a discussão subsequente.
Em geral, os exemplos podem não parecer ter utilidade prática, mas servem para entender as ideias. Aplicações práticas são encontradas nos capítulos subsequentes.
If
Ifs são estruturas condicionais: se essa condição é atendida, faça isso. Senão, faça aquilo outro. A sintaxe é:
if(condição){
ação se a condição for atendida} else {
ação se a condição não for atendida}
Por exemplo, podemos escrever um código que testa se xx - que deve ser um número - é igual a 18, e se sim ele nos mostra um “Sim”. Caso contrário, “Não”.
x <- 18
if(x==18){
print("Sim")} else {
print("Não")}
## [1] "Sim"
x <- 21
if(x==18){
print("Sim")} else {
print("Não")}
## [1] "Não"
Podemos concatenar vários else e ifs e testar várias condições. Podemos querer saber se x é menor que 5 ou maior que 7:
x <- 5
if(x < 5){
print("Menor que 5")} else if(x > 7){
print("Maior que 7")} else {
print("Nenhum dos dois")}
## [1] "Nenhum dos dois"
x <- 8
if(x < 5){
print("Menor que 5")} else if(x > 7){
print("Maior que 7")} else {
print("Nenhum dos dois")}
## [1] "Maior que 7"
Essa estrutura pode ser chata e requerer muitas linhas quando queremos algo simples. Pense no caso que queremos definir a variável h como 1 se x é maior que 1, e 0 caso contrário. Felizmente, o comando ifelse
resolve isso. A sintaxe dele é simples: a condição, o valor se a condição for atendida e o valor se a condição não for atendida. Assim, no exemplo acima:
h <- ifelse(x > 1 ,1,0)
h
## [1] 1
Entretanto, em muitas situações, usar a estrutura do if ao invés da função ifelse()
é útil.
For e While
For (e whiles) são loops: eles permitem repetir a mesma operação várias vezes. Para eles serem interessantes, eles tem que permitir alguma alteração no input e no output. A sintaxe do for é:
for(i in 1:n){
ações...
}
Veja que podemos indexar o for por qualquer letra (e não apenas i), e que podemos usar um vetor para indexar o for, o que vai fazer o for repetir a operação pelo comprimento daquele vetor - e definir o valor de i como o valor dos elementos do vetor. Por exemplo:
a <- c(1,2,3,4,5)
b <- 0
for(i in a){
b <- b + i
print(b)
}
## [1] 1
## [1] 3
## [1] 6
## [1] 10
## [1] 15
Hands on! |
---|
Podemos usar o for para ilustrar uma ideia bastante importante de estatística: a lei dos grandes números. Para refrescar a memória: a lei dos grandes números diz que se a variável aleatória tem média μμ, ¯XX¯ é a média amostral e nn é o tamanho da amostra, então plimn→∞(¯X)=μplimn→∞(X¯)=μ. O código para ilustrar isso é simples:
media : ele deve se aproximar da media verdadeira do processo conforme n cresce. Você pode testar nn diferente de 200 para ver o quão bom fica a aproximação, bem como diferentes distribuições e parâmetros. |
O while funciona de maneira parecida, mas ao invés de ir até o fim do contador, o while depende de alguma condição. O exemplo mais usual é um while que acaba quando uma variável alcança um certo valor. Por exemplo:
b <- 0
j <- 1
while(j < 6){
b <- b + j
j <- j + 1
}
Esse exemplo faz exatamente a mesma coisa que o for anterior. Observe que temos que adicionar a linha j <- j +1
, senão j nunca irá alcançar 6, e o R nunca vai sair do while: ele vai ver j=1j=1 e continuar no while infinitamente. Também observe que temos que criar o j <- 1
, enquanto no for não havia a necessidade de criar a variável i de antemão.
Diferenças e Semelhanças entre for e while
O exemplo anterior de while deixa claro que ele é muito semelhante ao for: ambos permitem repetir um conjunto de operações um certo número de vezes. A inclusão do while parece até um desperdício: uma função quase idêntica ao for que exige duas linhas de código a mais. Mas enquanto muitas vezes o for é mais usado que o while, o while tem suas vantagens, como o seguinte exemplo ilustra.
Suponha que queremos gerar 100 matrizes de 100 observações com 10 variáveis independentes de uma normal e queremos garantir que a matriz seja invertível9. Poderíamos escrever:
matrizes <- list()
for(i in 1:100){
matrizes[[i]] <- matrix(rnorm(100*100),ncol = 100, nrow = 100)
}
Veja o que o exemplo acima faz:
- Cria uma lista vazia chamada matrizes
- Para cada posição da lista, ele vai criar uma matriz com 10 colunas e 100 linhas
- o conteúdo dessa matriz são 1000 números saídos de uma normal de média zero e variância 1.
Não foi especificado que a matriz tem que ser invertível: em nenhum ponto nós testamos isso. Nós poderíamos construir um teste usando if, de forma que se a matriz não for invertível (por exemplo, tem determinante zero), a matriz é ignorada. Mas observe que isso gera um problema: se a matriz for ignorada, o for continua e vai gerar uma matriz a menos do que queríamos. É ai que o while entra: podemos escrever o código com while de maneira que, quando a matriz tiver determinante 0, o contador não cresce. O código seria algo como:
matrizes <- list()
i <- 1
while(i <= 100){
candidato <- matrix(rnorm(100*100),ncol = 100, nrow = 100)
teste <- det(candidato)
if(teste == 0){} else{
matrizes[[i]] <- candidato
i <- i + 1}
}
Veja que só aumentamos o contador quando o determinante é diferente de zero , ou seja, quando aceitamos a matriz.