Início

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.

Condiçõ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.


Operadores Lógicos

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

Looping

Existem dois comandos para a execução de loopings: while() e for(). Abaixo usaremos alguns exemplos.

Função 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

Função 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

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.