5 Programando com dados
Por quê programar?
- Evitar repetições desnecessárias de análises ou cálculos que são repetidos com frequência.
- Documentar as etapas que você realizou para chegar a um resultado.
- Fácil recuperação e modificação de programas.
Como programar?
- Criando programas! (Scripts, rotinas, algoritmos).
- Crie uma sequência lógica de comandos que devem ser executados em ordem.
- Utilize as ferramentas básicas da programação: estruturas de
repetição (
for()
) e estruturas de seleção (if()
).
5.1 Estrutura de repetição for()
Serve para repetir um ou mais comandos diversas vezes. Para ver como funciona, considere o seguinte exemplo:
for(i in 1:10){
print(i)
}1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10 [
O resultado é a chamada do comando print()
para cada valor que o
índice i
recebe (nesse caso i
recebe os valores de 1 a 10).
A sintaxe será sempre nesse formato:
for(<índice> in <valores>){
<comandos>
}
Veja outro exemplo em como podemos aplicar o índice:
<- 100:200
x for(j in 1:10){
print(x[j])
}1] 100
[1] 101
[1] 102
[1] 103
[1] 104
[1] 105
[1] 106
[1] 107
[1] 108
[1] 109 [
Veja que o índice não precisa ser i
, na verdade pode ser qualquer
letra ou palavra. Nesse caso, utilizamos os valores como índice
para selecionar elementos de x
nas posições específicadas.
Um outro exemplo seria se quisessemos imprimir o quadrado de alguns números (não necessariamente em sequência):
for(i in c(2, 9, 4, 6)){
print(i^2)
}1] 4
[1] 81
[1] 16
[1] 36 [
Ou mesmo imprimir caracteres a partir de um vetor de caracteres:
for(veiculos in c("carro", "ônibus", "trem", "bicicleta")){
print(veiculos)
}1] "carro"
[1] "ônibus"
[1] "trem"
[1] "bicicleta" [
Exemplo: cálculo de notas de uma disciplina.
## Importa os dados
<- "http://leg.ufpr.br/~fernandomayer/data/notas.csv"
url <- read.table(url, header = TRUE, sep = ";", dec = ",")
notas ## Analisa a estrutura dos dados
str(notas)
head(notas)
summary(notas)
Antes de seguir adiante, veja o resultado de
for(i in 1:30){
print(notas[i, c("prova1", "prova2", "prova3")])
}
Para calcular as médias das 3 provas, precisamos inicialmente de um vetor para armazenar os resultados. Esse vetor pode ser um novo objeto ou uma nova coluna no dataframe
## Aqui vamos criar uma nova coluna no dataframe, contendo apenas o
## valor 0
$media <- 0 # note que aqui será usada a regra da reciclagem, ou
notas# seja, o valor zero será repetido até completar todas
# as linhas do dataframe
## Estrutura de repetição para calcular a média
for(i in 1:30){
## Aqui, cada linha i da coluna media sera substituida pelo
## respectivo valor da media caculada
$media[i] <- sum(notas[i, c("prova1", "prova2", "prova3")])/3
notas
}
## Confere os resultados
head(notas)
nome prova1 prova2 prova3 media1 Aluno_1 8 4 1 4.333333
2 Aluno_2 2 7 6 5.000000
3 Aluno_3 9 2 4 5.000000
4 Aluno_4 1 10 9 6.666667
5 Aluno_5 7 6 8 7.000000
6 Aluno_6 10 0 3 4.333333
Agora podemos melhorar o código, tornando-o mais genérico. Dessa forma fica mais fácil fazer alterações e procurar erros. Uma forma de melhorar o código acima é generalizando alguns passos.
## Armazenamos o número de linhas no dataframe
<- nrow(notas)
nlinhas ## Identificamos as colunas de interesse no cálculo da média, e
## armazenamos em um objeto separado
<- c("prova1", "prova2", "prova3")
provas ## Sabendo o número de provas, fica mais fácil dividir pelo total no
## cálculo da média
<- length(provas)
nprovas ## Cria uma nova coluna apenas para comparar o cálculo com o anterior
$media2 <- 0
notas## A estrutura de repetição fica
for(i in 1:nlinhas){
$media2[i] <- sum(notas[i, provas])/nprovas
notas
}
## Confere
head(notas)
nome prova1 prova2 prova3 media media21 Aluno_1 8 4 1 4.333333 4.333333
2 Aluno_2 2 7 6 5.000000 5.000000
3 Aluno_3 9 2 4 5.000000 5.000000
4 Aluno_4 1 10 9 6.666667 6.666667
5 Aluno_5 7 6 8 7.000000 7.000000
6 Aluno_6 10 0 3 4.333333 4.333333
identical(notas$media, notas$media2)
1] TRUE [
Ainda podemos melhorar (leia-se: otimizar) o código, se utilizarmos
funções prontas do R. No caso da média isso é possível pois a função
mean()
já existe. Em seguida veremos como fazer quando o cálculo que
estamos utilizando não está implementado em nenhuma função pronta do R.
## Cria uma nova coluna apenas para comparação
$media3 <- 0
notas## A estrutura de repetição fica
for(i in 1:nlinhas){
$media3[i] <- mean(as.numeric(notas[i, provas]))
notas
}
## Confere
head(notas)
nome prova1 prova2 prova3 media media2 media31 Aluno_1 8 4 1 4.333333 4.333333 4.333333
2 Aluno_2 2 7 6 5.000000 5.000000 5.000000
3 Aluno_3 9 2 4 5.000000 5.000000 5.000000
4 Aluno_4 1 10 9 6.666667 6.666667 6.666667
5 Aluno_5 7 6 8 7.000000 7.000000 7.000000
6 Aluno_6 10 0 3 4.333333 4.333333 4.333333
## A única diferença é que aqui precisamos transformar cada linha em um
## vetor de números com as.numeric(), pois
1, provas]
notas[
prova1 prova2 prova31 8 4 1
## é um data.frame:
class(notas[1, provas])
1] "data.frame" [
No caso acima vimos que não era necessário calcular a média através
de soma/total
porque existe uma função pronta no R para fazer esse
cálculo. Mas, e se quisessemos, por exemplo, calcular a Coeficiente de
Variação (CV) entre as notas das três provas de cada aluno? Uma busca
por
help.search("coefficient of variation")
não retorna nenhuma função (dos pacotes básicos) para fazer esse cálculo. O motivo é simples: como é uma conta simples de fazer não há necessidade de se criar uma função extra dentro dos pacotes. No entanto, nós podemos criar uma função que calcule o CV, e usá-la para o nosso propósito
<- function(x){
cv <- sd(x)
desv.pad <- mean(x)
med <- desv.pad/med
cv return(cv)
}
NOTA: na função criada acima o único argumento que usamos foi x
, que
neste caso deve ser um vetor de números para o cálculo do CV. Os
argumentos colocados dentro de function()
devem ser apropriados para
o propósito de cada função.
Antes de aplicar a função dentro de um for()
devemos testá-la para ver
se ela está funcionando de maneira correta. Por exemplo, o CV para as
notas do primeiro aluno pode ser calculado “manualmente” por
sd(as.numeric(notas[1, provas]))/mean(as.numeric(notas[1, provas]))
1] 0.8104349 [
E através da função, o resultado é
cv(as.numeric(notas[1, provas]))
1] 0.8104349 [
o que mostra que a função está funcionando corretamente, e podemos aplicá-la em todas as linhas usando a repetição
## Cria uma nova coluna para o CV
$CV <- 0
notas## A estrutura de repetição fica
for(i in 1:nlinhas){
$CV[i] <- cv(as.numeric(notas[i, provas]))
notas
}
## Confere
head(notas)
nome prova1 prova2 prova3 media media2 media3 CV1 Aluno_1 8 4 1 4.333333 4.333333 4.333333 0.8104349
2 Aluno_2 2 7 6 5.000000 5.000000 5.000000 0.5291503
3 Aluno_3 9 2 4 5.000000 5.000000 5.000000 0.7211103
4 Aluno_4 1 10 9 6.666667 6.666667 6.666667 0.7399324
5 Aluno_5 7 6 8 7.000000 7.000000 7.000000 0.1428571
6 Aluno_6 10 0 3 4.333333 4.333333 4.333333 1.1842157
Podemos agora querer calcular as médias ponderadas para as provas. Por exemplo:
- Prova 1: peso 3
- Prova 2: peso 3
- Prova 3: peso 4
Usando a fórmula:
\[ \bar{x} = \frac{1}{N} \sum_{i=1}^{n} x_i \cdot w_i \]
onde \(w_i\) são os pesos, e \(N = \sum_{i=1}^{n} w_i\) é a soma dos pesos. Como já vimos, criar uma função é uma forma mais prática (e elegante) de executar determinada tarefa, vamos criar uma função que calcule as médias ponderadas.
<- function(notas, pesos){
med.pond ## Multiplica o valor de cada prova pelo seu peso
<- notas * pesos
pond ## Calcula o valor total dos pesos
<- sum(pesos)
peso.total ## Calcula a soma da ponderação
<- sum(pond)
sum.pond ## Finalmente calcula a média ponderada
<- sum.pond/peso.total
saida return(saida)
}
Antes de aplicar a função para o caso geral, sempre é importante testar e conferir o resultado em um caso menor. Podemos verificar o resultado da média ponderada para o primeiro aluno
sum(notas[1, provas] * c(3, 3, 4))/10
1] 4 [
e testar a função para o mesmo caso
med.pond(notas = notas[1, provas], pesos = c(3, 3, 4))
1] 4 [
Como o resultado é o mesmo podemos aplicar a função para todas as linhas
através do for()
## Cria uma nova coluna para a média ponderada
$MP <- 0
notas## A estrutura de repetição fica
for(i in 1:nlinhas){
$MP[i] <- med.pond(notas = notas[i, provas], pesos = c(3, 3, 4))
notas
}
## Confere
head(notas)
nome prova1 prova2 prova3 media media2 media3 CV MP1 Aluno_1 8 4 1 4.333333 4.333333 4.333333 0.8104349 4.0
2 Aluno_2 2 7 6 5.000000 5.000000 5.000000 0.5291503 5.1
3 Aluno_3 9 2 4 5.000000 5.000000 5.000000 0.7211103 4.9
4 Aluno_4 1 10 9 6.666667 6.666667 6.666667 0.7399324 6.9
5 Aluno_5 7 6 8 7.000000 7.000000 7.000000 0.1428571 7.1
6 Aluno_6 10 0 3 4.333333 4.333333 4.333333 1.1842157 4.2
NOTA: uma função para calcular a média ponderada já existe
implementada no R. Veja ?weighted.mean()
e confira os resultados
obtidos aqui.
Repare na construção da função acima: agora usamos dois argumentos,
notas
e pesos
, pois precisamos dos dois vetores para calcular a média
ponderada. Repare também que ambos argumentos não possuem um valor
padrão. Poderíamos, por exemplo, assumir valores padrão para os pesos, e
deixar para que o usuário mude apenas se achar necessário.
## Atribuindo pesos iguais para as provas como padrão
<- function(notas, pesos = rep(1, length(notas))){
med.pond ## Multiplica o valor de cada prova pelo seu peso
<- notas * pesos
pond ## Calcula o valor total dos pesos
<- sum(pesos)
peso.total ## Calcula a soma da ponderação
<- sum(pond)
sum.pond ## Finalmente calcula a média ponderada
<- sum.pond/peso.total
saida return(saida)
}
Repare que neste caso, como os pesos são iguais, a chamada da função sem
alterar o argumento pesos
gera o mesmo resultado do cálculo da média
comum.
## Cria uma nova coluna para a média ponderada para comparação
$MP2 <- 0
notas## A estrutura de repetição fica
for(i in 1:nlinhas){
$MP2[i] <- med.pond(notas = notas[i, provas])
notas
}
## Confere
head(notas)
nome prova1 prova2 prova3 media media2 media3 CV MP1 Aluno_1 8 4 1 4.333333 4.333333 4.333333 0.8104349 4.0
2 Aluno_2 2 7 6 5.000000 5.000000 5.000000 0.5291503 5.1
3 Aluno_3 9 2 4 5.000000 5.000000 5.000000 0.7211103 4.9
4 Aluno_4 1 10 9 6.666667 6.666667 6.666667 0.7399324 6.9
5 Aluno_5 7 6 8 7.000000 7.000000 7.000000 0.1428571 7.1
6 Aluno_6 10 0 3 4.333333 4.333333 4.333333 1.1842157 4.2
MP21 4.333333
2 5.000000
3 5.000000
4 6.666667
5 7.000000
6 4.333333
Exercícios
- Escreva um loop for que percorre os números de 1 a 700 e imprime o cubo de cada número.
- Escreva um loop for que percorre os nomes das colunas do conjunto de dados iris e imprime cada um junto com o número de caracteres na coluna nomes entre parênteses. Example de output Sepal.Length (12). Dica: Use as seguintes funções print(), paste0() e nchar().
- Escreva um loop while que imprime o erro padrão de amostras da distribuição normal padrão (use rnorm()) e para (break) se o erro padrão obtido for maior que 1.
- Usando o comando next adapte o loop do exercício (3) para que números menores que 0.75 não sejam mostrados.
- Use um loop for para simular o lançamento de uma moeda (1 - cara, 0 - coroa) e armazene os resultados em um vetor pré-especificado.
5.2 Estrutura de seleção if()
Uma estrutura de seleção serve para executar algum comando apenas se
alguma condição (em forma de expressão condicional) seja satisfeita.
Geralmente é utilizada dentro de um for()
.
No exemplo inicial poderíamos querer imprimir um resultado caso
satisfaça determinada condição. Por exemplo, se o valor de x
for menor
ou igual a 105, então imprima um texto informando isso.
<- 100:200
x for(j in 1:10){
if(x[j] <= 105){
print("Menor ou igual a 105")
}
}1] "Menor ou igual a 105"
[1] "Menor ou igual a 105"
[1] "Menor ou igual a 105"
[1] "Menor ou igual a 105"
[1] "Menor ou igual a 105"
[1] "Menor ou igual a 105" [
Mas também podemos considerar o que aconteceria caso contrário. Por
exemplo, se o valor de x
for maior do que 105, então imprima outro
texto.
<- 100:200
x for(j in 1:10){
if(x[j] <= 105){
print("Menor ou igual a 105")
else{
} print("Maior do que 105")
}
}1] "Menor ou igual a 105"
[1] "Menor ou igual a 105"
[1] "Menor ou igual a 105"
[1] "Menor ou igual a 105"
[1] "Menor ou igual a 105"
[1] "Menor ou igual a 105"
[1] "Maior do que 105"
[1] "Maior do que 105"
[1] "Maior do que 105"
[1] "Maior do que 105" [
A sintaxe será sempre no formato:
if(<condição>){
<comandos que satisfazem a condição>
else{
} <comandos que não satisfazem a condição>
}
Como vimos acima, a especificação do else{}
não é obrigatória.
Voltando ao exemplo das notas, podemos adicionar uma coluna com a
condição do aluno: aprovado
ou reprovado
de acordo com a sua nota.
Para isso precisamos criar uma condição (nesse caso se a nota é maior do
que 7), e verificar se ela é verdadeira.
## Nova coluna para armazenar a situacao
$situacao <- NA # aqui usamos NA porque o resultado será um
notas# caracter
## Estrutura de repetição
for(i in 1:nlinhas){
## Estrutura de seleção (usando a média ponderada)
if(notas$MP[i] >= 7){
$situacao[i] <- "aprovado"
notaselse{
} $situacao[i] <- "reprovado"
notas
}
}
## Confere
head(notas)
nome prova1 prova2 prova3 media media2 media3 CV MP1 Aluno_1 8 4 1 4.333333 4.333333 4.333333 0.8104349 4.0
2 Aluno_2 2 7 6 5.000000 5.000000 5.000000 0.5291503 5.1
3 Aluno_3 9 2 4 5.000000 5.000000 5.000000 0.7211103 4.9
4 Aluno_4 1 10 9 6.666667 6.666667 6.666667 0.7399324 6.9
5 Aluno_5 7 6 8 7.000000 7.000000 7.000000 0.1428571 7.1
6 Aluno_6 10 0 3 4.333333 4.333333 4.333333 1.1842157 4.2
MP2 situacao1 4.333333 reprovado
2 5.000000 reprovado
3 5.000000 reprovado
4 6.666667 reprovado
5 7.000000 aprovado
6 4.333333 reprovado
5.3 O modo R: vetorização
As funções vetorizadas do R, além de facilitar e resumir a execução de tarefas repetitivas, também são computacionalmente mais eficientes, i.e. o tempo de execução das rotinas é menor.
Já vimos que a regra da reciclagem é uma forma de vetorizar cálculos no R. Os cálculos feitos com funções vetorizadas (ou usando a regra de reciclagem) são muito mais eficientes (e preferíveis) no R. Por exemplo, podemos criar um vetor muito grande de números e querer calcular o quadrado de cada número. Se pensássemos em usar uma estrutura de repetição, o cálculo seria o seguinte:
## Vetor com uma sequência de 1 a 1.000.000
<- 1:1000000
x ## Calcula o quadrado de cada número da sequência em x usando for()
<- numeric(length(x)) # vetor de mesmo comprimento de x que vai
y1 # receber os resultados
for(i in 1:length(x)){
<- x[i]^2
y1[i] }
Mas, da forma vetorial e usando a regra da reciclagem, a mesma operação pode ser feita apenas com
## Calcula o quadrado de cada número da sequência em x usando a regra da
## reciclagem
<- x^2
y2 ## Confere os resultados
identical(y1, y2)
1] TRUE [
Note que os resultados são exatamente iguais, mas então porque se
prefere o formato vetorial? Primeiro porque é muito mais simples de
escrever, e segundo (e principalmente) porque a forma vetorizada é
muito mais eficiente computacionalmente. A eficiência computacional
pode ser medida de várias formas (alocação de memória, tempo de
execução, etc), mas apenas para comparação, vamos medir o tempo de
execução destas mesmas operações usando o for()
e usando a regra da
reciclagem.
## Tempo de execução usando for()
<- numeric(length(x))
y1 <- system.time(
st1 for(i in 1:length(x)){
<- x[i]^2
y1[i]
}
)
st1
user system elapsed 0.085 0.000 0.085
## Tempo de execução usando a regra da reciclagem
<- system.time(
st2 <- x^2
y2
)
st2
user system elapsed 0.002 0.001 0.002
Olhando o resultado de elapsed
, que é o tempo total de execução de uma
função medido por system.time()
, notamos que usando a regra da
reciclagem, o cálculo é aproximadamente
\(0.085/0.002 = 42.5\) vezes mais rápido.
Claramente esse é só um exemplo de um cálculo muito simples. Mas em
situações mais complexas, a diferença entre o tempo de execução das duas
formas pode ser muito maior.
Existem duas formas básicas de tornar um loop for
no R mais rápido:
- Faça o máximo possível fora do loop.
- Crie um objeto com tamanho suficiente para armazenar todos os resultados do loop antes de executá-lo.
Veja este exemplo:
## Vetor com uma sequência de 1 a 1.000.000
<- 1:1000000
x
## Cria um objeto de armazenamento com o mesmo tamanho do resultado
<- system.time({
st1 <- numeric(length(x))
out for(i in 1:length(x)){
<- x[i]^2
out[i]
}
})
st1
user system elapsed 0.073 0.000 0.073
## Cria um objeto de tamanho "zero" e vai "crescendo" esse vetor
<- system.time({
st2 <- numeric(0)
out for(i in 1:length(x)){
<- x[i]^2
out[i]
}
})
st2
user system elapsed 0.281 0.020 0.301
Essa simples diferença gera um aumento de tempo de execução da segunda
forma em aproximadamente
0.301/0.073 = 4.12 vezes. Isso acontece
porque, da segunda forma, o vetor out
precisa ter seu tamanho
aumentado com um elemento a cada iteração. Para fazer isso, o R precisa
encontrar um espaço na memória que possa armazenar o objeto maior. É
necessário então copiar o vetor de saída e apagar sua versão anterior
antes de seguir para o próximo loop. Ao final, foi necessário escrever
um milhão de vezes na memória do computador.
Já no primeiro caso, o tamanho do vetor de armazenamento nunca muda, e a memória para esse vetor já foi alocada previamente, de uma única vez.
Voltando ao exemplo das notas, por exemplo, o cálculo da média simples
poderia ser feito diretamente com a função apply()
$media.apply <- apply(X = notas[, provas], MARGIN = 1, FUN = mean)
notashead(notas)
nome prova1 prova2 prova3 media media2 media3 CV MP1 Aluno_1 8 4 1 4.333333 4.333333 4.333333 0.8104349 4.0
2 Aluno_2 2 7 6 5.000000 5.000000 5.000000 0.5291503 5.1
3 Aluno_3 9 2 4 5.000000 5.000000 5.000000 0.7211103 4.9
4 Aluno_4 1 10 9 6.666667 6.666667 6.666667 0.7399324 6.9
5 Aluno_5 7 6 8 7.000000 7.000000 7.000000 0.1428571 7.1
6 Aluno_6 10 0 3 4.333333 4.333333 4.333333 1.1842157 4.2
MP2 situacao media.apply1 4.333333 reprovado 4.333333
2 5.000000 reprovado 5.000000
3 5.000000 reprovado 5.000000
4 6.666667 reprovado 6.666667
5 7.000000 aprovado 7.000000
6 4.333333 reprovado 4.333333
As médias ponderadas poderiam ser calculadas da mesma forma, e usando a função que criamos anteriormente
$MP.apply <- apply(X = notas[, provas], MARGIN = 1, FUN = med.pond)
notashead(notas)
nome prova1 prova2 prova3 media media2 media3 CV MP1 Aluno_1 8 4 1 4.333333 4.333333 4.333333 0.8104349 4.0
2 Aluno_2 2 7 6 5.000000 5.000000 5.000000 0.5291503 5.1
3 Aluno_3 9 2 4 5.000000 5.000000 5.000000 0.7211103 4.9
4 Aluno_4 1 10 9 6.666667 6.666667 6.666667 0.7399324 6.9
5 Aluno_5 7 6 8 7.000000 7.000000 7.000000 0.1428571 7.1
6 Aluno_6 10 0 3 4.333333 4.333333 4.333333 1.1842157 4.2
MP2 situacao media.apply MP.apply1 4.333333 reprovado 4.333333 4.333333
2 5.000000 reprovado 5.000000 5.000000
3 5.000000 reprovado 5.000000 5.000000
4 6.666667 reprovado 6.666667 6.666667
5 7.000000 aprovado 7.000000 7.000000
6 4.333333 reprovado 4.333333 4.333333
Mas note que como temos o argumento pesos
especificado com um padrão,
devemos alterar na própria função apply()
$MP.apply <- apply(X = notas[, provas], MARGIN = 1,
notasFUN = med.pond, pesos = c(3, 3, 4))
head(notas)
nome prova1 prova2 prova3 media media2 media3 CV MP1 Aluno_1 8 4 1 4.333333 4.333333 4.333333 0.8104349 4.0
2 Aluno_2 2 7 6 5.000000 5.000000 5.000000 0.5291503 5.1
3 Aluno_3 9 2 4 5.000000 5.000000 5.000000 0.7211103 4.9
4 Aluno_4 1 10 9 6.666667 6.666667 6.666667 0.7399324 6.9
5 Aluno_5 7 6 8 7.000000 7.000000 7.000000 0.1428571 7.1
6 Aluno_6 10 0 3 4.333333 4.333333 4.333333 1.1842157 4.2
MP2 situacao media.apply MP.apply1 4.333333 reprovado 4.333333 4.0
2 5.000000 reprovado 5.000000 5.1
3 5.000000 reprovado 5.000000 4.9
4 6.666667 reprovado 6.666667 6.9
5 7.000000 aprovado 7.000000 7.1
6 4.333333 reprovado 4.333333 4.2
NOTA: veja que isso é possível devido à presença do argumento ...
na
função apply()
, que permite passar argumentos de outras funções
dentro dela.
Também poderíamos usar a função weighted.mean()
implementada no R
$MP2.apply <- apply(X = notas[, provas], MARGIN = 1,
notasFUN = weighted.mean, w = c(3, 3, 4))
head(notas)
nome prova1 prova2 prova3 media media2 media3 CV MP1 Aluno_1 8 4 1 4.333333 4.333333 4.333333 0.8104349 4.0
2 Aluno_2 2 7 6 5.000000 5.000000 5.000000 0.5291503 5.1
3 Aluno_3 9 2 4 5.000000 5.000000 5.000000 0.7211103 4.9
4 Aluno_4 1 10 9 6.666667 6.666667 6.666667 0.7399324 6.9
5 Aluno_5 7 6 8 7.000000 7.000000 7.000000 0.1428571 7.1
6 Aluno_6 10 0 3 4.333333 4.333333 4.333333 1.1842157 4.2
MP2 situacao media.apply MP.apply MP2.apply1 4.333333 reprovado 4.333333 4.0 4.0
2 5.000000 reprovado 5.000000 5.1 5.1
3 5.000000 reprovado 5.000000 4.9 4.9
4 6.666667 reprovado 6.666667 6.9 6.9
5 7.000000 aprovado 7.000000 7.1 7.1
6 4.333333 reprovado 4.333333 4.2 4.2
O Coeficiente de Variação poderia ser calculado usando nossa função
cv()
$CV.apply <- apply(X = notas[, provas], MARGIN = 1, FUN = cv)
notashead(notas)
nome prova1 prova2 prova3 media media2 media3 CV MP1 Aluno_1 8 4 1 4.333333 4.333333 4.333333 0.8104349 4.0
2 Aluno_2 2 7 6 5.000000 5.000000 5.000000 0.5291503 5.1
3 Aluno_3 9 2 4 5.000000 5.000000 5.000000 0.7211103 4.9
4 Aluno_4 1 10 9 6.666667 6.666667 6.666667 0.7399324 6.9
5 Aluno_5 7 6 8 7.000000 7.000000 7.000000 0.1428571 7.1
6 Aluno_6 10 0 3 4.333333 4.333333 4.333333 1.1842157 4.2
MP2 situacao media.apply MP.apply MP2.apply CV.apply1 4.333333 reprovado 4.333333 4.0 4.0 0.8104349
2 5.000000 reprovado 5.000000 5.1 5.1 0.5291503
3 5.000000 reprovado 5.000000 4.9 4.9 0.7211103
4 6.666667 reprovado 6.666667 6.9 6.9 0.7399324
5 7.000000 aprovado 7.000000 7.1 7.1 0.1428571
6 4.333333 reprovado 4.333333 4.2 4.2 1.1842157
Finalmente, a estrutura de repetição if()
também possui uma forma
vetorizada através da função ifelse()
. Essa função funciona da
seguinte forma:
ifelse(<condição>, <valor se verdadeiro>, <valor se falso>)
Dessa forma, a atribuição da situação dos alunos poderia ser feita da seguinte forma:
$situacao2 <- ifelse(notas$MP >= 7, "aprovado", "reprovado")
notashead(notas)
nome prova1 prova2 prova3 media media2 media3 CV MP1 Aluno_1 8 4 1 4.333333 4.333333 4.333333 0.8104349 4.0
2 Aluno_2 2 7 6 5.000000 5.000000 5.000000 0.5291503 5.1
3 Aluno_3 9 2 4 5.000000 5.000000 5.000000 0.7211103 4.9
4 Aluno_4 1 10 9 6.666667 6.666667 6.666667 0.7399324 6.9
5 Aluno_5 7 6 8 7.000000 7.000000 7.000000 0.1428571 7.1
6 Aluno_6 10 0 3 4.333333 4.333333 4.333333 1.1842157 4.2
MP2 situacao media.apply MP.apply MP2.apply CV.apply situacao21 4.333333 reprovado 4.333333 4.0 4.0 0.8104349 reprovado
2 5.000000 reprovado 5.000000 5.1 5.1 0.5291503 reprovado
3 5.000000 reprovado 5.000000 4.9 4.9 0.7211103 reprovado
4 6.666667 reprovado 6.666667 6.9 6.9 0.7399324 reprovado
5 7.000000 aprovado 7.000000 7.1 7.1 0.1428571 aprovado
6 4.333333 reprovado 4.333333 4.2 4.2 1.1842157 reprovado
Exercícios
- Faça uma função usando loop for que recebe duas matrizes de mesma dimensão e retorna a soma das matrizes. Note que é necessário verificar se as matrizes fornecidas pelo usuário podem ser somadas, caso contrário retorne uma mensagem de erro dizendo que as matrizes não podem ser somadas.
- Faça uma função usando loop for para multiplicar duas matrizes compatíveis. Note que é necessário verificar se as matrizes fornecidas pelo usuário podem ser multiplicadas, caso contrário retorne uma mensagem de erro dizendo que as matrizes não podem ser multiplicadas.
- Faça uma função para resolver sistemas lineares 2 x 2 usando o método de decomposição de Gauss. Veja esta página se você não conhece o método https://matrixcalc.org/pt/slu.html.
- Faça uma função que encontra o máximo de uma função fornecida pelo usuário em um intervalo e precisão pré-determinado pelo usuário.
- Faça uma função que resolve uma equação não-linear de um único parâmetro em um intervalo e precisão pré-determinado pelo usuário.
5.4 Outras estruturas: while e repeat
O while
executa comandos enquanto uma determinada condição permanece
verdadeira.
## Calcule a soma em 1,2,3... até que o soma seja maior do que 1000
<- 0
n <- 0
soma while(soma <= 1000){
<- n + 1
n <- soma + n
soma
}
soma1] 1035 [
O repeat
é ainda mais básico, e irá executar comandos até que você
explicitamente pare a execução com o comando break
.
## Mesmo exemplo
<- 0
n <- 0
soma repeat{
<- n + 1
n <- soma + n
soma if(soma > 1000) break
}
soma1] 1035 [
Exercícios
- Crie uma função que retorna o absoluto de um vetor de inteiros.
- Crie uma função em R que retorna o maior valor em um vetor de elementos númericos.
- Crie uma função que retorna o número de valores maiores que a média de um vetor. Você pode usar a função mean().
- Crie uma função que dado um vetor de tamanho 3 retorna os seus valores em ordem crescente e decrescente.
- Crie uma função que calcula o fatorial de um número.