dplyr
O dplyr é um dos pacotes do Tidyverse e é voltado especificamente para o trabalho de manipulação de dados.
Instalação e Requisição do Pacote dplyr
install.packages("dplyr")
library(dplyr)
Opcionalmente, podemos instalar de uma só vez todos os pacotes contidos no tidyverse, que incluem, entre outros, o dplyr, o tidyr, o ggplot2 e o magrittr.
install.packages("tidyverse")
library(tidyverse)
O dplyr se estrutura em torno de um conjunto de verbos, que operam como funções para a manipulação de grandes bancos de dados. Vamos conhecer os principais verbos!
select()
A função select() seleciona uma ou mais colunas de um dataframe. É utilizada para reduzir o tamanho da base de dados que estamos manipulando. Por exemplo, vamos supor que, no dataframe que criamos anteriormente, dados_aves, não precisemos lidar com dados de extensão das nadadeiras ou massa corporal dos pinguins; queremos apenas saber a espécie, o local de habitação e o sexo. Vamos selecionar somente essas colunas?
select(dados_aves, species, island, sex) # O primeiro parâmetro é o dataframe, os demais são as colunas
O pipe (%>%)
O dplyr possui uma sintaxe que facilita o trabalho e permite concatenar vários comandos dentro de uma só expressão. Para isso, vamos conhecer um pouquinho o “pipe” (ou %>%). O pipe é um operador que foi criado originalmente para o pacote magritrr. No dplyr, ele permite que você indique primeiro o banco de dados e depois estruture suas funções de modo encadeado. O mesmo comando anterior ficaria assim:
dados_aves %>% select(species, island, sex)
Se eu quiser dispor desse resultado em um novo dataframe:
dados_aves_resumido <- dados_aves %>%
select(species, island, sex)
Não se assuste: você pode digitar o pipe de forma simples com CTRL+SHIFT+M.
Um exemplo de Hadley Wickham de que gosto muito:
- Pense numa receita que tenha as seguintes instruções: junte os igredientes, misture e leve ao forno. Na forma usual do R, tais instruções provavelmente teriam a seguinte sintaxe:
forno(misture(junte(ingredientes)))
- Note que temos que pensar “de dentro para fora”. O primeiro comando que lemos é forno que, na verdade, é a última operação que será realizada! Com o operador pipe, por outro lado, você escreveria algo mais ou menos assim:
ingredientes %>% junte %>% misture %>% forno
- É quase igual a ler instruções verbais da receita. Parece mais intuitivo, não?
Vamos voltar agora a aprender outros verbos do dplyr…
filter()
A função filter() filtra um dataframe com vetores lógicos. Em outras palavras, deixa apenas as linhas que satisfazem a certo critério. Por exemplo: suponhamos que queiramos manter em nosso dataframe apenas os pinguins de sexo feminino e encontrados na ilha de Torgersen. Que comando executamos?
filter(dados_aves, sex == "female", island == "Torgersen")
Ou, usando o %>%:
dados_aves %>% filter(sex == "female", island == "Torgersen")
Posso usar filter() e select() na mesma expressão? SIM! Basta encadear os %>%:
dados_aves_resumido <- dados_aves %>%
select(species, island, sex) %>%
filter(sex == "female", island == "Torgersen")
mutate()
A função mutate() cria uma nova coluna com base nos parâmetros indicados. Por exemplo, vamos criar uma nova coluna com um operador lógico no nosso dataframe original dados_aves para indicar se a ave é grande ou não. Sempre que o espécime pesar mais de 4kg ele será classificado como “grande”. Adicionalmente, a massa corporal das aves está descrita em gramas (g) e nós gostaríamos de transpor esse valor para kg. Como fazemos?
dados_aves_massa <- dados_aves %>%
mutate(massa_kg = body_mass_g/1000) %>% # Transpor de g para kg
mutate(especime_grande = massa_kg > 4) %>% # Verificar através de um operador lógico todos os espécimes acima de 4kg
select(species, body_mass_g, massa_kg, especime_grande)
arrange()
A função arrange() orderna o dataframe com base em uma coluna. Por exemplo, nós gostaríamos de ordenar o dataframe que criamos no exercício anterior com base na coluna massa_kg. Assim, podemos ver quais os espécimes mais pesados.
dados_aves_massa <- dados_aves_massa %>%
arrange(massa_kg) # Do mais leve ao mais pesado
dados_aves_massa <- dados_aves_massa %>%
arrange(desc(massa_kg)) # Do mais pesado ao mais leve
Você notou que há dois pinguins sem informação de massa corporal? Vamos subtrai-los de nossos dados?
dados_aves_massa <- dados_aves_massa %>%
arrange(desc(massa_kg)) %>% # Do mais pesado ao mais leve
tidyr::drop_na() # Estamos chamando uma função que não está presente no pacote dplyr
# Por isso é necessário primeiro instalar o pacote tidyr se você ainda
# não tiver feito isso...
group_by()
Esta função agrupa um dataframe segundo um vetor de categorias. “Agrupar” aqui quer dizer que todas as operações subsequentes serão feitas separadas por grupos.
summarise() ou reframe()
Esta função transforma um vetor com vários números em um único número de acordo com uma função.
Geralmente os verbos group_by() e summarise() aparecem combinados entre si em uma expressão sequencial. Por exemplo, qual a espécie de pinguim com maior média de massa corporal?
dados_aves_especies <- dados_aves_massa %>%
group_by(species) %>%
summarise(media = mean(massa_kg))
Obs.: A função summarise() está deprecada, isto é, obsoleta. Ela vem sendo gradualmente substituída pela função reframe().
count()
Um outro verbo muito útil para tratamento e manipulação de dados é o count(). O resultado de count() é geralmente uma outra tabela, com informações sobre a contagem. A coluna n expressa os valores da contagem.
Vamos tentar descobrir quantos pinguins têm massa corporal superior a 4kg em toda a nossa amostra?
dados_aves %>%
filter(body_mass_g > 4000) %>%
count()
E quantos pinguins têm massa corporal inferior a 4kg?
dados_aves %>%
filter(body_mass_g < 4000) %>%
count()
E qual a média da massa corporal dos pinguins na nossa amostra?
dados_aves %>%
tidyr::drop_na() %>%
reframe(media = mean(body_mass_g))
Vamos fazer exercícios com outro conjunto de dados agora??
EXERCÍCIO 1
- Considere os dados do IBGE sobre a população brasileira em 2022.
install.packages("devtools")
devtools::install_github("tbrugz/ribge")
populacao2022 <- ribge::populacao_municipios(2022)
-
Quais os cinco municípios com maior população no estado do Rio de Janeiro?
-
Qual a média populacional dos municípios do Rio de Janeiro?
-
Quantos municípios do Rio de Janeiro estão acima dessa média?
EXERCÍCIO 2
- Considere os dados oficiais do TSE a respeito dos candidatos ao cargo de deputado federal nas eleições de 2022.
install.packages("electionsBR")
candidato_brasil <- electionsBR::elections_tse(2022, type = "candidate") %>% filter(DS_CARGO == "DEPUTADO FEDERAL")
-
Crie uma tabela somente com os dados dos nomes dos candidatos na urna, siglas dos partidos, estado por que se candidataram, estado em que nasceram, idade, sexo, raça e grau de instrução, nessa ordem.
-
Quais partidos têm mais pretos ou pardos como candidatos?
-
Quais partidos têm mais mulheres como candidatas?
-
Quais partidos têm mais mulheres pretas como candidatas?
-
Quantos e quais candidatos se candidataram por um estado diferente daquele que nasceram?
Filtrando a Base de Dados por Períodos Específicos
Em algumas ocasiões pode ser necessário filtrar a base de dados por um período específico no tempo. Para isso, utilize a função between, do pacote dplyr. Vamos descobrir, por exemplo, quem são os candidatos jovens que disputaram as últimas eleições?
candidato_brasil %>% mutate(DT_NASCIMENTO = lubridate::dmy(DT_NASCIMENTO)) %>%
filter(between(DT_NASCIMENTO, lubridate::as_date("1980-01-01"), lubridate::as_date("2000-01-01")))
Criando uma Variável Categórica a partir de Outra (case_when)
É possível recodificar uma variável com novos valores e categorias. Para isso, utilize, mais uma vez, a função grepl(), e combine-a com a função case_when() do pacote dplyr.
candidato_brasil %>%
mutate(
IDEOLOGIA = case_when(
grepl("PP", SG_PARTIDO) ~ "DIREITA",
grepl("REPUBLICANOS", SG_PARTIDO) ~ "DIREITA",
grepl("UNIÃO", SG_PARTIDO) ~ "DIREITA",
grepl("PL", SG_PARTIDO) ~ "DIREITA",
grepl("PSC", SG_PARTIDO) ~ "DIREITA",
grepl("PATRIOTA", SG_PARTIDO) ~ "DIREITA",
grepl("PT", SG_PARTIDO) ~ "ESQUERDA",
grepl("PSB", SG_PARTIDO) ~ "ESQUERDA",
grepl("PCO", SG_PARTIDO) ~ "ESQUERDA",
grepl("PC do B", SG_PARTIDO) ~ "ESQUERDA",
grepl("REDE", SG_PARTIDO) ~ "ESQUERDA",
T ~ "OUTRO"))
Anonimizando os Sujeitos
Para anonimizar os sujeitos de seu banco de dados, é necessário utilizar um pacote adicional de criptografia. Uma sugestão é o pacote anonymizer, desenvolvido por Paul Hendricks. Utilize o seguinte comando para instalar o pacote:
remotes::install_github("paulhendricks/anonymizer")
E, em seguida, indique o vetor a ser anonimizado. Uma boa opção é utilizar o algoritmo de criptografia md5.
candidato_brasil$NM_ANONIMO <- candidato_brasil$NM_CANDIDATO %>% anonymizer::hash(.algo = "md5")
Manipulando strings
Muitas vezes, os valores dispostos em nosso banco de dados se apresentam como variáveis de texto (strings). Algumas dessas variáveis textuais precisam ser remodeladas ou transformadas, a fim de facilitar nossa interpretação.
Vamos aprender algumas funções de manipulação de strings a seguir.
Convertendo strings em minúsculas e em maiúsculas:
str_to_lower
candidato_minuscula <- candidato_brasil %>%
select(NM_CANDIDATO, SG_PARTIDO) %>%
mutate(minuscula = str_to_lower(NM_CANDIDATO))
str_to_upper
candidato_maiuscula <- candidato_minuscula %>%
mutate(maiuscula = str_to_upper(minuscula))
str_to_title
candidato_versalete <- candidato_maiuscula %>%
mutate(versalete = str_to_title(maiuscula))
Localizando texto e/ou detectando padrões textuais em um vetor de strings
candidato_sobrenome <- candidato_brasil %>%
select(NM_CANDIDATO, SG_PARTIDO) %>%
mutate(SOBRENOME = str_detect(NM_CANDIDATO, "SOUZA|SOUSA|SILVA|SANTOS"))
E, se, ao invés de simplesmente detectar a ocorrência de um padrão textual, eu quiser efetivamente localizar e filtrar somente o texto correspondente?
candidato_sobrenome <- candidato_brasil %>%
select(NM_CANDIDATO, SG_PARTIDO) %>%
filter(str_detect(NM_CANDIDATO, "SOUZA|SOUSA|SILVA|SANTOS"))
Caso seja necessário filtrar a base de dados por palavras ou expressões no corpo do texto das mensagens, também é possível utilizar a função grepl(), nativa do R Base. A função comporta sintaxe em Regex. Mas, para efeito de simplificação, pesquisaremos apenas por operadores mais simples. Que tal descobrirmos quais candidatos e candidatas têm João, Joana, José ou Maria no nome?
candidato_nome <- candidato_brasil %>%
filter(grepl("JO(ÃO|ANA)|JOSÉ|MARIA", NM_CANDIDATO))
Substituindo padrões textuais em um vetor de strings
candidato_profissoes <- candidato_brasil %>%
select(NM_CANDIDATO, SG_PARTIDO, DS_OCUPACAO) %>%
mutate(DS_OCUPACAO = str_replace(DS_OCUPACAO, "JORNALISTA E REDATOR", "JORNALISTA")) %>%
mutate(DS_OCUPACAO = str_replace(DS_OCUPACAO, "LOCUTOR E COMENTARISTA DE RÁDIO E TELEVISÃO E RADIALISTA", "RADIALISTA"))
Também é possível realizar esse tipo de edição no banco de dados com a função gsub, nativa do R Base.
candidato_brasil %>%
filter(DS_OCUPACAO == "JORNALISTA E REDATOR") %>%
mutate(DS_OCUPACAO = gsub("JORNALISTA E REDATOR", "JORNALISTA", DS_OCUPACAO))
EXERCÍCIO 1
- Considere o conjunto de dados abaixo:
bbb21_mensagens <- read.csv(
"https://raw.githubusercontent.com/ombudsmanviktor/workshop_rstats/main/aula6/bbb21_mensagens.csv")
-
Procure quantas vezes Juliette é mencionada nesse conjunto de mensagens.
-
Substitua todas as menções a Bolsonaro (ou bolsonaro ou BOLSONARO) por Bozo
-
Transforme todos os caracteres das mensagens nos tweets em minúsculas.