Preliminares

Antes de iniciar o curso é importante que vocês alunos sigam algumas etapas. A primeira delas é responder o forms disponibilizado no Classroom para eu conhecer um pouco de vocês e modular o conteúdo/roteiro dos nossos encontros. Nele pergunto sobre os conhecimentos prévios em programação e seus objetos de pesquisa. O ideal seria algum dos objetos servir de fonte de dados para trabalharmos em aula. As respostas são anônimas.

A segunda etapa é seguir o tutorial abaixo de instalação do R e do RStudio. São dois programas diferentes, mas bem simples de serem instalados. Elaborei um tutorial próprio no Windows, mas também é possível instalar no Mac e no Linux. Os tutoriais para estes dois últimos são de terceiros.

Disponibilizo também dois livros sobre a linguagem e a interface RStudio. O de Aquino é um pouco datado mas ainda funciona e está em português. O de Wickham é super recente (atualizado em junho de 2023), possui exercícios e é gratuito, mas está em inglês. Usem ambos para consultas e/ou aprofundar os estudos.

Por fim, disponibilizo aqui um glossário de termos usados no roteiro, scripts e durante as aulas. Ele é passível de expansão tanto por mim quanto por vocês (caso haja demanda).

Esta página e o material aqui usado estarão sempre disponível aos alunos e podem ser consultados novamente e compartilhados.

Aproveitem!

Instruções para entregas

Como demanda da universidade, haverá um processo avaliativo dos alunos. Vocês precisam escolher dois dos exercícios de cada encontro e enviar no campo de resposta das respectivas atividades no classroom enumerados. A resolução precisa ser escrita em código R. Qualquer dúvida não hesitem em me comunicar ou comunicar o monitor Davi.

A avaliação dos alunos consistirá na presença nos encontros e na entrega das atividades. Apesar das atividades terem respostas corretas, erros e acertos não contarão pontos, e sim a entrega das atividades. Feedbacks sobre as resoluções poderão eventualmente serem escritos. Após o prazo da entrega, as soluções serão disponibilizadas no material didático ao lado das questões.

Contato

Abaixo disponibilizo algumas informações para contato. Não tenham receio de me comunicar sobre qualquer tipo de problema, eventualidade, dúvida ou ideia.

Primeiro encontro (06/09): R base

Neste curso, iremos nos familiarizar com a linguagem R e a interface RStudio. Não iremos exaurir todas as possibilidades, mas apenas introduzir de maneira geral noções básicas de programação para fins acadêmicos. Num segundo momento, cursos mais específicos serão ofertados focados em análise textual e análise estatística, os quais serão melhor aproveitados após o primeiro contato com a linguagem.

A linguagem R foi criada no próprio meio acadêmico por estatísticos. Logo, ela já nasce no nicho de nosso interesse. RStudio é uma interface que roda a linguagem R original, mas nos oferece vários artifícios gráficos mais intuitivos do que a linguagem original. Hoje, o RStudio passa por um rebranding e se tornou Posit, uma interface multi-tarefas de programação mais ampla.

A interface e suas abas

A interface possui quatro painéis. No (1) temos o editor de texto, onde os arquivos com nossos scripts aparecem. No (2) temos o console, um espaço destinado a executação dos comandos. No (3) temos o “enviroment”, espaço onde ficam expostos todos os objetos criados na sessão atual. No (4) temos um painel multifuncional, onde ficam visualizações criadas, arquivos localizados na área de trabalho selecionada (mais disso em outro momento ou consultando o glossário), entre outras funções (carinhosamente apelidado de “painel de resto”).

A diferença entre o editor de texto (1) e o console (2) é bem simples: o primeiro permite salvar códigos num arquivo dentro da máquina do usuário, passível de ser executado múltiplas vezes e compartilhado (no formato “.R”); o segundo apenas recebe comandos, não sendo possível salvá-lo para re-execução.

Além dessas quatro telas, temos também a barra de ferramentas no alto da página (5). Nela, temos opções tradicionais de todos os programas de computadores. Para nosso caso, as abas “Tools” e “Help são as mais importantes. Na primeira temos a subopção”Global Options”, que serve para configurar o software. Na segunda temos acesso as “cheatsheets”, (as “colinhas”), e ao “Keyboard Shortcut Help”, uma lista de atalhos no teclado.

Primeiras linhas de código

Iremos escrever nossas primeiras linhas de código no editor de texto, para mantê-las salvas. A função mais primária do R é a de uma calculadora. Abaixo temos alguns cálculos matemáticos.

Operações simples

1+1
## [1] 2
4-2
## [1] 2
2*5
## [1] 10
100/10
## [1] 10

Potência

10^2 
## [1] 100
2^2
## [1] 4

Múltiplas operações

(2+2)*100
## [1] 400

Porcentagem

((2+5+7+9+3+11+2)/39)*100
## [1] 100
((2+5+7+9+3)/39)*100
## [1] 66.66667

Média

(2+5+7+9+3+11+2)/7
## [1] 5.571429

Notem como os comandos são escritas e aninhados. Usamos parênteses para separar processos. No caso da média, por exemplo, a parte da soma do cálculo é toda contida dentro de um parênteses, para em seguida esse resultado ser dividido por 7 (o número de elementos somados). É um processo muito semelhante ao ordenamento de operações na matemática convencional.

Também podemos fazer comparações usando de operadores lógicos, sinais matemáticos que avaliam se uma determinada condição é verdadeira ou falsa. Abaixo temos uma lista retirada de Aquino (2014) de alguns operadores convencionais da área e alguns exemplos. Podemos amontoar múltiplas comparações usando operadores entre duas ou mais comparações.

Comparações simples

2 == 3
## [1] FALSE
3 == 3
## [1] TRUE
(9/3) == 3
## [1] TRUE
4 != 5
## [1] TRUE
7 != 7
## [1] FALSE
5 < 9
## [1] TRUE
11 > 9
## [1] TRUE

Comparações complexas

2 == 3 & 3 == 3
## [1] FALSE
3 == 3 & 9/3 == 3
## [1] TRUE

Comparações de condicionais

#T & F = F 
T == T & T == F 
## [1] FALSE
#F & F = F
T == F & T == F 
## [1] FALSE
#T | F = T
T != F | T != T 
## [1] TRUE
#F | F = F
T == F | F != F 
## [1] FALSE

