6.3 Iterações
Vocês usaram várias funções da família apply
, especialmente apply()
e tapply()
, que são funções especiais que repetem uma mesma função FUN
para cada objeto de um conjunto (vetores, matrizes, valores atômicos).
Essas funções utilizam portanto a lógica de iterações (em inglês, loops), ou seja, fazem a mesma ação repetidas vezes; em outras palavras, fazem LOOPs, dão voltas, realizam o mesmo percurso várias vezes, percorrem um circuito.
As expressões for(){}
e while(){}
permitem fazer LOOPs, e LOOPs dentro de LOOPS com muita liberdade.
Aprendê-las é o mesmo que aprender todas as funções da família apply
juntas (apply()
, tapply()
, sapply()
, lapply()
, mapply()
etc).
Se você compreende os LOOPS, pode fazer o que essas funções fazem sem precisar delas (embora elas possam executar a tarefa mais rapidamente).
6.3.1 Iteração com for(){}
6.3.1.1 Exemplo 1
Um exemplo simples do que seria uma iteração com o comando for(){}
:
# vamos imprimir na tela as letras do objeto LETTERS
for (let in 1:length(LETTERS)) {
<- paste(LETTERS[let], " é a letra de índice ", let)
paraimprimir print(paraimprimir)
}
## [1] "A é a letra de índice 1"
## [1] "B é a letra de índice 2"
## [1] "C é a letra de índice 3"
## [1] "D é a letra de índice 4"
## [1] "E é a letra de índice 5"
## [1] "F é a letra de índice 6"
## [1] "G é a letra de índice 7"
## [1] "H é a letra de índice 8"
## [1] "I é a letra de índice 9"
## [1] "J é a letra de índice 10"
## [1] "K é a letra de índice 11"
## [1] "L é a letra de índice 12"
## [1] "M é a letra de índice 13"
## [1] "N é a letra de índice 14"
## [1] "O é a letra de índice 15"
## [1] "P é a letra de índice 16"
## [1] "Q é a letra de índice 17"
## [1] "R é a letra de índice 18"
## [1] "S é a letra de índice 19"
## [1] "T é a letra de índice 20"
## [1] "U é a letra de índice 21"
## [1] "V é a letra de índice 22"
## [1] "W é a letra de índice 23"
## [1] "X é a letra de índice 24"
## [1] "Y é a letra de índice 25"
## [1] "Z é a letra de índice 26"
Ou seja, para cada elemento do objeto let
, assumindo os valores na sequência do elemento 1 ao elemento corresponden ao comprimento (== length(LETTERS)
) do objeto LETTERS, execute o que está dentro de {}
.
6.3.1.2 Exemplo 2
# Fazendo um loop com for(){} replicando o que a função apply() faz
# criamos uma matriz
<- rnorm(100, 30, 1)
vetn <- matrix(vetn, ncol = 10, dimnames = list(paste("linha", 1:10), paste("coluna", 1:10)))
mvetn head(mvetn)
coluna 1 | coluna 2 | coluna 3 | coluna 4 | coluna 5 | coluna 6 | coluna 7 | coluna 8 | coluna 9 | coluna 10 | |
---|---|---|---|---|---|---|---|---|---|---|
linha 1 | 29.83293 | 29.14018 | 29.23649 | 30.41905 | 30.94899 | 29.84389 | 29.97366 | 30.15412 | 29.34273 | 30.08479 |
linha 2 | 31.24129 | 31.05689 | 29.45685 | 30.92010 | 30.28868 | 30.51557 | 29.74122 | 30.46949 | 28.15604 | 30.88475 |
linha 3 | 30.29010 | 31.34928 | 29.17843 | 28.80200 | 30.94568 | 29.34699 | 29.88953 | 28.76698 | 29.47358 | 29.82502 |
linha 4 | 29.94628 | 30.14674 | 30.23371 | 28.56894 | 31.47962 | 32.13595 | 29.62404 | 28.93148 | 30.15042 | 31.61015 |
linha 5 | 30.07430 | 30.81179 | 29.26558 | 29.58111 | 29.59002 | 29.91044 | 32.09775 | 31.96293 | 27.54644 | 30.83061 |
linha 6 | 29.88561 | 28.47641 | 29.62197 | 30.23359 | 29.96315 | 28.71014 | 30.48448 | 31.47933 | 30.73691 | 31.11348 |
# Fazendo algo == apply(mvetn,2,mean)
# cria um objeto para salvar o resultado
<- NULL
resultado for (coluna in 1:ncol(mvetn)) {
# pega a coluna
<- mvetn[, coluna]
cl # calcula a media
<- mean(cl)
mcl print(paste("Média da coluna", colnames(mvetn)[cl], "=", round(mcl, 2)))
# salva o resultado com a media do item anterior
<- c(resultado, mcl)
resultado }
## [1] "Média da coluna NA = 30.02" "Média da coluna NA = 30.02"
## [3] "Média da coluna NA = 30.02" "Média da coluna NA = 30.02"
## [5] "Média da coluna NA = 30.02" "Média da coluna NA = 30.02"
## [7] "Média da coluna NA = 30.02" "Média da coluna NA = 30.02"
## [9] "Média da coluna NA = 30.02" "Média da coluna NA = 30.02"
## [1] "Média da coluna NA = 29.77" "Média da coluna NA = 29.77"
## [3] "Média da coluna NA = 29.77" "Média da coluna NA = 29.77"
## [5] "Média da coluna NA = 29.77" "Média da coluna NA = 29.77"
## [7] "Média da coluna NA = 29.77" "Média da coluna NA = 29.77"
## [9] "Média da coluna NA = 29.77" "Média da coluna NA = 29.77"
## [1] "Média da coluna NA = 29.92" "Média da coluna NA = 29.92"
## [3] "Média da coluna NA = 29.92" "Média da coluna NA = 29.92"
## [5] "Média da coluna NA = 29.92" "Média da coluna NA = 29.92"
## [7] "Média da coluna NA = 29.92" "Média da coluna NA = 29.92"
## [9] "Média da coluna NA = 29.92" "Média da coluna NA = 29.92"
## [1] "Média da coluna NA = 29.8" "Média da coluna NA = 29.8"
## [3] "Média da coluna NA = 29.8" "Média da coluna NA = 29.8"
## [5] "Média da coluna NA = 29.8" "Média da coluna NA = 29.8"
## [7] "Média da coluna NA = 29.8" "Média da coluna NA = 29.8"
## [9] "Média da coluna NA = 29.8" "Média da coluna NA = 29.8"
## [1] "Média da coluna NA = 30.21" "Média da coluna NA = 30.21"
## [3] "Média da coluna NA = 30.21" "Média da coluna NA = 30.21"
## [5] "Média da coluna NA = 30.21" "Média da coluna NA = 30.21"
## [7] "Média da coluna NA = 30.21" "Média da coluna NA = 30.21"
## [9] "Média da coluna NA = 30.21" "Média da coluna NA = 30.21"
## [1] "Média da coluna NA = 29.85" "Média da coluna NA = 29.85"
## [3] "Média da coluna NA = 29.85" "Média da coluna NA = 29.85"
## [5] "Média da coluna NA = 29.85" "Média da coluna NA = 29.85"
## [7] "Média da coluna NA = 29.85" "Média da coluna NA = 29.85"
## [9] "Média da coluna NA = 29.85" "Média da coluna NA = 29.85"
## [1] "Média da coluna NA = 30.34" "Média da coluna NA = 30.34"
## [3] "Média da coluna NA = 30.34" "Média da coluna NA = 30.34"
## [5] "Média da coluna NA = 30.34" "Média da coluna NA = 30.34"
## [7] "Média da coluna NA = 30.34" "Média da coluna NA = 30.34"
## [9] "Média da coluna NA = 30.34" "Média da coluna NA = 30.34"
## [1] "Média da coluna NA = 30.33" "Média da coluna NA = 30.33"
## [3] "Média da coluna NA = 30.33" "Média da coluna NA = 30.33"
## [5] "Média da coluna NA = 30.33" "Média da coluna NA = 30.33"
## [7] "Média da coluna NA = 30.33" "Média da coluna NA = 30.33"
## [9] "Média da coluna NA = 30.33" "Média da coluna NA = 30.33"
## [1] "Média da coluna NA = 29.95" "Média da coluna NA = 29.95"
## [3] "Média da coluna NA = 29.95" "Média da coluna NA = 29.95"
## [5] "Média da coluna NA = 29.95" "Média da coluna NA = 29.95"
## [7] "Média da coluna NA = 29.95" "Média da coluna NA = 29.95"
## [9] "Média da coluna NA = 29.95" "Média da coluna NA = 29.95"
## [1] "Média da coluna NA = 30.69" "Média da coluna NA = 30.69"
## [3] "Média da coluna NA = 30.69" "Média da coluna NA = 30.69"
## [5] "Média da coluna NA = 30.69" "Média da coluna NA = 30.69"
## [7] "Média da coluna NA = 30.69" "Média da coluna NA = 30.69"
## [9] "Média da coluna NA = 30.69" "Média da coluna NA = 30.69"
# adicona o nome das colunas
names(resultado) <- colnames(mvetn)
# ver o resultado
resultado
## coluna 1 coluna 2 coluna 3 coluna 4 coluna 5 coluna 6 coluna 7 coluna 8
## 30.02231 29.76714 29.91783 29.79591 30.21034 29.85470 30.33654 30.32650
## coluna 9 coluna 10
## 29.94533 30.69054
# identico ao apply, maior controle de como a média é aplicada
== apply(mvetn, 2, mean) resultado
## coluna 1 coluna 2 coluna 3 coluna 4 coluna 5 coluna 6 coluna 7 coluna 8
## TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## coluna 9 coluna 10
## TRUE TRUE
6.3.1.3 Exemplo 3
Agora usando for(){}
para fazer algo como o tapply()
.
# Fazendo algo == tapply(mvetn[,2],mvetn$classe,sum)
# criamos uma matriz
<- rnorm(100, 30, 1)
vetn <- matrix(vetn, ncol = 10, dimnames = list(paste("linha", 1:10), paste("coluna", 1:10)))
mvetn # transformamos num data.frame adicionando uma coluna categorica
<- data.frame(classe = sample(paste("categ", 1:3, sep = ""), size = nrow(mvetn), replace = T), mvetn)
mvetn head(mvetn[, 1:5])
# cria um objeto para salvar o resultado
<- NULL
resultado # para cada categoria
for (ct in 1:length(levels(mvetn$classe))) {
# pega a categoria
<- levels(mvetn$classe)[ct]
cl # filtra os dados (vetor logico)
<- mvetn$classe == cl
vl # calcula a soma dos dados da categoria
<- sum(mvetn[vl, 2], na.rm = T)
soma # imprime o passo
print(paste("A soma da categoria", cl, " é igual a ", soma))
# junta os resultados
<- c(resultado, soma)
resultado
}# atribui nomes aos elementos do vetor de somas
names(resultado) <- levels(mvetn$classe)
# confere
== tapply(mvetn[, 2], mvetn$classe, sum) resultado
6.3.1.4 Exemplo 4
Calculando somas e médias de linhas, similar ao que podemos fazer com a função apply()
:
<- NULL # objeto vazio para salvar soma de cada linha
somas <- NULL # objeto vazio para salvar medias de cada linha
medias for (i in 1:nrow(X)) { # para cada linha
<- sum(X[i, ]) # soma dos valores na linha i
somai <- c(somas, somai) # junta a somai com o resto (que estará vazio na primeira vez)
somas <- mean(X[i, ]) # média dos valores na linha i
mediai <- c(medias, mediai) # junta as medias
medias
}# como a matriz tem nomes, acrescenta esses nomes aos vetores com resultados
names(medias) <- rownames(X)
medias
## ln 1 ln 2 ln 3 ln 4
## 17 18 19 20
names(somas) <- rownames(X)
somas
## ln 1 ln 2 ln 3 ln 4
## 153 162 171 180
6.3.2 Iteração com while(){}
O comando while(){}
funciona de forma parecida, mas faz algo ENQUANTO (em inglês, while) a condição em while(){}
seja verdadeira.
Um exemplo simples:
6.3.2.1 Exemplo 1
# cria um vetor de valores aleatorizados
<- sample(10:100)
vet # amostra um valor do vetor até que este valor seja 10
<- 1
conta <- 0
valor while (valor != 10) {
<- sample(vet, 1)
valor print(paste("o valor selecionado na iteração", conta, "foi de ", valor))
<- conta + 1
conta }
## [1] "o valor selecionado na iteração 1 foi de 81"
## [1] "o valor selecionado na iteração 2 foi de 23"
## [1] "o valor selecionado na iteração 3 foi de 30"
## [1] "o valor selecionado na iteração 4 foi de 32"
## [1] "o valor selecionado na iteração 5 foi de 39"
## [1] "o valor selecionado na iteração 6 foi de 74"
## [1] "o valor selecionado na iteração 7 foi de 88"
## [1] "o valor selecionado na iteração 8 foi de 16"
## [1] "o valor selecionado na iteração 9 foi de 60"
## [1] "o valor selecionado na iteração 10 foi de 61"
## [1] "o valor selecionado na iteração 11 foi de 62"
## [1] "o valor selecionado na iteração 12 foi de 74"
## [1] "o valor selecionado na iteração 13 foi de 10"
6.3.3 Iteração com for(){}
e a condicional if(){}
6.3.3.1 Exemplo 1
# cria um vetor de valores aleatorizados
<- sample(10:100, 60, replace = T)
vet # amostra um valor do vetor até que este valor seja 10
for (v in 1:10000) {
<- sample(vet, 1)
valor if (valor == 10) {
# se o valor selecionado aleatoriamente for 10, ou seja se a expressão valor==10 for TRUE execute:
# imprima isso
print(paste("A primeira vez que o valor 10 foi selecionado aleatoriamente foi quando o objeto v assumiu o valor de", v))
# interrompa (quebre) o loop
break # note este argumento
else {
} # caso contrario, valor!=10, imprime o valor selecionado e continua o loop
print(paste("O valor selecionado foi ", valor, "no indice", v))
} }
É possível que o script acima repita as 10000 vezes do for(){}
sem encontrar o valor 10, até porque o 10 pode não estar em vet se não for amostrado.