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.
= "Fulano"
nome1 <- "Ciclano"
nome2 message("Um nome é ", nome1, ", o outro é ", nome2)
## Um nome é Fulano, o outro é Ciclano
Pode-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
<- function(argumento_1, argumento_2, ...) {
nome_da_funcao 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:
<- function(entrada){
minhaFuncao + 10
entrada
}
minhaFuncao(2)
## [1] 12
minhaFuncao(6)
## [1] 16
<- function(entrada1, entrada2){
minhaFuncao2 + entrada2
entrada1
}minhaFuncao2(2,4)
## [1] 6
minhaFuncao2(1,7)
## [1] 8
arg_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, ...)
## NULL
Ao 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:
<- function(){
x 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:
<- function(a = 2, b = 3) {
minhafuncao <- a + b
resultado 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] 6
Geralmente, 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.:
<- function(arg1){
minhafuncao 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 5
4.4.2 else if
Podemos colocar mais condições intermediárias, quantas quisermos, com else if
<- function(arg1){
comes 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
<- function(arg_entrada1, arg_entrada2){
verifica 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 2
Há 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)
<- c(5, 6, 3, 9, 7)
a 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] 9
Como 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 15
Há 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
<- "teste"
variavel == "abacate"
variavel ## [1] FALSE
!= "TESTE"
variavel ## [1] TRUE
4.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
<- c("bla bla", "bla ble", "bla bli", "bla non")
txt grep('bla (bla|ble)', txt, value =T)
## [1] "bla bla" "bla ble"
<- c("bla", "ble", "bli")
y =="bla"
y## [1] TRUE FALSE FALSE
!="bla"
y## [1] FALSE TRUE TRUE
Algumas 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
<- 5:10
x
x## [1] 5 6 7 8 9 10
# gerando uma sequencia de letras minúsculas
1:5]
letters[## [1] "a" "b" "c" "d" "e"
# gerando uma sequencia de letras miúsculas
5:10]
LETTERS[## [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
<- c("a", "b", "c", 1, 2, 67, 53, 73)
v1 <- c("x", "y", "z", "2", "h", "j", "c")
v2 # obtendo um vetor com booleanos (TRUE e FALSE) de todos os elementos
%in% v2
v1 ## [1] FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE
# observando apenas os elementos que tem intersecção entre os vetores
%in% v2]
v1[v1 ## [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 FALSE
4.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:
<- c(1, 3, 5)
x
# 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] 6
Também podemos aplicar loops a strings:
<- c('bla', 'ble')
x
for (i in x){
print(paste('Alguém disse: ', i))
}## [1] "Alguém disse: bla"
## [1] "Alguém disse: ble"
<- c("Fulano", "Beltrano", "Maria", "Karen")
nomes 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
<- 1
i # 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 + 1
i # 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 7
No 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
<- c("Fulano", "Beltrano", "Maria", "Karen") nomes
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] 5
Podemos fazer algo parecido com o apply
sapply(nomes, nchar)
## Fulano Beltrano Maria Karen
## 6 8 5 5
Alé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.