Curso
Neste tutorial, você vai conhecer várias funções e utilitários fáceis e muito usados na linguagem de programação R. Primeiro, vamos falar de algumas funções matemáticas. Depois, você verá funções ligadas às estruturas de dados do R, como manipulação de listas aninhadas, expressões regulares, tempo e datas.
Funções matemáticas
Vamos analisar os trechos de código a seguir que usam várias funções matemáticas.
Primeiro, você vai definir dois vetores, x e y, que contêm valores positivos e negativos.
x <- c(1.1, -2.3, -4.5)
y <- c(2.4,-44, -2.2)
print(x)
[1] 1.1 -2.3 -4.5
print(y)
[1] 2.4 -44.0 -2.2
Agora, com esses dois vetores x e y:
- pegue os valores absolutos,
- arredonde para zero casas decimais,
- some cada um deles e
- por fim, calcule a média de ambos.
mean(c(sum(round(abs(x))),sum(round(abs(y)))))
27.5
Que tal quebrar a linha acima em partes menores e olhar de perto cada função?
- A função
abs()simplesmente considera o valor positivo ou absoluto dos elementos dos vetoresxey.
Por exemplo, ao aplicar abs() em x e y, você verá só valores positivos, como abaixo.
abs(x)
- 1.1
- 2.3
- 4.5
abs(y)
- 2.4
- 44
- 2.2
- A próxima função é
round(). Ela apenas arredonda a entrada. Aceita um argumento extra para você indicar quantas casas decimais quer manter. Por padrão,round()arredonda para zero casas decimais.
Por exemplo, após aplicar round() aos vetores x e y, a saída fica assim:
round(x)
- 1
- -2
- -4
round(y)
- 2
- -44
- -2
- Já a função
sum()simplesmente calcula a soma dos elementos de um vetor ou matriz. Por exemplo, se você passar um vetor linha como argumento, ela retorna um escalar com a soma de todos os elementos.
Neste caso, os vetores x e y são passados para sum(). Assim, o R calcula a soma dos elementos e retorna um escalar.
sum(abs(round(x)))
7
sum(abs(round(y)))
48
- Por fim, a função
mean()(média) calcula a média aritmética: soma um conjunto de valores numéricos e divide pelo número de termos.
Aqui, a entrada de mean() é um vetor linha de comprimento 2 com os números 7 e 48. A média é a soma desses valores dividida pelo número de elementos, ou seja, 2.
mean(c(7,48))
27.5
Bem tranquilo, né?
Vamos agora para a próxima parte — a mais interessante deste tutorial!
Funções para estruturas de dados
Agora vamos ver algumas estruturas de dados, como listas e vetores. Diferentes formas de operar com list, inverter uma list e como converter uma lista em vetor e vice-versa.
A função abaixo é um list(), ou seja, uma lista de listas, também chamada de lista aninhada. Ela cria uma lista de elementos que podem ser lógicos, numéricos e strings.
No exemplo a seguir, há três listas dentro de uma lista: log, ch e int_vec. Cada uma tem um tipo de dado/objeto do R: lógico, numérico e caractere.
list_define <- list(log = TRUE, ch = "hello_datacamp", int_vec = sort(rep(seq(8,2, by = -2), times = 2)))
list_define
- $log
- TRUE
- $ch
- 'hello_datacamp'
- $int_vec
-
- 2
- 2
- 4
- 4
- 6
- 6
- 8
- 8
logé um valor lógico, TRUE ou FALSEché a string de caractereshello_datacampint_vecé uma sequência de valores numéricos.
Como log e ch são diretos, vamos olhar com mais atenção para int_vec.
int_vec = sort(rep(seq(8,2, by = -2), times = 2))
int_vec
- 2
- 2
- 4
- 4
- 6
- 6
- 8
- 8
Vamos entender essa expressão passo a passo.
A função seq produz uma sequência de números em ordem decrescente de 8 até 2.
A sintaxe de seq() é: seq(x1,x2, by = y)
Os dois primeiros argumentos, x1 e x2, definem o intervalo (início e fim). O argumento by indica o incremento ou decremento a cada passo.
Por exemplo, a linha abaixo gera uma sequência de 100 a 200 com passo 20.
seq(100,200, by = 20)
- 100
- 120
- 140
- 160
- 180
- 200
No nosso exemplo, seq retorna uma sequência de 8 até 2 (inclusive) com passo -2, gerando um vetor de comprimento 4.
a = seq(8,2, by = -2)
a
- 8
- 6
- 4
- 2
Agora, vamos entender a função rep.
Ela repete o argumento de entrada (geralmente um vetor ou lista) usando o parâmetro times, que recebe um inteiro com o número de repetições. rep recebe dois argumentos: a entrada e quantas vezes ela deve ser repetida.
Aplicando rep ao nosso vetor de comprimento 4, teremos um vetor de comprimento 8.
b = rep(a, times = 2)
Se você quiser repetir cada elemento do vetor (e não o vetor completo), use o argumento each em vez de times.
A diferença entre times e each é o padrão de repetição dos elementos.
rep(a, each = 2)
- 8
- 8
- 6
- 6
- 4
- 4
- 2
- 2
Por último, a função sort(). Ela é autoexplicativa e genérica para ordenar estruturas como vetores ou listas. Não se limita a valores numéricos — também funciona com lógicos e caracteres. Por padrão, ordena em ordem crescente.
Vamos passar a saída de rep para sort e chegar ao resultado final.
sort(b)
- 2
- 2
- 4
- 4
- 6
- 6
- 8
- 8
Mandou bem! Você desvendou a expressão comprida int_vec, que estava dentro da lista list_define, de um jeito simples.
Agora vamos inspecionar o conteúdo de list_define usando a função str(), que mostra a estrutura de objetos no R.
str(list_define)
List of 3
$ log : logi TRUE
$ ch : chr "hello_datacamp"
$ int_vec: num [1:8] 2 2 4 4 6 6 8 8
Vamos ver algumas expressões úteis do R:
- A função
ispode ser usada para checar o tipo da sua estrutura de dados. Ela retorna um valor lógico e é útil em condicionais.
is.list(list_define) #retorna TRUE se o argumento for uma lista.
TRUE
Se você passar um vetor (que não é lista), retorna FALSE, como abaixo.
is.list(c(1,2,3)) #retorna FALSE pois você passou um vetor.
FALSE
- Converter um vetor em lista é muito simples no R. Use a função
asseguida de.list()e passe o vetor como argumento.
vec_to_list <- as.list(c(1,2,3))
is.list(vec_to_list) #verifique com is.list()
TRUE
- Por outro lado, uma lista pode ser “desenrolada” em um vetor com
unlist. O R faz isso “achatando” toda a estrutura da lista e retornando um único vetor.
list_to_vec <- unlist(vec_to_list)
list_to_vec
- 1
- 2
- 3
Assim como is.list(), você pode usar is.vector() para saber se o argumento é um vetor.
is.vector(list_to_vec)
TRUE
Vamos converter a lista maior, list_define, em vetor. Importante: um vetor só pode conter um único tipo de dado/objeto do R. Por isso, os valores lógicos e numéricos serão convertidos em strings.
unlist(list_define)
- log
- 'TRUE'
- ch
- 'hello_datacamp'
- int_vec1
- '2'
- int_vec2
- '2'
- int_vec3
- '4'
- int_vec4
- '4'
- int_vec5
- '6'
- int_vec6
- '6'
- int_vec7
- '8'
- int_vec8
- '8'
Antes de seguir, vamos ver as funções append() e rev().
- Como o nome sugere,
append()permite anexar/adicionar dois ou mais vetores ou listas a um vetor/lista existente ou novo.
Vamos aplicar append() em list_define. Você vai notar que a lista passa a ter 6 elementos em vez de 3, já que você anexou a lista a ela mesma.
str(append(list_define, list_define))
List of 6
$ log : logi TRUE
$ ch : chr "hello_datacamp"
$ int_vec: num [1:8] 2 2 4 4 6 6 8 8
$ log : logi TRUE
$ ch : chr "hello_datacamp"
$ int_vec: num [1:8] 2 2 4 4 6 6 8 8
- Por fim, vamos inverter a ordem de
list_definecom a funçãorev()no R.
str(rev(list_define))
List of 3
$ int_vec: num [1:8] 2 2 4 4 6 6 8 8
$ ch : chr "hello_datacamp"
$ log : logi TRUE
Expressões regulares
Muita gente acha expressões regulares um tema complexo. Mas é essencial, não só em R como em várias linguagens, como Python. Muitas delas, incluindo o R, oferecem suporte nativo a regex.
Expressões regulares são úteis em várias aplicações, especialmente para pré-processar texto. Elas são usadas em diversos problemas de NLP (Processamento de Linguagem Natural).
Também aparecem em mecanismos de busca e editores de texto.
Expressões regulares, conhecidas como regex, regexp ou operadores racionais, são sequências de caracteres que definem um padrão de busca. Em geral, esses padrões são usados por algoritmos de busca em strings para encontrar um padrão, encontrar e substituir ou filtrar correspondências.
Vamos começar entendendo o uso das funções grep() e grepl().
Para simplificar, vamos definir um vetor linha animals_regex de comprimento 5, no qual você vai aplicar padrões de regex.
animals_regex <- c('cat','dog','cheetah','lion','mice')
Primeiro, entenda grepl(). Ela retorna um resultado lógico: se a string casa com o padrão, retorna TRUE; caso contrário, FALSE.
Abaixo está uma sintaxe simples e intuitiva de grepl(), onde o primeiro argumento é o padrão que você quer buscar e o segundo é a string (entrada) onde quer encontrar/filtrar o padrão. Você pode ignorar os outros argumentos por ora. grepl(pattern, x, ignore.case = FALSE, perl = FALSE, fixed = FALSE, useBytes = FALSE) Vamos ver quais dos cinco animais acima têm a letra c usando grepl().
Neste caso, você procura animais que tenham c no nome — então o padrão é simplesmente c.
grepl(pattern = 'c', x = animals_regex)
- TRUE
- FALSE
- TRUE
- FALSE
- TRUE
Pela saída, como há c em cat, cheetah e mice, o R retorna TRUE nessas posições do vetor animals_regex, e FALSE onde não houve correspondência.
Vamos encontrar agora os elementos que começam com c, e não apenas contêm essa letra.
Para isso, basta usar o acento circunflexo ^ no início do padrão que você quer encontrar.
grepl(pattern = '^c', x = animals_regex) #apenas cat e cheetah começam com `c`.
- TRUE
- FALSE
- TRUE
- FALSE
- FALSE
Como esperado, só cat e cheetah começam com c, então apenas essas posições retornam TRUE.
De forma parecida ao ^, o símbolo $ no fim do padrão busca elementos que terminam com o padrão especificado. Para achar um animal que termina com n, use n seguido de $.
grepl(pattern = 'n$', x = animals_regex) #apenas lion termina com `n`.
- FALSE
- FALSE
- FALSE
- TRUE
- FALSE
Observação: para saber mais sobre regex, digite ?regex em uma célula do Jupyter Notebook e a documentação vai abrir. E, se quiser aprender mais, confira esta fonte, que oferece uma ferramenta para criar padrões de busca e testá-los nas suas strings.
- Semelhante ao
grepl(), existegrep(), que em vez de retornar lógicos, devolve os índices do vetor/matriz que casam com o padrão.
A sintaxe de grep() é exatamente a mesma de grepl() e é: grep(pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE, fixed = FALSE, useBytes = FALSE, invert = FALSE). Vamos usar o mesmo exemplo de acima, mas agora com grep()!
grep(pattern = 'c', x = animals_regex)
- 1
- 3
- 5
Como esperado, a saída retorna os índices de cat, cheetah e mice, e não TRUE/FALSE. É isso!
Vamos usar a função which para comparar grep() e grepl(). A função which() retorna os índices onde um objeto lógico é TRUE.
Conectando os pontos: como grepl() retorna um objeto lógico, podemos passá-lo a which(), que converterá o resultado para algo equivalente ao que grep() retornaria.
which(grepl(pattern = 'c', x = animals_regex))
- 1
- 3
- 5
Assim como grepl(), grep() também lida com diferentes padrões de regex.
Se você aplicar grep() para achar os elementos em animals_regex que terminam com n, a saída será 4, já que apenas lion termina com n, como abaixo.
grep(pattern = 'n$', x = animals_regex)
4
Muito bom!
Você aprendeu o básico de expressões regulares, como filtrar elementos de um vetor que casam com um padrão. Mas o R vai além de casar padrões. Ele tem várias funções úteis, e uma delas é sub().
A função sub(), em vez de filtrar, substitui as correspondências por outras strings. Vamos entender melhor!
- A
sub()recebe três argumentos principais:- pattern, o padrão/regex que você quer casar,
- replacement, o valor que substituirá o elemento casado no vetor e
- x, a string vetorial de entrada onde você aplicará a regex.
A sintaxe é: sub(pattern, replacement, x, ignore.case = FALSE, perl = FALSE,fixed = FALSE, useBytes = FALSE). Vamos usar o mesmo exemplo de acima para entender a função!
sub(pattern = 'c', replacement = 'a', x = animals_regex)
- 'aat'
- 'dog'
- 'aheetah'
- 'lion'
- 'miae'
Como você vê, cat vira aat, cheetah vira aheetah e mice vira miae. Nesses elementos, o padrão foi casado com sucesso.
Note também que sub() procura apenas a primeira ocorrência na string: se houver dois c em uma string, só o primeiro será substituído por a; o segundo permanece.
Se quiser substituir todas as ocorrências em uma string, use gsub(), que foge ao escopo deste tutorial!
Antes de fechar este tema, vamos testar mais uma expressão.
Desta vez, use o operador | (ou), que tenta casar qualquer um dos padrões definidos e, se casar, substitui por -. Lembre que, como usamos gsub(), ele substitui todas as ocorrências do padrão na string.
gsub(pattern = 'c|d|l', replacement = '-', x = animals_regex) #animais com `c`,`d`,`l` viram `-`.
- '-at'
- '-og'
- '-heetah'
- '-ion'
- 'mi-e'
Vamos ao último tópico de hoje: Tempo e datas!
Tempo e datas
Informações de tempo e data podem ser muito úteis em diferentes cenários. Por exemplo, suponha que você trabalha com Visão Computacional e quer medir o FPS (frames por segundo) do seu algoritmo. Nesse caso, você pode usar o objeto de tempo para medir a velocidade de processamento. Para problemas como previsão de séries temporais e estudos de sazonalidade, o potencial do R pode ser usado ao máximo.
Para começar, vamos imprimir a data de hoje no R com Sys.Date(). Aqui, Sys se refere ao sistema — ou seja, retorna a data do sistema.
Sys.Date()
Simples, né?
Tempo e datas no R pertencem ao objeto Date, ou seja, o tipo de dado é Date. Você pode verificar isso com a função class, como visto no tutorial Data Types in R.
De forma semelhante, há a função Sys.time(), que retorna a hora atual do sistema — na verdade, retorna hora e data.
Sys.time()
[1] "2020-02-04 02:05:04 IST"
Criando objetos Date
Você já viu como obter a data e a hora atuais. Agora, vamos criar datas de outros dias passando apenas uma string como argumento.
Para criar um objeto de data para 10 de maio de 1993, use a sintaxe abaixo:
date_may <- as.Date('1993-05-10') #converte string de caracteres em objeto Date
date_may
class(date_may)
'Date'
Um ponto importante: por padrão, as.Date() espera o formato YYYY-MM-DD. Se você trocar ano, mês ou dia, ocorre erro. Vamos ver:
date_may <- as.Date('05-1993-10') #o R segue o formato ISO por padrão
Error in charToDate(x): character string is not in a standard unambiguous format
Traceback:
1. as.Date("05-1993-10")
2. as.Date.character("05-1993-10")
3. charToDate(x)
4. stop("character string is not in a standard unambiguous format")
A boa notícia é que você pode definir o formato explicitamente com o argumento format e personalizá-lo.
date_may <- as.Date('05-1993-10', format = '%m-%Y-%d')
as.Date() aceita formatos variados, mas sempre converte de volta para o formato ISO. É só imprimir date_may para ver.
date_may
date_may <- as.Date('05-10-1993', format = '%m-%d-%Y')
date_may
Aritmética com datas
Não seria ótimo poder fazer operações como soma e subtração com objetos Date no R?
Some 1 a date_may e você verá a data avançar um dia.
date_may + 1
Perfeito: adicionar 1 mudou a data de 10 para 11 de maio de 1993. Da mesma forma, você pode subtrair 1.
Suponha que você queira calcular a diferença de tempo entre a sua data de nascimento e a do seu irmão mais velho.
elder_sib <- as.Date('1989-03-21')
date_may - elder_sib
Time difference of 1511 days
Conclusão
Parabéns por concluir o tutorial.
Este conteúdo é um ótimo ponto de partida para quem quer conhecer várias funções utilitárias no R. Como exercício, vale aprofundar em Expressões Regulares: elas são usadas em muitas aplicações e são muito poderosas para limpar e pré-processar dados de texto.
Fique à vontade para deixar suas dúvidas nos comentários abaixo.
Se você quiser aprender mais sobre R, faça o curso Intermediate R da DataCamp e confira nosso tutorial Using Functions in R.