Percebam como acima eu faço uso de hashtags (#) nos códigos. O R não interpreta nada que vem depois de uma hashtag, logo é comum, além de uma boa prática, usar desse símbolo para comentar o código, como fizemos acima.

Funções

Apesar de ser possível de executar cálculos e outros procedimentos dessa forma, a magia do R vem das funções, comandos que executam processos pré-definidos usando de argumentos. Elas funcionam de forma muito semelhante a funções do Excel ou até funções matemáticas, sendo necessário chamarmos seus nomes, abrirmos parênteses, oferecermos os argumentos obrigatórios e/ou opcionais e finalmente fecharmos os parênteses.

Abaixo temos a função seq, que cria sequências numéricas. Ela tem como argumentos obritatórios: “from”, que define um ponto de partido da sequência; e “to”, que define o ponto de chegada da sequência. Há outros argumentos opcionais que podem limitar a unidade de contagem (“by”) e o tamanho da sequência (“length.out”).

seq(from = 100, to = 125)
##  [1] 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
## [20] 119 120 121 122 123 124 125

Podemos escrever manualmente o nome do argumento seguido de “=” e o valor que queremos dar pra ele ou ainda só escrever o valor no lugar que a função espera que esteja este argumento. Por exemplo, em seq o primeiro argumento sempre é o “from” e o segundo sempre é o “to”. Se rodarmos o código abaixo veremos que o resultado é o mesmo de antes. Memorizar a posição dos argumentos nem sempre é uma boa ideia. É preferível saber quais os nomes dos argumentos.

seq(100,125)
##  [1] 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
## [20] 119 120 121 122 123 124 125

O R permite o encadeamento de funções e processos, ou seja, o resultado de uma função pode ser passado à uma outra ad infinitum. Só precisamos no atentar com o fecharmos e abrir dos parênteses. Abaixo pegamos nossa sequência criada acima, somamos os números com 10 e só depois dividimos por 100.

(seq(100,125)+10)/100
##  [1] 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 1.19 1.20 1.21 1.22 1.23 1.24
## [16] 1.25 1.26 1.27 1.28 1.29 1.30 1.31 1.32 1.33 1.34 1.35

Caso não tívemos usado os parênteses, o resultado seria diferente, como ocorre abaixo.

seq(100,125)+10/100
##  [1] 100.1 101.1 102.1 103.1 104.1 105.1 106.1 107.1 108.1 109.1 110.1 111.1
## [13] 112.1 113.1 114.1 115.1 116.1 117.1 118.1 119.1 120.1 121.1 122.1 123.1
## [25] 124.1 125.1

Para consultar os argumentos de uma função, digite “?” seguido do nome da função. Uma janela irá abrir no painel multifunção (canto inferior direito), com infos da função, os argumentos e até alguns exemplos de código.

?seq

Objetos unidimensionais

Objetos em R são itens referenciáveis que contém informações. Referenciável porque ele pode ser “chamado” e usado com outros objetos, processos ou funções. Informações podem ter diversos tamanhos e formatos.

Chamamos eles de unidimensionais porque eles armazenam as informações em formato “de linha”, sempre contendo apenas um tipo de dado. Essa caracterização ficará mais evidente quando tratarmos dos objetos multidimensionais.

A criação de objetos em R é bem simples. Damos um nome ao objeto (que não pode conter espaços e nem começar com números), utilizamos o operador de associação <- (sinal de “menor que” seguido de um hífen) e oferecemos o conteúdo do objeto. No caso abaixo nós criamos um objeto com quatro elementos (neste caso, letras), o que implica a necessidade de usar a função c(), de concatenar. Para consultarmos o objeto, basta digitarmos seu nome e rodarmos o código.

Objetos com letras

objeto <- c("a","b","c","d")
objeto
## [1] "a" "b" "c" "d"

Objetos com números

objeto_numero <- c(3,4,1,2)
objeto_numero
## [1] 3 4 1 2

Percebam como para o objeto com letras (texto), cada elemento precisa estar fechado em aspas, enquanto que para o objeto com números isso não ocorre. O R não interpreta elementos de texto sem aspas, por isso o objeto abaixo que combina letras e números nos oferece um erro. Na aba seguinte temos a versão correta desse objeto.

Letras e números (errado)

objeto_misto <- c(a,5,b,9,c,1)
## Error in eval(expr, envir, enclos): objeto 'a' não encontrado

Letras e números (correto)

objeto_misto <- c("a",5,"b",9,"c",1)
objeto_misto
## [1] "a" "5" "b" "9" "c" "1"

Também podemos ainda apenas solicitar um print dos dois objetos separados criados antes. Essa função apenas mostra o conteúdo solicitado no console. Percebam como o R, na impressão, coloca aspas em todos os elementos. Isso ocorre porque é impossível criar um objeto unidimensional (mais sobre isso adiante) com múltiplos tipos de dados (números, letras, booleanos, etc.).

print(c(objeto,objeto_numero))
## [1] "a" "b" "c" "d" "3" "4" "1" "2"

Podemos criar sequências de números usando algumas estratégias. Primeiro, usando o carácter de dois pontos(“:”), oferecemos um número de partida a esquerda, de chegada a direita e amarramos tudo dentro da função c. Outra forma seria usando a função seq, já mencionada antes aqui: oferecemos um número de partida (from) e um de chegada (to). Aqui oferecemos também a unidade do incremento da sequência (by).

sequencia <- c(1:10)
sequencia
##  [1]  1  2  3  4  5  6  7  8  9 10
sequencia_par <- seq(from = 0, to = 10, by = 2)
sequencia_par
## [1]  0  2  4  6  8 10

Esses objetos numéricos podem ser usados em cálculos matemáticos. Basta digitarmos o nome do objeto e a operação que desejamos aplicar. O resultado é a aplicação do cálculo para cada elemento do objeto.

objeto_numero+2
## [1] 5 6 3 4
sequencia_par+5
## [1]  5  7  9 11 13 15

Tipos de dados

A linguagem R suporta uma variedade de tipos de dados. O que os diferencia é o tipo de processos/funções que são aplicáveis a cada um deles. Não é por acaso os tipos são muito semelhantes àqueles usados nas clássicas definições metodológicas (quanti/quali,categórico,nominal,ordinal, etc). Para consultarmos a classe de um objeto usamos a função class.

Character (texto)

Qualquer tipo de texto, inclusive números declarados como texto.

objeto_character <- c("ave","cachorro","gato")
objeto_character
## [1] "ave"      "cachorro" "gato"
class(objeto_character)
## [1] "character"

Factor (categoria)

Texto transformado em categoria. Diferente do character, os factors impedem a entrada de dados que não apresentem valores listados no conjunto de valores permitidos. Para consultar os valores permitidos, usamos a função levels.

objeto_factor <- factor(c("muito","normal","pouco"))
objeto_factor
## [1] muito  normal pouco 
## Levels: muito normal pouco
class(objeto_factor)
## [1] "factor"
levels(objeto_factor)
## [1] "muito"  "normal" "pouco"

Numeric (número)

Valores numéricos usados em cálculos matemáticos.

objeto_numeric <- c(1.3,2,4.9,7.2,9.5)

class(objeto_numeric)
## [1] "numeric"
objeto_numeric+2
## [1]  3.3  4.0  6.9  9.2 11.5

Logical (booleano/binário)

Verdadeiros (T, TRUE) e falsos (F, FALSE).

objeto_logical <- c(T,F,T,T,F,F)
objeto_logical
## [1]  TRUE FALSE  TRUE  TRUE FALSE FALSE
class(objeto_logical)
## [1] "logical"

É possível converter os dados entre os diferentes tipos, porém é preciso cautela porque nem toda conversão é automaticamente compatível e acaba gerando perda de informações.

As funções que fazem conversões são as que começam com o prefixo as.. Abaixo temos alguns exemplos das conversões e dos resultados após.

Character para factor (e vice-versa)

as.factor(objeto_character)
## [1] ave      cachorro gato    
## Levels: ave cachorro gato
class(as.factor(objeto_character))
## [1] "factor"
as.character(objeto_factor)
## [1] "muito"  "normal" "pouco"
class(as.character(objeto_factor))
## [1] "character"

Numeric para character

as.character(objeto_numeric)
## [1] "1.3" "2"   "4.9" "7.2" "9.5"
class(as.character(objeto_numeric))
## [1] "character"

Factor para numeric

as.numeric(objeto_factor)
## [1] 1 2 3
class(as.numeric(objeto_factor))
## [1] "numeric"

Logical para character ou numeric

as.character(objeto_logical)
## [1] "TRUE"  "FALSE" "TRUE"  "TRUE"  "FALSE" "FALSE"
class(as.character(objeto_logical))
## [1] "character"
as.numeric(objeto_logical)
## [1] 1 0 1 1 0 0
class(as.numeric(objeto_logical))
## [1] "numeric"

Índices

Todo elemento de um objeto possui um índice, um lugar específico dentro daquele objeto. Caso chamemos o objeto junto com um índice, recuperaremos apenas o(s) elemento(s) respectivo(s) daquele índice. A melhor analogia é a de uma cadeira enumerada dentro de uma sala: apenas uma pessoa senta numa cadeira, logo há apenas um nome num determinado lugar.

Para referenciar um índice usamos o nome do objeto, seguido de colchetes e o número do índice desejado. Podemos também selecionar múltiplos índices usando os dois pontos (“:”). Abaixo temos alguns exemplos com os nossos objetos criados até então.

objeto_character[3]
## [1] "gato"
objeto_factor[1]
## [1] muito
## Levels: muito normal pouco
objeto_numeric[1:4]
## [1] 1.3 2.0 4.9 7.2
objeto_logical[4:6]
## [1]  TRUE FALSE FALSE

Objetos multidimensionais

Objetos multidimensionais são aqueles que armazenam mais de um objeto unidimensional (como aqueles criados e estudados nas seções acima). Temos vários tipos deles, mas os que estão presentes no R base são: as matrizes, as listas e os data frames.

Matrizes (matrix)

Matrizes em R são como as suas homônimas em matemática: um conjunto de números armazenados em linhas e colunas. Elas se assemelham em muito com tabelas em Excel e afins. Nem sempre usamos elas, já que os data.frames são muito semelhantes e mais versáteis para manipular, mas é comum nos depararmos com elas em análises estatísticas (como matrizes de correlação). Estes objetos armazenam apenas objetos do mesmo tipo (todos números, todos texto, etc).

matrix(data=c(1,2,3,4,5,6,7,8,9),nrow=3,ncol=3)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9

Listas (list)

Listas são objetos que armazenam outros objetos de tamanhos e tipos distintos. Uma lista pode conter uma matriz de 500 por 500, junto com um objeto character de um só elemento, um objeto numeric com múltiplos valores e um data.frame com centenas de linhas e colunas.

list(x=list("a",c(1,2,3),"c"),
     y=list(T,F,c("a","b")),
     z=list("teste1","teste2",c(T,F,T)))
## $x
## $x[[1]]
## [1] "a"
## 
## $x[[2]]
## [1] 1 2 3
## 
## $x[[3]]
## [1] "c"
## 
## 
## $y
## $y[[1]]
## [1] TRUE
## 
## $y[[2]]
## [1] FALSE
## 
## $y[[3]]
## [1] "a" "b"
## 
## 
## $z
## $z[[1]]
## [1] "teste1"
## 
## $z[[2]]
## [1] "teste2"
## 
## $z[[3]]
## [1]  TRUE FALSE  TRUE

A melhor analogia é de um gabinete de escritório: um gabinete tem múltiplas gavetas, todas com números diferentes de pastas; estas armazenam diferentes documentos, de diferentes tamanhos e funcionalidades.

Listas têm seus usos em casos específicos. Um deles são em regressões: o resultado de um cálculo de uma regressão em R (usando a função lm, por exemplo) são múltiplos valores. Temos R², resíduos, matrizes de correlação, coeficientes, equação inicial (y=a+bx+u), todos de tipos e tamanhos diferentes.

Data frame

Data frames são versões melhoradas de matrizes, já que também trabalham com linhas e colunas, mas eles permitem o armazenamento de múltiplos tipos de dados em cada uma das colunas. Por exemplo, temos o objeto abaixo que possui dados de alunos e comidas (textos ou factors), presença (booleano/lógico) e idade (numérico). Nele, manualmente preenchemos as colunas usando a função c e separamos cada coluna usando uma vírgula (“,”).

data.frame(alunos=c("matheus","carlos","bossa","gustavo"),
           comida_preferida=c("macarronada","salgadinho","bolacha","churrasco"),
           presenca=c(T,T,F,T),
           idade=c(14,18,20,47))

Para facilitar a leitura, após cada coluna eu pressiono a tecla “Enter” para descer uma linha. O R não lê esse Enter e nem espaços ou tabs (na maioria dos contextos), logo usamos disso para tornar nosso código mais organizado. Mesmo assim, posso escrever tudo numa só linha sem problema alguma.

data.frame(alunos=c("matheus","carlos","bossa","gustavo"),comida_preferida=c("macarronada","salgadinho","bolacha","churrasco"),idade=c(14,18,20,47))

Grande parte da atuação com R para análise de dados e mesmo desenvolvimento de estudos em outros objetos de pesquisa usa muito dos data.frames e suas particularidades. Por isso dedicaremos mais tempo para eles.

Mais sobre data.frames

Como fica aparente, um data.frame é uma junção de vários objetos unidimensionais, o que significa que também podemos criá-los combinandos esses objetos, como fazemos abaixo. Há algumas limitações sobre o tamanho dos objetos, mas se tratam de casos mais específicos que não convém referenciar aqui.

alunos <- c("maria","joao","caio","matheus")
portugues <- c(4,7,9,10)

data.frame(alunos,portugues)

Podemos também misturar abordagens, combinando objetos com dados inseridos dentro da função data.frame.

data.frame(alunos,portugues,faltas=c(1,2,3,4))

Ou ainda atribuir um mesmo valor para todas as observações.

data.frame(alunos,portugues,faltas=1)

Podemos usar, dentro da própria função, objetos para gerar múltiplas colunas. No exemplo abaixo temos um objeto com notas em português de alunos e a nota final na disciplina após a soma de um ponto extra.

data.frame(alunos,portugues,nota_com_ponto_extra=portugues+1)

Se vocês notarem no enviroment não há nenhum objeto data.frame. Isso porque não salvamos o resultado dessas linhas de código digitadas acima num objeto. Para criar e armazenar um objeto data.frame usamos o já mencionado operador de associação <-. Podemos então referenciar ele em outros processos.

df <- data.frame(alunos,portugues,faltas=c(1,2,3,4))
df

Da mesma forma que com outros objetos, índices podem ser usados em data.frames, mas com uma leve diferença. Dado que temos linhas e colunas, ao usar índices aqui precisamos fornecer valores tanto para linhas quanto para colunas. Fazemos do mesmo jeito que antes, com colchetes, escrevendo o número das linhas primeiro, seguido de uma vírgula e o número das colunas. Um exemplo.

df[1,1:3]

Há, porém, uma exceção. Quando queremos todas as linhas ou colunas podemos simplesmente deixar o respectivo espaço destinado para linhas ou colunas dentro dos colchetes vazio. O R entende assim que queremos todas as linhas ou colunas.

df[,1]
## [1] "maria"   "joao"    "caio"    "matheus"
df[1,]
df[1:3,]
df[,1:3]

Se combinarmos a função c com índices, é possível extrair linhas e colunas em qualquer ordem. No caso abaixo, pegamos as linhas 2 e 3 (nesta ordem) e as colunas 2 e 1 (também nesta ordem).

df[c(2,3),c(2,1)]

Por fim, é possível criar um objeto que conterá números que atuará como um índice dentro de colchetes. Fazemos isso quando iremos fazer uma seleção de linhas e colunas muitas vezes. Uma outra justificativa a ser visto mais para frente é usar esse objeto-índice para filtar nossa tabela/data.frame.

indice <- c(1,3)
#todas as linhas das colunas 1 e 3
df[,indice]
#todas as colunas da linha 1 e 3
df[indice,]
#linhas 1 e 3 das colunas 1 e 3
df[indice,indice]

Salvando

Há dois tipos de “save” em R: salvar script e salvar o enviroment. Toda vez programamos por um tempo e que formos fechar o programa ele pergunta se queremos executar um desses “save”: “document” para o script; “workspace image” para enviroment.

Salvar o script salva tudo aquilo que foi escrito no editor de texto ao clicarmos no disquete, como mostra a imagem abaixo. Também podemos rapidamente fazer isso pressionando o botão Control e a letra S (Ctrl+S). O resultado é um arquivo em formato “.R”.

Salvar o enviroment salva todos os objetos contidos no enviroment (o painel 3). Normalmente usamos essa opção para pausar uma análise e continuar em outro momento ou caso os processos executados com os dados forem muito complexos e demorados de serem feito, gerando uma economia de tempo. O resultado é um arquivo em formato “.RData”.

Precisa de ajuda?

Uma primeira forma de resolver um problema é consultando tanto a documentação da(s) função(ões) usadas como do pacote-pai desta(s). Para consultar a documentação de uma função espefícica, digite “?” seguido do nome da função e rode, como já fizemos acima.

?paste

Para buscar a documentação do pacote procure por “nome-do-pacote cran documentation pdf” no Google. Todo pacote é obrigado a oferecer esse documentação no CRAN (repositório de pacotes). Abaixo temos o documento para o “stringr”.

Por fim, usem o Google. Procurem o pacote da função, a própria função ou ainda algo que você gostaria de fazer no Google para consultar vídeos no YouTube de tutoriais ou posts no StackOverFlow, um “yahoo respostas” referente à programação no geral. Lembre-se de colocar “in r”/“no r” nas suas buscas, já que é muito fácil acabar caindo em algum post de outra linguagem de programação.

Exercícios

Questões

  1. Crie um data.frame contendo dados fictícios. Coloque ao menos 6 linhas com: nome, cor favorita, idade e se possui alguma animal de estimação (booleano).

  2. Extraia apenas nome e animal de estimação usando índices.

  3. Extraia apenas as observações 3,4,5 usando índices.

  4. (Desafio) Escolha aleatoriamente duas linhas dos dados e extraia todas as informações de ambas do nosso data.frame.

  • Dica: primeiro precisamos armazenar os respectivos índices em um objeto separado e depois usar de índices para fazer a extração dos respectivos dados.
  1. (Desafio) Você gostaria de saber quantas horas cada uma das pessoas do data.frame tem de vida. Para isso, você precisa primeiro saber quantos dias cada pessoa tem e em seguida quantas horas. Faça esse cálculo.
  • Dica: você precisará usar índices para selecionar apenas as idades, para em seguida multiplicá-las por 365 dias e o resultado disso multiplicar por 24 horas.
  1. (Desafio) Adicione uma nova coluna que contenha o time de futebol chamada time que contenha o time de cada uma das pessoas. Extraia então usando índices o nome e o time.
  • Dica: vimos que é possível criar um data.frame combinando objetos e escrevendo manualmente os dados. Também é possível fazer o mesmo com um data.frame já existente. Para isso, pensem em como fizemos isso no exemplo das faltas usado acima. Lembrem-se de que se não usarmos o operador de associação o objeto não é salvo e não pode ser referenciado.

Soluções

dados1 <- data.frame(nome=c("caio","joão","camila","bruna","denis","joselito"),
                    cor=c("azul","vermelho","amarelo","azul","azul","amarelo"),
                    idade=c(18,26,30,13,49,58),
                    animal_de_estimacao=c(T,T,F,T,F,F))
dados1[,c(1,4)]
dados1[3:5,]
nomes <- c(2,4)

dados1[nomes,]
(dados1[,3]*365)*24
## [1] 157680 227760 262800 113880 429240 508080
  1. Há duas formas (por enquanto) de fazer a inserção de uma nova coluna. Podemos escrever os times num objeto a parte e depois unir ao data.frame ou escrever manualmente dentro da função data.frame.
#primeira opcao
times <- c("corinthians","flamengo","fluminense","bahia","santos","palmeiras")
dados2 <- data.frame(dados1,times)

#segunda opcao
dados2 <- data.frame(dados1,
                     times=c("corinthians","flamengo","fluminense","bahia","santos","palmeiras"))

dados2[,c(1,5)]

Segundo encontro (13/09): dplyr

Neste segundo encontro daremos continuidade aos estudos em R, dessa vez já introduzindo uma base de dados reais, o uso de pacotes e scripts de agregação. Aprenderemos a preparar um ambiente de análise, abrir um arquivo .csv e manipularmos ele.

Arrumando a casa

O primeiro passo para toda análise é organizar um espaço dentro do seu computador que irá conter todos os dados e arquivos relevantes a serem usados. Criamos uma pasta de fácil acesso na nossa máquina (de preferência dentro de “Documentos” ou “Meus Documentos”). No meu caso essa pasta se encontra em “Documentos > GitHub” e se chama “curso-r-pos-grad”.

Feito isso, baixaremos o arquivo de dados disponibilizado para vocês entitulado “cartao_bolsonaro2019.csv” e jogaremos ele dentro dessa pasta. Abriremos então o RStudio, clicaremos em “File”, “New File” e “R Script”. Isso irá abrir o editor de texto. Podemos também só usar o atalho “Ctrl+Shift+N”.

Clicaremos então no disquete para salvar o script, o que abrirá uma janela padrão de salvar documentos. Navegaremos até nossa pasta criada, daremos um nome simples e elucidativo para o script e clicaremos em “Save”/“Salvar”.

O último passo consiste em mostrar para o R, através do script, que iremos trabalhar dentro da pasta criada. Para isso usamos a função setwd, que significa “set working directory”, junto com o endereço da pasta. Para obtê-lo, vamos até a pasta, clicamos na barra superior que aparece descrito o caminho da pasta. Isso irá converter o caminho em endereço. Copiamos ele e colamos dentro do setwd, com aspas. Depois disso, trocamos todos os “\” por “/” (uma particularidade muito específica do R). Para confirmar se tudo correu bem, usamos a função getwd, ou “get working directory”. O resultado deve ser a pasta que criamos anteriormente.

setwd("C:/Users/arjon/Documents/GitHub/curso-r-pos-grad")
getwd()
## [1] "C:/Users/arjon/Documents/GitHub/curso-r-pos-grad"

Pronto, estamos aptos a começar a trabalhar. Há outras formas de otimizar esse processo, mas por hora essa definição feita manualmente já basta.

Abrindo nossa primeira base

O R base é capaz de abrir diversos tipos de arquivos de base de dados. Quando há um novo ou diferente formato, usamos pacotes (mais sobre isso daqui a pouco) para abrir os arquivos. O formato mais tradicional é o “.csv”, “comma-separated-value”, mas é comum também usarmos “.txt” ou “.xlsx”.

Para abrir nossa base usamos a função read.table. Ela possui vários argumentos opcionais que podemos usar eventualmente. Abaixo temos o código, lembrando sempre de associar o resultado de uma função a um objeto usando <-. O processo de importação é concluído quando o objeto aparece no enviroment e quando a placa vermelha de pare no canto superior direito do console desaparece. O resultado é um data.frame.

dados <- read.table("cartao_bolsonaro2019.csv",
                    sep=",",dec=".",
                    header=TRUE,
                    fileEncoding = "latin1")

Há uma função chamada read.csv. Não usamos ela já que há algumas configurações nela que são padronizadas e não servem para nosso caso. Por exemplo, ela tem a premissa de que as colunas são separadas por vírgula (“,”) e os números decimais por ponto (“.”). Qualquer coisa que fuja disso nos oferece um erro. read.table nos dá autonomia para definir esses aspectos padronizados. De qualquer forma, não há problema em usar uma ou outra, desde que vocês conheçam as necessidades de cada uma.

Podemos conhecer nossos dados de várias formas. Primeiro, se digitarmos seu nome e rodarmos, o R mostrará ele no console, mas normalmente nao fazemos isso já que a visualização não é muito boa (tentem mesmo assim). Segundo, podemos usar a função View (com V maiúsculo), que abre uma janela ao lado do editor de texto com os dados. Terceiro, podemos rodar “funções-resumo”, que nos oferecemos rápidas infos dos dados.

View

Abre uma visualização dos dados mas amigável.

View(dados)

str

Mostra a classe de todas as colunas, junto com alguns valores.

str(dados)
## 'data.frame':    115481 obs. of  15 variables:
##  $ CÓDIGO.ÓRGÃO.SUPERIOR : int  63000 63000 63000 63000 63000 63000 63000 63000 63000 63000 ...
##  $ NOME.ÓRGÃO.SUPERIOR   : chr  "Advocacia-Geral da União" "Advocacia-Geral da União" "Advocacia-Geral da União" "Advocacia-Geral da União" ...
##  $ CÓDIGO.ÓRGÃO          : int  63000 63000 63000 63000 63000 63000 63000 63000 63000 63000 ...
##  $ NOME.ÓRGÃO            : chr  "Advocacia-Geral da União - Unidades com vínculo direto" "Advocacia-Geral da União - Unidades com vínculo direto" "Advocacia-Geral da União - Unidades com vínculo direto" "Advocacia-Geral da União - Unidades com vínculo direto" ...
##  $ CÓDIGO.UNIDADE.GESTORA: int  110096 110096 110096 110096 110096 110096 110096 110096 110096 110096 ...
##  $ NOME.UNIDADE.GESTORA  : chr  "SUPERINTENDENCIA ADMINISTRACAO EM PERNAMBUCO" "SUPERINTENDENCIA ADMINISTRACAO EM PERNAMBUCO" "SUPERINTENDENCIA ADMINISTRACAO EM PERNAMBUCO" "SUPERINTENDENCIA ADMINISTRACAO EM PERNAMBUCO" ...
##  $ ANO.EXTRATO           : int  2019 2019 2019 2019 2019 2019 2019 2019 2019 2019 ...
##  $ MÊS.EXTRATO           : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ CPF.PORTADOR          : chr  "***.061.482-**" "***.061.482-**" "***.299.005-**" "***.299.005-**" ...
##  $ NOME.PORTADOR         : chr  "CRISTINA SILVA CAMARA DOS SANTOS" "CRISTINA SILVA CAMARA DOS SANTOS" "ALCIO RIBEIRO BRITTO" "ALCIO RIBEIRO BRITTO" ...
##  $ CNPJ.OU.CPF.FAVORECIDO: num  4.33e+13 4.33e+13 1.62e+13 1.62e+13 4.98e+12 ...
##  $ NOME.FAVORECIDO       : chr  "KALUNGA COMERCIO E INDUSTRIA GRAFICA LTDA" "KALUNGA COMERCIO E INDUSTRIA GRAFICA LTDA" "PITUBA MATERIAIS DE CONSTRUCAO LTDA" "PITUBA MATERIAIS DE CONSTRUCAO LTDA" ...
##  $ TRANSAÇÃO             : chr  "COMPRA A/V - R$ - APRES" "COMPRA A/V - R$ - APRES" "COMPRA A/V - R$ - APRES" "COMPRA A/V - R$ - APRES" ...
##  $ DATA.TRANSAÇÃO        : chr  "11/12/2018" "03/12/2018" "14/12/2018" "07/12/2018" ...
##  $ VALOR.TRANSAÇÃO       : num  72.1 115 136.4 9.9 98 ...

summary

Gera números de todas as colunas. As numéricas nos oferecem estatísticas descritivas, as character o número de linhas e as factor (que não aparecem aqui) o número de linhas com cada um dos valores de levels.

summary(dados)
##  CÓDIGO.ÓRGÃO.SUPERIOR NOME.ÓRGÃO.SUPERIOR  CÓDIGO.ÓRGÃO    NOME.ÓRGÃO       
##  Min.   :20000         Length:115481       Min.   :20101   Length:115481     
##  1st Qu.:25000         Class :character    1st Qu.:25000   Class :character  
##  Median :26000         Mode  :character    Median :26246   Mode  :character  
##  Mean   :30011                             Mean   :29896                     
##  3rd Qu.:30000                             3rd Qu.:30108                     
##  Max.   :81000                             Max.   :81000                     
##  CÓDIGO.UNIDADE.GESTORA NOME.UNIDADE.GESTORA  ANO.EXTRATO    MÊS.EXTRATO    
##  Min.   :110001         Length:115481        Min.   :2019   Min.   : 1.000  
##  1st Qu.:114624         Class :character     1st Qu.:2019   1st Qu.: 5.000  
##  Median :158336         Mode  :character     Median :2019   Median : 7.000  
##  Mean   :184149                              Mean   :2019   Mean   : 7.209  
##  3rd Qu.:200356                              3rd Qu.:2019   3rd Qu.:10.000  
##  Max.   :810005                              Max.   :2019   Max.   :12.000  
##  CPF.PORTADOR       NOME.PORTADOR      CNPJ.OU.CPF.FAVORECIDO
##  Length:115481      Length:115481      Min.   :-1.100e+01    
##  Class :character   Class :character   1st Qu.:-2.000e+00    
##  Mode  :character   Mode  :character   Median : 2.493e+12    
##                                        Mean   : 1.290e+13    
##                                        3rd Qu.: 1.463e+13    
##                                        Max.   : 9.841e+13    
##  NOME.FAVORECIDO     TRANSAÇÃO         DATA.TRANSAÇÃO     VALOR.TRANSAÇÃO   
##  Length:115481      Length:115481      Length:115481      Min.   :    0.75  
##  Class :character   Class :character   Class :character   1st Qu.:   77.00  
##  Mode  :character   Mode  :character   Mode  :character   Median :  198.58  
##                                                           Mean   :  452.76  
##                                                           3rd Qu.:  531.00  
##                                                           Max.   :97684.15

colnames

Nos mostra o nome de todas as colunas do arquivo.

colnames(dados)
##  [1] "CÓDIGO.ÓRGÃO.SUPERIOR"  "NOME.ÓRGÃO.SUPERIOR"    "CÓDIGO.ÓRGÃO"          
##  [4] "NOME.ÓRGÃO"             "CÓDIGO.UNIDADE.GESTORA" "NOME.UNIDADE.GESTORA"  
##  [7] "ANO.EXTRATO"            "MÊS.EXTRATO"            "CPF.PORTADOR"          
## [10] "NOME.PORTADOR"          "CNPJ.OU.CPF.FAVORECIDO" "NOME.FAVORECIDO"       
## [13] "TRANSAÇÃO"              "DATA.TRANSAÇÃO"         "VALOR.TRANSAÇÃO"

Uma outra forma de referenciar colunas de um data.frame é usando o operador de cifrão (“$”). Ao digitarmos o nome do nosso objeto seguido de um cifrão podemos digitar o nome de qualquer uma das colunas e rodar o código assim. O resultado será apenas a coluna selecionada. Abaixo rodamos esse código com um head para reduzir o número de resultados e facilitar a visualização.

head(dados$NOME.ÓRGÃO,n=10)
##  [1] "Advocacia-Geral da União - Unidades com vínculo direto"
##  [2] "Advocacia-Geral da União - Unidades com vínculo direto"
##  [3] "Advocacia-Geral da União - Unidades com vínculo direto"
##  [4] "Advocacia-Geral da União - Unidades com vínculo direto"
##  [5] "Advocacia-Geral da União - Unidades com vínculo direto"
##  [6] "Advocacia-Geral da União - Unidades com vínculo direto"
##  [7] "Advocacia-Geral da União - Unidades com vínculo direto"
##  [8] "Advocacia-Geral da União - Unidades com vínculo direto"
##  [9] "Advocacia-Geral da União - Unidades com vínculo direto"
## [10] "Advocacia-Geral da União - Unidades com vínculo direto"

Um porém. Nomes com espaço, acentos ou até alguns caracteres especiais podem dificultar esse tipo de referenciação. Por isso é importante limpar os dados das colunas quando essa premissa for rompida. Para isso usamos a função names, seguido do nome do objeto, operador de associação e os novos nomes, como fazemos abaixo. O formato não é totalmente ideal ainda, mas já é o suficiente para nossos objetivos.

names(dados) <- c("código_órgão_superior","nome_órgão_superior","código_órgão",
                  "nome_órgão","código_unidade_gestora","nome_unidade_gestora",
                  "ano_extrato","mês_extrato","cpf_portador","nome_portador",
                  "cnpj_ou_cpf_favorecido","nome_favorecido","transação",
                  "data_transação","valor_transação")

table e prop.table

Há duas outras funções do R base que podemos usar para navegar nos dados sem ainda entrar em pacotes: table e prop.table. Ambas são mais usadas para quando temos variáveis de tipo factor ou characters com número limitado de opções e servem para contar quantas observações de cada valor de uma coluna há na nossa base.

Nos dados que estamos usando, “nome_órgão_superior” possui um número limitado de valores respectivo às seções do Poder Executivo Federal. Enquanto table apenas conta observações, prop.table nos dá a proporção de um dos valores na soma total de observações. Para a primeira delas, basta usarmos só o nome da função, enquanto que para a segunda precisamos chamar um table antes e só daí usarmos prop.table.

table

table(dados$nome_órgão_superior)
## 
##                      Advocacia-Geral da União 
##                                          1242 
##                  Controladoria-Geral da União 
##                                           107 
## Ministério da Agricultura, Pecuária e Abastec 
##                                          9927 
##                       Ministério da Cidadania 
##                                           566 
## Ministério da Ciência, Tecnologia, Inovações  
##                                          2941 
##                          Ministério da Defesa 
##                                         11419 
##                        Ministério da Economia 
##                                         32411 
##                        Ministério da Educação 
##                                         20861 
##                  Ministério da Infraestrutura 
##                                          1005 
##     Ministério da Justiça e Segurança Pública 
##                                         13970 
## Ministério da Mulher, Família e Direitos Huma 
##                                             6 
##                           Ministério da Saúde 
##                                          3744 
##            Ministério das Relações Exteriores 
##                                            69 
##                 Ministério de Minas e Energia 
##                                          4094 
##        Ministério do Desenvolvimento Regional 
##                                          2915 
##                   Ministério do Meio Ambiente 
##                                          1029 
##              Ministério do Trabalho e Emprego 
##                                           373 
##                      Presidência da República 
##                                          8802

prop.table

prop.table(table(dados$nome_órgão_superior))
## 
##                      Advocacia-Geral da União 
##                                  0.0107550160 
##                  Controladoria-Geral da União 
##                                  0.0009265593 
## Ministério da Agricultura, Pecuária e Abastec 
##                                  0.0859621929 
##                       Ministério da Cidadania 
##                                  0.0049012392 
## Ministério da Ciência, Tecnologia, Inovações  
##                                  0.0254673929 
##                          Ministério da Defesa 
##                                  0.0988820672 
##                        Ministério da Economia 
##                                  0.2806608879 
##                        Ministério da Educação 
##                                  0.1806444350 
##                  Ministério da Infraestrutura 
##                                  0.0087027303 
##     Ministério da Justiça e Segurança Pública 
##                                  0.1209722812 
## Ministério da Mulher, Família e Direitos Huma 
##                                  0.0000519566 
##                           Ministério da Saúde 
##                                  0.0324209177 
##            Ministério das Relações Exteriores 
##                                  0.0005975009 
##                 Ministério de Minas e Energia 
##                                  0.0354517193 
##        Ministério do Desenvolvimento Regional 
##                                  0.0252422476 
##                   Ministério do Meio Ambiente 
##                                  0.0089105567 
##              Ministério do Trabalho e Emprego 
##                                  0.0032299686 
##                      Presidência da República 
##                                  0.0762203306

Apesar da praticidade, o problema é que o resultado das funções table e prop.table não é facilmente manipulável em decorrência da sua classe. Por isso essas duas funções são mais exploratórias do que análise de fato.

Pacotes

Muitas coisas já são possíveis de serem feitas com nosso objeto no R base. Porém são nos pacotes que ganhamos poder e facilidade para nos aprofundar nos dados. Pacotes são conjuntos de funções criadas pela comunidade visando responder alguma demanda dela mesma, seja oferecendo mais o que fazer (novas funcionalidades) ou facilitando procesos antigos (novos meios de fazer a mesma coisa). Para (quase) qualquer coisa que pensemos, há um pacote para tal.

  • Automatizar análises estatísticas;
  • Criar um robô que navega em sites super rápido;
  • Baixar dados esportivos;
  • Abrir arquivos .epub (arquivos Kindle);
  • Acessar APIs;
  • Gerar gráficos;
  • Criar sites e aplicativos;
  • Entre várias outras coisas…

O mais conhecido pacote na área é o Tidyverse. Trata-se de uma coletânea de pacotes, que abrange pacotes estáveis, confiáveis, atualizados, úteis e consistentes. Nele temos praticamente tudo o que um usuário médio de R precisaria, por isso não é incomum acharmos análises que só usam ele.

Para usá-lo, precisamos fazer duas coisas: baixar o pacote e carregá-lo. Para baixar, rodamos a função install.packages, seguida do nome do pacote entre aspas. Precisamos apenas rodá-lo uma vez por máquina, já que o arquivo baixado fica salvo nas pastas do R.

install.packages("tidyverse")

Para carregar um pacote, usamos a função library, seguida do nome do pacote, mas dessa vez sem aspas. Ao contrário da instalação, toda vez que fecharmos o R, abrirmos ele de novo e desejamos usar as funções de um pacote, precisamos carregá-lo novamente. Por isso, junto com setwd, é muito comum ver scripts com essas funções no topo do arquivo.

library(tidyverse)

Neste curso usaremos três pacotes do Tidyverse: dplyr, para manipular de data.frames; stringr, para manipulação de texto; e ggplot2, para criação de gráficos. Além disso, usaremos o operador pipe %>%, que também vem pelo Tidyverse.

Dplyr

Apesar da amplitude de funções e opções, o pacote dplyr possui meia dúzia de funções que usaremos de maneira constante em análises. Elas servem para selecionar variáveis, agrupar observações, filtrar dados, criar variáveis e organizar visualizações.

select

Essa função seleciona colunas usando seus índices ou apenas seus nomes. Também podemos usar para remover colunas específicas. Seus argumentos são: primeiro, o nosso data.frame; segundo, as colunas a serem mantidas ou removidas. Podemos fazer como os índices e associar as colunas a um objeto e então usar este dentro do select.

Quando queremos manter ou remover mais de uma coluna e armazenamos os índices ou nomes num objeto, precisamos fechar o objeto dentro de uma função auxiliar chamda all_of. Essa é uma particularidade recente do dplyr e não tem implicações significativas neste caso.

Selecionando colunas não usando objeto

head(select(dados,c(1,2,3)),n=3)

Selecionando colunas usando objeto

vars <- c(1,2,3)
head(select(dados,all_of(vars)),n=3)

Removendo colunas não usando objetos

Para remover, só precisamos colocar um sinal de menos (ou hífen) antes da lista de colunas. Lê-se “todas as colunas exceto essas indicadas”. No caso abaixo removemos da coluna 4 até a 15, o que resulta na mesma coisa que o código da outra aba.

head(select(dados,-c(4:15)),n=3)

Removendo colunas usando objetos

vars <- c(4:15)
head(select(dados,-all_of(vars)),n=3)

Podemos também usar os nomes das colunas para fazer esse tipo de manipulação. O mesmo processo de antes pode ser feito: com ou sem objetos. Perceba que não fechamos os nomes das colunas com aspas quando colocamos eles direto no select, enquanto que na abordagem que usamos o objeto precisamos colocar aspas já no objeto. Novamente, uma particularidade do pacote. É preferível usar os índices ao invés dos nomes.

head(select(dados,c(nome_órgão_superior)),n=3)
head(select(dados,-c(nome_órgão_superior)),n=3)
vars <- c("nome_órgão_superior")

head(select(dados,all_of(vars)),n=3)
head(select(dados,-all_of(vars)),n=3)

filter

Como o nome já diz, filter aplica um filtro nos dados usando condições lógicas (TRUE ou FALSE). Seus argumentos são os dados e a condição usada para filtrar. Todos os dados que derem verdadeiro (TRUE) para o teste lógico da condição são mantidos, o restante é removido.

head(filter(dados,nome_órgão_superior == "Presidência da República"))

Atenção para três pontos: o nome das colunas aqui precisa estar exatamente do jeito que é escrito no objeto data.frame; por outro lado, o texto que será procurado (“Presidência da República”, por exemplo) precisa estar com aspas; usamos os operadores lógicos vistos lá no primeiro encontro para descrever condições lógicas (neste caso usamos o ==, que significa igualdade). No caso acima filtramos apenas despesas efetuadas pela Presidência da República (junto com um head para termos apenas um resumo dos dados).

Muito pode ser feito com filtros. Podemos aplicar múltiplas condições concomitantes (x E y), concorrentes (x OU y) ou intervales (valor numérico 1 < x < valor númerico 2). Abaixo temos alguns exemplos. O importante a notar são os operadores lógicos usados, os mesmos dos exemplos de comparações da primeira aula. (Por conta do tamanho dos resultados, alguns códigos podem não apresentar resultados tão intuitivos, por isso dê preferência para rodá-los no R e acompanhar a explicação por aqui).

Filtrando valores

Usamos os operador de maior(“>”) / maior-igual(“>=”) ou menor(“<”) / menor-igual(“<=”).

head(filter(dados,valor_transação >10000),n=3)

Duas condições concomitantes

Usamos o operador lógico “&” (Shift+7) para unir as condições. Leia-se “x E y”.

head(filter(dados,nome_órgão_superior=="Presidência da República" & valor_transação >10000),n=3)

Duas condições concorrentes

Usamos o operador lógico “|” (Shift+\) para diferenciar as condições. Leia-se “x OU y”.

head(filter(dados,
            nome_órgão_superior=="Presidência da República" | nome_órgão_superior== "Ministério da Economia"),n=10)

Condições concorrentes e concomitantes

Há um cenário mais complexo ainda: duas condições juntas OU outras duas condições juntas. Por exemplo presidência e valor acima de 10.000 reais ou Ministério da Economia com tipo de transação “saque” (que nos nossos dados aparece na coluna “transação” com o nome “SAQUE CASH/ATM BB”). Para isso precisamos amarrar as condições concomitantes com parênteses.

head(filter(dados, (nome_órgão_superior=="Presidência da República" & valor_transação >10000) | nome_órgão_superior=="Ministério da Economia" & transação=="SAQUE CASH/ATM BB"),n=3)

Por fim, temos o filtro por contenção. Nele usamos um objeto contendo um conjunto de valores e o operador lógico de contenção %in% (porcentagem-in-porcentagem). Por exemplo, o código abaixo cria um objeto contém dois órgãos a serem considerados () e aplica um filtro selecionando despesas feitas pelos órgãos superiores com nomes que estejam contidos dentro de um conjunto de nomes (nosso objeto criado previamente, no caso). Lemos um filtro desses como: “filtre observações do data.frame em que a variável/coluna ‘nome_órgão_superior’ esteja contido em objeto criado”.

orgaos <- c("Presidência da República","Ministério da Economia")

head(filter(dados,nome_órgão_superior %in% orgaos),n=5)

O céu é o limite! Podemos misturar todos esses tipos de filtros juntos, de forma concorrente ou concomitante. Experimentem, mas tenham cautela com os parênteses.

group_by + summarise

Essas duas funções estão sempre juntas já uma depende da outra: group_by junta as observações com base em uma ou mais colunas; summarise “cria” variáveis agrupadas para os grupos formados. No exemplo abaixo, agrupamos por nome_órgão_superior no group_by e pedimos a soma de todas as transações para cada grupo formado no summarise.

summarise(group_by(dados,nome_órgão_superior),soma=sum(valor_transação))

A parte “soma=” do nosso código indica que o cálculo a ser executado no summarise (que se encontra depois do sinal de igual) será associado a uma coluna chamada “soma”. A visualização conterá apenas as variáveis usadas no agrupamento e aquelas criadas no summarise. Podemos “criar” mais de uma variável nesse processo dentro do summarise, precisando apenas que separemos cada uma delas com uma vírgula.

Abaixo executamos um desdobramento do código anterior com várias medidas: soma total, número de despesas, média, mediana, mínimo e máximo. Cada uma delas usa uma função do R base para fazer o cálculo desejado: sum,n,mean,median,min e max. Salvamos o resultado num objeto porque iremos utilizá-lo em seguida.

resumo <- summarise(group_by(dados,nome_órgão_superior),
                    soma=sum(valor_transação),
                    contagem=n(),
                    media=mean(valor_transação),
                    mediana=median(valor_transação),
                    min=min(valor_transação),
                    max=max(valor_transação))

resumo

Podemos também referenciar as próprias variáveis criadas dentro de um summarise para criar outras variáveis.

summarise(group_by(dados,nome_órgão_superior),
          media=mean(valor_transação),
          media_vezes_2=media*2)

O mais importante a se lembrar é que esse processo de agrupamento+sumarização apenas gera resumos dos dados. Ele reduz a base original a uma linha por grupo criado (ou seja, agregado os dados) e não cria variáveis na base original. Para isso usamos a função mutate.

arrange

Como o nome já diz, a função arrange organiza os dados com base em algum critério (ascendente ou descente) aplicado a alguma variável (numérica, textual ou lógica). Para números, vamos do menor ao maior, para letras do A ao Z e para lógica vamos do FALSE (lido como 0) ao TRUE (lido como 1).

Podemos aninhar tipos de organização e misturar ordens crescentes e decrescentes, apenas precisamos indicar quais casos queremos a ordem descrescente amarrando a variável selecionada na função desc, como no caso abaixo. Nela ordenamos por nome do órgão (de A até Z) e por média decrescente (da maior até a menor).

arrange(resumo,nome_órgão_superior,desc(media))

A ordem com que escrevemos as ordenações importa: na letra A podemos ter múltiplas médias iguais que não necessariamente serão organizadas da mesma maneira caso ordenassemos por média e depois alfabética.

mutate

Finalmente, a função cria novas variáveis/colunas de fato na nossa base. Seguimos um formato muito semelhante ao usado na função summarise, indicando o nome da coluna, sinal de =, e o conteúdo da coluna. Esta pode ser uma fórmula matemática, outras colunas tratadas (como textos que foram modificados ou numéros convertidas) e até uma condicional onde o conteúdo muda a depender do conteúdo de outras colunas.

No caso abaixo criamos uma nova coluna chamada “diff_media” que nos oferece a diferença do valor de cada despesa feita e da média geral das despesas. Muitos valores serão negativos justamente porque alguns poucos outliers conseguem jogar a média lá pra cima.

head(mutate(dados,diff_media=valor_transação-mean(valor_transação)),n=5)

Podemos usar a mediana ao invés disso. Os valores são muito mais modestos.

head(mutate(dados,diff_media=valor_transação-median(valor_transação)),n=5)

Um mutate com condição lógica usando de funções condicionais. Aqui usamos a ifelse que tem como argumento: a condição a ser avaliada/testada (“test”); um valor para caso a avaliação dê verdadeiro/TRUE (“yes”); e um valor para caso a avaliação dê falso/FALSE (“no”). Como há muitos parênteses, no código abaixo usaremos muito da tecla Enter para quebrar um pouco a visualização do código.

head(mutate(dados,
            mutate_condicional=ifelse(valor_transação>500,
                                      "Maior que 500",
                                      "Menor que 500")),
     n=10)

O resultado considerou se o valor da despesa é maior que 500 reais, dando valor “Maior que 500” para caso positivo e “Menor que 500” para caso negativo. É possível aninhar múltiplas condições, da mesma forma que na função filter.

Atenção! Caso você nomeie uma coluna com um mutate com o mesmo nome de outra coluna já existente naquela base, a função irá substituir uma pela outra. Há casos onde isso é útil ou não.

Operador pipe %>%

As funções acima quando separadas perdem muito da sua praticidade e quando elas são unidas a estratégia do R base é aninhar umas dentro das outras como fizemos anteriormente (sempre tomando cuidado com os parênteses). O operador pipe resolve isso ao permitir uma nova forma de unir funções para gerar um resultado, ao tornar a execução de um código mais “linear”. Vejamos um exemplo.

mean(head(seq(100,125),n=3))
## [1] 101

Na linha acima, a função é executada de dentro para fora: primeiro, geramos a sequência (que neste caso terá 25 números de 100 até 125); segundo, pedimos um head deste resultado que deverá ter apenas 3 números (argumento n=3); terceiro, usamos a função mean para obtermos a média dos 3 números. Percebam como saímos da função “mais interna” até a “mais externa”. A analogia aqui é das ondas de uma gota d’água.

O pipe (%>%, porcentagem-menor que-porcentagem, ou Ctrl+Shift+M) permite executarmos uma função depois da outra, da esquerda para direita e de cima para baixo. A mesma sequência de códigos acima poderia ser reescrita usando o pipe da seguinte forma:

seq(100,125) %>% 
  head(n=3) %>% 
  mean()
## [1] 101

Percebam a lógica: a primeira linha gera uma sequência que é passa para a segunda linha que extrai um head de 3 observações que são então usadas na terceira linha para calcular a média. A melhor analogia para um pipe é a de uma linha de produção onde o produto de um processo é passado ao segundo, terceiro, quarto ad infinitum.

Por trás do pipe o que ocorre é a passagem dos resultados de uma etapa para o primeiro argumento da etapa seguinte, o que na maioria das funções em R, é sempre os dados aos quais iremos aplicar uma função. No caso acima, o primeiro argumento de head e mean é x, uma forma comum referenciar um objeto qualquer. Por isso nos casos seguintes após seq apenas ofeceremos às funções os respectivos argumentos opcionais de nosso interesse (no caso do mean não oferecemos argumento algum!). Essa é a única limitação do operador pipe.

dplyr + pipe: manipulando dados

Estando familiarizados com essas funções e o operador pipe, podemos começar a manipular nossos dados combinando as coisas. O que faremos a seguir é unir cada uma das funções mencionadas a cima em grandes blocos de código que resumirão nossos dados de determinada forma.

Nosso primeiro código será para obtermos apenas as despesas executadas pela Presidência da República no mês de maio (escolha arbitrária), o nome da pessoa portadora do cartão corporativo, o nome do estabelecimento, o tipo de transação e o valor da transação. Para isso rodamos primeiro um select, seguido de um filter e finalizamos com um head. Para ver mais dos dados, use uma View.

dados %>% 
  select(2,8,10,12,13,15) %>% 
  filter(mês_extrato == 5 & nome_órgão_superior == "Presidência da República") %>% 
  head(n=15)

Se desejarmos saber mais sobre as despesas de cada nome_órgão_superior, podemos usar o código abaixo, que usa de um summarise para gerar diversas métricas para cada um dos órgãos. Usamos arrange com um desc interno para organizar os dados da maior soma até a menor.

dados %>% 
  group_by(nome_órgão_superior) %>% 
  summarise(contagem=n(),
            soma=sum(valor_transação),
            media=mean(valor_transação),
            mediana=median(valor_transação),
            min=min(valor_transação),
            max=max(valor_transação)) %>% 
  arrange(desc(soma))

Digamos que estejamos interessados em conhecer o perfil das despesas sigilosas. Por conta dessa categoria, não sabemos do que se trata, mas podemos obter alguns insights olhando o número delas, suas métricas e os seus órgãos “praticantes”. É o que fazemos abaixo usando group_by e summarise. Na nossa base, é possível saber que quando uma despesa é sigilosa essa informação é colocada em várias colunas. Por isso usamos “nome_favorecido” para filtrar apenas despesas sigilosas.

dados %>% 
  filter(nome_favorecido=="Sigiloso") %>% 
  group_by(nome_órgão_superior) %>% 
  summarise(contagem=n(),
            soma=sum(valor_transação),
            media=mean(valor_transação),
            mediana=median(valor_transação),
            min=min(valor_transação),
            max=max(valor_transação)) %>% 
  arrange(desc(soma))

Podemos ver “em tempo real” os dilemas do uso da média VS mediana: a presidência, fazendo numericamente menos despesas, apresentou valores em reais bem superiores aos dos outros órgãos. Uma próxima etapa poderia ser focar só na presidência.

Segundo a ordem das colunas, a hierarquia das instituições é “nome_órgão_superior”, “nome_órgão” e “nome_unidade_gestora”. No caso da presidência, dentro do maior nível “Presidência da República” temos apenas “Gabinete da Vice-Presidência” e novamente “Presidência da República”. A diluição maior das despesas aqui se encontra em “nome_unidade_gestora”. Por isso usamos ela para aplicar nosso group_by. Usamos “nome_órgão” para filtrar por “Presidência da República”.

dados %>% 
  filter(nome_órgão=="Presidência da República" & nome_favorecido=="Sigiloso") %>% 
  group_by(nome_unidade_gestora) %>% 
  summarise(contagem=n(),
            soma=sum(valor_transação),
            media=mean(valor_transação),
            mediana=median(valor_transação),
            min=min(valor_transação),
            max=max(valor_transação)) %>% 
  arrange(desc(soma))

Faço três observações aqui. Primeiro, na existência de duas ABIN, decorrente (provavelmente) de algum erro de digitação no nome (um tem “ê”, outra não). Isso é muito comum nesses dados e será algo que iremos corrigir no próximo encontro.

Segundo, na divergência entre média, mediana e número de despesas entre os órgãos: há órgãos com gastos mais seletivos (menos despesas), mais caros (maiores médias e medianas) e que “vencem” na soma total (maior soma).

Terceiro, não é por acaso que as despesas sigilosas da Presidência se encontrem em órgãos de inteligência, afinal eles já constam como providas desse direito na documentação que cria o CPGF. O órgão superior que mais fez despesas desse tipo (segundo nossa consulta acima) foi o Ministério da Justiça, novamente respaldado pela lei. O que seria necessário saber é porque essas despesas foram feitas usando esse mecanismo.

Finalmente, podemos estar usando o mutate para criar uma nova coluna que separa as despesas entre sigilosas ou abertas. Com isso, usando um group_by múltiplo (com o nome do órgão e essa nova coluna), podemos obter as mesmas estatísticas para ambos os casos e compará-las numa mesma visualização. Como não são todos os órgãos que fizeram despesas sigilosas, há casos onde apenas temos uma combinação de “órgão-status”.

dados %>% 
  mutate(status=ifelse(nome_favorecido=="Sigiloso","Sigiloso","Aberto")) %>% 
  group_by(nome_órgão_superior,status) %>% 
  summarise(contagem=n(),
            soma=sum(valor_transação),
            media=mean(valor_transação),
            mediana=median(valor_transação),
            min=min(valor_transação),
            max=max(valor_transação))

O mutate foi usado para reduzir a diversidade de respostas em “nome_favorecido”. Nela temos “Sigiloso” e vários outros valores (os nomes dos estabelecimentos que foram pagos com o CPGF), enquanto que na nossa coluna criada temos apenas “Sigiloso” e “Aberto”.

Para conhecer mais sobre o pacote acesse seu site oficial ou consulte a sua “cheatsheet/colinha” aqui.

Cenas do próximo capítulo

Vimos aqui que muito dos processos do dplyr dependem de como estão escritas partes dos nossos data.frames: nome das colunas e nome dos factors/characters. Apesar de ser possível modificar essas informações manualmente (reescrevendo-as), o Tidyverse oferece um pacote só para lidar com textos: o stringr. Nele temos dezenas de funções para executar processamento de texto das mais diversas naturezas. Veremos ele no nosso próximo encontro.

Exercícios

Questões

  1. Extraia métricas (como as obtidas usando summarise) para da um dos valores da coluna “transação”. Esta coluna define se a transação foi uma compra ou um saque em espécie.

  2. Luciano Hang, dono das lojas Havan, foi uma figura muito presente durante o governo de Bolsonaro. Extraia as despesas feitas em suas lojas, que aparecem com o nome “HAVAN LOJAS DE DEPARTAMENTOS LTDA” (exatamente dessa forma!) em “nome_favorecido.

  3. Selecione as despesas que constam no extrato de Agosto (mês_extrato==8), agrupe por dia e obtenha a soma total das despesas para cada um dos dias. Qual foi o dia com o menor valor total?

  4. (Desafio) Extraia informações da despesa de maior valor feita. Quem a fez, qual seu valor e em que foi gasto o dinheiro?

  • Dica: é possível usar as funções max e min para criar condições lógicas de filtro.
  1. (Desafio) Corrija o valor da maior despesa feita em 2019 pela inflação em Dezembro de 2022. Para corrigir um valor monetário passado pela inflação de forma a compararmos poderes de compra, multiplicamos o valor antigo pelo IPCA acumulado do período considerado. Para 01/2019 até 12/2022, o valor a ser multiplicado é de 1.64. Qual é o novo valor?
  • Dica: precisamos usar um mutate para criar os valores corrigidos e logo em seguida um arrange decrescente pelo valor corrigido para termos a maior despesa no topo da nossa visualização
  1. (Desafio) Encontre todas as despesas feitas pelo Ministério da Educação no cartão corporativo para a UFSCar. A universidade aparece nos dados com o nome “Fundação Universidade Federal de São Carlos” (exatamente dessa forma!) na coluna “nome_órgão”. Use um arrange decrescente de valor_transação . Selecione apenas as colunas “nome_órgão”, “nome_portador”, “nome_favorecido” e “valor_transação”. Qual o valor da maior despesa?

Soluções

Para entender o que cada sigla significa, use este site.

dados %>% 
  group_by(transação) %>% 
  summarise(contagem=n(),
            soma=sum(valor_transação),
            media=mean(valor_transação),
            mediana=median(valor_transação),
            min=min(valor_transação),
            max=max(valor_transação))
dados %>% 
  filter(nome_favorecido=="HAVAN LOJAS DE DEPARTAMENTOS LTDA")
dados %>% 
  filter(mês_extrato==8) %>% 
  group_by(data_transação) %>% 
  summarise(soma=sum(valor_transação)) %>% 
  arrange(soma)

O dia 24 de Junho de 2019 foi o que teve o menor valor total de despesas.

Para fazer isso, iremos usar um filter que selecionará apenas os casos em que o valor da despesa é igual ao valor máximo de despesas apresentado nos nossos dados, ou seja, onde valor_transação==max(valor_transação).

dados %>% 
  filter(valor_transação==max(valor_transação))

A maior despesa foi feita pela Secretaria Especial de Administração da Presidência, no valor de R$97.684,15 e é de caráter sigiloso.

dados %>% 
  mutate(valor_corrigido=valor_transação*1.64) %>% 
  arrange(desc(valor_corrigido))

O valor de 97.684,15 reais corrigido valia 160.202 reais ao final de 2022.

dados %>% 
  filter(nome_órgão=="Fundação Universidade Federal de São Carlos") %>% 
  arrange(desc(valor_transação)) %>% 
  select(nome_órgão,nome_portador,nome_favorecido,valor_transação) %>% 
  head()

A maior despesa custou 1.649,99 reais.

Terceiro encontro (20/09): stringr

Neste encontro lidaremos com dados em formato de texto, isto é, characters ou factors. No encontro anterior vimos que há entradas equivocadas nos nossos dados quanto a alguns órgãos e sub-órgãos. Além disso, o título das colunas também foi modificado para se encaixar em padrões de boas práticas em programação. Por fim, podemos ter interesse em quebrar datas e nomes de pessoas. Todas essas tarefas podem ser feitas usando o stringr.

De início, prepararemos nosso script selecionando nosso working directory, a pasta que conterá nossos dados, e carregando o tidyverse. Notem que como já instalamos ele antes, agora só precisamos rodar a função library.

setwd("C:/Users/arjon/Documents/GitHub/curso-r-pos-grad")

library(tidyverse)

Feito isso, carregamos nossos dados como feito anteriormente.

dados <- read.table("cartao_bolsonaro2019.csv",
                    sep=",",dec=".",
                    header=TRUE,
                    fileEncoding = "latin1")

As funções do stringr lidam com objetos unidimensionais de texto, o que significa que sempre que formos usar alguma delas, nós precisamos oferecer ao R um objeto desse gênero.

Dado que data.frames são junções de objetos unidimensionais, caso queiramos aplicar uma de suas funções, precisamos oferecer apenas a coluna de interesse, seja usando índices, seja usando cifrão e o nome da coluna. Enquanto o dplyr só trabalhava com data.frames, o stringr só trabalha com esses objetos unidimensionais. Todas as suas funções começando com o prefixo str_ (com exceção de str, que é do R base).

Nossa primeira tarefa consistirá em corrigir os nomes de forma mais ágil. No código abaixo, colnames(dados) produz um objeto unidimensional textual, de tipo character. As funções do stringr aceitarão ele como argumento.

colnames(dados)
##  [1] "CÓDIGO.ÓRGÃO.SUPERIOR"  "NOME.ÓRGÃO.SUPERIOR"    "CÓDIGO.ÓRGÃO"          
##  [4] "NOME.ÓRGÃO"             "CÓDIGO.UNIDADE.GESTORA" "NOME.UNIDADE.GESTORA"  
##  [7] "ANO.EXTRATO"            "MÊS.EXTRATO"            "CPF.PORTADOR"          
## [10] "NOME.PORTADOR"          "CNPJ.OU.CPF.FAVORECIDO" "NOME.FAVORECIDO"       
## [13] "TRANSAÇÃO"              "DATA.TRANSAÇÃO"         "VALOR.TRANSAÇÃO"

Neste caso, queremos que os nomes das colunas estejam todos em minúsculo e os pontos (“.”) sejam convertidos em underlines (“_“). Seria interessante também remover acentos e outros caracteres especiais (o que não faremos nesses nomes mas ensinaremos a ser feito). Usaremos o pipe para fazer essas duas mudanças de uma só vez.

Para remover o caixa-alta, usamos a função str_to_lower (para fazer o contrário, usamos o str_to_upper). Seu único argumento (relevante aqui) é o objeto que será tirado do caixa-alta. Usando um pipe para passar o resultado de colnames(dados) como argumento em str_to_lower.

colnames(dados) %>% 
  str_to_lower()
##  [1] "código.órgão.superior"  "nome.órgão.superior"    "código.órgão"          
##  [4] "nome.órgão"             "código.unidade.gestora" "nome.unidade.gestora"  
##  [7] "ano.extrato"            "mês.extrato"            "cpf.portador"          
## [10] "nome.portador"          "cnpj.ou.cpf.favorecido" "nome.favorecido"       
## [13] "transação"              "data.transação"         "valor.transação"

Para substituir o ponto por underline, usamos a função str_replace_all. Seus argumentos são: o objeto a ser aplicada a função; “pattern” que é um padrão textual para identificar um caractere; e “replacement” que é aquilo que será colocado no lugar do “pattern”. O replace do nome da função vem dessa troca. O all garante que caso hajam mais de uma correspondência do “pattern” por elemento do objeto, todos eles serão substituídos (como no caso de “NOME.ÓRGÃO.SUPERIOR”, que tem dois pontos).

colnames(dados) %>% 
  str_replace_all(pattern="\\.",replacement = "_")
##  [1] "CÓDIGO_ÓRGÃO_SUPERIOR"  "NOME_ÓRGÃO_SUPERIOR"    "CÓDIGO_ÓRGÃO"          
##  [4] "NOME_ÓRGÃO"             "CÓDIGO_UNIDADE_GESTORA" "NOME_UNIDADE_GESTORA"  
##  [7] "ANO_EXTRATO"            "MÊS_EXTRATO"            "CPF_PORTADOR"          
## [10] "NOME_PORTADOR"          "CNPJ_OU_CPF_FAVORECIDO" "NOME_FAVORECIDO"       
## [13] "TRANSAÇÃO"              "DATA_TRANSAÇÃO"         "VALOR_TRANSAÇÃO"

Podemos juntar tudo num pipe e já usar o operador de associação para corrigir os nomes da nossa base.

names(dados) <- colnames(dados) %>% 
  str_to_lower() %>% 
  str_replace_all(pattern="\\.",replacement = "_")

colnames(dados)
##  [1] "código_órgão_superior"  "nome_órgão_superior"    "código_órgão"          
##  [4] "nome_órgão"             "código_unidade_gestora" "nome_unidade_gestora"  
##  [7] "ano_extrato"            "mês_extrato"            "cpf_portador"          
## [10] "nome_portador"          "cnpj_ou_cpf_favorecido" "nome_favorecido"       
## [13] "transação"              "data_transação"         "valor_transação"

Um adendo muito importante. No “pattern” para substituir o ponto, escrevemos “\\.” ao invés de “.” porque esse caracter tem um significado especial para o stringr (que consta na segunda página da colinha). Em 75% dos casos escrevemos o “pattern” normalmente, porém há esses poucos casos que são exceções. Usem a colinha ou pesquisem no Google (provavelmente em inglês) sobre como substituir um caracter especial que esteja dando problemas para vocês.

Corrigindo nomes dos órgãos

Apenas com str_replace_all e str_to_upper já é possível limparmos os dados problemáticos do último encontro. Com essas funções convertemos todo o texto em caixa-alta e removemos “ê” ou “Ê” dos nossos dados. Quando ocorrem essas divergências, o R passa a entender essas várias versões como valores diferentes e não os unifica. Logo, quando fizemos um agrupamento para checar dados sigilosos, observamos que a ABIN tinha duas formas diferentes de ser mencionada, o que dividia as despesas em dois grupos, mesmo se tratando do mesmo órgão.

Esse problema ocorre tradicionalmente quando temos dados inseridos no sistema manualmente, digitados por seres humanos. Temos então: abreviados VS completos; com acento VS sem acento; nomes VS siglas. Quando maior a base, mais difícil é de corrigirmos isso, já que não é fácil conhecermos todos os possíveis erros que diferenciam valores.

Para observar todos os valores possíveis que há nos nossos dados usamos a função unique, do R base. A função levels faz algo parecido, mas apenas caso o tipo do dado seja factor. unique, por outro lado, independe do tipo de dado.

nome_órgão_superior

unique(dados$nome_órgão_superior)
##  [1] "Advocacia-Geral da União"                     
##  [2] "Controladoria-Geral da União"                 
##  [3] "Ministério da Agricultura, Pecuária e Abastec"
##  [4] "Ministério da Cidadania"                      
##  [5] "Ministério da Ciência, Tecnologia, Inovações "
##  [6] "Ministério da Defesa"                         
##  [7] "Ministério da Economia"                       
##  [8] "Ministério da Educação"                       
##  [9] "Ministério da Infraestrutura"                 
## [10] "Ministério da Justiça e Segurança Pública"    
## [11] "Ministério da Saúde"                          
## [12] "Ministério das Relações Exteriores"           
## [13] "Ministério de Minas e Energia"                
## [14] "Ministério do Desenvolvimento Regional"       
## [15] "Ministério do Meio Ambiente"                  
## [16] "Ministério do Trabalho e Emprego"             
## [17] "Presidência da República"                     
## [18] "Ministério da Mulher, Família e Direitos Huma"

nome_órgão

unique(dados$nome_órgão)
##   [1] "Advocacia-Geral da União - Unidades com vínculo direto"                                   
##   [2] "Controladoria-Geral da União - Unidades com vínculo direto"                               
##   [3] "Companhia Nacional de Abastecimento"                                                      
##   [4] "Empresa Brasileira de Pesquisa Agropecuária"                                              
##   [5] "Instituto Nacional de Colonização e Reforma Agrária"                                      
##   [6] "Ministério da Agricultura, Pecuária e Abastecimento - Unidades com vínculo direto"        
##   [7] "Serviço Florestal Brasileiro"                                                             
##   [8] "Agência Nacional do Cinema"                                                               
##   [9] "Fundação Casa de Rui Barbosa"                                                             
##  [10] "Fundação Cultural Palmares"                                                               
##  [11] "Fundação Nacional de Artes"                                                               
##  [12] "Instituto Brasileiro de Museus"                                                           
##  [13] "Instituto do Patrimônio Histórico e Artístico Nacional"                                   
##  [14] "Ministério da Cidadania - Unidades com vínculo direto"                                    
##  [15] "Agência Espacial Brasileira"                                                              
##  [16] "Agêncial Nacional de Telecomunicações"                                                    
##  [17] "Comissão Nacional de Energia Nuclear"                                                     
##  [18] "Conselho Nacional de Desenvolvimento Científico e Tecnológico"                            
##  [19] "Ministério da Ciência, Tecnologia, Inovações e Comunicações - Unidades com vínculo direto"
##  [20] "Comando da Aeronáutica"                                                                   
##  [21] "Comando do Exército"                                                                      
##  [22] "Fundo do Exército"                                                                        
##  [23] "Indústria de Material Bélico do Brasil"                                                   
##  [24] "Ministério da Defesa - Unidades com vínculo direto"                                       
##  [25] "Banco Central do Brasil - Orçamento Fiscal e Seguridade Social"                           
##  [26] "Comissão de Valores Mobiliários"                                                          
##  [27] "Fundação Instituto Brasileiro de Geografia e Estatística"                                 
##  [28] "Fundo Constitucional do Distrito Federal"                                                 
##  [29] "Fundo de Amparo ao Trabalhador"                                                           
##  [30] "Instituto de Pesquisa Econômica Aplicada"                                                 
##  [31] "Instituto Nacional de Metrologia, Qualidade e Tecnologia"                                 
##  [32] "Instituto Nacional do Seguro Social"                                                      
##  [33] "Ministério da Economia - Unidades com vínculo direto"                                     
##  [34] "Superintendência Nacional de Previdência Complementar"                                    
##  [35] "Colégio Pedro II"                                                                         
##  [36] "Empresa Brasileira de Serviços Hospitalares"                                              
##  [37] "Fundação Joaquim Nabuco"                                                                  
##  [38] "Fundação Universidade Federal de Ciências da Saúde de Porto Alegre"                       
##  [39] "Fundação Universidade Federal de Pelotas"                                                 
##  [40] "Fundação Universidade Federal de São Carlos"                                              
##  [41] "Fundação Universidade Federal de São João Del-Rei"                                        
##  [42] "Fundação Universidade Federal do Piauí"                                                   
##  [43] "Fundação Universidade Federal do Vale do São Francisco"                                   
##  [44] "Hospital de Clínicas de Porto Alegre"                                                     
##  [45] "Instituto Federal Baiano"                                                                 
##  [46] "Instituto Federal Catarinense"                                                            
##  [47] "Instituto Federal da Bahia"                                                               
##  [48] "Instituto Federal de Alagoas"                                                             
##  [49] "Instituto Federal de Minas Gerais"                                                        
##  [50] "Instituto Federal de Rondônia"                                                            
##  [51] "Instituto Federal de Roraima"                                                             
##  [52] "Instituto Federal de Sergipe"                                                             
##  [53] "Instituto Federal do Amazonas"                                                            
##  [54] "Instituto Federal do Espírito Santo"                                                      
##  [55] "Instituto Federal do Maranhão"                                                            
##  [56] "Instituto Federal do Mato Grosso"                                                         
##  [57] "Instituto Federal do Piauí"                                                               
##  [58] "Instituto Federal do Rio Grande do Sul"                                                   
##  [59] "Instituto Federal do Sudeste de Minas Gerais"                                             
##  [60] "Instituto Federal do Tocantins"                                                           
##  [61] "Instituto Federal do Triângulo Mineiro"                                                   
##  [62] "Instituto Federal Fluminense"                                                             
##  [63] "Instituto Federal Goiano"                                                                 
##  [64] "Instituto Federal Sul-rio-grandense"                                                      
##  [65] "Universidade Federal da Integração Latino-Americana"                                      
##  [66] "Universidade Federal da Paraíba"                                                          
##  [67] "Universidade Federal de Alfenas"                                                          
##  [68] "Universidade Federal de Campina Grande"                                                   
##  [69] "Universidade Federal de Goiás"                                                            
##  [70] "Universidade Federal de Itajubá"                                                          
##  [71] "Universidade Federal de Juiz de Fora"                                                     
##  [72] "Universidade Federal de Lavras"                                                           
##  [73] "Universidade Federal de Ouro Preto"                                                       
##  [74] "Universidade Federal de Pernambuco"                                                       
##  [75] "Universidade Federal de Santa Catarina"                                                   
##  [76] "Universidade Federal de Santa Maria"                                                      
##  [77] "Universidade Federal de Viçosa"                                                           
##  [78] "Universidade Federal do Espírito Santo"                                                   
##  [79] "Universidade Federal do Oeste da Bahia"                                                   
##  [80] "Universidade Federal do Pará"                                                             
##  [81] "Universidade Federal do Recôncavo da Bahia"                                               
##  [82] "Universidade Federal do Rio de Janeiro"                                                   
##  [83] "Universidade Federal do Rio Grande"                                                       
##  [84] "Universidade Federal do Rio Grande do Norte"                                              
##  [85] "Universidade Federal do Triângulo Mineiro"                                                
##  [86] "Universidade Federal Rural de Pernambuco"                                                 
##  [87] "Agência Nacional de Aviação Civil"                                                        
##  [88] "Agência Nacional de Transportes Aquaviários"                                              
##  [89] "Agência Nacional de Transportes Terrestres"                                               
##  [90] "Departamento Nacional de Infraestrutura de Transportes"                                   
##  [91] "Departamento de Polícia Federal"                                                          
##  [92] "Departamento de Polícia Rodoviária Federal"                                               
##  [93] "Fundação Nacional do Índio"                                                               
##  [94] "Fundo Nacional Antidrogas"                                                                
##  [95] "Fundo Penitenciário Nacional"                                                             
##  [96] "Ministério da Justiça e Segurança Pública - Unidades com vínculo direto"                  
##  [97] "Agência Nacional de Vigilância Sanitária"                                                 
##  [98] "Fundação Nacional de Saúde"                                                               
##  [99] "Fundação Oswaldo Cruz"                                                                    
## [100] "Hospital Nossa Senhora da Conceição S.A."                                                 
## [101] "Ministério da Saúde - Unidades com vínculo direto"                                        
## [102] "Fundação Alexandre de Gusmão"                                                             
## [103] "Ministério das Relações Exteriores - Unidades com vínculo direto"                         
## [104] "Agência Nacional de Energia Elétrica"                                                     
## [105] "Companhia de Pesquisa de Recursos Minerais"                                               
## [106] "Departamento Nacional de Produção Mineral"                                                
## [107] "Empresa de Pesquisa Energética"                                                           
## [108] "Ministério de Minas e Energia - Unidades com vínculo direto"                              
## [109] "Agência Nacional de Águas"                                                                
## [110] "Companhia Brasileira de Trens Urbanos"                                                    
## [111] "Companhia de Desenvolvimento dos Vales do São Francisco e do Parnaíba"                    
## [112] "Departamento Nacional de Obras Contra as Secas"                                           
## [113] "Superintendência do Desenvolvimento da Amazônia"                                          
## [114] "Superintendência do Desenvolvimento do Nordeste"                                          
## [115] "Instituto Chico Mendes de Conservação da Biodiversidade"                                  
## [116] "Ministério do Trabalho e Emprego - Unidades com vínculo direto"                           
## [117] "Empresa Brasil de Comunicação"                                                            
## [118] "Instituto Nacional de Tecnologia da Informação"                                           
## [119] "Presidência da República"                                                                 
## [120] "Fundação Universidade Federal de Sergipe"                                                 
## [121] "Fundação Universidade Federal do Tocantins"                                               
## [122] "Instituto Federal de Santa Catarina"                                                      
## [123] "Instituto Federal de São Paulo"                                                           
## [124] "Universidade Federal de Minas Gerais"                                                     
## [125] "Universidade Federal dos Vales do Jequitinhonha e Mucuri"                                 
## [126] "Universidade Tecnológica Federal do Paraná"                                               
## [127] "Ministério da Infraestrutura - Unidades com vínculo direto"                               
## [128] "Agência Nacional de Saúde Suplementar"                                                    
## [129] "Agência Nacional do Petróleo, Gás Natural e Biocombustíveis"                              
## [130] "Superintendência de Desenvolvimento do Centro-Oeste"                                      
## [131] "Gabinete da Vice-Presidência da República"                                                
## [132] "Fundação Jorge Duprat Figueiredo, de Segurança e Medicina do Trabalho"                    
## [133] "Superintendência da Zona Franca de Manaus"                                                
## [134] "Centro Federal de Educação Tecnológica de Minas Gerais"                                   
## [135] "Fundação Universidade de Brasília"                                                        
## [136] "Fundação Universidade Federal do ABC"                                                     
## [137] "Fundação Universidade Federal do Mato Grosso"                                             
## [138] "Fundação Universidade Federal do Pampa"                                                   
## [139] "Instituto Federal do Mato Grosso do Sul"                                                  
## [140] "Universidade Federal da Bahia"                                                            
## [141] "Universidade Federal de Alagoas"                                                          
## [142] "Universidade Federal do Paraná"                                                           
## [143] "Universidade Federal Rural do Rio de Janeiro"                                             
## [144] "Universidade Federal Rural do Semi-Árido"                                                 
## [145] "Agência Nacional de Mineração"                                                            
## [146] "Instituto Brasileiro do Meio Ambiente e dos Recursos Naturais Renováveis"                 
## [147] "Instituto de Pesquisas Jardim Botânico do Rio de Janeiro"                                 
## [148] "Ministério do Meio Ambiente - Unidades com vínculo direto"                                
## [149] "Fundo de Imprensa Nacional"                                                               
## [150] "Comando da Marinha"                                                                       
## [151] "Fundação Universidade Federal de Rondônia"                                                
## [152] "Instituto Federal da Paraíba"                                                             
## [153] "Instituto Federal do Norte de Minas Gerais"                                               
## [154] "Universidade Federal da Fronteira Sul"                                                    
## [155] "Universidade Federal do Estado do Rio de Janeiro"                                         
## [156] "Universidade Federal do Rio Grande do Sul"                                                
## [157] "Universidade Federal Fluminense"                                                          
## [158] "Fundação Escola Nacional de Administração Pública"                                        
## [159] "Fundação Universidade Federal da Grande Dourados"                                         
## [160] "Fundação Universidade Federal de Uberlândia"                                              
## [161] "Fundação Universidade Federal do Mato Grosso do Sul"                                      
## [162] "Instituto Federal de Educação, Ciência e Tecnologia de Goiás"                             
## [163] "Instituto Federal do Ceará"                                                               
## [164] "Instituto Federal do Paraná"                                                              
## [165] "Instituto Federal do Rio de Janeiro"                                                      
## [166] "Conselho Administrativo de Defesa Econômica"                                              
## [167] "Ministério do Desenvolvimento Regional - Unidades com vínculo direto"                     
## [168] "Instituto Federal de Pernambuco"                                                          
## [169] "Ministério da Mulher, Família e Direitos Humanos - Unidades com vínculo direto"           
## [170] "Instituto Federal do Rio Grande do Norte"                                                 
## [171] "Empresa de Planejamento e Logística S.A."

nome_unidade gestora

unique(dados$nome_unidade_gestora) %>% 
  head(n=25)
##  [1] "SUPERINTENDENCIA ADMINISTRACAO EM PERNAMBUCO" 
##  [2] "SUPERINTENDENCIA ADMINISTRACAO EM SAO PAULO"  
##  [3] "SUPERINTENDENCIA ADMINISTRACAO NO RIO G. SUL" 
##  [4] "SUPERINTENDENCIA ADMINISTRACAO RIO DE JANEIRO"
##  [5] "SUPERINTENDENCIA DE ADM. NO DISTRITO FEDERAL" 
##  [6] "COORD-GERAL LICITACAO, CONT.E DOCUMENTACAO"   
##  [7] "COMPANHIA NACIONAL DE ABASTECIMENTO"          
##  [8] "CONAB SEDE SUREG BAHIA"                       
##  [9] "CONAB SEDE SUREG PARANA"                      
## [10] "CONAB SEDE SUREG RIO GRANDE DO SUL"           
## [11] "CONAB SEDE SUREG RONDONIA"                    
## [12] "CONAB SEDE SUREG RORAIMA"                     
## [13] "CONAB SEDE SUREG SANTA CATARINA"              
## [14] "EMBRAPA/CENARGEN"                             
## [15] "EMBRAPA/CNPA"                                 
## [16] "EMBRAPA/CNPAT"                                
## [17] "EMBRAPA/CNPGC"                                
## [18] "EMBRAPA/CNPMA"                                
## [19] "EMBRAPA/CPAA"                                 
## [20] "EMBRAPA/CPAC"                                 
## [21] "EMBRAPA/CPAF-AMAPA"                           
## [22] "EMBRAPA/CPAF-RORAIMA"                         
## [23] "EMBRAPA/CPAMN"                                
## [24] "EMBRAPA/CPAMT"                                
## [25] "EMBRAPA/CPATC"

Tanto para “nome_órgão_superior” quanto para “nome_órgão”, não parece que temos muitos problemas, apesar dos caracteres especiais e do texto fora do caixa-alta. É provável que esses campos sejam preenchidos automaticamente, seja oferecendo opções ao usuário, seja não permitindo mudar seu conteúdo com base em alguma norma. Ambos os casos parecem não permitirem respostas abertas. Por outro lado, o “nome_unidade_gestora” é muito mais volátil e suscetível a erros, bem como possui muito mais valores. São cerca de 1022 valores diferentes.

Aqui temos o problema da dificuldade de descobrir todos os possíveis erros. Resolvemos ele de duas formas: minuciosamente estudando os dados e descobrindo caso a caso as divergências; reduzindo, por filtros, o número de casos que lidaremos, focalizando apenas nos nomes problemáticos relacionados a nossa temática de pesquisa. Aqui optamos pela segunda opção. Iremos apenas lidar com alguns órgãos, aqueles ligados à Presidência da República.

presidencia <- dados %>% 
  filter(nome_órgão_superior=="Presidência da República")

unique(presidencia$nome_unidade_gestora)
## [1] "EMPRESA BRASIL DE COMUNICACAO S.A"            
## [2] "INSTITUTO NAC.DE TECNOLOGIA DA INFORMACAO ITI"
## [3] "AGENCIA BRASILEIRA DE INTELIGENCIA"           
## [4] "AGENCIA BRASILEIRA DE INTELIGÊNCIA"           
## [5] "GABINETE DE SEGURANÇA INSTITUCIONAL/PR"       
## [6] "SECRETARIA ESPECIAL DE ADMINISTRACAO/PR"      
## [7] "GABINETE DA VICE-PRESIDENCIA DA REPUBLICA"    
## [8] "FUNDO DE IMPRENSA NACIONAL/EXEC.ORC.FINANC."  
## [9] "INTERVENÇÃO FEDERAL RIO DE JANEIRO"

Vemos aqui que temos duas ABIN, uma com acento e outra sem. Além disso, temos um “ÇÔ em “INTERVENÇÃO” e um “Ç” em “SEGURANÇA”. Para corrigir isso, usamos o str_replace_all. Lembrem-se que caso não associemos o resultado de uma função a um objeto, ele não é salvo. Abaixo usamos a coluna “nome_unidade_gestora” nas funções e com o operador de associação <- para substituir a coluna original pela sua versão modificada.

presidencia$nome_unidade_gestora <- presidencia$nome_unidade_gestora %>% 
  str_replace_all(pattern = "Ê",replacement="E") %>%
  str_replace_all(pattern= "ÇÃ",replacement = "CA") %>% 
  str_replace_all(pattern = "Ç",replacement = "C")

unique(presidencia$nome_unidade_gestora)
## [1] "EMPRESA BRASIL DE COMUNICACAO S.A"            
## [2] "INSTITUTO NAC.DE TECNOLOGIA DA INFORMACAO ITI"
## [3] "AGENCIA BRASILEIRA DE INTELIGENCIA"           
## [4] "GABINETE DE SEGURANCA INSTITUCIONAL/PR"       
## [5] "SECRETARIA ESPECIAL DE ADMINISTRACAO/PR"      
## [6] "GABINETE DA VICE-PRESIDENCIA DA REPUBLICA"    
## [7] "FUNDO DE IMPRENSA NACIONAL/EXEC.ORC.FINANC."  
## [8] "INTERVENCAO FEDERAL RIO DE JANEIRO"

Quando temos múltiplos padrões e substituições, podemos amarrar “pattern” e “replacement” dentro de uma função c da seguinte forma:

dados$nome_órgão %>% 
  str_to_upper() %>% 
  str_replace_all(c("ÇÃ"="CA","Ê"="E","Ç"="C","É"="E","Ã"="A")) %>% 
  unique() %>% 
  head(n=10)
##  [1] "ADVOCACIA-GERAL DA UNIAO - UNIDADES COM VÍNCULO DIRETO"                           
##  [2] "CONTROLADORIA-GERAL DA UNIAO - UNIDADES COM VÍNCULO DIRETO"                       
##  [3] "COMPANHIA NACIONAL DE ABASTECIMENTO"                                              
##  [4] "EMPRESA BRASILEIRA DE PESQUISA AGROPECUÁRIA"                                      
##  [5] "INSTITUTO NACIONAL DE COLONIZACAO E REFORMA AGRÁRIA"                              
##  [6] "MINISTERIO DA AGRICULTURA, PECUÁRIA E ABASTECIMENTO - UNIDADES COM VÍNCULO DIRETO"
##  [7] "SERVICO FLORESTAL BRASILEIRO"                                                     
##  [8] "AGENCIA NACIONAL DO CINEMA"                                                       
##  [9] "FUNDACAO CASA DE RUI BARBOSA"                                                     
## [10] "FUNDACAO CULTURAL PALMARES"

No código acima, colocamos dentro do c duplas de “pattern” e “replacement” separadas por vírgula. Além do str_replace_all, temos três outras funções que são muito úteis em rotinas de limpeza de dados.

str_detect

Essa função retorna TRUE ou FALSE para um determinado padrão especificado dentro de um objeto. Por exemplo, se queremos saber se há outras nomes no restante da nossa base que possuem “ê” ou “Ê”, podemos usar essa função. Abaixo juntamos ela com um table para vermos as quantidades de casos TRUE e FALSE.

str_detect(dados$nome_unidade_gestora,pattern="Ê") %>% 
  table()
## .
##  FALSE   TRUE 
## 107482   7999

Como o resultado é um TRUE/FALSE podemos associá-lo a um objeto e depois usá-lo num índice para obtermos da nossa base apenas os casos onde o str_detect achou uma correspondência.

indice <- str_detect(dados$nome_unidade_gestora,pattern="Ê")

dados[indice,]

str_extract e str_extract_all

Essa função checa cada elemento de um objeto fornecido a procura do padrão especificado. Se meu padrão for “cão”, a função retornará apenas “cão” (caso encontre esse padrão) e NA (dado “vazio”) para casos onde nada foi encontrado. Sua versão all retorna todas as correspondência do padrão de um elemento caso exista mais de uma.

Apesar de não parecer muito útil, tradicionalmente usamos ela com regex, que são formas de criar padrões textuais complexos e flexíveis (já já discutiremos isso). De qualquer forma temos o exemplo abaixo que procura “QUEIROZ” em “nome_portador”. Usamos um table para checar quantos dados com o padrão foram encontrados.

str_extract(dados$nome_portador,pattern="QUEIROZ") %>% 
  table()
## .
## QUEIROZ 
##     345

Se não usarmos o table, o R imprimirá a checagem inteira, com NAs e “QUEIROZ” (usamos head aqui para não encher essa página com a checagem inteira).

str_extract(dados$nome_portador,pattern="QUEIROZ") %>% 
  head(n=100)
##   [1] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
##  [26] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
##  [51] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
##  [76] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA

str_subset

Essa função é parecida com a anterior, mas ao invés de retornar apenas o padrão desejado ela retorna todo o elemento que possui o padrão. No caso anterior obtivemos apenas o padrão e NAs. Aqui iremos obter o texto completo e sem NAs. Num exercício passado que foi pedido dados sobre a UFSCar usamos essa função para extrair de que forma a universidade aparecia nos dados (usando “SÃO CARLOS” como “pattern”). Abaixo temos outro exemplo, dessa vez com a palavra “JOIA”.

str_subset(dados$nome_favorecido,pattern="JOIA")
##  [1] "GILBERTO CHINELLATO TROFEUS E JOIAS LTDA"                       
##  [2] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
##  [3] "G TORBAN COMERCIO E SERVICOS DE RELOJOARIA OTICA E JOIAS EIRELI"
##  [4] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
##  [5] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
##  [6] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
##  [7] "G TORBAN COMERCIO E SERVICOS DE RELOJOARIA OTICA E JOIAS EIRELI"
##  [8] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
##  [9] "G TORBAN COMERCIO E SERVICOS DE RELOJOARIA OTICA E JOIAS EIRELI"
## [10] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [11] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [12] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [13] "G TORBAN COMERCIO E SERVICOS DE RELOJOARIA OTICA E JOIAS EIRELI"
## [14] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [15] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [16] "POSTO JOIA DO VALE LTDA"                                        
## [17] "AUTO POSTO JOIA LTDA"                                           
## [18] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [19] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [20] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [21] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [22] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [23] "TURQUESA COMERCIO DE JOIAS LTDA"                                
## [24] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [25] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [26] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [27] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [28] "G TORBAN COMERCIO E SERVICOS DE RELOJOARIA OTICA E JOIAS EIRELI"
## [29] "G TORBAN COMERCIO E SERVICOS DE RELOJOARIA OTICA E JOIAS EIRELI"
## [30] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [31] "ELETRO FOTO JOIA EIRELI"                                        
## [32] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [33] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [34] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [35] "JOIA COMERCIO DE COMBUSTIVEIS LTDA"                             
## [36] "GILBERTO CHINELLATO TROFEUS E JOIAS LTDA"

Normalmente usamos ela para testar se estamos usando o nome correto para outras funções do stringr ou até para explorar os dados.

patterns e regex

Como vimos nos tópicos anteriores, é possível identificar um texto (inteiro ou uma parte) usando “patterns”/padrões, sejam eles de uma só letra (como “ê”,“ç”,“ã”), sejam eles maiores (“Inteligência”,“Gabinete”,“Presidência da República”). Acontece que nem todo caso nós sabemos exatamente qual será o conteúdo escrito, e sim apenas o seu “formato”.

Por exemplo, sabemos que siglas de estados ou países são compostos apenas por letras maiúsculas, duas delas no primeiro caso e três no segundo. Nunca deverá haver qualquer outro caracter nesses casos. Mas erros acontecem e podemos estar trabalhando com uma base onde isso ocorra, seja por conta de erros humanos, seja porque conta de escolhas dos criadores da base.

As possíveis combinações são infinitas e não podemos elencar todas elas para fazer a corrreção. Mesmo se pudéssemos, o que garante que uma nova atualização não introduziria novos erros!?

Para resolver esse problema usamos o regex, abreviação para regular expressions, ou expressões regulares. São formas lógicas de estabelecer padrões de texto mais complexos e amplos. Usamos essas expressões no argumento “pattern” das nossas funções do stringr. Apesar de não serem super cruciais, podemos precisar delas caso estejamos trabalhando com dados muito sujos. Abaixo temos alguns exemplos de regex tirados da colinha do pacote.

Testando regex

No exemplo citado acima, precisaríamos de um regex que pegue apenas números/dígitos e esta expressão é “[:digit:]”. Com ela, todo número será selecionado e podemos prosseguir com o tratamento indicando o que deverá ser feito com eles. Neste caso queremos excluí-los, o que no str_replace_all pode ser feito se deixarmos o argumento “replacement” vazio.

letras_numeros <- c("AA2","BB20","CC190","DD10000000")

str_replace_all(letras_numeros,pattern="[:digit:]",replacement = "")
## [1] "AA" "BB" "CC" "DD"

Quando usamos “\\.” ao invés de “.”, estamos usando de regex. O ponto por si só é usado para indicar todo conteúdo dos elementos de um objeto de texto. Abaixo demonstramos isso.

teste_regex <- c("joao","caio","maria","camila")

teste_regex
## [1] "joao"   "caio"   "maria"  "camila"
str_replace_all(teste_regex,pattern=".",replacement = "A")
## [1] "AAAA"   "AAAA"   "AAAAA"  "AAAAAA"

A colinha do stringr, na segunda página, contém alguns regex bastante comuns: números, letras, espaços em branco, caracteres especiais, maiúsculas e minúsculas, etc. Há ainda algumas expressões bem complexas que consideram o que vem antes ou depois de algo, quantidade de vezes que algo aparece, algo seguido da alguma outra coisa, etc. É realmente algo muito extenso e complexo que vale um estudo a parte (algo que não faremos totalmente aqui).

Usando regex nas datas

Uma rápida olhada nos dados nos mostra que há dentro do nosso arquivo despesas feitas antes de 2019, mas que acabaram caindo no extrato dos meses desse ano.

Consequentemente, nossa análise pode acabar falhando ao considerar esses custos. Para resolver esse “tira-teima”, observamos “data_transação”.

head(dados$data_transação)
## [1] "11/12/2018" "03/12/2018" "14/12/2018" "07/12/2018" "04/12/2018"
## [6] "07/12/2018"

Há algumas formas de tratar uma coluna com datas, mas usaremos o stringr para obter o dia, mês e ano reais da despesa. Um padrão é bem claro nelas: os dias são sempre os dois primeiro dígitos da esquerda; os anos são sempre os quatro últimos dígitos da direita; e os meses são sempre os dois dígitos contidos entre as duas barras (“/”). Mesmo se fossem hífens (“-”), o padrão é o mesmo. Isso só mudará se estivermos usando dados de uma base estrangeira (onde o padrão é mês/dia/ano).

Usando um mutate com um str_extract, podemos criar três colunas diferentes: uma para dia; uma para mês; e uma para ano. Precisamos apenas separar cada coluna no mutate com uma vírgula. Não se preocupem se isso soar complexo demais, a ideia é só introduzir a possibilidade de tratar texto em R de maneira bastante versátil. Há pacotes específicos para datas, como o lubridate.

Usaremos dentro do str_extract três tipos de regex: para dia será "[:digit:]{2}(?=/)"; para mês será "(?<=/)[:digit:]{2}(?=/)" ; e para ano será "(?<=/)[:digit:]{4}". Iremos salvar essa modificação usando o operador de associação <-.

dados <- dados %>% 
  mutate(dia=str_extract(data_transação,pattern="[:digit:]{2}(?=/)"),
         mes=str_extract(data_transação,pattern="(?<=/)[:digit:]{2}(?=/)"),
         ano=str_extract(data_transação,pattern="(?<=/)[:digit:]{4}"))

dados %>% 
  select(data_transação,dia,mes,ano) %>% 
  head()

Os valores entre colchetes (“{}”) após “[:digit:]” indicam quantos dígitos queremos que estejam juntos para serem reconhecidos e extraídos (2 para dias e meses, 4 para anos). O conteúdo entre parêntenses (“(?=/)” para antes,“(?<=/)” para depois) indicam se queremos os números antes das barras (“/”), entre elas ou depois delas.

O resultado é uma coluna para cada parte da data. Logo de cara vemos que há dados de 2018 na nossa base e que podem inflacionar nossas métricas. Logo, precisaríamos retirá-los para considerar verdadeiramente os valores do governo Bolsonaro.

Há, porém, um enorme problema. As despesas sigilosas não tem data, o que significa que esse processo acima resultada em dados inválidos (NAs) para este caso. Usamos o argumento “useNA” com o valor “always” em table para o R nos oferecer uma contagem do número de casos para cada valor. Isso dificulta em muito uma análise temporal dos gastos sigilosos.

table(dados$ano,useNA = "always")
## 
##  2018  2019  <NA> 
##  7578 87774 20129

Para conhecer mais sobre o pacote acesse seu site oficial ou consulte a sua “cheatsheet/colinha” aqui.

Cenas do próximo e último capítulo

Vimos que é possível corrigir e manipular textos em R de maneira bastante flexível, sempre em resposta às nossas necessidades como pesquisadores. Uma base de dados perfeita não existe, mas podemos mexer naquilo que temos em mãos para chegar num resultado esperado (ou ao menos perto).

Porém, após a análise minuciosa vem a exposição dos achados. O mundo acadêmico (e fora dele também) não saberá do que estamos falando ou nossos resultados se não os comunicarmos de maneira efetiva. Tabelas funcionam até certo ponto.

É ai que gráficos entram como ferramentas para facilitar essa comunicação, focalizando no que é importante e desenhando (literalmente ou não) as relações encontradas. O R tem um pacote só para gráficos, o ggplot2, que iremos tratar no próximo encontro.

Exercícios

Questões

  1. Num encontro anterior, selecionamos as despesas feitas em nome da UFSCar, usando um nome específico. Use “SÃO CARLOS” em “nome_unidade_gestora” para encontrar os possíveis nomes que a universidade pode receber (só os nomes mesmo).
  • Dica: use unique para pegar apenas valores únicos.
  1. Troque “SÃO CARLOS” por “UFSCAR”. Há alguma diferença? Se sim, quais outras unidades surgem?

  2. Com nossos novos dados de data, filtre apenas pelas despesas feitas em 2019 (usando a nova coluna “ano”), agrupe por dia do mês e obtenha a soma, o número de despesas e a mediana das despesas. Qual dia do mês foi o que no total teve a maior soma?

  3. Usando nossa base “presidencia” e str_subset obtenha os valores possíves (com unique) das despesas em que “nome_favorecido” contenha “LTDA”.

  4. Corrija o valor da transação, substituindo o ponto (“.”) como separador por vírgula (“,”).

  • Dica: lembre-se que quando o “pattern” é um ponto “.” a forma correta de se referir a ele é com “\.”
  1. (Desafio) Temos um problema com pessoas chamadas Fabrício. Suspeitamos que as despesas que elas fizeram usando o cartão sejam fraudulentas. Extraia todas as despesas onde o “nome_portador” contenha “FABRICIO” (exatamente dessa forma!!) usando str_detect. Faça um arrange decrescente pelo valor da transação. Qual o maior valor e qual órgão o fez?
  • Dica: um str_detect retorna apenas as observações que possuam totalmente aquilo que colocamos em “pattern”, isto é, retorna TRUE para elas e FALSE para as demais. É possível usarmos o resultado do str_detect dentro de um índice para selecionar um conjunto de linhas. Como queremos outras informações, nosso espaço para colunas no índice deverá estar vazio.

Soluções

A serem divulgadas posteriormente.

Quarto encontro (27/09): ggplot2

Visualizações servem para comunicarmos de maneira mais rápida e simples informações/insights obtidos dos dados. São essencialmente ferramentas que simplificam nosso processo comunicativo ao desenhar os resultados de nossas análises. Usamos elas quando preciamos dialogar com partes que não conhecem a fundo o objeto de nossa fala ou ainda quando nossos achados são demasiado complexos em forma tabular para serem apreendidos apenas com tabelas.

Como vimos até o momento, muito do que fazemos no R não é intuitivo ao amplo público (e às vezes nem mesmo pra nós que escrevemos os scripts hahaha), o que significa que precisamos nos apoiar em simplificações. Mesmo numa banca de pós-graduação há um limite pra o quanto é viável e desejável ficar falando sobre métodos e processos. Um especialista em teoria pode ter dificuldade em entender métodos e vice-versa. Abaixo temos uma analogia desse processo.

Para além de coletar, organizar dados e gerar análises, temos também que produzir formas visuais que são mais fáceis de digerir da nossa trajetória, bem como amarrar tudo com uma narrativa (storytelling) que dá sentido às nossas conclusões e escolhas. É aí que podemos de construção de gráficos surgem.

ggplot2 e a gramática dos gráficos

O ggplot2 é um pacote do tidyverse que é completamente focado em ferramentas para gerar e customizar visualizações. Ele usa algo chamado “gramática dos gráficos” (daí o “gg”) que consiste em uma forma pré-definida de códigos. A analogia comumente usada é a de várias folhas de papel-manteiga empilhadas, formando camadas.

Há uma tonelada de informação sobre o ggplot2. A melhor foram de conhecer o pacote é usando e lendo sobre. Vocês podem acessar ao site do pacote ou ver a colinha dele.

Aqui iremos apenas sobrevoar alguns dos gráficos mais comuns e visualizar os achados dos nossos encontros anteriores. Mais uma vez, pesquisem os tópicos que chamem a atenção de vocês. Sempre haverá algo novo a ser aprendido.

Como de praxe, primeiro iremos selecionar nosso diretório de trabalho e carregar o tidyverse.

setwd("C:/Users/arjon/Documents/GitHub/curso-r-pos-grad")

library(tidyverse)

Além disso, iremos carregar novamente nossa base. Diferente dos arquivos usados antes, este é uma versão que acumula as modificações feitas nos dois últimos encontros: os nomes das colunas estão corretos; alguns caracteres especiais foram removidos; temos a coluna de “data_transação” quebrada.

dados_rev <- read.table("cartao_bolsonaro2019_revisado.csv",
                    sep=",",dec=".",
                    header=TRUE,
                    fileEncoding = "latin1")

O primeiro gráfico

Como exposto na imagem e explicação acima, precisamos encadear as funções do ggplot2 uma atrás da outra para criar um gráfico. A primeira delas é propriamente a função ggplot. Ela pode receber alguns argumentos ou até mesmo nenhum, tudo dependerá do tipo de organização do seu código. No nosso caso colocaremos o nome da nossa base no argumento “data”.

ggplot(data=dados_rev)

Se rodarmos esse código iremos obter apenas uma tela em branco no canto inferior direito. É o canvas em branco citado antes. Ele apenas indica que iremos construir um gráfico usando o ggplot2. A próxima etapa é selecionar um tipo de gráfico e aplicar a função desejada. Neste pacote, os gráficos recebem o nome de “geom_” seguido do tipo de gráfico. Por exemplo, um gráficos de pontos recebe o nome de “geom_point”.

Todas as funções “geom_” aceitam vários argumentos, sendo o mais importante deles o “mapping”. Nele usamos a função aes para definimos qual variável será colocada em qual parte do gráfico (eixo x, eixo y, cores, formatos, etc.). Lembrem-se dos parênteses. Para unir todas as camadas de um gráfico, usamos o sinal de adição (“+”) entre elas.

No código abaixo criamos um data.frame fictício que contém números relacionados, onde o valor de um deles cresce num ritmo maior que o outro. Em seguida usamos esse objeto para criar um gráfico de pontos.

objeto_teste <- data.frame(num_1=seq(1,10),
                           num_2=seq(1,10)^2)

ggplot(objeto_teste)+
  geom_point(mapping=aes(x=num_1,y=num_2))

Percebam que, por conta de termos usado o nome do objeto dentro de ggplot, na hora que iremos referenciar as variáveis em “aes” podemos escrever como fizemos nas funções do dplyr. Isso é mais uma vantagem do tidyverse: as funções e pacotes são feitos para se comunicarem da mesma forma.

Os dados do cartão corporativo

Conhecendo algumas noções de pesquisa, sabemos que nem todo gráfico serve para todo tipo de dados. Como na nossa base não temos mais de uma variável numérica (apenas “valor_transação”) usamos dados fictícios no exemplo anterior. Por outro lado, dados qualitativos e quantitativos permitem muitas formas de serem representados graficamente. Temos o tradicional gráfico de barras.

ggplot(dados_rev)+
  geom_bar(mapping=aes(x=nome_órgão_superior))

Há muito o que comentar aqui. Primeiro, “geom_bar” requer apenas o eixo X porque por padrão o eixo Y é sempre a contagem de obervações dos valores de X. Segundo, como o nome dos órgãos são grandes, fica impossível de ler as legendas. Para facilitar a visualização usamos a função “coord_flip” logo após o “geom_bar”, juntando tudo com um “+”. Ela virará o gráfico em 90 graus.

ggplot(dados_rev)+
  geom_bar(mapping=aes(x=nome_órgão_superior))+
  coord_flip()

Estamos chegando perto de um formato melhor. Podemos adicionar cor no gráfico para diferenciar os tipos de transação com o argumento “fill” dentro de aes. O R automaticamente cria uma legenda com nomes e cores (que podem ainda serem modificados depois).

ggplot(dados_rev)+
  geom_bar(mapping=aes(x=nome_órgão_superior,fill=transação))+
  coord_flip()

O gráfico já está mais interessante, em especial quanto aos dados sigilosos. Mas a ausência de ordem por quantidade nas barras dificulta a leitura. Iremos resolver isso mais a frente integrando códigos em dplyr com ggplot2. Por hora não lidaremos com isso ainda.

Outros gráficos comuns e úteis

Os gráficos do ggplot2 são divididos em número de variáveis e seus tipos. O gráfico de barras (ou colunas) usa uma variável discreta e uma contínua, bem como um boxplot. Gráficos de linhas usam duas variáveis contínuas, assim como gráficos de pontos (dispersão). Logo, precisamos conhecer nossas variáveis e nossos objetivos para escolher o melhor dos gráficos.

O gráfico de linhas é útil para observarmos padrões temporais e relações entre variáveis numéricas. Usando a coluna de dia criada, podemos plotar uma leitura do perfil dos gastos por dia do mês ao longo do ano de 2019 (filtramos 2018). Este “geom” não faz cálculos prévios, o que significa que precisamos oferecer para ele as métricas de interesse já calculadas. Para isso criamos um objeto com nossos dados agrupados pelo dia e com um summarise contendo as métricas desejadas (média e desvio padrão de despesas).

dados_metricas <- dados_rev %>% 
  filter(ano=="2019") %>% 
  group_by(dia) %>% 
  summarise(media=mean(valor_transação),
            desvio=sd(valor_transação))

ggplot(dados_metricas)+
  geom_line(mapping=aes(x=media,y=desvio))

Se desejarmos usar alguma diferenciação por cor, introduzimos outro agrupamento no nosso código do dplyr (neste caso mês) usamos o argumento “color” em aes com esse novo agrupamento. A diferença entre “fill” e “color/colour” se refere ao tipo de gráfico: barras, boxplots e afins usam “fill” porque são elementos gráficos “fechados” (caixas ou barras); linhas e pontos usam “color/colour” porque são elementos gráficos “abertos” (como desenhos que fazemos no paint).

O gráfico abaixo não é dos melhores mas exemplifica a possibilidade de combinações. A única diferença é que precisamos colocar um as.factor antes do “mes” no código do gráfico para o R não converter os números do mês (uma categoria) em números matemáticos (numeric).

dados_metricas <- dados_rev %>% 
  filter(ano=="2019") %>% 
  group_by(dia,mes) %>% 
  summarise(media=mean(valor_transação),
            desvio=sd(valor_transação))

ggplot(dados_metricas)+
  geom_line(mapping=aes(x=media,
                        y=desvio,
                        color=as.factor(mes)))

Temos também o tradicional boxplot, um gráfico com uma capacidade muito grande de comunicar diversas métricas. Para fins expositivos usaremos apenas dados das despesas sigilosas feitas pela Presidência da República.

Devido ao tamanho dos valores, faremos uma rápida conversão com um mutate do valor das despesas para log de base dois. Especificidades matemáticas à parte, essa conversão mantém a distribuição dos valores (e as proporções) e padroniza os valores para uma escala menor (como um z-score).

sigilosas <- dados_rev %>% 
  filter(nome_portador=="Sigiloso" & nome_órgão=="PRESIDENCIA DA REPUBLICA") %>% 
  mutate(valor_log=log(valor_transação,base = 2))

table(sigilosas$nome_unidade_gestora)
## 
##      AGENCIA BRASILEIRA DE INTELIGENCIA  GABINETE DE SEGURANCA INSTITUCIONAL/PR 
##                                    3537                                     605 
## SECRETARIA ESPECIAL DE ADMINISTRACAO/PR 
##                                    2964
ggplot(sigilosas)+
  geom_boxplot(mapping=aes(x=nome_unidade_gestora,y=valor_log))

Vemos como os valores da ABIN se concentram nos maiores números e são muito dispersos (não formam nem as caixas do boxplot). Por outro lado, o GSI tem os gastos mais consistentes entre as três unidades. A Secretaria Especial de Administração (a presidência em si), é um meio termo, mas apresenta muitos outliers superiores.

Títulos e legendas

Podemos modificar legendas, título dos eixos e título do gráfico usando a função labs, que deverá ser anexada ao gráfico também após todo seu código com o sinal de adição. Seus argumentos são vários mas bastante intuitivos já que referem-se diretamente aos elementos do gráfico a serem renomeados. Usamos o mesmo código de antes para número de despesas por nome_órgão_superior e adicionamos o labs.

ggplot(dados_rev)+
  geom_bar(aes(x=nome_órgão_superior,fill=transação))+
  coord_flip()+
  labs(x="Órgão superior",
       y="Número de despesas",
       title="Número de despesas por órgão e tipo de transação",
       subtitle="Dados coletados do site do Portal da Transparência para o ano de 2019",
       fill="Tipo de transação")

Apesar de agora mais auto explicativo, o gráfico está exprimido demais pelo nome dos órgãos. Conseguimos resolver isso usando a função theme, que nos oferece uma enorme quantidade de recursos de customização.

Modificaremos a legenda e o texto do eixo Y. Para o primeiro, usaremos os argumentos “legend.title” e “legend.text” para selecionar o tamanho do texto. Para o segundo usaremos o argumento “axis.text.y” para selecionar o tamanho do texto também. Em ambos os casos usamos a função element_text, do próprio ggplot2, que permite configurar texto. Dentro dela no argumento “size” selecionamos o tamanho desejado (a unidade de medida é um pouco nebulosa, é mais fácil ir testando tamanhos). Nela também temos “family” para fontes, “face” para negritos/itálicos/sublinhados, “hjust/vjust” para justificação, “angle” para angulação do texto. A ordem em que colocamos theme não importa, desde que não esqueçamos o sinal de adição.

ggplot(dados_rev)+
  geom_bar(aes(x=nome_órgão_superior,fill=transação))+
  coord_flip()+
  theme(legend.title = element_text(size=9),
        legend.text = element_text(size=7),
        axis.text.y=element_text(size=7))+
  labs(x="Órgão superior",
       y="Número de despesas",
       title="Número de despesas por órgão e tipo de transação",
       subtitle="Portal da Transparência (2019)",
       fill="Tipo de transação")

O gráfico já está mais legível, mas longe de ser o ideal. A verdade é que a customização é todo um trabalho de design, onde podemos perder muito tempo nele. O ideal seria não trabalharmos com tantos valores e/ou com nomes tão grandes. Se isso for extremamente necessário, seria importante dedicar algum tempo para melhor configurar os aspectos estéticos do gráfico.

Como mencionado, as funções dos gráficos executam cálculos por trás para montar as visualizações. Mas às vezes não queremos que elas façam esse trabalho (sejam porque são lentas, seja porque não queremos exatamente os cálculos que elas fazem). Por isso juntamos códigos usando group_by/summarise do dplyr com funções do ggplot2.

Um exemplo bem simples. Queremos novamente um gráfico de barras por “nome_órgão_superior”, mas usando a média das despesas no eixo Y, ao invés da contagem. Escrevemos nosso código de agrupamento e passamos ele para o ggplot2 usando um pipe. Dentro dele seguimos o ritmo normal descrito acima, trocando “geom_bar” por “geom_col” (esta permite definirmos X e Y). Especificamos quem será X e quem será Y.

dados_rev %>% 
  group_by(nome_órgão_superior) %>% 
  summarise(media=mean(valor_transação)) %>% 
  ggplot()+
  geom_col(aes(x=nome_órgão_superior,y=media))+
  coord_flip()

Muita cautela para não trocar o pipe pelo sinal de adição “+” quando estiver escrevendo um código desses. O sinal não funciona no lugar do pipe e o este não funciona no lugar do adição!!!

Para resolver o problema da ordem citado antes, usamos da mesma abordagem junto com a função reorder dentro do “aes” e mais algumas diferenças. Seus argumentos são o objeto a ser reordenado e o que será usado para reordenar. Neste caso o objeto é “nome_órgão_superior” e ele será reordenado pela contagem de observações contido em “contagem”. Num outro exemplo abaixo, podemos ordenar uma variável com base num cálculo feito em outra.

Quanto às diferenças, como agora estamos retirando da função do ggplot2 o papel de fazer os cálculos e agrupamentos necessários, eles precisam estar no nosso objeto agrupado que será passado para o ggplot2. Neste caso, nosso agrupamento precisará agrupar por “nome_órgão_superior”. Também colocamos “transação” para adicionar uma variável para a cor das barras

dados_rev %>% 
  group_by(nome_órgão_superior,transação) %>% 
  summarise(contagem=n()) %>% 
  ggplot()+ 
  geom_col(aes(x=reorder(nome_órgão_superior,
                         contagem),
               y=contagem,
               fill=transação))+
  coord_flip()

Seria possível usar labs e theme para renomear e customizar o gráfico. O processo é exatamente o mesmo de antes, por isso não o faremos aqui.

Objetos de configuração

Vimos como criar e customizar gráficos. A fim de automizar e reduzir redundância nos códigos, podemos associar um conjunto de configurações a um objeto a parte e juntá-lo nos nossos códigos do ggplot2 usando o sinal de adição. Isso facilita e uniformiza nossos gráficos. Todos conhecem gráficos que são “a cara do seu autor” (como os do Jairo Nicolau) e isso só é possível usando desses objetos de configuração.

Quando lidamos com a função theme e com customizações, vimos que é possível alcançar códigos de muitas linhas só para definirmos exatamente a aparência de um gráfico. Objetos de configuração externos aos códigos dos gráficos também servem justamente para evitar isso.

Abaixo criamos dois objetos. O primeiro deles contém configurações mais gerais da estética do gráfico usando a função theme, já referenciada. Mudamos tamanho das letras de alguns textos e mexemos nas cores das linhas dos eixos e do fundo do gráfico.

objeto_config <- theme(title = element_text(size = 14),
                       axis.title = element_text(size = 12),
                       axis.text = element_text(size = 8),
                       legend.title = element_text(size = 12),
                       legend.text = element_text(size = 8),
                       panel.border = element_rect(colour = "black",fill = NA),
                       panel.background = element_rect(fill = "#f2f4f7"),
                       panel.grid = element_line(colour = "grey70"))

O segundo contém uma palheta de cores personalizada usando códigos hexadecimais de cores, usando a função scale_fill_manual. Usamos ela para definir uma escala de valores (limites, quebras, valores em si) para um tipo de variável no gráfico (x, y, color, fill, linetype, etc.). O manual indica que vamos definir manualmente aspectos estéticos de uma variável (neste caso cor, mas bem poderia ser nome dos valores). Neste caso abaixo usamos o argumento “values” para dizer quais serão os “valores de cor” usados, que são os códigos hexadecimais de cor (retirados de sites no internet como este). Amarramos os códigos dentro de uma função c, separando-os com vírgula e usando aspas.

objeto_cores <- scale_fill_manual(values = c("#f6b395","#f6e095",
                                             "#b9f695","#acf5ed",
                                             "#acbff5"))

Com isso feito, basta conectarmos esses dois objetos nos nossos gráficos usando o sinal de adição. As configurações serão aplicadas sempre da mesma forma.

dados_rev %>% 
  filter(nome_órgão_superior=="Presidencia da Republica") %>% 
  group_by(nome_unidade_gestora,transação) %>% 
  summarise(contagem=n()) %>% 
  ggplot()+ 
  geom_col(aes(x=reorder(nome_unidade_gestora,
                         contagem),
               y=contagem,
               fill=transação))+
  coord_flip()+
  labs(x="Unidade gestora",
       y="Número de despesas",
       fill="Tipo de transação",
       title="Número de despesas por unidade gestora e tipo de transação")+
  objeto_config+
  objeto_cores

O mesmo pode ser feito com nosso boxplot. Filtramos pela presidência e aplicamos a mesma transformação em log feita antes. A reordenação é feita usando um cálculo: reordernamos os órgãos pelo valor em log de forma decrescente considerando a mediana dos categorias (reorder(nome_unidade_gestora,valor_log,median)).

dados_rev %>% 
  filter(nome_órgão_superior=="Presidencia da Republica") %>% 
  mutate(valor_log=log(valor_transação,base=2)) %>% 
  ggplot()+
  geom_boxplot(aes(x=reorder(nome_unidade_gestora,valor_log,median),
                   y=valor_log,
                   fill=transação))+
  coord_flip()+
  labs(x="Unidade gestora",
       y="Valor da despesa",
       fill="Tipo de transação",
       title="Valor das despesas por unidade gestora e tipo de transação")+
  objeto_config+
  objeto_cores

Poderíamos trocar a fonte, aplicar negritos, modificar os textos das categorias dos eixos, remover o cinza do fundo. Construção de temas é uma tarefa complexa e realmente válida apenas para quem pretender se estender muito na parte da comunicação dos seus achados, seja produzindo artigos para revistas bem conceituadas, seja para trabalhar na divulgação científica.

Salvando plots

Finalmente, para exportar um gráfico clicamos no botão “Export” na aba “Plots” no painel inferior direito. Ela abrirá algumas opções, como salvar como imagem, como PDF ou copiar para o Ctrl+C/Ctrl+V. Clicando em “Save as image” a seguinte janela abre.

“Image format” permite a seleção do formato desejado. “Directory” permite mudar o local onde será salvo o gráfico.”File name” é o campo para mudarmos o nome do arquivo. “Width/Height” é uma mudamos a proporção do gráfico (algo muito último quando queremos um gráfico grande e com boa resolução). A caixa logo abaixo permite que o R recalcule automicamente uma dimensão do gráfico caso alteremos a outra para manter a proporção original. Ao concluir as configurações clicamos em “Save”. O arquivo estára na pasta desejada no formato e com o nome selecionado.

Exercícios

Questões

  1. Usando dplyr filtre pelos dados feitos com a UFSCAR (nome_unidade_gestora=="FUNDACAO UNIVERSIDADE FEDERAL DE SAO CARLOS") e plote um boxplot para “nome_portador” e “valor_transação”. Use coord_flip para melhorar a visualização. Há algo anormal?

  2. (Desafio) Usando mutate crie uma nova variável na nossa base para gastos maiores que 1000 reais usando uma condição ifelse onde se sim o valor será “Maior que mil” e se não o valor será “Menor que mil” (reveja aula dois se for preciso). Junte esse resultado num gráfico de barras por “nome_órgão_superior” e adicione a variável criada no argumento fill.

  • Dica: retomem a explicação sobre um mutate condicional. Como a métrica que estamos usando é número de despesas podemos usar geom_bar ao invés de geom_col, como vinhamos fazendo.
  1. (Desafio) Em métodos quantitativos, é comum encontrarmos relações entre variáveis onde os retornos de uma variável independente é decrescente, ou seja, quanto mais aumentamos X menos Y cresce. Acredita-se que esse é o caso da relação entre escolaridade e salário. Esse tipo de relação é conhecida como logarítmica. Monte um data.frame com duas variáveis que se relacionem dessa forma e plote o gráfico usando geom_point.
  • Dica: no exemplo usado neste material da função geom_point fizemos algo parecido mas com uma relação exponencial. Para obter o logarítmo de um número usamos a função log e como argumento o número em si.

Soluções

A serem divulgadas posteriormente.

Final do curso

Se você chegou até aqui, parabéns!! Você acaba de ser iniciado em R e RStudio. A jornada para adquirir maestria na ferramenta é bem mais longa e particular do que esses poucos encontros deram a entender. Agora cabe a cada um de vocês, conhecendo seus objetos de pesquisa, definir quais passos serão tomados.

Lembrem-se: a linguagem R serve para facilitar nossa vida. Seu uso passa pelo processo de identificar um problema (acadêmico ou não, formal ou informal), estudar caminhos e possibilidades, criar soluções e aplicá-las. Isso significa que nunca chegaremos num ponto de total conhecimento da linguagem. As documentações estão aí justamente para permitir o aprendizado. Mesmo aqueles que entendem muito de um tópico nela podem ter dificuldades em outro ou até mesmo na integração do conhecido com o desconhecido. Tenham perseverança!

Até uma próxima!