4 Noções básicas de programação em R
Objetivos deste capítulo:
- Apresentar uma breve introdução aos principais comandos usados em programação
4.1 Sequências de scaping
Há alguns caracteres especiais que não podem ser usados diretamente numa string, pois possuem um significado especial. As aspas são um caso. Assim, por exemplo:
variavel <- 'moinho d'agua' retorna erro. Para poder utilizar as aspas, temos de dizer ao programa para “escapar”. Isto é feito de modo geral com o caractere \. Assim, para funcionar, nosso exemplo fica: variavel <- 'moinho d\'agua'.
No caso de aspas simples ' ou duplas ", é possível escapar estes caracteres colocando um dentro do outro. Por exemplo: variavel <- "moinho d'agua" ou variavel <- 'O conto "Trio em Lá Menor" de Machado de Assis foi publicado em 1896.'.
Outros caracteres que levam escape são:
4.1.1 Comentando o código
Nas linguagens de programação é possível acrescentar comentários para orientar os humanos e que não serão lidos pelo computador.
Cada linguagem tem o seu próprio padrão.
No R, assim como em muitas linguagens de programação, os comentários no código são feito com a tralha # ou hashtag, jogo da velha, etc.
Tudo que vier depois deste símbolo é então ignorado.
print("Olá mundo!")
## [1] "Olá mundo!"
print("Olá mundo R!") # comentário que o computador ignora
## [1] "Olá mundo R!"Se retirarmos o símbolo # temos então mensagem de erro.
print("Olá mundo! Olá R") comentários que dará erro
## Error: <text>:1:28: unexpected symbol
## 1: print("Olá mundo! Olá R") comentários
## ^4.2 Variável e atribuição
Em programação, no processo de automatização de tarefas, o uso de variáveis é essencial. Ele permite que reutilizemos as coisas, através de nomes mais simplificados. Normamente, usa-se o símbolo de igual =para atribuir algo a uma variável, no seguinte modo:
Noma_da_variavel = valores
O R também usa este símbolo, mas também usa outro que lhe é prório, o <- que lembra uma seta.
nome1 = "Fulano"
nome2 <- "Ciclano"
message("Um nome é ", nome1, ", o outro é ", nome2)
## Um nome é Fulano, o outro é CiclanoPode-se usar na direção contrária também
"Beltrano" -> nome3
nome3
## [1] "Beltrano"Há algumas regras para criar variáveis. Não conter espaço no nome é uma delas. Ao invés disso, pode-se usar o underscore (Ex.: bla_ble) ou ponto (bla.ble).
Há alguns caracteres especiais que não podem ser usados diretamente numa string, pois possuem um significado especial. As aspas são um caso. Assim, por exemplo:
variavel <- 'moinho d'agua' retorna erro. Para poder utilizar as aspas, temos de dizer ao programa para “escapar”. Isto é feito de modo geral com o caractere \. Assim, para funcionar, nosso exemplo fica: variavel <- 'moinho d\'agua'.
No caso de aspas simples ' ou duplas ", é possível escapar estes caracteres colocando um dentro do outro. Por exemplo: variavel <- "moinho d'agua" ou variavel <- 'O conto "Trio em Lá Menor" de Machado de Assis'.
4.3 Funções no R
Identificamos as funções no R por elas sempre virem acompanhados dos parênteses, como function().
Criar nossas próprias funções é útil para evitar retrabalho. Possuem a seguinte sintaxe:
# criando uma função no R
nome_da_funcao <- function(argumento_1, argumento_2, ...) {
fazendo_algo_com(argumento_1)
fazendo_algo_mais_com(argumento_2)
}
# rodando a função
nome_da_funcao(argumento_1,sargumento_2)E com um exemplo:
minhaFuncao <- function(entrada){
entrada + 10
}
minhaFuncao(2)
## [1] 12
minhaFuncao(6)
## [1] 16
minhaFuncao2 <- function(entrada1, entrada2){
entrada1 + entrada2
}
minhaFuncao2(2,4)
## [1] 6
minhaFuncao2(1,7)
## [1] 8arg_1, arg_2 são os parâmetros de entrada na função, que serão processados. Podemos ver quais argumentos são requeridos por determinada função através do comando args() (que por sua vez, também é uma função).
args(mean)
## function (x, ...)
## NULL
args(median)
## function (x, na.rm = FALSE, ...)
## NULLAo chamar uma função, passa-se argumentos para esta processar e nos retornar um determinado resultado. No R, repassamos argumentos 1) pela ordem apresentado em args(), ou 2) indicando qual valor para qual argumento. Nesta segunda opção, podemos enviar argumentos fora de ordem.
Ao criar nossas próprias funções, os argumentos usados na entrada também podem conter valores padrão, caso a informação não lhe seja repassada à função.
Em um exemplo simples de função:
x <- function(){
print('Olá Mundo')
}
x()
## [1] "Olá Mundo"Ou um outro exemplo, com a função tendo argumentos de entrada:
# Criando função com valores padrão:
minhafuncao <- function(a = 2, b = 3) {
resultado <- a + b
print(resultado)
}
# chamando a função sem nenhum argumento.
minhafuncao()
## [1] 5
# chamando a função repassando argumentos.
minhafuncao(10,4)
## [1] 14
# chamando a função repassando parte dos argumentos.
minhafuncao(,4)
## [1] 6Geralmente, mas não sempre, como fazem transformações, funções são nomeadas com verbos, como “filtrar”, “mutar”, “cortar”, , etc. Isso nos ajuda a compreender mais intuitivamente do que se trata a função.
Quanto aos tipos de argumentos, esses podem ser 1) os dados a serem computados, ou 2) detalhes dos argumentos, especificando melhor um modo específico/diferente do padrão para computar estes dados. Por exemplo, ao observarmos os argumentos da função cor(), de correlation/correlação:
args(cor)
## function (x, y = NULL, use = "everything", method = c("pearson",
## "kendall", "spearman"))
## NULL- x e y: indicam os dados que entrarão na função. De modo geral - mas nem sempre! - os dados aparecem como primeiro argumento das funções. Este é o padrão sobretudo nas funções mais recentes do R, mas vamos encontrar algumas funções onde isso não é verdade, como na função grep.
method = c("pearson", "kendall", "spearman")mostram os argumentos possíveis em “method”, no caso desta função, especificando o tipo de correlação que queremos. Para especificarmos então qual destas usar, digamos “spearman”, o argumento ficariamethod = "spearman".
4.4 Condicionais: se/então, If/else
- Se uma condição, então faça algo.
- Se outra condição, então faça outra coisa.
else: Se nenhuma das condições anteriores for satisfeita, então faça o seguinte.
Em sua versão mais simples
if (condição) {
fazer_algo()
}Se certa condição for satisfeita, for verdadeira, então algo especificado será feito. Se certa condição não for satisfeita, for falsa, então nada será feito.
Perceba que nossa função apenas retorna algo se o argumento de entrada for maior que 5. Caso contrário - como foi com o valor 3 - ela nada faz.
if(3 > 5){
print("X é maior que 5")
}
if(14 > 5){
print("X é maior que 5")
}
## [1] "X é maior que 5"4.4.1 Else
Uma versão mais elaborada da condicional envolve a condição else
if (condição) {
fazer_algo()
} else {
fazer_outra_coisa()
}Se certa condição for satisfeita, for verdadeira, então algo especificado - a função fazer_algo() - será realizada. Se certa condição não for satisfeita, for falsa, então outra coisa será feita. Ex.:
minhafuncao <- function(arg1){
if(arg1 > 5){
message(arg1, " é maior que 5")
} else {
message(arg1, ' não é maior que 5')
}
}
minhafuncao(3)
## 3 não é maior que 5
minhafuncao(13)
## 13 é maior que 54.4.2 else if
Podemos colocar mais condições intermediárias, quantas quisermos, com else if
comes <- function(arg1){
if (arg1 == "laranja"){
print("Prefiro tamarindo")
} else if (arg1 == "rucula"){
print("bleaaaargh")
} else if (arg1 == "sanduiche"){
print("Com suco de tamarindo!")
} else {
print("Só sei com laranjas")
}
}
# chamando a função acima
comes("laranja")
## [1] "Prefiro tamarindo"
comes("rucula")
## [1] "bleaaaargh"
comes("sanduiche")
## [1] "Com suco de tamarindo!"
comes("abacaxi")
## [1] "Só sei com laranjas"
comes("morango")
## [1] "Só sei com laranjas"Combinando função e If/Else
verifica <- function(arg_entrada1, arg_entrada2){
if (arg_entrada1 > arg_entrada2) {
message(arg_entrada1, ' é maior que ', arg_entrada2)
} else {
message(arg_entrada1, ' não é maior que ', arg_entrada2)
}
}Chamando a função
verifica(1,5)
## 1 não é maior que 5
verifica(7,2)
## 7 é maior que 2Há ainda uma versão compacta de condicionais com a função ifelse(), e que segue a mesma lógica:
ifelse(condição, se TRUE faça X, Se FALSE faça Y)
a <- c(5, 6, 3, 9, 7)
ifelse(a > 5 ,"maior","menor")
## [1] "menor" "maior" "menor" "maior" "maior"4.5 Operadores
Usamos operadores para realizar transformações ou comparações entre valores ou variáveis (que por sua vez, contém valores).
4.5.1 Operadores de atribuição (assignment)
Os operadores de atribuição são aqueles que vimos na sessão “variável”, que são =, <-, <<-, -> e ->>.
4.5.2 Operadores Aritiméticos
| Operador | Descrição |
|---|---|
| + | adição |
| - | subtração |
| * | multiplicação |
| / | divisão |
| ^ ou ** | exponencial |
| x %% y | modulus: ao dividir x por y, %% retorna o resto |
5+7
## [1] 12
2-1
## [1] 1
4*2 # 4 vezes 2
## [1] 8
15/3 # 15 dividido por 3
## [1] 5
2^3 # dois elevado a 3
## [1] 8
3**2 # 3 elevado a 2
## [1] 9Como no operador %% nos dá a sobra da divisão (relembrando, os outros elementos da divisão são dividendo, divisor, quociente ou produto), a operação x %% y == 0 nos diz se há ou não resto, e portando, diz se x é divisível por y.
10 %% 3
## [1] 1
10 %% 5
## [1] 0
# De 1 a 10, quais são múltiplos de 2? (retorna lógicos)
1:10 %% 2 == 0
## [1] FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE
# múltiplos de 2 até 10
(1:10)[1:10 %% 2 == 0]
## [1] 2 4 6 8 10
# múltiplos de 3 até 15
(1:15)[1:15 %% 3 == 0]
## [1] 3 6 9 12 15Há ainda o operador %/%, utilizado em divisão integral.
4.5.3 Operadores relacionais
| Operador | Descrição |
|---|---|
| < | menor que |
| <= | menor ou igual a |
| > | maior que |
| >= | maior ou igual que |
| == | exatamente igual a |
| != | diferente de |
5>6
## [1] FALSE
7<=6
## [1] FALSE
variavel <- "teste"
variavel == "abacate"
## [1] FALSE
variavel != "TESTE"
## [1] TRUE4.5.4 Operadores booleanos
| E | OU | NÃO | |
|---|---|---|---|
| AND | OR | NOT | |
| Símbolos | & | | | ! |
| No R também temos | && | || | ! |
| Operador | Descrição |
|---|---|
| != | não igual a |
| !x | não x |
| x | y | x ou y |
| x & y | x E y |
| isTRUE(x) | teste se X é TRUE |
https://stat.ethz.ch/R-manual/R-devel/library/base/html/Logic.html
txt <- c("bla bla", "bla ble", "bla bli", "bla non")
grep('bla (bla|ble)', txt, value =T)
## [1] "bla bla" "bla ble"y <- c("bla", "ble", "bli")
y=="bla"
## [1] TRUE FALSE FALSE
y!="bla"
## [1] FALSE TRUE TRUEAlgumas buscas na internet disponibilizam alguns operadores. No portal da Cãmara dos deputados, pode-se buscar discursos dos parlamentares no banco de discursos utilizando “and” e “or” (link aqui). Na busca do Google, é possível excluir termos da busca (no caso, o operador “NOT”), utilizando o sinal de menos antes do termo.
4.5.5 Outros operadores
| Operador | Descrição |
|---|---|
: |
Cria uma sequência de números em uma sequência |
%in% |
Se um elemento pertence/está contido em um vetor de elementos |
%*% |
Multiplicação de matrizes |
# geranto automaticamente uma sequencia de 5 a 10
x <- 5:10
x
## [1] 5 6 7 8 9 10
# gerando uma sequencia de letras minúsculas
letters[1:5]
## [1] "a" "b" "c" "d" "e"
# gerando uma sequencia de letras miúsculas
LETTERS[5:10]
## [1] "E" "F" "G" "H" "I" "J"
# checando se os numeros estão contidos no vetor x
2 %in% x
## [1] FALSE
7 %in% x
## [1] TRUE
# Num outro exemplo, vamos usar o operador para checar intesecção entre dois vetores
v1 <- c("a", "b", "c", 1, 2, 67, 53, 73)
v2 <- c("x", "y", "z", "2", "h", "j", "c")
# obtendo um vetor com booleanos (TRUE e FALSE) de todos os elementos
v1 %in% v2
## [1] FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE
# observando apenas os elementos que tem intersecção entre os vetores
v1[v1 %in% v2]
## [1] "c" "2"Num exemplo prático do operador %in%, o comando colors() lista as cores que possuem nome no R. Com o operador %in%, podemos checar se um nome de cor específico ou um vetor de nomes está presente no vetor de cores que o comando colors() retorna.
"darkred" %in% colors()
## [1] TRUE
# Um vetor
c("darkred", "lightred") %in% colors()
## [1] TRUE FALSE4.6 Loops, repetições
4.6.1 For Loops
Quando necessita de fazer uma mesma operação, repetida, em vários itens de uma lista, usamos os loops. Com loops iteramos, aplicamos uma operação a cada item de uma série de itens.
for (item in variavel_com_varios_itens){
faça algo com cada item n da variável
}Por exemplo:
x <- c(1, 3, 5)
# o loop abaixo pegará os elementos 1,3 e 5
# e adicionará 1 a cada um deles.
for (i in x){
print(i+1)
}
## [1] 2
## [1] 4
## [1] 6Também podemos aplicar loops a strings:
x <- c('bla', 'ble')
for (i in x){
print(paste('Alguém disse: ', i))
}
## [1] "Alguém disse: bla"
## [1] "Alguém disse: ble"nomes <- c("Fulano", "Beltrano", "Maria", "Karen")
for(i in nomes) {
# o comando nchar() conta quantos caracteres há no item
print(paste("O nome", i, "contém", nchar(i), "caracteres."))
}
## [1] "O nome Fulano contém 6 caracteres."
## [1] "O nome Beltrano contém 8 caracteres."
## [1] "O nome Maria contém 5 caracteres."
## [1] "O nome Karen contém 5 caracteres."4.6.2 While loop
O for loops é usado quando temos uma lista que sabemos quantos elementos temos. Para o caso de não sabermos ao certo quantos e quais elementos temos, há ainda um outro tipo de loop em programação, o while loop, que diz enquanto uma condição for verdadeira, ela continuará rodando, e irá parar assim que for falsa.
# criando a variável "i" de valor 1
i <- 1
# Enquanto a condição i for menor que 7, continue
while (i < 7) {
# imprime a mensagem
message(i, " é menor que 7")
# adiciona 1 ao valor de i
i <- i + 1
# volta ao início
}
## 1 é menor que 7
## 2 é menor que 7
## 3 é menor que 7
## 4 é menor que 7
## 5 é menor que 7
## 6 é menor que 7No exemplo acima, criamos a variável “i” que tem valor 1, e dentro do loop há a operação de acrescentar +1 a cada “rodada” do loop, que começa com o valor “1”. A cada rodada, o loop avalia se a condição i < 7 é verdadeira. Se sim, imprime o valor atual da variável i e adiciona +1 ao valor de i. O loop continua rodando para o próximo item. Assim que chega em 7, o loop pára, já que “7 < 7” é falso.
4.6.3 apply (lapply, sapply, tapply e mapply)
Além de for loop e while loop, no R temos a família apply (lapply, sapply, tapply e mapply), que funciona como um for loop normal, mas que pode simplificar um pouco a repetição, além de ser mais rápido que o for loop. Entretanto, o apply funciona aplicando uma função já pré definida anteriormente.
Assim, no nosso exemplo com o vetor
nomes <- c("Fulano", "Beltrano", "Maria", "Karen")Em que aplicamos o for loop
for(i in nomes) {
# o comando nchar() conta quantos caracteres há no item
print(nchar(i))
}
## [1] 6
## [1] 8
## [1] 5
## [1] 5Podemos fazer algo parecido com o apply
sapply(nomes, nchar)
## Fulano Beltrano Maria Karen
## 6 8 5 5Além de forloops e da família apply, o R conta também com:
- família de funções
map_do pacote purrr do tidyverse - pacote foreach, que possibilita forloops com processamento paralelo, isto é, mais rápido.
- As funções do purrr também podem ser paralelizadas para ficarem mais rápidas através do pacote furrr.