Nessa aula, vamos ver alguns exemplos de como trabalhar com a
linguagem R a partir de condições, funções e loopings a serem
aplicados em um data frame. Antes de qualquer ação, vamos utilizar os
microdados do Censo
Demográfico do IBGE para a Unidade da Federação de Roraima (RR). Não
se esqueçam de usar o comando setwd()
para a pasta de
trabalho das atividades.
#setwd(choose.dir()) #coloquei como comentário, mas usem esse comando para mudar o diretório.
RR<-read.fwf("C:/Users/letho/OneDrive/PROJETO PROFESSOR/UFJF/NUDES/TREINAMENTO R/PRIMEIRO DIA/DADOS/RR/RR/Amostra_Pessoas_14.txt",
widths = c(2,5,13,8,16,1,2,3,2,1,2,2,1,3,3,2,1,1,1,1,1,1,1,1,1,1,4,1,7,7,3,3,1,7,7,7,1,7,7,7,1,1,2,2,1,1,2,1,1,1,3,3,3,1,7,7,7,1,2,1,1,1,1,1,1,1,4,5,1,1,1,1,6,6,6,1,6,9,7,9,7,9,7,10,8,9,3,1,1,1,1,1,1,6,1,7,7,7,1,1,1,2,2,2,1,2,2,2,1,3,1,1,1,2,4,1,2,2,2,2,1,2,1,1,1,1,1,3,1,2,2,2,8,9,4,5,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1),
col.names = c("V0001","V0002","V0011","V0300","V0010","V1001","V1002","V1003","V1004","V1006","V0502","V0504","V0601","V6033","V6036","V6037","V6040","V0606","V0613","V0614","V0615","V0616","V0617","V0618","V0619","V0620","V0621","V0622","V6222","V6224","V0623","V0624","V0625","V6252","V6254","V6256","V0626","V6262","V6264","V6266","V0627","V0628","V0629","V0630","V0631","V0632","V0633","V0634","V0635","V6400","V6352","V6354","V6356","V0636","V6362","V6364","V6366","V0637","V0638","V0639","V0640","V0641","V0642","V0643","V0644","V0645","V6461","V6471","V0648","V0649","V0650","V0651","V6511","V6513","V6514","V0652","V6521","V6524","V6525","V6526","V6527","V6528","V6529","V6530","V6531","V6532","V0653","V0654","V0655","V0656","V0657","V0658","V0659","V6591","V0660","V6602","V6604","V6606","V0661","V0662","V0663","V6631","V6632","V6633","V0664","V6641","V6642","V6643","V0665","V6660","V6664","V0667","V0668","V6681","V6682","V0669","V6691","V6692","V6693","V6800","V0670","V0671","V6900","V6910","V6920","V6930","V6940","V6121","V0604","V0605","V5020","V5060","V5070","V5080","V6462","V6472","V5110","V5120","V5030","V5040","V5090","V5100","V5130","M0502","M0601","M6033","M0606","M0613","M0614","M0615","M0616","M0617","M0618","M0619","M0620","M0621","M0622","M6222","M6224","M0623","M0624","M0625","M6252","M6254","M6256","M0626","M6262","M6264","M6266","M0627","M0628","M0629","M0630","M0631","M0632","M0633","M0634","M0635","M6352","M6354","M6356","M0636","M6362","M6364","M6366","M0637","M0638","M0639","M0640","M0641","M0642","M0643","M0644","M0645","M6461","M6471","M0648","M0649","M0650","M0651","M6511","M0652","M6521","M0653","M0654","M0655","M0656","M0657","M0658","M0659","M6591","M0660","M6602","M6604","M6606","M0661","M0662","M0663","M6631","M6632","M6633","M0664","M6641","M6642","M6643","M0665","M6660","M0667","M0668","M6681","M6682","M0669","M6691","M6692","M6693","M0670","M0671","M6800","M6121","M0604","M0605","M6462","M6472","V1005"))
RR$PESO<-RR$V0010/10000000000000 # transformação da variável peso, incluindo 13 casas decimais
Vamos, agora, entender como funcionam algumas propriedades de condições, loopings e funções.
As condições são sintaxes de verificação de determinações feitas pelo
usuário, buscando determinada ação como resultado. Parece complicado,
mas pensemos nos dados do Censo Demográfico de 2010: eles são todos
codificados. Podemos criar tabelas adicionais, tendo como chave primária
o código e como campo adicional a descrição para, depois disso, aplicar
a função merge()
. Outra alternativa, talvez mais simples
quando temos poucas categorias, é utilizar funções como
if()
, else()
ou ifelse()
.
Vamos para um exemplo, digamos que em um determinado momento de uma programação, um objeto possui um determinado valor e, caso supere um determinado limite, queremos que uma série de comandos seja executada.
a<-55
if(a>50){
print("Acima de 50%")
a<-a-20
a
}
## [1] "Acima de 50%"
## [1] 35
Vejam que, como o objeto possui valor superior a 50 - ou seja, atende
a condição dentro da função if()
- o que vem entre as
chaves ({}
) é executado. Caso o objeto não atendesse a
condição, nada aconteceria. Veja também que, entre as chaves, vários
comandos podem ser exectudados, caso a condição seja atendida.
a<-49
if(a>50){
print("Acima de 50%")
a<-a-20
a
}
Vejam que nada acontece. Nesse caso, podemos usar um comando auxiliar
else
para a execução caso a condição não seja atendida.
a<-49
if(a>50){
print("Acima de 50%")
a<-a-20
a
} else {
print("Abaixo de 50%")
a<-a+20
a
}
## [1] "Abaixo de 50%"
## [1] 69
Atenção: Os comandos if()
e
else
funcionam para programação de funções quando um objeto
atende a determinadas condições. Entretanto, eles não testam condições
para cada celula de um vetor, como é prática em tratamento de dados.
Nesse caso, usa-se o comando ifelse()
.
Digamos que queremos criar um campo com o nome
DV1006. A variável V1006 corresponde a
Situação do Domicílio, se ele está em ambiente rural ou
urbano. Consultando a documentação, podemos utilizar a função
ifelse()
.
RR$DV1006<-ifelse(RR$V1006==1,"Urbano","Rural")
xtabs(RR$PESO ~ RR$DV1006)
## RR$DV1006
## Rural Urbano
## 104587 345892
sitdom<-as.data.frame(xtabs(RR$PESO ~ RR$DV1006))
sitdom$perc<-100*sitdom$Freq/sum(sitdom$Freq) #daqui dá para avaliar o grau de urbanização.
sitdom
## RR.DV1006 Freq perc
## 1 Rural 104587 23.21683
## 2 Urbano 345892 76.78317
Observação: Não é recomendado utilizar qualquer
alteração por meio do script se os valores da tabela associada
mudam com o tempo. Por exemplo, você pode querer vincular uma tabela de
serviços prestados por um órgão público ao nome dos órgãos. Se há uma
reforma administrativa, você teria que mudar a programação. O
recomendado é usar uma outra tabela associada que, caso sofra alteração,
você podera alterar a tabela externa que será lida automaticamente -
inserida anteriormente com o comando merge()
, por exemplo -
, sem mudar a programação.
É possível trabalhar com as funções de condição com alguns operadores espaciais. Abaixo uma tabela com suas respectivas descrições.
Símbolo | Descrição |
---|---|
! | Lógico de negação |
& | Lógico E |
| | Lógico OU |
&& | Lógico E, se a primeira é falta o R não testa a segunda |
|| | Lógico OU, se a primeira for TRUE não se testa a segunda |
== | Igualdade |
!= | Diferente de |
> | Maior que |
>= | Maior ou igual que |
< | Menor que |
<= | Menor ou igual que |
Observação: && e || são operadores que funcionam para testes de valores isolados, tal como if() e else, mas não operam testes de vários valores ao mesmo tempo, como em vetores.
Ainda no nosso exemplo do Censo Demográfico, digamos que nosso objetivo seja analisar as mulheres que declararam residir no ambiente rural no ano de 2010. Nesse caso, consultando a documentação teríamos:
filtro<-subset(RR,RR$V1006==2 & RR$V0601==2)
nrow(filtro) # número de linhas na base de dados.
## [1] 9862
sum(filtro$PESO) # número de mulheres na população de Roraima que vivem em ambiente rural.
## [1] 47242.63
Existem dois comandos para a execução de loopings:
while()
e for()
. Abaixo usaremos alguns
exemplos.
for()
A função for()
é aplicável quando se tem uma lista de
elementos ou valores e queremos que, para cada um destes, uma série de
comandos seja executada. Para tanto, basta substituir dentro da
programação entre chaves ({}
) o nome do objeto da função.
Para ficar mais claro, utilizamos abaixo a função com o objeto
i, que ira trocar o valor a cada execução do comando,
entre 1 e 10.
A função paste()
irá retornar um tipo
character
, colando o que estiver disponível como argumento.
a estratégia foi colar o valor i - que assumirá valores
de 1 a 10, mudando a cada repetição -, um texto explicativo e o valor de
i ao quadrado. Note que a função paste()
cola os argumentos com um caracter de espaço entre eles. Caso não queira
esse caracter, a função a ser utilizada é paste0
.
for (i in 1:10){
print(paste(i,"é menor ou igual a",i^2))
}
## [1] "1 é menor ou igual a 1"
## [1] "2 é menor ou igual a 4"
## [1] "3 é menor ou igual a 9"
## [1] "4 é menor ou igual a 16"
## [1] "5 é menor ou igual a 25"
## [1] "6 é menor ou igual a 36"
## [1] "7 é menor ou igual a 49"
## [1] "8 é menor ou igual a 64"
## [1] "9 é menor ou igual a 81"
## [1] "10 é menor ou igual a 100"
Observação: o comando for()
será muito
exigente em relação a memória do seu equipamento. Lembre-se de ser
parcimonioso com os valores possíveis de i.
Para mostrar como o comando for()
opera em outras
situações, vejamos mais um exemplo.Vamos criar um
data.frame
de alunos, com suas respectivas notas e
turmas.
set.seed(123)
d<-data.frame(aluno=c(1001:1100),
turma=rep(c("A","B","C","D"),25),
nota=rnorm(n=100,mean=60,sd=15)
)
O desafio agora é estimar a média de notas por turma. Para estimar a
média de todos os alunos podemos executar o comando
mean(d$nota)
. Contudo, queremos criar uma outra tabela com
o nome da turma e sua correspondente média. Abaixo temos a
resolução.
notas<-data.frame() #criamos um objeto onde as notas estarão armazenadas.
lista<-c("A","B","C","D") # criamos um objeto com nome qualquer, mas que será um vetor com o nome das turmas, tal como apresentado no campo d$turma.
lista
## [1] "A" "B" "C" "D"
Uma forma alternativa de se conseguir os valores únicos de uma coluna
para compor uma listagem é o uso do comando unique()
.
lista<-unique(d$turma) # forma alternativa de adquirir os valores únicos presentes no campo d$turma
lista
## [1] "A" "B" "C" "D"
Agora vamos para o comando for()
. Alterarei o comumente
usado i por r para exemplificar que o
nome do objeto temporário pode ser qualquer um, desde que não haja
conflito com outros objetos da programação. Nosso objetivo é adicionar
linhas na tabela notas com as médias por turma.
for(r in lista){
x<-data.frame(turma=r,
nota.media=mean(d$nota[d$turma==r]))
notas<-rbind(notas,x)
}
notas
## turma nota.media
## 1 A 60.56203
## 2 B 61.54766
## 3 C 62.75286
## 4 D 60.56181
Outra alternativa seria utilizar o comando subset()
.
rm(notas) # removendo, pois já foi criado
notas<-data.frame()
for(r in lista){
t<-subset(d,d$turma==r) # criamos um objeto t que, a cada loop, receberá um novo filtro com base no valor de "r".
x<-data.frame(turma=r,
nota.media=mean(t$nota))
notas<-rbind(notas,x)
}
notas
## turma nota.media
## 1 A 60.56203
## 2 B 61.54766
## 3 C 62.75286
## 4 D 60.56181
while()
A função while()
serve para executar uma série de
comandos entre as chaves ({}
) enquanto uma determinada
condição ainda for satisfeita. Abaixo criamos um objeto com valor zero.
Enquanto o objeto possuir um valor inferior a 100, o script irá executar
o comando print()
, expondo o valor do objeto e adicionar 10
unidades ao objeto. Quando a condição deixar de ser satisfeita, o
comando para.
a<-0
while(a<100){
print(a)
a<-a+10
}
## [1] 0
## [1] 10
## [1] 20
## [1] 30
## [1] 40
## [1] 50
## [1] 60
## [1] 70
## [1] 80
## [1] 90
Observe que o comando print()
é executado antes da soma.
Lembrem-se sempre que a sequencia é importante para a programação.
Atenção: Se a condição nunca deixar de ser satisfeita, o comando não irá parar de executar a programação, exceto com interrupção do usuário.
Vamos trabalhar com um problema conhecido. Sabemos que um dado tem
seis lados, o que corresponderia a um vetor 1:6
com iguais
probabilidades de ter a face voltada para cima, caso o dado não seja
viciado. Digamos que temos dois dados e queremos que a soma deles seja
igual a sete. Para simular o dado, iremos utilizar o
comando sample()
, que irá selecionar aleatoriamente um
valor.
# sample(universo, quantidade da amostra)
dado1<-sample(1:6,1)
dado2<-sample(1:6,1)
dado1+dado2
## [1] 12
Vemos que não obtivemos exito em nossa primeira jogada. Mas e se repetirmos a ação até que o valor seja igual a sete?
set.seed(11)
t<-1
soma<-0
while(soma!=7){
dado1<-sample(1:6,1)
dado2<-sample(1:6,1)
soma<-dado1+dado2
print(paste0("Na ",t,"ª tentativa, a soma dos dados foi igual a ",soma))
t<-t+1
}
## [1] "Na 1ª tentativa, a soma dos dados foi igual a 4"
## [1] "Na 2ª tentativa, a soma dos dados foi igual a 2"
## [1] "Na 3ª tentativa, a soma dos dados foi igual a 9"
## [1] "Na 4ª tentativa, a soma dos dados foi igual a 10"
## [1] "Na 5ª tentativa, a soma dos dados foi igual a 11"
## [1] "Na 6ª tentativa, a soma dos dados foi igual a 12"
## [1] "Na 7ª tentativa, a soma dos dados foi igual a 11"
## [1] "Na 8ª tentativa, a soma dos dados foi igual a 8"
## [1] "Na 9ª tentativa, a soma dos dados foi igual a 8"
## [1] "Na 10ª tentativa, a soma dos dados foi igual a 3"
## [1] "Na 11ª tentativa, a soma dos dados foi igual a 12"
## [1] "Na 12ª tentativa, a soma dos dados foi igual a 6"
## [1] "Na 13ª tentativa, a soma dos dados foi igual a 5"
## [1] "Na 14ª tentativa, a soma dos dados foi igual a 9"
## [1] "Na 15ª tentativa, a soma dos dados foi igual a 5"
## [1] "Na 16ª tentativa, a soma dos dados foi igual a 4"
## [1] "Na 17ª tentativa, a soma dos dados foi igual a 5"
## [1] "Na 18ª tentativa, a soma dos dados foi igual a 5"
## [1] "Na 19ª tentativa, a soma dos dados foi igual a 5"
## [1] "Na 20ª tentativa, a soma dos dados foi igual a 9"
## [1] "Na 21ª tentativa, a soma dos dados foi igual a 6"
## [1] "Na 22ª tentativa, a soma dos dados foi igual a 6"
## [1] "Na 23ª tentativa, a soma dos dados foi igual a 9"
## [1] "Na 24ª tentativa, a soma dos dados foi igual a 9"
## [1] "Na 25ª tentativa, a soma dos dados foi igual a 7"
No nosso exemplo, apenas na vigésima quinta tentativa o valor da soma dos dados foi igual a sete.
Funções são ferramentes muito úteis para o trabalho em R. Em geral,
trabalhamos com funções presentes em pacotes já programados por outros
autores. Contudo, podemos construir uma função para evitar códigos
extensos e trabalho repetitivo. As funções são objetos do tipo
function()
e são construídos a partir de
argumentos e declarações.
function(#argumentos
){
#declarações
}
## function ()
## {
## }
Vamos criar um exemplo simples, no qual a função executa uma operação aritmética simples.
expoente<-function(a,b){
return(a^b)
}
expoente(a=2,b=4)
## [1] 16
expoente(3,3)
## [1] 27
Nesse caso, a é a base e b é o
expoente. A declaração return()
mostra o resultado, da
mesma forma que o argumento print()
visto anteriormente.
Vamos criar uma função um pouco mais complexa. Digamos que eu queria uma
função que role dois dados fictícios um número determinado de vezes.
Caso eu acerte, quero que seja indicado que ganhei, caso contrário, se
perdi.
dados<-function(n="número de lances",x="valor em que se está apostando"){
resultado_final<-0
for (i in 1:n){
dados<-sample(1:6,2,replace = TRUE)
soma<-sum(dados)
if(soma==x){
resultado<-"acertou"
resultado_final<-resultado_final+1
} else {
resultado<-"errou"
resultado_final<-resultado_final+0
}
print(paste0("Na ",i,"ª tentativa o resultado deu ",soma,", você ",resultado,"!"))
}
if(resultado_final>0){return("Parabéns!")} else {"Tente outra vez!"}
}
Parece complicado, mas não há nada que já não tenhamos utilizado aqui. Vamos buscar executar alguns exemplos!
dados(n=10,x=5)
## [1] "Na 1ª tentativa o resultado deu 10, você errou!"
## [1] "Na 2ª tentativa o resultado deu 7, você errou!"
## [1] "Na 3ª tentativa o resultado deu 2, você errou!"
## [1] "Na 4ª tentativa o resultado deu 7, você errou!"
## [1] "Na 5ª tentativa o resultado deu 10, você errou!"
## [1] "Na 6ª tentativa o resultado deu 11, você errou!"
## [1] "Na 7ª tentativa o resultado deu 12, você errou!"
## [1] "Na 8ª tentativa o resultado deu 11, você errou!"
## [1] "Na 9ª tentativa o resultado deu 7, você errou!"
## [1] "Na 10ª tentativa o resultado deu 7, você errou!"
## [1] "Tente outra vez!"
dados(x=7,n=5)
## [1] "Na 1ª tentativa o resultado deu 9, você errou!"
## [1] "Na 2ª tentativa o resultado deu 6, você errou!"
## [1] "Na 3ª tentativa o resultado deu 7, você acertou!"
## [1] "Na 4ª tentativa o resultado deu 7, você acertou!"
## [1] "Na 5ª tentativa o resultado deu 7, você acertou!"
## [1] "Parabéns!"
dados(10,8)
## [1] "Na 1ª tentativa o resultado deu 8, você acertou!"
## [1] "Na 2ª tentativa o resultado deu 10, você errou!"
## [1] "Na 3ª tentativa o resultado deu 2, você errou!"
## [1] "Na 4ª tentativa o resultado deu 3, você errou!"
## [1] "Na 5ª tentativa o resultado deu 7, você errou!"
## [1] "Na 6ª tentativa o resultado deu 9, você errou!"
## [1] "Na 7ª tentativa o resultado deu 10, você errou!"
## [1] "Na 8ª tentativa o resultado deu 2, você errou!"
## [1] "Na 9ª tentativa o resultado deu 11, você errou!"
## [1] "Na 10ª tentativa o resultado deu 3, você errou!"
## [1] "Parabéns!"
Poderíamos tornar ainda mais complexa nossa função, colocando alertar ou impedir um número muito grande de tentativas. Nas próximas aulas vamos rever operações aritméticas e, depois disso, construção de gráficos.