# Exemplo: Atribuição de valores a variáveis
<- 850000 # Receita mensal da empresa
receita_mensal <- 500000 # Custos mensais
custos_mensais
# Cálculo do lucro
<- receita_mensal - custos_mensais
lucro_mensal lucro_mensal
[1] 350000
Um tutorial básico sobre a linguagem R para Ciência de Dados.
Prof. Dr. Washington S. da Silva
7 julho 2024
Este tutorial é destinado aos estudantes do bacharelado em Administração e aos mestrandos do Mestrado Profissional em Administração do IFMG - Campus Formiga.
Também é útil para administradores, economistas, contabilistas, auditores e outros profissionais que desejam utilizar ferramentas modernas para criar relatórios e outros produtos de forma reproduzível e auditável.
O objetivo principal é proporcionar uma compreensão sólida da linguagem R, desde seus fundamentos até aplicações em análise de dados, permitindo que alunos de graduação, mestrandos e demais profissionais e pesquisadores interessados desenvolvam habilidades para criar análises reproduzíveis e auditáveis. Embora o foco inicial seja a Ciência de Dados aplicada à Administração, o conteúdo foi elaborado para ser útil em diversas áreas do conhecimento.
Acesse https://cloud.r-project.org/
Selecione o sistema operacional, clicando em Download R for Windows por exemplo.
Na página seguinte clique em base.
Clique em Download R-4.4.3 for Windows.
Feito o download basta ir clicando em próximo/next até a instalação ser concluída.
Para uma experiência de programação mais produtiva com R, recomenda-se fortemente o uso do RStudio, um IDE (Ambiente de Desenvolvimento Integrado) especialmente projetado para trabalhar com a linguagem R.
O RStudio oferece diversas funcionalidades que facilitam o aprendizado e uso da linguagem, como editor de código com destaque de sintaxe, projetos Rstudio, integração com Git e suporte nativo ao sistema Quarto.
Para instalar e configurar o RStudio, consulte nosso Tutorial sobre RStudio, onde são apresentadas instruções detalhadas para iniciantes.
Embora seja perfeitamente possível utilizar R com outros IDEs, a combinação (R + RStudio) facilita e potencializa significativamente a experiência de aprendizado e desenvolvimento.
R é um ambiente ou sistema para computação estatística e gráfico.
Este sistema é composto por duas partes: a própria linguagem R (que é o que a maioria das pessoas querem dizer quando falam sobre R) e um ambiente de tempo de execução (runtime environment).
R é uma linguagem interpretada, o que significa que os usuários acessam suas funções por meio de um interpretador de linha de comando.
Ao contrário de linguagens como Python e Java, R não é uma linguagem de programação de uso geral.
Em vez disso, R é considerada uma linguagem de domínio específica (DSL), o que significa que suas funções e uso foram projetados para uma área específica de uso ou domínio.
No caso de R, o domínio e a computação estatística. Por extensão, R é comumente usada para todos os tipos de tarefas de ciência de dados.
A linguagem R está equipada com um grande conjunto de funções internas para a manipulação, análise e visualização de dados.
Além das funções internas da linguagem, existem inúmeros pacotes (como os módulos de Python) que estendem as capacidades da linguagem.
A linguagem S
A linguagem S foi desenvolvida em meados da década de 1970 por John Chambers no lendário Bell Labs. O objetivo era oferecer uma abordagem interativa para a computação estatística, que fosse fácil de usar e tornasse as tarefas de análise de dados mais fáceis e rápidas.
Em uma entrevista de 2013, Chambers observou que a equipe do Bell Labs queria que as pessoas começassem em um ambiente interativo, onde não pensassem em si como programadores. Então, à medida que suas necessidades se tornaram mais claras e sua sofisticação aumentasse, eles dseriam capazes de se orientar gradualmente para a programação com a linguagem S.
A filosofia geral de S era muito semelhante à de R: oferecer um ambiente de software que facilitasse a programação computacional e a análise estatística, que qualquer um possa aprender a usar.
Como R, S também pode ser usada para escrever programas mais longos centrados em tarefas estatísticas. Ao contrário de R, no entanto, S e sua iteração posterior, S-Plus, eram produtos licenciados, o que significa que tinham que ser comprados de uma empresa.
Portanto, é importante notar que a linguagem R é um dialeto da linguagem S.
Sintáxe e Semântica
Os linguistas usam os termos sintaxe e semântica para descrever elementos de linguagens naturais, e os cientistas da computação também adotaram esses termos para linguagens de programação.
Na programação de computadores, a sintaxe se refere às regras que ditam a ‘ortografia’ e a ‘gramática’ de uma linguagem, enquanto a semântica se refere a como os dados ou comandos de uma linguagem são apresentados.
A sintaxe de R era muito semelhante à de S em seus primeiros anos. Isso tornou mais fácil para as pessoas que usavam S-Plus mudar para R, o que desempenhou um papel fundamental na eventual popularidade de R na academia.
A semântica de R, no entanto, está mais próxima da linguagem Scheme, uma linguagem de programação funcional.
R é uma linguagem de baixo ou alto nível?
R é considerada uma linguagem de programação de alto nível. Essa classificação é baseada em seu nível de abstração da linguagem de máquina.
Ao contrário das linguagens de baixo nível que exigem conhecimento aprofundado da memória e dos processos do computador, linguagens de alto nível como R são projetadas para serem facilmente compreendidas e escritas por humanos, tornando-as mais acessíveis para estatísticos, analistas de dados e pesquisadores.
1991: Os professores e estatísticos Ross Ihaka e Robert Gentleman começam a trabalhar em um novo dialeto da linguagem S como um projeto de pesquisa para o Departamento de Estatística da Universidade de Auckland na Nova Zelândia.
1993: O primeiro anúncio de R chega ao público através do arquivo de dados StatLib e da lista de discussão s-news.
1995: O estatístico Martin Mächler convence os criadodes de R a lançar a linguagem sob uma licença pública geral GNU, tornando R gratuita e de código aberto. Ihaka e Gentleman lançam seu artigo seminal apresentando R ao mundo.
1997: O R Core Team foi formado, este grupo é o único com acesso ao código-fonte R. No mesmo ano, foi criada a Comprehensive R Archive Network (CRAN). Este repositório de pacotes R ajuda os profissionais em inúmeras tarefas.
2000: R versão 1.0.0 foi lançada ao público.
Março de 2024: Estamos atualmente na versão R 4.3.3
Gratuito e de código aberto: Diferentemente de softwares estatísticos proprietários, R é completamente gratuito e seu código-fonte é aberto, permitindo total transparência e personalização.
Especialmente projetado para análise estatística e ciência de dados: Enquanto outras linguagens podem ser adaptadas para estas tarefas, R foi concebida especificamente para computação estatística e visualização de dados.
Ampla comunidade acadêmica e profissional: R possui uma comunidade ativa de usuários que contribuem constantemente com novos pacotes, métodos e soluções para problemas complexos.
Integração com o sistema Quarto: Perfeita compatibilidade com o sistema de publicação Quarto, permitindo a criação de documentos, apresentações e websites dinâmicos e reproduzíveis.
Ecossistema Tidyverse: O conjunto de pacotes Tidyverse fornece uma gramática consistente para manipulação, visualização e modelagem de dados, especialmente útil para iniciantes.
Excelência em visualização de dados: Pacotes como ggplot2 permitem criar visualizações estatísticas sofisticadas e personalizáveis.
Relevância no mercado: Profissionais com conhecimento em R são valorizados em setores como finanças, consultorias, pesquisa de mercado e análise de negócios.
Reprodutibilidade científica: R facilita a implementação de práticas de ciência reproduzível, essencial para pesquisas acadêmicas e relatórios corporativos auditáveis.
Versatilidade em tipos de análise: Desde estatísticas descritivas simples até modelos complexos de machine learning e econometria aplicada, R oferece ferramentas para diversos níveis de análise.
Documentação extensa: Ampla disponibilidade de documentação, tutoriais, livros e recursos online, facilitando o aprendizado contínuo.
Nas próximas seções do tutorial vamos explorar os conceitos básicos da linguagem R, que servirão como alicerce para os tópicos posteriores. Compreender esses fundamentos é essencial antes de avançarmos para análises mais complexas.
Em R, os termos “variável” e “objeto” são frequentemente usados de forma intercambiável, o que pode causar confusão inicial, especialmente para quem já possui experiência com outras linguagens de programação. Esta seção esclarece essa terminologia para facilitar seu aprendizado.
R segue uma filosofia fundamental: tudo que existe em R é um objeto. Isso significa que todos os elementos que você manipula — desde números simples até funções complexas — são tratados como objetos.
Esta abordagem difere de muitas outras linguagens de programação que fazem distinção clara entre “variáveis primitivas” (como números) e “objetos” (estruturas mais complexas).
Quando criamos algo em R usando um operador de atribuição (<-
), estamos essencialmente:
Por exemplo, em idade <- 25
, criamos um objeto do tipo numérico com valor 25 e o nomeamos como “idade”. Este nome funciona como uma etiqueta que nos permite acessar e manipular o objeto.
Por questões de clareza e para facilitar seu aprendizado:
Utilizarei o termo variável principalmente quando falarmos de valores simples que “variam”, como números, textos ou valores lógicos. Este termo é mais intuitivo para iniciantes e comum em estatística e análise de dados.
Utilizarei o termo objeto quando precisarmos enfatizar a natureza mais complexa de algumas estruturas em R, como data frames, listas, funções ou quando discutirmos conceitos mais avançados.
Em muitos contextos, usarei ambos os termos de forma intercambiável, refletindo a prática comum na comunidade R.
Esta flexibilidade terminológica espelha a documentação oficial da linguagem R e a literatura sobre a linguagem, preparando você para diferentes materiais que poderá encontrar em sua jornada de aprendizado.
Imagine uma biblioteca onde cada livro é um “objeto” de dados:
O conteúdo do livro representa os dados ou valores armazenados.
O título na lateral representa o nome da variável
As prateleiras e estantes representam a memória do computador
O catálogo da biblioteca equivale ao ambiente R, que mantém registro de onde cada objeto está armazenado
Quando você cria uma variável como receita <- 5000
, é como se estivesse colocando um novo livro (com o conteúdo “5000”) na biblioteca e rotulando sua lateral como “receita” para poder encontrá-lo depois.
Este entendimento sobre variáveis e objetos em R estabelece uma base conceitual importante antes de mergulharmos nos tipos específicos de dados e em como manipulá-los para análises eficazes.
Em R, a atribuição de valores a variáveis é fundamental para armazenar e manipular dados. Por exemplo, podemos criar variáveis para armazenar informações financeiras, como receitas, custos e lucros, que são essenciais para análises em Administração.
# Exemplo: Atribuição de valores a variáveis
receita_mensal <- 850000 # Receita mensal da empresa
custos_mensais <- 500000 # Custos mensais
# Cálculo do lucro
lucro_mensal <- receita_mensal - custos_mensais
lucro_mensal
[1] 350000
Todas as instruções R com as quais criamos variáveis ou objetos têm o mesmo formato:
Lemos esse código como: “valor é atribuído a nome_objeto”
Em R, podemos atribuir informações às variáveis (ou objetos) utilizando os seguintes operadores de atribuição:
# Diferentes formas de atribuição em R
# Mesmo resultado, estilos diferentes
# Operador recomendado (<-)
receita_mensal <- 850000
receita_mensal
[1] 850000
[1] 320000
Em R, como em todas as linguagens, fazemos muitas atribuições de valores a variáveis, e não é agradável digitar o operador manualmente. Assim, o RStudio oferece um atalho de teclado simples para inserir o operador <-
:
Atalho do RStudio: Alt + -
(Windows/Linux) ou Option + -
(Mac)
Observe que o RStudio automaticamente envolve <-
com espaços, o que é uma boa prática de formatação de código.
Códigos sem espaços são difíceis de ler compare:
lucro<-receita-custos
versus
lucro <- receita - custos
Nomes de variáveis devem começar com uma letra e podem conter letras
, números
, _
e .
É importante criar nomes de objetos simples e descritivos que representem claramente seu conteúdo. Em Administração, é comum trabalhar com dados financeiros, de desempenho ou de mercado, então use nomes que facilitem a compreensão do código.
Exemplos de boas práticas:
Estilos de nomenclatura:
margem_bruta
, fluxo_caixa_operacional
MargemBruta
, FluxoCaixaOperacional
Escolha um estilo e mantenha a consistência em todo o código.
Evite os seguintes erros comuns:
dados
, resultado
, x
receita_anual
, lucro_liquido
calculo_da_margem_de_contribuicao_ajustada
margem_contribuicao
margem bruta <- 0.35
(causa erro)margem_bruta <- 0.35
1trimestre <- "Janeiro-Março"
(inválido)trimestre1 <- "Janeiro-Março"
mean <- 10
(sobrescreve a função mean()
)media <- 10
Em R, existem algumas formas simples e eficazes de exibir informações sobre objetos ou variáveis. Esses métodos são ideais para visualizar valores, depurar código ou criar saídas personalizadas. Abaixo estão as principais formas:
1. Usando print()
A função print()
é a maneira mais básica de exibir o conteúdo de um objeto:
[1] 850000.5
2. Imprimindo diretamente no console
Em R, você pode exibir o conteúdo de um objeto simplesmente digitando seu nome no console. Isso chama automaticamente a função print()
implicitamente:
3. Usando a função cat()
A função cat()
permite exibir informações de forma mais personalizada, combinando texto e valores. É útil para criar mensagens ou relatórios simples.
A receita mensal é: 850000.5
Resumo:
Use print()
para exibir valores de forma explícita.
Digite o nome do objeto diretamente no console para exibir seu valor de forma rápida.
Use cat()
para criar saídas personalizadas, combinando texto e valores.
Em R, os dados são armazenados em diferentes tipos atômicos (básicos), cada um com características específicas. A Tabela 3 mostra os principais tipos.
Tipo | Classe | Descrição |
---|---|---|
double |
numeric |
um vetor contendo valores reais (números com casas decimais) |
integer |
numeric |
um vetor contendo valores inteiros (números sem casas decimais) |
character |
character |
um vetor contendo valores de texto (caracteres) |
logical |
logical |
um vetor contendo valores lógicos (TRUE /FALSE ) |
A Tabela 2 exibe alguns tipos especiais que podem aparecer em análises de dados.
Tipo | Descrição |
---|---|
NA |
Not Available : representa dados faltantes |
NaN |
Not a Number : (ex: 0 / 0 ) |
Inf |
+ \infty ou - \infty: (ex: 1 / 0 ) |
Na prática da Ciência de Dados, estima-se que analistas e cientistas dedicam entre 60% a 80% do tempo de um projeto à importação, limpeza e preparação dos dados antes de iniciar análises mais sofisticadas. Compreender profundamente os tipos e classes de dados em R é fundamental por várias razões:
Evita erros sutis de processamento: Operações matemáticas em dados textuais ou cálculos com valores ausentes podem produzir resultados inesperados.
Otimiza o desempenho: Estruturas de dados apropriadas melhoram a eficiência computacional, especialmente em conjuntos grandes.
Facilita transformações: O conhecimento dos tipos permite conversões adequadas (como texto para número) sem perda de informação.
Melhora a interpretabilidade: Identificar corretamente dados faltantes (NA
), indefinidos (NaN
), ou infinitos (Inf
) é crucial para conclusões válidas.
Aumenta a compatibilidade: Diferentes funções e pacotes em R exigem tipos específicos de dados como entrada.
O domínio dos tipos e classes de dados não é apenas uma questão técnica, mas um requisito fundamental para análises confiáveis em contextos administrativos e financeiros. Este conhecimento permite ao analista de dados concentrar-se mais nos insights e menos na correção de problemas estruturais nos dados.
double
e integer
Em R, existem dois tipos principais de dados numéricos:
double
: Armazena números com casas decimais (ponto flutuante), ideal para valores monetários, índices financeiros, taxas percentuais e outras medidas que exigem precisão decimal.
integer
: Armazena números inteiros sem casas decimais, útil para contagens, quantidades discretas e índices em séries temporais.
Na prática de Administração e Finanças, o tipo double
é frequentemente utilizado para representar valores monetários, taxas de juros ou indicadores financeiros, enquanto integer
é mais comum para representar quantidades como número de funcionários, produtos vendidos ou períodos de análise.
O sufixo L
após um número (como em 50L
) indica explicitamente que se trata de um valor inteiro. Na maioria das operações, R utiliza automaticamente o tipo mais apropriado, o que simplifica a programação para análises financeiras e administrativas.
# double (números com casas decimais)
receita <- 850000.50
# integer (números inteiros)
total_funcionarios <- 50L
# verifica os tipos
typeof(receita)
[1] "double"
[1] "integer"
numeric
Apesar dos tipos double
e integer
representarem números decimais e inteiros de forma diferente, ambos pertencem à classe numeric
, assim, na maioria das situações, você não precisa se preocupar com a possível diferença.
Diferença entre typeof
e class
Em R, as funções typeof
e class
fornecem informações diferentes sobre um objeto:
typeof
: Retorna o tipo interno do objeto, ou seja, como R armazena o objeto na memória. Por exemplo:class
: Retorna a classe do objeto, que define como R trata o objeto em operações e funções. Por exemplo:Em resumo:
typeof
para entender como R armazena o objeto internamente.class
para entender como R trata o objeto em operações e funções.character
O tipo character
é essencial para armazenar e manipular informações textuais. Este tipo de dado armazena sequências de caracteres (texto) e é indicado por aspas simples ('
) ou duplas ("
).
Em contextos de Administração, o tipo character
é utilizado para armazenar:
A manipulação de dados textuais é particularmente importante em análises de mercado, pesquisas de satisfação, classificação de produtos e organização de relatórios gerenciais, onde a categorização textual precede análises quantitativas.
logical
O tipo logical
representa valores booleanos (TRUE
ou FALSE
) e é fundamental para operações condicionais e filtragem de dados.
Em contextos práticos de gestão e finanças, o tipo logical
é utilizado para:
Os valores TRUE
e FALSE
devem ser escritos em maiúsculas em R, e podem ser abreviados como T
e F
, respectivamente, embora a forma completa seja recomendada para maior clareza do código.
NA
O tipo especial NA
(Not Available) é comum em análises de dados reais, onde frequentemente nos deparamos com informações ausentes. Em contextos de Administração e Finanças, dados faltantes podem representar:
Identificar e tratar corretamente os valores NA
é essencial para evitar conclusões tendenciosas. R oferece funções específicas como is.na()
para detectar valores ausentes e métodos estatísticos para lidar com eles de forma apropriada.
# Exemplo: Detectando valores ausentes em dados de vendas
vendas_trimestrais <- c(150000, 165000, NA, 180000)
is.na(vendas_trimestrais)
[1] FALSE FALSE TRUE FALSE
[1] 165000
O tratamento adequado de dados falantes é uma habilidade fundamental em Ciência de Dados.
NaN
O valor NaN
(Not a Number) ocorre quando uma operação matemática produz um resultado indefinido. Em contextos de gestão e finanças, este tipo especial pode surgir em:
Enquanto NA
representa dados ausentes, NaN
indica especificamente um resultado numérico indefinido. Diferenciá-los é importante para diagnóstico de problemas em cálculos complexos, como em modelos de precificação de ativos ou simulações financeiras.
A função is.nan()
permite identificar estes valores em conjuntos de dados:
inf
O valor especial Inf
(e -Inf
para infinito negativo) ocorre principalmente em divisões por zero e representa valores que excedem os limites computacionais. Em análises administrativas e financeiras, este tipo pode aparecer em:
Diferentemente de NA
e NaN
, valores Inf
podem ser utilizados em operações aritméticas seguindo regras matemáticas de infinito:
# Exemplo: Comportamento de infinito em operações
infinito_positivo <- 1/0
infinito_positivo + 1000 # Continua sendo Inf
[1] Inf
[1] Inf
Identificar valores infinitos é importante, por exemplo, em modelos financeiros, pois podem indicar problemas estruturais nas fórmulas utilizadas ou divisões por zero que comprometem a validade das análises.
Você pode estar se perguntando como converter um tipo ou classe de dados em outro(a) (por exemplo, transformar um texto em número ou vice-versa).
Embora R base ofereça funções como as.numeric()
, as.character()
e as.logical()
para essas conversões, abordaremos este tópico mais adiante no tutorial, quando estudarmos a manipulação de dados com o pacote dplyr
.
Especificamente, aprenderemos como usar as funções mutate()
e transmute()
para realizar conversões de tipos de maneira eficiente e legível em conjuntos de dados estruturados. Esta abordagem se alinha com as práticas modernas de ciência de dados e permite transformar múltiplas variáveis simultaneamente dentro de um fluxo de trabalho analítico coerente.
Por enquanto, foque em compreender as características e comportamentos dos diferentes tipos de dados apresentados nesta seção, pois este conhecimento fundamentará toda sua jornada na análise de dados com R.
Em R, os dados são organizados em diferentes estruturas, cada uma adequada a tipos específicos de operações e análises. As principais estruturas de dados são:
A compreensão dessas estruturas facilita uma escolha eficiente para diferentes contextos analíticos, sendo essencial para utilizar efetivamente os pacotes e recursos avançados do R.
A função básica para criar vetores é c()
, que concatena valores.
Utilize colchetes []
para selecionar elementos. Lembre-se de que a indexação no R começa por 1.
R possui diversas funções que facilitam cálculos matemáticos e estatísticos diretamente aplicáveis a vetores. Algumas essenciais são:
[1] 25
[1] 1 4 9 16 25
[1] 945
[1] 1 3 15 105 945
[1] 0.000000 1.098612 1.609438 1.945910 2.197225
[1] 2.718282 20.085537 148.413159 1096.633158 8103.083928
[1] 5
[1] 5
[1] 3.162278
[1] 10
[1] 1
[1] 9
Essas funções são especialmente úteis em aplicações estatísticas e econométricas, como o cálculo de retornos médios, dispersão de dados financeiros ou identificação de extremos em séries temporais.
Operações matemáticas são aplicadas diretamente em vetores, permitindo grande eficiência:
Sempre verifique o tipo e comprimento dos vetores para evitar problemas na análise:
Além de numéricos, vetores podem conter caracteres (texto) ou valores lógicos:
typeof()
e class()
para checar e evitar coerções não desejadas.Matrizes são estruturas bidimensionais que organizam elementos homogêneos em linhas e colunas. Em análises estatísticas, econométricas e métodos numéricos, matrizes desempenham papel central, especialmente devido à eficiência computacional nas operações de álgebra linear.
[linha, coluna]
.Em R, matrizes são criadas com a função matrix()
. Esta função recebe um vetor de dados e distribui-os em uma matriz especificando o número de linhas (nrow
) ou colunas (ncol
). O parâmetro byrow
define se o preenchimento será feito por linhas (TRUE
) ou por colunas (FALSE
, padrão).
# Criação por linhas
A <- matrix(c(4, 2, 1,
3, 5, 2,
1, 2, 6), nrow = 3, byrow = TRUE)
# Criação por colunas (default)
B <- matrix(c(2, 1, 2,
1, 4, 1,
3, 2, 5), nrow = 3)
A
[,1] [,2] [,3]
[1,] 4 2 1
[2,] 3 5 2
[3,] 1 2 6
[,1] [,2] [,3]
[1,] 2 1 3
[2,] 1 4 2
[3,] 2 1 5
# Matriz econométrica simulada
set.seed(123)
X <- matrix(c(rep(1, 5), 2:6, seq(1.5, 3.5, 0.5)), nrow = 5)
colnames(X) <- c("Intercepto", "X1", "X2")
X
Intercepto X1 X2
[1,] 1 2 1.5
[2,] 1 3 2.0
[3,] 1 4 2.5
[4,] 1 5 3.0
[5,] 1 6 3.5
As operações básicas entre matrizes ocorrem elemento a elemento ou por meio de multiplicação matricial:
[,1] [,2] [,3]
[1,] 6 3 4
[2,] 4 9 4
[3,] 3 3 11
[,1] [,2] [,3]
[1,] 2 1 -2
[2,] 2 1 0
[3,] -1 1 1
[,1] [,2] [,3]
[1,] 8 2 3
[2,] 3 20 4
[3,] 2 2 30
[,1] [,2] [,3]
[1,] 2.0 2.00 0.3333333
[2,] 3.0 1.25 1.0000000
[3,] 0.5 2.00 1.2000000
[,1] [,2] [,3]
[1,] 12 6 3
[2,] 9 15 6
[3,] 3 6 18
[,1] [,2] [,3]
[1,] 12 13 21
[2,] 15 25 29
[3,] 16 15 37
[,1] [,2] [,3]
[1,] 4 3 1
[2,] 2 5 2
[3,] 1 2 6
O determinante indica se uma matriz quadrada é invertível (determinante diferente de zero). A inversa de uma matriz A é a matriz A^{-1} tal que A A^{-1} = I, onde I é a matriz identidade.
R permite criar matrizes especiais úteis em aplicações específicas:
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
[,1] [,2] [,3]
[1,] 2 0 0
[2,] 0 5 0
[3,] 0 0 3
[1] 4 5 6
[,1] [,2] [,3]
[1,] 4 2 1
[2,] 0 5 2
[3,] 0 0 6
[,1] [,2] [,3]
[1,] 4 0 0
[2,] 3 5 0
[3,] 1 2 6
Para uma matriz quadrada A, um autovalor \lambda e seu respectivo autovetor v satisfazem:
A v = \lambda v
Decomposições matriciais facilitam cálculos complexos e análises estruturais, expressando matrizes como produtos de outras com propriedades específicas.
Expressa uma matriz A como A = QR, onde Q é ortogonal e R é triangular superior.
Expressa qualquer matriz A como A = U D V', onde U e V são ortogonais e D é diagonal contendo valores singulares.
No modelo de regressão linear múltipla Y = X \beta + \varepsilon, a estimativa por Mínimos Quadrados Ordinários (MQO) é dada por:
\hat{\beta} = (X'X)^{-1} X'Y
Listas são as estruturas mais flexíveis do R, fundamentais em econometria para armazenar resultados de simulações, outputs de modelos estatísticos e organizar dados de diferentes tipos e dimensões. São especialmente úteis em simulações de Monte Carlo e no desenvolvimento de funções econométricas personalizadas.
# Lista para armazenar resultados de um modelo de regressão
set.seed(123)
n <- 100
X <- cbind(1, rnorm(n), rnorm(n)) # Matriz de regressores
beta_true <- c(2, 1.5, -0.8) # Parâmetros verdadeiros
epsilon <- rnorm(n, 0, 2) # Termo de erro
Y <- X %*% beta_true + epsilon # Variável dependente
# Estimação do modelo
XtX_inv <- solve(t(X) %*% X)
beta_hat <- XtX_inv %*% t(X) %*% Y
residuos <- Y - X %*% beta_hat
sigma2_hat <- sum(residuos^2) / (n - ncol(X))
# Armazenando resultados em uma lista
resultado_regressao <- list(
coeficientes = as.vector(beta_hat),
matriz_covariancia = sigma2_hat * XtX_inv,
residuos = as.vector(residuos),
R_quadrado = 1 - sum(residuos^2) / sum((Y - mean(Y))^2),
graus_liberdade = n - ncol(X),
observacoes = n,
dados = list(X = X, Y = Y)
)
# Visualizando a estrutura da lista
str(resultado_regressao)
List of 7
$ coeficientes : num [1:3] 2.27 1.234 -0.752
$ matriz_covariancia: num [1:3, 1:3] 0.03697 -0.00376 0.00403 -0.00376 0.04399 ...
$ residuos : num [1:100] 4.012 2.281 -0.374 0.852 -1.019 ...
$ R_quadrado : num 0.346
$ graus_liberdade : num 97
$ observacoes : num 100
$ dados :List of 2
..$ X: num [1:100, 1:3] 1 1 1 1 1 1 1 1 1 1 ...
..$ Y: num [1:100, 1] 6.13 4.07 4.01 3.47 2.13 ...
[1] 2.2701309 1.2336569 -0.7523774
[1] 0.3462614
[1] 0.3462614
[1] 6.125232 4.074053 4.005126 3.470185 2.126547
$coeficientes
[1] 2.2701309 1.2336569 -0.7523774
$R_quadrado
[1] 0.3462614
# Função para simulação de Monte Carlo
simulacao_regressao <- function(n, beta_true, sigma, n_sim = 1000) {
# Lista para armazenar resultados de cada simulação
resultados <- list()
for(i in 1:n_sim) {
# Gerando dados
X <- cbind(1, rnorm(n), rnorm(n))
epsilon <- rnorm(n, 0, sigma)
Y <- X %*% beta_true + epsilon
# Estimando parâmetros
beta_hat <- solve(t(X) %*% X) %*% t(X) %*% Y
# Armazenando resultado da i-ésima simulação
resultados[[i]] <- list(
beta_hat = as.vector(beta_hat),
iteracao = i
)
}
return(resultados)
}
# Executando simulação (versão reduzida para demonstração)
set.seed(456)
sim_resultados <- simulacao_regressao(
n = 50,
beta_true = c(1, 2, -1),
sigma = 1,
n_sim = 100
)
# Analisando resultados da simulação
betas_simulados <- sapply(sim_resultados, function(x) x$beta_hat)
media_betas <- rowMeans(betas_simulados)
cat("Parâmetros verdadeiros:", c(1, 2, -1), "\n")
Parâmetros verdadeiros: 1 2 -1
Média das estimativas: 1.013 2 -1.002
Número de simulações: 100
# Função para estimar e comparar diferentes modelos
comparar_modelos <- function(Y, X1, X2, X3) {
# Modelo 1: apenas X1
modelo1 <- lm(Y ~ X1)
# Modelo 2: X1 e X2
modelo2 <- lm(Y ~ X1 + X2)
# Modelo 3: X1, X2 e X3
modelo3 <- lm(Y ~ X1 + X2 + X3)
# Organizando resultados em lista
comparacao <- list(
modelo_1 = list(
coeficientes = coef(modelo1),
R2 = summary(modelo1)$r.squared,
AIC = AIC(modelo1),
n_parametros = length(coef(modelo1))
),
modelo_2 = list(
coeficientes = coef(modelo2),
R2 = summary(modelo2)$r.squared,
AIC = AIC(modelo2),
n_parametros = length(coef(modelo2))
),
modelo_3 = list(
coeficientes = coef(modelo3),
R2 = summary(modelo3)$r.squared,
AIC = AIC(modelo3),
n_parametros = length(coef(modelo3))
),
criterios_selecao = data.frame(
Modelo = c("Modelo 1", "Modelo 2", "Modelo 3"),
R2 = c(summary(modelo1)$r.squared,
summary(modelo2)$r.squared,
summary(modelo3)$r.squared),
AIC = c(AIC(modelo1), AIC(modelo2), AIC(modelo3))
)
)
return(comparacao)
}
# Gerando dados para demonstração
set.seed(789)
n <- 80
X1 <- rnorm(n)
X2 <- rnorm(n)
X3 <- rnorm(n)
Y <- 2 + 1.5*X1 + 0.8*X2 + rnorm(n, 0, 1)
# Executando comparação
resultados_comparacao <- comparar_modelos(Y, X1, X2, X3)
# Acessando resultados
print("Critérios de Seleção:")
[1] "Critérios de Seleção:"
Modelo R2 AIC
1 Modelo 1 0.5164472 280.1806
2 Modelo 2 0.7801518 219.1228
3 Modelo 3 0.7872469 218.4984
R² do melhor modelo: 0.7872469
# Função para realizar múltiplos testes diagnósticos
testes_diagnosticos <- function(modelo) {
# Teste de normalidade dos resíduos (Shapiro-Wilk)
teste_normalidade <- shapiro.test(residuals(modelo))
# Teste de heterocedasticidade (Breusch-Pagan simplificado)
residuos2 <- residuals(modelo)^2
valores_ajustados <- fitted(modelo)
teste_hetero <- summary(lm(residuos2 ~ valores_ajustados))
# Organizando resultados em lista estruturada
diagnosticos <- list(
normalidade = list(
estatistica = teste_normalidade$statistic,
p_valor = teste_normalidade$p.value,
interpretacao = ifelse(teste_normalidade$p.value > 0.05,
"Resíduos seguem distribuição normal",
"Evidência contra normalidade")
),
heterocedasticidade = list(
R2 = teste_hetero$r.squared,
F_estatistica = teste_hetero$fstatistic[1],
interpretacao = ifelse(teste_hetero$r.squared < 0.1,
"Não há evidência de heterocedasticidade",
"Possível heterocedasticidade")
),
resumo_modelo = list(
R2_ajustado = summary(modelo)$adj.r.squared,
erro_padrao = summary(modelo)$sigma,
observacoes = nobs(modelo)
)
)
return(diagnosticos)
}
# Aplicando função de testes
modelo_exemplo <- lm(Y ~ X1 + X2)
resultados_testes <- testes_diagnosticos(modelo_exemplo)
# Visualizando resultados
str(resultados_testes, max.level = 2)
List of 3
$ normalidade :List of 3
..$ estatistica : Named num 0.973
.. ..- attr(*, "names")= chr "W"
..$ p_valor : num 0.0887
..$ interpretacao: chr "Resíduos seguem distribuição normal"
$ heterocedasticidade:List of 3
..$ R2 : num 0.00434
..$ F_estatistica: Named num 0.34
.. ..- attr(*, "names")= chr "value"
..$ interpretacao: chr "Não há evidência de heterocedasticidade"
$ resumo_modelo :List of 3
..$ R2_ajustado: num 0.774
..$ erro_padrao: num 0.923
..$ observacoes: int 80
[1] "Resíduos seguem distribuição normal"
[1] "Não há evidência de heterocedasticidade"
As estruturas tabulares organizam informações em formato de tabela, com linhas representando observações e colunas representando variáveis. Data frames e tibbles constituem a base para a maioria das análises estatísticas e financeiras.
Estas estruturas permitem:
Diferentemente das matrizes (homogêneas), data frames e tibbles permitem colunas de tipos diferentes, sendo ideais para conjuntos de dados típicos em administração e finanças.
O data frame é a estrutura de dados mais utilizada em R para análises estatísticas. Conceptualmente similar a uma planilha, um data frame organiza dados em formato retangular onde cada linha representa uma observação e cada coluna representa uma variável.
Um data frame possui as seguintes características essenciais:
A função data.frame()
permite criar estruturas tabulares combinando vetores de mesmo comprimento:
# Dados de desempenho empresarial
empresa <- c("TechCorp", "FinanceMax", "RetailPlus")
receita_milhoes <- c(125.8, 89.3, 156.7)
crescimento_percentual <- c(12.5, -3.2, 8.9)
meta_atingida <- c(TRUE, FALSE, TRUE)
# Criando o data frame
desempenho_empresas <- data.frame(
empresa = empresa,
receita_milhoes = receita_milhoes,
crescimento_percentual = crescimento_percentual,
meta_atingida = meta_atingida
)
# Exibindo o resultado
desempenho_empresas
empresa receita_milhoes crescimento_percentual meta_atingida
1 TechCorp 125.8 12.5 TRUE
2 FinanceMax 89.3 -3.2 FALSE
3 RetailPlus 156.7 8.9 TRUE
Para compreender a estrutura interna de um data frame, utilizamos funções específicas:
'data.frame': 3 obs. of 4 variables:
$ empresa : chr "TechCorp" "FinanceMax" "RetailPlus"
$ receita_milhoes : num 125.8 89.3 156.7
$ crescimento_percentual: num 12.5 -3.2 8.9
$ meta_atingida : logi TRUE FALSE TRUE
[1] 3 4
[1] "empresa" "receita_milhoes" "crescimento_percentual"
[4] "meta_atingida"
[1] "1" "2" "3"
R oferece múltiplas formas de acessar elementos em data frames:
[1] 125.8 89.3 156.7
empresa receita_milhoes
1 TechCorp 125.8
2 FinanceMax 89.3
3 RetailPlus 156.7
[1] -3.2
# Filtrando observações por condição
desempenho_empresas[desempenho_empresas$meta_atingida == TRUE, ]
empresa receita_milhoes crescimento_percentual meta_atingida
1 TechCorp 125.8 12.5 TRUE
3 RetailPlus 156.7 8.9 TRUE
Para análises preliminares, a função summary()
fornece estatísticas descritivas:
empresa receita_milhoes crescimento_percentual meta_atingida
Length:3 Min. : 89.3 Min. :-3.200 Mode :logical
Class :character 1st Qu.:107.5 1st Qu.: 2.850 FALSE:1
Mode :character Median :125.8 Median : 8.900 TRUE :2
Mean :123.9 Mean : 6.067
3rd Qu.:141.2 3rd Qu.:10.700
Max. :156.7 Max. :12.500
Tibbles são uma versão modernizada dos data frames, desenvolvida como parte do ecosistema tidyverse. Mantêm compatibilidade com data frames tradicionais, mas incorporam melhorias significativas para análise de dados contemporânea.
library(tibble)
# Convertendo o data frame em tibble
desempenho_tibble <- as_tibble(desempenho_empresas)
# Exibindo o tibble
desempenho_tibble
# A tibble: 3 × 4
empresa receita_milhoes crescimento_percentual meta_atingida
<chr> <dbl> <dbl> <lgl>
1 TechCorp 126. 12.5 TRUE
2 FinanceMax 89.3 -3.2 FALSE
3 RetailPlus 157. 8.9 TRUE
A função tibble()
oferece uma sintaxe mais moderna para criação:
# Criando tibble com dados financeiros trimestrais
resultados_trim <- tibble(
trimestre = c("Q1", "Q2", "Q3", "Q4"),
receita = c(2.8, 3.1, 3.5, 4.2),
margem_bruta = c(0.32, 0.35, 0.38, 0.41),
roi = receita * margem_bruta / 2.5 # Calculando ROI diretamente
)
resultados_trim
# A tibble: 4 × 4
trimestre receita margem_bruta roi
<chr> <dbl> <dbl> <dbl>
1 Q1 2.8 0.32 0.358
2 Q2 3.1 0.35 0.434
3 Q3 3.5 0.38 0.532
4 Q4 4.2 0.41 0.689
O tibble oferece funções específicas para inspeção detalhada:
Rows: 4
Columns: 4
$ trimestre <chr> "Q1", "Q2", "Q3", "Q4"
$ receita <dbl> 2.8, 3.1, 3.5, 4.2
$ margem_bruta <dbl> 0.32, 0.35, 0.38, 0.41
$ roi <dbl> 0.3584, 0.4340, 0.5320, 0.6888
[1] "character"
[1] "numeric"
[1] "numeric"
[1] "numeric"
Para análises robustas, é fundamental identificar dados faltantes:
# Criando tibble com alguns valores ausentes para demonstração
dados_com_na <- tibble(
empresa = c("Alpha", "Beta", "Gamma", "Delta"),
vendas = c(150, NA, 180, 165),
custo = c(120, 140, NA, 135),
lucro = vendas - custo
)
# Visualizando o tibble
dados_com_na
# A tibble: 4 × 4
empresa vendas custo lucro
<chr> <dbl> <dbl> <dbl>
1 Alpha 150 120 30
2 Beta NA 140 NA
3 Gamma 180 NA NA
4 Delta 165 135 30
# Contando valores ausentes por coluna usando loop
for(coluna in names(dados_com_na)) {
na_count <- sum(is.na(dados_com_na[[coluna]]))
cat("Coluna", coluna, ":", na_count, "valores ausentes\n")
}
Coluna empresa : 0 valores ausentes
Coluna vendas : 1 valores ausentes
Coluna custo : 1 valores ausentes
Coluna lucro : 2 valores ausentes
# A tibble: 2 × 4
empresa vendas custo lucro
<chr> <dbl> <dbl> <dbl>
1 Beta NA 140 NA
2 Gamma 180 NA NA
Para demonstrar a aplicação prática dessas estruturas, utilizaremos dados reais de performance de carteiras do pacote PerformanceAnalytics
:
library(PerformanceAnalytics)
library(tidyverse)
# Carregando dados de retornos de gestores e benchmarks
data(managers, package = "PerformanceAnalytics")
# Convertendo para tibble e preservando datas
retornos_gestores <- as_tibble(managers, rownames = "data")
# Exibindo estrutura dos dados
glimpse(retornos_gestores)
Rows: 132
Columns: 11
$ data <chr> "1996-01-31", "1996-02-29", "1996-03-31", "1996-04-30", …
$ HAM1 <dbl> 0.0074, 0.0193, 0.0155, -0.0091, 0.0076, -0.0039, -0.023…
$ HAM2 <dbl> NA, NA, NA, NA, NA, NA, NA, -0.0001, 0.1002, 0.0338, 0.0…
$ HAM3 <dbl> 0.0349, 0.0351, 0.0258, 0.0449, 0.0353, -0.0303, -0.0337…
$ HAM4 <dbl> 0.0222, 0.0195, -0.0098, 0.0236, 0.0028, -0.0019, -0.044…
$ HAM5 <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ HAM6 <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ `EDHEC LS EQ` <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0.0281, …
$ `SP500 TR` <dbl> 0.0340, 0.0093, 0.0096, 0.0147, 0.0258, 0.0038, -0.0442,…
$ `US 10Y TR` <dbl> 0.00380, -0.03532, -0.01057, -0.01739, -0.00543, 0.01507…
$ `US 3m TR` <dbl> 0.00456, 0.00398, 0.00371, 0.00428, 0.00443, 0.00412, 0.…
[1] "1996-01-31" "2006-12-31"
# Contando observações válidas por gestor (excluindo valores ausentes)
cat("Observações válidas por coluna:\n")
Observações válidas por coluna:
for(coluna in names(retornos_gestores)[-1]) { # Excluindo coluna 'data'
obs_validas <- sum(!is.na(retornos_gestores[[coluna]]))
cat(coluna, ":", obs_validas, "observações\n")
}
HAM1 : 132 observações
HAM2 : 125 observações
HAM3 : 132 observações
HAM4 : 132 observações
HAM5 : 77 observações
HAM6 : 64 observações
EDHEC LS EQ : 120 observações
SP500 TR : 132 observações
US 10Y TR : 132 observações
US 3m TR : 132 observações
HAM1 HAM2 HAM3
Min. :-0.094400 Min. :-0.03710 Min. :-0.071800
1st Qu.:-0.000025 1st Qu.:-0.00980 1st Qu.:-0.005375
Median : 0.011150 Median : 0.00820 Median : 0.010200
Mean : 0.011123 Mean : 0.01414 Mean : 0.012447
3rd Qu.: 0.024850 3rd Qu.: 0.02520 3rd Qu.: 0.031375
Max. : 0.069200 Max. : 0.15560 Max. : 0.179600
NA's :7
Este conjunto de dados será utilizado nas próximas seções para demonstrar:
Nesta seção estabelecemos os fundamentos das principais estruturas de dados em R:
Critérios para Escolha da Estrutura:
Compreender quando e como utilizar cada estrutura é fundamental para desenvolver análises eficientes e código limpo em contextos administrativos e financeiros.
O tidyverse é um ecossistema coerente de pacotes R para ciência de dados que compartilham uma filosofia de design e gramática comuns.
Desenvolvido por Hadley Wickham e mantido pela Posit, o tidyverse facilita todo o fluxo de trabalho de análise de dados através de pacotes integrados.
readr/readxl: Importação eficiente de dados retangulares
tidyr: Estruturação de dados no formato “tidy” (pivot_longer
, pivot_wider
)
dplyr: Manipulação de dados com verbos intuitivos (filter
, select
, mutate
)
ggplot2/gt: Visualização de dados baseada na gramática dos gráficos
O tidyverse implementa o princípio de “tidy data”, criando um fluxo de trabalho coeso através do operador pipe (%>%
ou |>
).
O grande poder do tidyverse está na integração entre seus pacotes. Exemplo: um fluxo completo que:
mutate
)group_by
, summarise
)pivot_longer
)ggplot2
)%>%
ou |>
.A filosofia do tidyverse está alinhada com os princípios modernos de ciência de dados transparente, auditável e reproduzível.
O conceito de Tidy Data (Dados Organizados) foi formalizado por Hadley Wickham.
Um arquivo de dados organizado possui a seguinte estrutura:
A Figura 1 ilustra o conceito de dados organizados visualmente.
Adequação para Ferramentas: Formato de armazenamento de dados adequado para análise em linguagens (R/Python) e softwares de análise de dados.
Consistência: Estrutura uniforme para todos os conjuntos de dados
Facilidade para operações comuns:
Colunas contendo valores: Nomes de colunas contendo valores de uma ou mais variáveis.
| Empresa | Ano | Valor |
|-----------|------|---------|
| Empresa A | 2020 | 350.000 |
| Empresa A | 2021 | 425.000 |
| Empresa A | 2022 | 510.000 |
| Empresa B | 2020 | 780.000 |
| Empresa B | 2021 | 815.000 |
| Empresa B | 2022 | 840.000 |
| Empresa C | 2020 | 540.000 |
| Empresa C | 2021 | 490.000 |
| Empresa C | 2022 | 620.000 |
Características:
Múltiplas variáveis em uma coluna: Uma coluna contendo mais de uma variável
| Nome_Empresa (Ano) | Receita | Despesa |
|--------------------|---------------|---------------|
| Empresa A (2020) | R$ 350.000,00 | R$ 290.000,00 |
| Empresa A (2021) | R$ 425.000,00 | R$ 320.000,00 |
| Empresa B (2020) | R$ 780.000,00 | R$ 710.000,00 |
| Empresa B (2021) | R$ 815.000,00 | R$ 735.000,00 |
| Empresa | T1 2023 | T2 2023 | T3 2023 | T4 2023 |
|------------|---------|---------|---------|---------|
| TechSoft | 25.3 | 31.7 | 28.4 | 35.2 |
| VarejoMax | 12.8 | 15.4 | 19.3 | 22.7 |
| FinGroup | 41.6 | 38.9 | 45.2 | 51.8 |
Problemas:
| Empresa | Trimestre | Ano | Lucro_Liquido |
|-----------|-----------|------|---------------|
| TechSoft | T1 | 2023 | 25.3 |
| TechSoft | T2 | 2023 | 31.7 |
| TechSoft | T3 | 2023 | 28.4 |
| TechSoft | T4 | 2023 | 35.2 |
| VarejoMax | T1 | 2023 | 12.8 |
| VarejoMax | T2 | 2023 | 15.4 |
| VarejoMax | T3 | 2023 | 19.3 |
| VarejoMax | T4 | 2023 | 22.7 |
| FinGroup | T1 | 2023 | 41.6 |
| FinGroup | T2 | 2023 | 38.9 |
| FinGroup | T3 | 2023 | 45.2 |
| FinGroup | T4 | 2023 | 51.8 |
Variáveis em linhas e colunas
| Empresa | Indicador | Valor |
|------------|---------------------|-------------|
| Empresa XYZ| ROE | 0.152 |
| Empresa XYZ| Liquidez Corrente | 1.8 |
| Empresa XYZ| Lucro Líquido | 2500000 |
| Empresa XYZ| Patrimônio Líquido | 16400000 |
| Empresa XYZ| Ativo Circulante | 3600000 |
| Empresa XYZ| Passivo Circulante | 2000000 |
Por que a maioria das pessoas que trabalham na área de negócios não está familiarizada com os princípios da organização de dados para análise e utilizam planilhas eletrônicas para trabalhar com dados.
Planilhas de dados são frequentemente organizadas pensando em apresentar os dados ou para tornar a entrada de dados mais simples, não em um formato adequado para armazenamento e análise.
Isso significa que, para a maioria das análises reais, cientistas e analistas de dados dispendem muito tempo e esforço organizando e preparando dados elaborados por terceiros.
A primeira etapa é sempre descobrir quais são as observações e as variáveis associadas a cada observação.
Dados organizados viabilizam e facilitam a:
Reprodutibilidade: Formato padronizado que outros pesquisadores podem entender e utilizar
Visualizações avançadas: Estrutura ideal para a criação de diversos tipos de tabelas e gráficos.
Análise econométrica: Adequação imediata para estudos e modelos econométricos em (regressão linear, painel, logit, probit etc.)
Planilhas eletrônicas têm alto risco de erros: Em 13 auditorias de planilhas reais, uma média de 88% continham erros (Broman e Woo, 2018).
Problemas comuns incluem:
Conversão automática de formatos (ex: nomes de genes interpretados como datas)
Armazenamento de datas de forma diferente entre sistemas operacionais
Cálculos incorporados que podem corromper dados originais
A mistura de análise, visualização e armazenamento no mesmo arquivo aumenta o risco de comprometer os dados brutos e os resultados.
Mas dada a ubiquidade de planilhas nas organizações, caso precise usar planilhas para armazenar dados, siga as seguintes boas práticas:
Artigo de Broman e Woo (2018)
Crie planilhas organizadas (uma linha = uma observação, uma coluna = uma variável, uma célula = um valor)
Seja consistente e escolha bons nomes para as variáveis:
snake_case
ou CamelCase
Lucro Líquido (R$)
😱lucro_liquido
ou LucroLiquido
😃Escreva datas conforme a Norma ISO 8601:
YYYY-MM-DD
, exemplo: 2025-05-07
Sem células vazias: use hífen (-
) e no caso de usar R, use NA
Crie um dicionário dos dados
NUNCA faça cálculos na planilha dos dados originais/brutos
NUNCA use unidades de medida (R$), cor ou realce como um dado.
R$ 50.000,00
😱50000
😃10 %
😱O.1
😃Faça backups
Use validação dos dados para evitar erros
Salve os dados em arquivos de texto simples (.csv
):
Na próxima seção, vamos aprender sobre como o pacote tidyr do tidyverse pode ser usado para tornar alguns tipos de dados desorganizados em dados organizados para análise.
O tidyr é um pacote do tidyverse para organizar dados desorganizados
Seu nome vem de “tidy” (organizado) + “r” (R)
Foi criado para facilitar a transformação de dados desorganizados em dados organizados (tidy data) para análise
É muito útil para a preparação de dados na fase 3 do CRISP-DM (Preparação dos Dados)
Permite que dados em formatos comuns de planilhas e relatórios sejam transformados em formatos adequados para análise e visualização
pivot_longer()
: Converte dados do formato amplo (onde valores de uma ou mais variáveis são espalhadas por colunas) em um formato longo (onde cada variável está em uma única coluna).
Útil quando você precisa de de dados para análise ou visualização
Ex: Transformar colunas de trimestres (Q1, Q2, Q3, Q4) em uma única coluna “trimestre”
Iremos estudar somente a função pivot_longer()
, porque o foco deste módulo é a preparação de dados para análise.
Mas há diversas outras funções úteis para a organização de dados:
Quando você tem planilhas financeiras com colunas para diferentes períodos (meses, trimestres, anos)
Quando você recebe planilhas Excel organizadas para visualização humana, mas não para análise de dados.
Quando precisa combinar dados de diferentes fontes que estão em formatos incompatíveis.
Quando precisa preparar dados para visualizações específicas com ggplot2 (gráficos de linhas, facetas, etc.)
Quando realiza análises temporais e precisa converter entre formatos de data/hora.
Aplicar a função pivot_longer() com seus parâmetros essenciais: cols
, names_to
e values_to
Organizar/Transformar dados complexos extraindo múltiplas informações de colunas
Integrar pivot_longer() em pipelines de análise com dplyr
Implementar soluções para casos reais de análise de dados administrativos
A função pivot_longer()
converte dados do formato amplo (wide) para o formato longo (long)
É muito útil quando as colunas contêm valores em vez de variáveis
Geralmente, é o primeiro passo para transformar planilhas de negócios em dados organizados para análise (tidy data)
A Figura 2 ilustra o uso desta função
valores_de_uma_nova_coluna: as colunas que contêm valores de uma variável e serão transformadas.
nome_nova_coluna: nome da nova coluna/variável que conterá os nomes das colunas originais.
nome_outra_nova_coluna: nome da nova coluna/variável que conterá os valores originais.
Característica | pivot_longer() |
---|---|
Transforma | Colunas → Linhas |
Formato resultante | Longo (mais linhas) |
Quando usar | Para análise e visualização |
Exemplo típico | Transformar colunas de anos em uma variável “ano” |
A função tribble()
(abreviação de “transposed tibble”) é uma forma elegante de criar pequenas tibbles/data frames para exemplos ou testes:
# Criando uma data frame com tribble() - "tibble transposta"
produtos <- tribble(
~codigo, ~produto, ~preco, # Nomes das colunas começam com ~
"A123", "Notebook", 3500, # Cada linha é um registro
"B456", "Smartphone", 1800, # Os valores são separados por vírgulas
"C789", "Monitor", 950 # A formatação facilita a leitura
)
# Visualizando a data frame criada
produtos
# A tibble: 3 × 3
codigo produto preco
<chr> <chr> <dbl>
1 A123 Notebook 3500
2 B456 Smartphone 1800
3 C789 Monitor 950
Vantagens da função tribble():
Layout Visual: Cada linha do código corresponde a uma linha da data frame, tornando o código mais legível
Especificação direta: Os nomes das colunas são definidos com ~ (til)
Flexibilidade de tipos: Cada coluna pode conter diferentes tipos de dados
Ideal para exemplos: Perfeita para criar pequenas data frames para demonstrações ou testes.
Esta função faz parte do pacote tibble
, que é carregado automaticamente quando você carrega o tidyverse
.
# Criando a data frame de exemplo
receitas <- tribble(
~produto, ~T1, ~T2, ~T3, ~T4,
"Produto A", 50000, 55000, 60000, 65000,
"Produto B", 30000, 32000, 35000, 37000,
"Produto C", 20000, 22000, 25000, 27000
)
# Visualizando a data frame original (formato amplo/wide)
receitas
# A tibble: 3 × 5
produto T1 T2 T3 T4
<chr> <dbl> <dbl> <dbl> <dbl>
1 Produto A 50000 55000 60000 65000
2 Produto B 30000 32000 35000 37000
3 Produto C 20000 22000 25000 27000
Este formato é para apresentação, não para armazenamento e análise.
# Transformando para o formato longo usando pivot_longer
receitas_longas <- receitas %>%
pivot_longer(
cols = c("T1", "T2", "T3", "T4"), # colunas que serão valores da nova coluna
names_to = "trimestre", # nome da nova coluna
values_to = "receita" # nome de outra nova coluna
)
# Visualizando o resultado (formato longo/long)
receitas_longas
# A tibble: 12 × 3
produto trimestre receita
<chr> <chr> <dbl>
1 Produto A T1 50000
2 Produto A T2 55000
3 Produto A T3 60000
4 Produto A T4 65000
5 Produto B T1 30000
6 Produto B T2 32000
7 Produto B T3 35000
8 Produto B T4 37000
9 Produto C T1 20000
10 Produto C T2 22000
11 Produto C T3 25000
12 Produto C T4 27000
Agora os dados estão organizados:
# Criando a data frame com múltiplas métricas por trimestre
desempenho <- tribble(
~empresa, ~receita_T1, ~receita_T2, ~despesa_T1, ~despesa_T2,
"Empresa A", 150000, 175000, 120000, 130000,
"Empresa B", 250000, 270000, 200000, 220000,
"Empresa C", 100000, 115000, 80000, 95000
)
# Visualizando a data frame original
desempenho
# A tibble: 3 × 5
empresa receita_T1 receita_T2 despesa_T1 despesa_T2
<chr> <dbl> <dbl> <dbl> <dbl>
1 Empresa A 150000 175000 120000 130000
2 Empresa B 250000 270000 200000 220000
3 Empresa C 100000 115000 80000 95000
Este formato é ainda mais desorganizado, pois mistura três variáveis (receita, despesa e trimestre) nos nomes das colunas.
# Transformando para o formato longo usando pivot_longer com nomes separados
desempenho_longo <- desempenho %>%
pivot_longer(
cols = -empresa, # todas as colunas exceto "empresa"
names_to = c("indicador", "trimestre"), # nomes das duas novas colunas
names_sep = "_", # separador nos nomes das colunas
values_to = "valor" # nome de nova coluna para receber os valores
)
# Visualizando o resultado
desempenho_longo
# A tibble: 12 × 4
empresa indicador trimestre valor
<chr> <chr> <chr> <dbl>
1 Empresa A receita T1 150000
2 Empresa A receita T2 175000
3 Empresa A despesa T1 120000
4 Empresa A despesa T2 130000
5 Empresa B receita T1 250000
6 Empresa B receita T2 270000
7 Empresa B despesa T1 200000
8 Empresa B despesa T2 220000
9 Empresa C receita T1 100000
10 Empresa C receita T2 115000
11 Empresa C despesa T1 80000
12 Empresa C despesa T2 95000
Observação importante:
Os nomes das colunas originais (receita_T1
, receita_T2
, etc.) são divididos pelo separador “_” em exatamente duas partes.
A primeira parte (“receita” ou “despesa”) vai para a coluna “indicador” e a segunda parte (“T1” ou “T2”) vai para a coluna “trimestre”.
Este é um padrão comum em dados financeiros: quando os nomes de colunas seguem um formato consistente com separadores, podemos extrair as informações contidas neles para criar novas variáveis.
# Exemplo mais gerenciável para slides
receita_trimestral <- tribble(
~empresa, ~`2022_T1_Receita`, ~`2022_T2_Receita`, ~`2023_T1_Receita`, ~`2023_T2_Receita`,
"ABC Ltda", 1200000, 1350000, 1500000, 1620000,
"XYZ S.A.", 2500000, 2700000, 2900000, 3100000
)
# Visualizando a data frame original
receita_trimestral
# A tibble: 2 × 5
empresa `2022_T1_Receita` `2022_T2_Receita` `2023_T1_Receita`
<chr> <dbl> <dbl> <dbl>
1 ABC Ltda 1200000 1350000 1500000
2 XYZ S.A. 2500000 2700000 2900000
# ℹ 1 more variable: `2023_T2_Receita` <dbl>
# Transformando para o formato longo usando pivot_longer com três níveis
receita_trimestral_organizada <- receita_trimestral %>%
pivot_longer(
cols = -empresa, # todas as colunas exceto "empresa"
names_to = c("ano", "trimestre"), # nomes de duas novas colunas
names_sep = "_", # separador nos nomes das colunas
values_to = "receita" # nome de nova coluna para receber os valores da receita
)
# Visualizando o resultado
receita_trimestral_organizada
# A tibble: 8 × 4
empresa ano trimestre receita
<chr> <chr> <chr> <dbl>
1 ABC Ltda 2022 T1 1200000
2 ABC Ltda 2022 T2 1350000
3 ABC Ltda 2023 T1 1500000
4 ABC Ltda 2023 T2 1620000
5 XYZ S.A. 2022 T1 2500000
6 XYZ S.A. 2022 T2 2700000
7 XYZ S.A. 2023 T1 2900000
8 XYZ S.A. 2023 T2 3100000
Finalidade: Transformar dados do formato amplo (wide) para o formato longo (long), organizando-os conforme o princípio tidy data
Sintaxe básica:
cols
: Quais colunas serão transformadas em pares nome-valornames_to
: Nome da nova coluna que receberá os nomes das colunas originaisvalues_to
: Nome da nova coluna que receberá os valores
4. Caso avançado:
Quando os nomes de colunas contêm múltiplas informações, use:
names_to = c("variavel1", "variavel2", ...)
names_sep = "_"
(ou outro separador presente nos nomes)
5. Benefícios:
Identifique as variáveis: Antes de transformar, identifique claramente quais são as observações e variáveis reais nos seus dados
Comece com subconjuntos: Para dados complexos, comece testando com um pequeno subconjunto de dados
Use nomes descritivos: Escolha bons nomes para as novas colunas criadas por pivot_longer()
Combine com dplyr: As transformações com tidyr geralmente são seguidas por operações com dplyr para análise
Verifique os resultados: Sempre confira se os dados transformados mantêm as mesmas informações dos dados originais
O que faz: O pacote tidyr transforma dados entre os formatos amplo (wide) e longo (long)
Principal função:
pivot_longer()
: Converte de amplo (wide) para longo (long) (colunas para linhas)Quando usar:
pivot_longer()
quando colunas contiverem valores em vez de variáveisImportância na análise de dados:
É essencial para a preparação de dados (fase 3 do CRISP-DM)
Permite transformar dados comuns de negócios em formatos adequados para análise
Facilita a aplicação de funções do dplyr e criação de visualizações
Lembre-se sempre:
O dplyr é um dos pacotes principais do tidyverse, criado por Hadley Wickham
Seu nome vem de “data plier” (alicate para dados) - uma ferramenta para manipular dados
Foi projetado seguindo a filosofia “tidy data” (dados organizados) - cada variável é uma coluna, cada observação é uma linha
É escrito em C++ para performance otimizada
Permite manipulação de dados de forma consistente, clara e encadeada
O pacote dplyr é parte do tidyverse
Enquanto os pacotes readr e readxl ajudam na importação de dados, o dplyr é especializado na manipulação de dados
O dplyr foi otimizado para manipular sobre dados organizados, longos ou tidy data
O dplyr trabalha com uma estrutura de dados de R que já conhecemos: data frames/tibbles
As funções do dplyr foram projetadas para serem usadas com o operador pipe (%>%
), que já vimos brevemente no relatório Junglivet
Imagine o processo de análise de dados como uma linha de produção:
Os dados brutos são sua “matéria-prima”
Cada função do dplyr é uma “estação de trabalho” que realiza uma operação específica:
filter()
seleciona apenas os materiais que atendem a certos critériosselect()
separa apenas as partes que você precisamutate()
transforma ou cria novos componentesgroup_by()
+ summarize()
agrupam e calculam estatísticasarrange()
organiza o resultado finalO operador pipe (%>%
) é a “esteira” que move os dados de uma estação para outra
Muitas vezes precisamos filtrar somente certas linhas (observações ) de uma data frame.
Muitas vezes precisamos selecionar somente certas colunas (variáveis) de uma data frame.
Muitas vezes precisamos agrupar os dados por uma determinada(s) variável(s) categórica.
Muitas vezes precisamos calcular estatísticas descritivas para esses subconjuntos de dados (função summarize
).
# pib per capita médio dos países do continente americano
mean(gapminder$gdpPercap[gapminder$continent == "Americas"])
[1] 7136.11
# pib per capita médio dos países do continente americano
gapminder %>%
filter(continent == "Americas") %>%
summarize(mean(gdpPercap))
# A tibble: 1 × 1
`mean(gdpPercap)`
<dbl>
1 7136.
# Calcular a média de PIB per capita para
# países asiáticos com população > 50 milhões
# em 2007
mean(gapminder$gdpPercap[
gapminder$continent == "Asia" &
gapminder$pop > 50000000 &
gapminder$year == 2007
])
[1] 7130.141
Difícil de ler e entender
Propenso a erros
Difícil de modificar
Exemplo 2: Com dplyr e o operador pipe
# O mesmo cálculo com dplyr
gapminder %>%
filter(
continent == "Asia",
pop > 50000000,
year == 2007
) %>%
summarize(mean(gdpPercap))
# A tibble: 1 × 1
`mean(gdpPercap)`
<dbl>
1 7130.
Base R: Funções aninhadas
Vantagens: Não requer pacotes adicionais, disponível em qualquer instalação do R
Desvantagens:
dplyr: Gramática da manipulação de dados
Vantagens:
Desvantagens:
O fluxo típico de uma análise de dados com tidyverse segue este padrão:
joins
)filter
)select
)mutate
)group_by
)summarize
)arrange
)# Um pipeline de análise com dplyr
relatorio_expectativa <- gapminder %>%
# Filtra apenas os dados de 2007
filter(year == 2007) %>%
# Agrupa por continente
group_by(continent) %>%
# Calcula estatísticas resumidas
summarize(
expectativa_media = mean(lifeExp),
expectativa_minima = min(lifeExp),
expectativa_maxima = max(lifeExp),
num_paises = n()
) %>%
# Ordena do maior para o menor
arrange(desc(expectativa_media))
# Visualiza o resultado final
relatorio_expectativa
# A tibble: 5 × 5
continent expectativa_media expectativa_minima expectativa_maxima num_paises
<fct> <dbl> <dbl> <dbl> <int>
1 Oceania 80.7 80.2 81.2 2
2 Europe 77.6 71.8 81.8 30
3 Americas 73.6 60.9 80.7 25
4 Asia 70.7 43.8 82.6 33
5 Africa 54.8 39.6 76.4 52
Este exemplo demonstra como um conjunto de funções do dplyr pode ser combinado para transformar dados brutos organizados em um relatório informativo com apenas algumas linhas de código.
O pacote dplyr fornece uma série de funções muito úteis para manipular data frames de uma maneira que:
Vamos aprender 5 das funções mais usadas do pacote dplyr,
Função | Descrição |
---|---|
dplyr::filter() |
para filtrar linhas (observações) |
dplyr::select() |
para selecionar colunas (variáveis ) |
dplyr::mutate() |
para criar novas variáveis |
dplyr::group_by() |
para operações “por grupo” |
dplyr::summarize() |
para calcular estatísticas |
dplyr::arrange() |
para ordenar resultados |
Além disso, veremos como como usar o operador pipe (%>%
) para combiná-las.
Indentação consistente:
Nomeie seu código:
dados_filtrados
, relatorio_vendas_por_regiao
Comente seu código:
Dividir análises complexas em etapas:
Consistência de estilo:
O pacote gapminder da linguagem R contém uma data frame também chamada gapminder.
A df gapminder fornece informações detalhadas sobre indicadores socioeconômicos reais de vários países ao longo do tempo.
Este conjunto de dados é muito utilizado no ensino da linguagem R e de métodos estatísticos.
Vamos utilizar a df gapminder
para ilustrar as funções do pacote dplyr.
Para acessar os dados gapminder, basta instalar e carregar o pacote gapminder:
Para obter uma visão geral da estrutura da df gapminder, podemos usar a função glimpse do pacote dplyr:
Rows: 1,704
Columns: 6
$ country <fct> "Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan", …
$ continent <fct> Asia, Asia, Asia, Asia, Asia, Asia, Asia, Asia, Asia, Asia, …
$ year <int> 1952, 1957, 1962, 1967, 1972, 1977, 1982, 1987, 1992, 1997, …
$ lifeExp <dbl> 28.801, 30.332, 31.997, 34.020, 36.088, 38.438, 39.854, 40.8…
$ pop <int> 8425333, 9240934, 10267083, 11537966, 13079460, 14880372, 12…
$ gdpPercap <dbl> 779.4453, 820.8530, 853.1007, 836.1971, 739.9811, 786.1134, …
Podemos também inspecionar as primeiras 6 linhas da data frame com a função head:
# A tibble: 6 × 6
country continent year lifeExp pop gdpPercap
<fct> <fct> <int> <dbl> <int> <dbl>
1 Afghanistan Asia 1952 28.8 8425333 779.
2 Afghanistan Asia 1957 30.3 9240934 821.
3 Afghanistan Asia 1962 32.0 10267083 853.
4 Afghanistan Asia 1967 34.0 11537966 836.
5 Afghanistan Asia 1972 36.1 13079460 740.
6 Afghanistan Asia 1977 38.4 14880372 786.
A data frame gapminder contida no pacote de mesmo nome, possui 1704 linhas (observações) e 6 colunas (variáveis).
Variável | Classe/Tipo | Descrição |
---|---|---|
country |
factor |
Nome do país (142 níveis/países) |
continent |
factor |
Continente ao qual o país pertence (5 níveis/continentes) |
year |
integer |
Ano da observação (1952 a 2007 em incrementos de 5 anos) |
lifeExp |
double |
Expectativa de vida ao nascer, em anos |
pop |
integer |
População total do país |
gdpPercap |
double |
PIB per capita em US$, ajustado pela inflação |
A função select()
permite escolher quais variáveis (colunas) você quer manter ou remover de uma data frame
Enquanto select()
trabalha com colunas (variáveis), filter()
trabalha com linhas (observações),
É essencial para simplificar seus dados, focando apenas nas variáveis relevantes para sua análise
Imagine que você é um analista financeiro internacional e precisa preparar um relatório sobre PIB:
# Seleciona apenas as variáveis relevantes para análise financeira
dados_financeiros <- gapminder %>%
select(country, year, gdpPercap)
# Visualiza as primeiras linhas do resultado
head(dados_financeiros)
# A tibble: 6 × 3
country year gdpPercap
<fct> <int> <dbl>
1 Afghanistan 1952 779.
2 Afghanistan 1957 821.
3 Afghanistan 1962 853.
4 Afghanistan 1967 836.
5 Afghanistan 1972 740.
6 Afghanistan 1977 786.
Interpretação: Este código seria equivalente a extrair apenas os dados financeiros relevantes (país, ano e PIB per capita) de uma grande base de dados para uma análise específica de desempenho econômico.
# Selecionar variáveis por inclusão
gapminder %>% select(country, year, gdpPercap)
# Selecionar variáveis por exclusão (com sinal de menos)
gapminder %>% select(-continent, -lifeExp)
# Selecionar variáveis em sequência
gapminder %>% select(country:pop)
# Selecionar variáveis que começam com determinado texto
gapminder %>% select(starts_with("c"))
# Selecionar variáveis que terminam com determinado texto
gapminder %>% select(ends_with("p"))
# Selecionar variáveis que contêm determinado texto
gapminder %>% select(contains("exp"))
Estas técnicas são muito úteis quando você trabalha com:
Erro | Errado | Correto |
---|---|---|
Nomes de variáveis com aspas | select(gapminder, "country") |
select(gapminder, country) |
Tentar condições como em filter | select(gapminder, gdpPercap > 1000) |
Use filter() para isso, não select() |
Não salvar o resultado | gapminder %>% select(country, year) |
dados_novos <- gapminder %>% select(country, year) |
Remover variáveis necessárias | select(country) e depois tentar usar continent |
Verifique se manteve todas as variáveis necessárias |
Lembre-se: select()
é para escolher colunas (variáveis) e filter()
é para escolher linhas (observações)!
# A tibble: 1,704 × 5
country year lifeExp pop gdpPercap
<fct> <int> <dbl> <int> <dbl>
1 Afghanistan 1952 28.8 8425333 779.
2 Afghanistan 1957 30.3 9240934 821.
3 Afghanistan 1962 32.0 10267083 853.
4 Afghanistan 1967 34.0 11537966 836.
5 Afghanistan 1972 36.1 13079460 740.
6 Afghanistan 1977 38.4 14880372 786.
7 Afghanistan 1982 39.9 12881816 978.
8 Afghanistan 1987 40.8 13867957 852.
9 Afghanistan 1992 41.7 16317921 649.
10 Afghanistan 1997 41.8 22227415 635.
# ℹ 1,694 more rows
|>
ou %>%
)|>
ou %>%
Nos slides anteriores, usamos a sintáxe ‘normal’ da linguagem R.
Mas o ponto forte do dplyr está na combinação de várias funções usando o operador pipe %>%
.
Vamos analisar a gramática do uso de funções do dplyr combinadas com o operador %>%
.
Atalho para inserir o operador pipe: Ctrl + shift + M
O operador pipe pode ser lido como “então” ou “em seguida”
Fluxo da esquerda para a direita, similar à leitura natural
Transforma:
funcao(dados, arg1, arg2)
em
dados %>% funcao(arg1, arg2)
Uma linha de montagem onde cada função faz uma operação nos dados
gapminder %>% # Pegue os dados gapminder, então...
filter(year == 2007) %>% # Filtre para apenas o ano 2007, então...
group_by(continent) %>% # Agrupe por continente, então...
summarize( # Calcule resumos:
mean(lifeExp), # expectativa de vida média
sum(pop) # população total
)
# A tibble: 5 × 3
continent `mean(lifeExp)` `sum(pop)`
<fct> <dbl> <dbl>
1 Africa 54.8 929539692
2 Americas 73.6 898871184
3 Asia 70.7 3811953827
4 Europe 77.6 586098529
5 Oceania 80.7 24549947
gapminder %>% # Pegue os dados gapminder, então...
filter(year == 2007) %>% # Filtre para apenas o ano 2007, então...
group_by(continent) %>% # Agrupe por continente, então...
summarize( # Calcule resumos:
exp_vida_media = mean(lifeExp), # expectativa de vida média
populacao_total = sum(pop) # população total
)
# A tibble: 5 × 3
continent exp_vida_media populacao_total
<fct> <dbl> <dbl>
1 Africa 54.8 929539692
2 Americas 73.6 898871184
3 Asia 70.7 3811953827
4 Europe 77.6 586098529
5 Oceania 80.7 24549947
Vamos entender o código:
Primeiro invocamos a df gapminder e a passamos, usando o operador pipe %>%
, para a próxima etapa, que é a função select().
Neste caso, não especificamos qual df usamos na função select(), porque que ela obtém essa informação do pipe anterior.
Salvamos o resultado no objeto variaveis_selecionadas
Para que serve: Selecionar apenas as colunas (variáveis) que você deseja manter ou remover
Sintaxe básica:
select(país, ano, vendas)
select(-observações, -notas)
select(starts_with("venda"))
select()
trabalha com COLUNASfilter()
trabalha com LINHASA função filter()
permite filtrar subconjuntos de observações (linhas) que atendem determinadas condições ou critérios.
É uma das funções mais utilizadas na análise de dados para criar subconjuntos específicos dos dados
Pense nela como um “filtro” que deixa passar apenas as observações que atendem aos critérios que você definir
Imagine que você tem uma planilha de vendas e quer analisar apenas as vendas:
A função filter()
permite fazer essa filtragem de forma rápida e precisa
Operador | Exemplo em Linguagem Natural | Código em R |
---|---|---|
== | Apenas os países europeus | continent == “Europe” |
!= | Todos, exceto os países europeus | continent != “Europe” |
> | Países com PIB per capita maior que 10.000 | gdpPercap > 10000 |
< | Países com menos de 1 milhão de habitantes | pop < 1000000 |
>= | Países a partir do ano 2000 | year >= 2000 |
& | Países europeus a partir de 2000 | continent == “Europe” & year >= 2000 |
| |
Países da Europa ou da Ásia | continent == “Europe” | continent == “Asia” |
==
para igualdade (lembre-se: dois sinais de igual, não apenas um)&
para “E” (quero este critério E aquele também)|
para “OU” (quero este critério OU aquele)Imagine que a data frame gapminder
representa dados de filiais de uma empresa multinacional:
# Filtra apenas países das Américas
# como se fossem filiais da região Américas
filiais_americas <- gapminder %>%
filter(continent == "Americas")
# Visualiza as primeiras 6 linhas do resultado
head(filiais_americas)
# A tibble: 6 × 6
country continent year lifeExp pop gdpPercap
<fct> <fct> <int> <dbl> <int> <dbl>
1 Argentina Americas 1952 62.5 17876956 5911.
2 Argentina Americas 1957 64.4 19610538 6857.
3 Argentina Americas 1962 65.1 21283783 7133.
4 Argentina Americas 1967 65.6 22934225 8053.
5 Argentina Americas 1972 67.1 24779799 9443.
6 Argentina Americas 1977 68.5 26983828 10079.
Interpretação: Este filtro seria equivalente a selecionar apenas dados de filiais localizadas nas Américas para uma análise regional de desempenho.
Pergunta de Negócio | Código com filter() |
---|---|
Quais países tiveram PIB per capita acima de $20.000 em 2007? | filter(year == 2007 & gdpPercap > 20000) |
Quais países da Ásia tiveram expectativa de vida acima de 75 anos? | filter(continent == "Asia" & lifeExp > 75) |
Quais países tiveram população superior a 100 milhões em 2007? | filter(year == 2007 & pop > 100000000) |
Quais países não são da Europa nem da América? | filter(continent != "Europe" & continent != "Americas") |
Dica: Comece sempre pensando na pergunta de negócio, depois traduza para o código
Há duas maneiras principais de combinar condições:
Dica importante:
Com &
(“E”) ambas as condições precisam ser TRUE
para que a linha seja mantida
Com |
(“OU”), apenas uma das condições precisa ser TRUE
Utilize operadores relacionais para:
# Países europeus em 2007, mostrando apenas país e expectativa de vida
europeus_lifeExp_2007 <- gapminder %>%
filter(continent == "Europe" & year == 2007) %>%
select(country, lifeExp)
# Ordenando o resultado por expectativa de vida (decrescente)
europeus_lifeExp_2007_ordenado <- gapminder %>%
filter(continent == "Europe" & year == 2007) %>%
select(country, lifeExp) %>%
arrange(desc(lifeExp))
head(europeus_lifeExp_2007_ordenado)
# A tibble: 6 × 2
country lifeExp
<fct> <dbl>
1 Iceland 81.8
2 Switzerland 81.7
3 Spain 80.9
4 Sweden 80.9
5 France 80.7
6 Italy 80.5
Ordem correta das operações:
Lembre-se: primeiro filter(), depois select()!
Erro | Errado | Correto |
---|---|---|
Usar = em vez de == | filter(continent = "Europe") |
filter(continent == "Europe") |
Esquecer as aspas em nomes | filter(continent == Europe) |
filter(continent == "Europe") |
Não salvar o resultado | gapminder %>% filter(year == 2007) |
dados_2007 <- gapminder %>% filter(year == 2007) |
# Países europeus com expectativa de vida acima de 78 anos em 2007
resultado_final <- gapminder %>%
# Filtrar por continente, ano e expectativa de vida
filter(continent == "Europe" & year == 2007 & lifeExp > 78) %>%
# Selecionar variáveis de interesse
select(country, lifeExp, gdpPercap) %>%
# Ordenar por expectativa de vida (decrescente)
arrange(desc(lifeExp))
# Mostrar resultados
resultado_final
# A tibble: 17 × 3
country lifeExp gdpPercap
<fct> <dbl> <dbl>
1 Iceland 81.8 36181.
2 Switzerland 81.7 37506.
3 Spain 80.9 28821.
4 Sweden 80.9 33860.
5 France 80.7 30470.
6 Italy 80.5 28570.
7 Norway 80.2 49357.
8 Austria 79.8 36126.
9 Netherlands 79.8 36798.
10 Greece 79.5 27538.
11 Belgium 79.4 33693.
12 United Kingdom 79.4 33203.
13 Germany 79.4 32170.
14 Finland 79.3 33207.
15 Ireland 78.9 40676.
16 Denmark 78.3 35278.
17 Portugal 78.1 20510.
Observe o fluxo de análise:
Para que serve: Selecionar apenas as linhas (observações) que atendem a determinadas condições
Sintaxe básica:
Comparações mais usadas:
Múltiplas condições:
filter(condição1 & condição2)
filter(condição1 | condição2)
Lembre-se sempre de salvar o resultado:
A função mutate()
permite criar novas variáveis ou modificar variáveis existentes
Enquanto filter()
seleciona linhas e select()
seleciona colunas, mutate()
adiciona ou modifica colunas
É como ter uma “calculadora” que cria novas informações a partir dos dados existentes
Ideal para cálculos como: percentuais, totais, médias, categorias, etc.
O que cada parte significa:
Imagine que a data frame gapminder
contém dados de vendas globais da sua empresa:
# Criando variáveis para análise de vendas
vendas_analise <- gapminder %>%
filter(year == 2007) %>% # Filtra dados somente de 2007
mutate(
# PIB total representa a receita total da região
receita_total = gdpPercap * pop,
# Receita em milhões (para facilitar a leitura)
receita_milhoes = receita_total / 1000000,
# Indicador de destaque (regiões com alta receita por pessoa)
destaque = gdpPercap > 20000
) %>%
# Vamos visualizar apenas algumas colunas e 5 linhas
select(country, receita_milhoes, gdpPercap, destaque) %>%
head(5)
vendas_analise
Interpretação administrativa: Este tipo de transformação é usado diariamente nas empresas para converter dados brutos em métricas de negócios úteis para tomada de decisão.
# Operações aritméticas básicas com mutate()
gapminder %>%
filter(country == "Brazil", year >= 2000) %>%
mutate(
# Adição: adiciona um valor fixo
pop_ajustada = pop + 1000000,
# Multiplicação: multiplica por um fator
gdp_reais = gdpPercap * 5.2, # Convertendo para reais
# Divisão: divide para mudar a escala
pop_milhoes = pop / 1000000 # População em milhões
) %>%
select(year, pop, pop_ajustada, pop_milhoes, gdpPercap, gdp_reais)
Dica: As operações mais utilizadas em análises de negócios são multiplicação (para fatores, taxas, conversões) e divisão (para mudar escalas e calcular proporções).
A função ifelse()
permite criar novas variáveis categóricas baseadas em condições:
Como funciona: ifelse(condição, valor_se_verdadeiro, valor_se_falso)
gapminder %>%
filter(year == 2007) %>%
mutate(
pib_total = gdpPercap * pop, # PIB total
pib_percentual_global = (pib_total/sum(pib_total))*100, # % do PIB global
performance = ifelse(gdpPercap > mean(gdpPercap),
"Acima da média",
"Abaixo da média")
) %>%
select(country, pib_total, pib_percentual_global, performance)
Isso mostra como transformar dados brutos em informações gerenciais.
case_when()
é como um “sistema de classificação” para criar categorias mais complexas:
# Exemplo de múltiplas categorias
paises_classificados <- gapminder %>%
filter(year == 2007) %>%
mutate(
classe_desenvolvimento = case_when(
gdpPercap < 2000 ~ "Baixo",
gdpPercap < 10000 ~ "Médio",
gdpPercap >= 10000 ~ "Alto"
)
) %>%
select(country, gdpPercap, classe_desenvolvimento) %>%
head(6)
paises_classificados
Como funciona:
condição ~ "valor a atribuir"
Função | Quando usar | Exemplo |
---|---|---|
ifelse() |
Para divisões simples em duas categorias | ifelse(vendas > meta, "Meta atingida", "Meta não atingida") |
case_when() |
Para múltiplas categorias ou condições complexas | Classificar clientes em “Bronze”, “Prata”, “Ouro” e “Platina” baseado em diferentes critérios |
Analogia de negócios:
ifelse()
é como uma decisão “sim/não” (aprovação de crédito simples)
case_when()
é como um sistema de classificação de clientes com várias categorias
Usar o operador de atribuição errado
mutate(nova_var <- expressão)
❌mutate(nova_var = expressão)
✅Esquecer de salvar o resultado
dados %>% mutate(nova_var = x * 2)
❌ (resultado não salvo)dados_novos <- dados %>% mutate(nova_var = x * 2)
✅Tentar usar variáveis que acabou de criar sem manter os resultados
ERRADO:
CORRETO (Pipeline único):
O que faz: mutate()
cria novas variáveis ou modifica existentes
Usos comuns no mundo dos negócios:
Como usar na prática:
Ferramentas complementares:
ifelse()
para classificações simples (sim/não)case_when()
para classificações múltiplasLembre-se de salvar o resultado em um novo objeto:
A função group_by()
permite agrupar dados por uma ou mais variáveis categóricas
A função summarize()
(ou summarise()
) permite calcular estatísticas resumidas para cada grupo
Estas funções geralmente trabalham juntas como uma ferramenta poderosa para análise
É como criar “subtotais” ou “relatórios consolidados” por categorias (ex: vendas por região, despesas por departamento)
Imagine que você é um analista financeiro e precisa preparar um relatório executivo comparando regiões:
# Cria um relatório de PIB médio por continente
relatorio_continentes <- gapminder %>%
filter(year == 2007) %>% # Filtra para dados mais recentes
group_by(continent) %>% # Agrupa por continente
summarize(
PIB_medio = mean(gdpPercap), # Média do PIB per capita
Total_populacao = sum(pop), # População total
Paises_analisados = n(), # Número de países
PIB_minimo = min(gdpPercap), # PIB mínimo
PIB_maximo = max(gdpPercap) # PIB máximo
) %>%
arrange(desc(PIB_medio)) # Ordena do maior para o menor PIB médio
# Visualiza o resultado
relatorio_continentes
# A tibble: 5 × 6
continent PIB_medio Total_populacao Paises_analisados PIB_minimo PIB_maximo
<fct> <dbl> <dbl> <int> <dbl> <dbl>
1 Oceania 29810. 24549947 2 25185. 34435.
2 Europe 25054. 586098529 30 5937. 49357.
3 Asia 12473. 3811953827 33 944 47307.
4 Americas 11003. 898871184 25 1202. 42952.
5 Africa 3089. 929539692 52 278. 13206.
Interpretação Este tipo de relatório consolidado por região é crítico para análises comparativas entre mercados e para apresentações executivas. Mostra claramente as estatísticas-chave para cada grupo (continente), facilitando comparações e decisões estratégicas.
Função | O que calcula | Exemplo em R | Uso em Negócios |
---|---|---|---|
mean() |
Média | mean(vendas) |
Valor médio de vendas por região |
sum() |
Soma total | sum(receita) |
Receita total por categoria |
min() |
Valor mínimo | min(preco) |
Menor preço praticado |
max() |
Valor máximo | max(despesa) |
Maior despesa do período |
sd() |
Desvio padrão | sd(producao) |
Variabilidade da produção |
n() |
Contagem de linhas | n() |
Número de transações |
n_distinct() |
Contagem de valores únicos | n_distinct(cliente) |
Número de clientes únicos |
median() |
Mediana | median(vendas) |
Valor típico de vendas |
Dica para gestores: Sempre inclua tanto medidas de “tendência central” (média, mediana) quanto de “variação” (desvio padrão) para ter uma visão mais completa dos dados.
# Análise de expectativa de vida por continente e ano
tendencias_por_continente <- gapminder %>%
group_by(continent, year) %>% # Agrupa por DUAS variáveis
summarize(
expectativa_vida_media = mean(lifeExp),
paises_analisados = n()
) %>%
arrange(continent, year)
# Mostra resultados parciais
tendencias_por_continente %>%
filter(continent == "Americas") %>%
head(3)
# A tibble: 3 × 4
# Groups: continent [1]
continent year expectativa_vida_media paises_analisados
<fct> <int> <dbl> <int>
1 Americas 1952 53.3 25
2 Americas 1957 56.0 25
3 Americas 1962 58.4 25
Contexto empresarial: Este tipo de análise é comum em:
Erro | Errado | Correto |
---|---|---|
Não usar summarize após group_by | dados %>% group_by(regiao) |
dados %>% group_by(regiao) %>% summarize(...) |
Tentar agrupar antes de filtrar | group_by(regiao) %>% filter(mean(vendas) > 1000) |
Usar filter() ANTES de group_by() |
Esquecer de desagrupar | Continuar usando dados agrupados | Usar ungroup() quando terminar com análises agrupadas |
Dica: group_by
por si não produz nenhum resultado.
Para que servem:
group_by()
: Agrupa dados por categorias (como agrupar linhas em uma planilha)
summarize()
: Calcula estatísticas para cada grupo (como criar subtotais)
Sintaxe básica:
Funções estatísticas básicas:
sum()
mean()
n()
min()
, max()
Fluxo de trabalho típico:
filter()
)group_by()
)summarize()
)arrange()
)Lembre-se sempre de salvar o resultado:
A função arrange()
ordena as linhas (observações) de uma data frame com base nos valores de uma ou mais colunas (variáveis)
Por padrão, organiza em ordem crescente (do menor para o maior)
Use desc()
para ordenar em ordem decrescente (do maior para o menor)
desc()
para ordem descrescente (do maior para o menor)Imagine que você é um analista de mercado e precisa identificar rapidamente os países mais promissores para expansão:
# Criando um ranking de países por PIB per capita em 2007
ranking_paises <- gapminder %>%
filter(year == 2007) %>% # Filtra dados apenas de 2007
select(country, continent, gdpPercap) %>% # Seleciona colunas relevantes
arrange(desc(gdpPercap)) %>% # Ordena do maior para o menor PIB
head(6) # Mostra os 10 primeiros resultados
# Visualiza o resultado
ranking_paises
# A tibble: 6 × 3
country continent gdpPercap
<fct> <fct> <dbl>
1 Norway Europe 49357.
2 Kuwait Asia 47307.
3 Singapore Asia 47143.
4 United States Americas 42952.
5 Ireland Europe 40676.
6 Hong Kong, China Asia 39725.
Interpretação Este tipo de ordenação é relevante em análises de mercado para identificar rapidamente os países mais ricos (potenciais mercados premium) ou para encontrar as regiões que precisam de mais atenção (ordenando do menor para o maior).
Erro | Problema | Solução |
---|---|---|
Ordem incorreta | arrange(dados, desc()) sem especificar a variável |
arrange(dados, desc(variavel)) |
Tentar ordenar por variável não existente | arrange(vendas_por_regiao) quando a coluna não existe |
Verificar primeiro os nomes das colunas com names() |
Não salvar o resultado ordenado | Ordenar mas não atribuir a um objeto | dados_ordenados <- dados %>% arrange(...) |
Lembre-se: A ordenação é temporária se você não salvar o resultado em um novo objeto!
Para que serve: Ordenar as linhas (observações) com base nos valores de uma ou mais colunas
Sintaxe básica:
Usos comuns em negócios:
Lembre-se sempre:
desc()
para ordem decrescentearrange(var1, var2)
Função | Propósito |
---|---|
dplyr::filter() |
Seleciona linhas baseadas em condições |
dplyr::select() |
Seleciona colunas específicas |
dplyr::mutate() |
Cria ou modifica colunas |
dplyr::group_by() |
Agrupa dados por categorias |
dplyr::summarize() |
Calcula estatísticas resumidas |
dplyr::arrange() |
Ordena linhas |
Lembre-se: O poder do dplyr está em combinar estas funções com o operador pipe %>%
Dados financeiros raramente estão concentrados em uma única base ou sistema:
Análises de dados muitas vezes exigem a integração dessas múltiplas fontes
Exemplo: Para estudar a relação entre governança e retorno ajustado ao risco, precisamos combinar:
Joins (Uniões) são operações fundamentais para esta integração em pesquisas financeiras empíricas
Dados Multidimensionais: Pesquisas financeiras tipicamente requerem a integração de:
Estudos de Evento: Análises que combinam séries temporais de preços de ativos com datas específicas de eventos corporativos (fusões, aquisições, distribuição de dividendos)
Análises de Dados em Painel: Pesquisas que acompanham múltiplas empresas ao longo do tempo, exigindo combinação de dados transversais e longitudinais
Reprodutibilidade Científica: Joins documentados garantem que outros pesquisadores possam reproduzir exatamente o mesmo conjunto de dados da análise
Estudos de Retornos Anormais:
Estudos sobre Governança e Valor:
Modelos de Precificação de Ativos:
Mercado de Crédito e Ratings:
Joins são operações fundamentais na Fase 3 (Preparação dos Dados) de CRISP-DM, permitindo:
Integrar dados fragmentados que estão distribuídos em múltiplas tabelas relacionadas entre si
Consolidar informações de diferentes fontes ou sistemas para análise (vendas + produtos + clientes)
Enriquecer dados principais com informações contextuais adicionais (ex: adicionar categoria de produto aos dados de vendas)
Completar o ciclo de preparação iniciado com:
read_csv()
, read_xlsx()
)pivot_longer()
) para análiserename()``,
as.___()`)filter()
) e seleção (select()
) de dados relevantesmutate()
) para criar novas variáveisgroup_by()
, summarize()
e arrange()
)Dados bem integrados facilitam as Fases 4 e 5 (Modelagem e Avaliação) por fornecerem uma visão completa do problema
Joins são operações que combinam duas tabelas de dados
Em termos simples, joins são como “colar” duas tabelas lado a lado, combinando linhas que têm valores em comum, como um “código de cliente” ou “código de produto”
No pacote dplyr, temos funções específicas para cada tipo de join:
left_join()
: Mantém todas as linhas da tabela da esquerdainner_join()
: Mantém apenas correspondências entre as tabelasfull_join()
: Mantém todas as linhas de ambas as tabelasright_join()
: Mantém todas as linhas da tabela da direitaSão essenciais quando precisamos combinar informações que estão separadas
# Cria a tabela de produtos
produtos <- tribble(
~codigo_produto, ~nome_produto, ~preco_unitario, ~categoria,
"P001", "Notebook Pro", 4500, "Eletrônicos",
"P002", "Smartphone X", 2800, "Eletrônicos",
"P003", "Monitor 24pol", 1200, "Informática",
"P004", "Mouse Gamer", 250, "Informática",
"P005", "Cadeira Ergonômica", 950, "Mobiliário"
)
# exibe a tabela
produtos
# A tibble: 5 × 4
codigo_produto nome_produto preco_unitario categoria
<chr> <chr> <dbl> <chr>
1 P001 Notebook Pro 4500 Eletrônicos
2 P002 Smartphone X 2800 Eletrônicos
3 P003 Monitor 24pol 1200 Informática
4 P004 Mouse Gamer 250 Informática
5 P005 Cadeira Ergonômica 950 Mobiliário
# Cria a tabela de vendas
vendas <- tribble(
~id_venda, ~codigo_produto, ~id_cliente, ~data_venda, ~quantidade,
1, "P001", "C001", "2025-04-15", 1,
2, "P002", "C002", "2025-04-16", 2,
3, "P003", "C001", "2025-04-18", 2,
4, "P002", "C003", "2025-04-20", 1,
5, "P006", "C002", "2025-04-22", 3,
6, "P004", "C004", "2025-04-23", 4
)
# exibe a tabela
vendas
# A tibble: 6 × 5
id_venda codigo_produto id_cliente data_venda quantidade
<dbl> <chr> <chr> <chr> <dbl>
1 1 P001 C001 2025-04-15 1
2 2 P002 C002 2025-04-16 2
3 3 P003 C001 2025-04-18 2
4 4 P002 C003 2025-04-20 1
5 5 P006 C002 2025-04-22 3
6 6 P004 C004 2025-04-23 4
# Crian a tabela de clientes
clientes <- tribble(
~id_cliente, ~nome_cliente, ~cidade,
"C001", "Empresa Alpha", "São Paulo",
"C002", "Empresa Beta", "Rio de Janeiro",
"C003", "João Silva", "Belo Horizonte",
"C005", "Maria Oliveira", "Recife"
)
# exibe a tabela
clientes
# A tibble: 4 × 3
id_cliente nome_cliente cidade
<chr> <chr> <chr>
1 C001 Empresa Alpha São Paulo
2 C002 Empresa Beta Rio de Janeiro
3 C003 João Silva Belo Horizonte
4 C005 Maria Oliveira Recife
# A tibble: 5 × 4
codigo_produto nome_produto preco_unitario categoria
<chr> <chr> <dbl> <chr>
1 P001 Notebook Pro 4500 Eletrônicos
2 P002 Smartphone X 2800 Eletrônicos
3 P003 Monitor 24pol 1200 Informática
4 P004 Mouse Gamer 250 Informática
5 P005 Cadeira Ergonômica 950 Mobiliário
# A tibble: 6 × 5
id_venda codigo_produto id_cliente data_venda quantidade
<dbl> <chr> <chr> <chr> <dbl>
1 1 P001 C001 2025-04-15 1
2 2 P002 C002 2025-04-16 2
3 3 P003 C001 2025-04-18 2
4 4 P002 C003 2025-04-20 1
5 5 P006 C002 2025-04-22 3
6 6 P004 C004 2025-04-23 4
# A tibble: 4 × 3
id_cliente nome_cliente cidade
<chr> <chr> <chr>
1 C001 Empresa Alpha São Paulo
2 C002 Empresa Beta Rio de Janeiro
3 C003 João Silva Belo Horizonte
4 C005 Maria Oliveira Recife
Observe que há dados “imperfeitos”:
Chaves são as colunas usadas para combinar as tabelas
Na prática:
A tabela de clientes tem um “codigo_cliente” único para cada cliente
A tabela de vendas usa esse mesmo “codigo_cliente” para indicar qual cliente fez cada compra
O “codigo_cliente” é a “chave” que permite combinar as informações das duas tabelas
Nas funções de join do dplyr, as chaves são especificadas pelo argumento by
Chave primária: Identificador único para cada registro em uma tabela
codigo_cliente
na tabela de clientes identifica unicamente cada clienteChave estrangeira: Coluna que referencia a chave primária de outra tabela
codigo_cliente
na tabela de vendas é uma chave estrangeiraAnalogia: Pense em chaves como um sistema de CPF
Tabela CLIENTES Tabela VENDAS
+--------------+ +---------------+
| codigo_cliente| <--------- |codigo_cliente |
| nome_cliente | | id_venda |
| cidade | | data_venda |
+--------------+ +---------------+
Chave Primária Chave Estrangeira
Exemplos comuns de chaves em sistemas de informação empresariais:
A identificação correta das chaves é fundamental para o sucesso de joins e para garantir a integridade das análises de dados.
Chaves duplicadas:
Chaves ausentes:
Inconsistência de tipos:
Diferenças de nomenclatura:
by = c("codigo_produto" = "codigo")
O que cada parte significa:
vendas
: A primeira tabela (tabela da esquerda)produtos
: A segunda tabela (tabela da direita)by = "codigo_produto"
: A coluna comum que existe em ambas as tabelasleft_join
: O tipo de join que queremos usarvendas_com_produtos
: O resultado da combinação que salvaremosTipo de Join | Função no dplyr | Quando usar |
---|---|---|
Left join | left_join() |
Quando você precisa manter todos os registros da tabela principal (à esquerda) |
Inner join | inner_join() |
Quando você precisa apenas dos registros que existem em ambas as tabelas |
Full join | full_join() |
Quando você precisa de todos os dados, independentemente de correspondências |
Right join | right_join() |
Quando você precisa manter todos os registros da tabela secundária (à direita) |
Mantém todos os registros da tabela da esquerda (primeira tabela)
Para registros sem correspondência na tabela da direita, preenche com NA
Quando usar:
Exemplo: Manter todas as vendas e adicionar dados dos produtos
# Tabela de empresas listadas
empresas_listadas <- tribble(
~codigo_cvm, ~empresa, ~setor, ~segmento_listagem,
"11592", "Petrobras", "Petróleo e Gás", "Nível 2",
"19615", "Vale", "Mineração", "Novo Mercado",
"14311", "Itaú Unibanco", "Financeiro", "Nível 1",
"18112", "Natura", "Bens de Consumo", "Novo Mercado",
"22691", "Magazine Luiza", "Varejo", "Novo Mercado"
)
# visualiza o resultado
empresas_listadas
# A tibble: 5 × 4
codigo_cvm empresa setor segmento_listagem
<chr> <chr> <chr> <chr>
1 11592 Petrobras Petróleo e Gás Nível 2
2 19615 Vale Mineração Novo Mercado
3 14311 Itaú Unibanco Financeiro Nível 1
4 18112 Natura Bens de Consumo Novo Mercado
5 22691 Magazine Luiza Varejo Novo Mercado
# Tabela de indicadores contábeis
indicadores_contabeis <- tribble(
~codigo_cvm, ~ano_fiscal, ~roa, ~roe, ~ebitda_margem, ~divida_liquida,
"11592", 2023, 0.089, 0.235, 0.392, 315780000,
"19615", 2023, 0.112, 0.268, 0.468, 185230000,
"14311", 2023, 0.064, 0.195, 0.412, NULL,
"22691", 2023, 0.052, 0.148, 0.185, 12450000
)
# visualiza o resultado
indicadores_contabeis
# A tibble: 4 × 6
codigo_cvm ano_fiscal roa roe ebitda_margem divida_liquida
<chr> <dbl> <dbl> <dbl> <dbl> <list>
1 11592 2023 0.089 0.235 0.392 <dbl [1]>
2 19615 2023 0.112 0.268 0.468 <dbl [1]>
3 14311 2023 0.064 0.195 0.412 <NULL>
4 22691 2023 0.052 0.148 0.185 <dbl [1]>
# Left join: todas as empresas, mesmo sem indicadores contábeis disponíveis
analise_empresas <- empresas_listadas %>%
left_join(indicadores_contabeis, by = "codigo_cvm")
# Visualizando o resultado
analise_empresas
# A tibble: 5 × 9
codigo_cvm empresa setor segmento_listagem ano_fiscal roa roe
<chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
1 11592 Petrobras Petróleo… Nível 2 2023 0.089 0.235
2 19615 Vale Mineração Novo Mercado 2023 0.112 0.268
3 14311 Itaú Unibanco Financei… Nível 1 2023 0.064 0.195
4 18112 Natura Bens de … Novo Mercado NA NA NA
5 22691 Magazine Luiza Varejo Novo Mercado 2023 0.052 0.148
# ℹ 2 more variables: ebitda_margem <dbl>, divida_liquida <list>
Observe que:
A empresa “Natura” (código CVM “18112”) aparece no resultado
Como não há dados contábeis disponíveis para esta empresa, as colunas de indicadores aparecem com NA
O left_join é muito utilizado em pesquisas quando queremos manter todas as empresas da amostra, mesmo aquelas com dados incompletos - decisão metodológica comum em estudos com amostras pequenas
Mantém apenas os registros que possuem correspondência em ambas as tabelas
Descarta linhas que não têm correspondência
Quando usar:
Quando você precisa garantir que todos os registros tenham informações completas
Quando registros sem correspondência não são relevantes para sua análise
Exemplo: Relatório de vendas que precisa mostrar dados do produto
# Tabela de títulos de dívida corporativa (bonds)
titulos_divida <- tribble(
~isin, ~emissor, ~valor_emissao, ~yield_to_maturity, ~vencimento,
"BRPETRDBS036", "Petrobras", 1000000000, 0.0785, "2030-03-15",
"BRVALEDBF009", "Vale", 750000000, 0.0652, "2032-10-08",
"BRITAUDB0025", "Itaú Unibanco", 500000000, 0.0723, "2028-05-22",
"BRBTGPDB0017", "BTG Pactual", 650000000, 0.0798, "2029-08-30",
"BRCVCODB0032", "Cielo", 350000000, 0.0815, "2027-11-12"
)
# visualiza o resultado
titulos_divida
# A tibble: 5 × 5
isin emissor valor_emissao yield_to_maturity vencimento
<chr> <chr> <dbl> <dbl> <chr>
1 BRPETRDBS036 Petrobras 1000000000 0.0785 2030-03-15
2 BRVALEDBF009 Vale 750000000 0.0652 2032-10-08
3 BRITAUDB0025 Itaú Unibanco 500000000 0.0723 2028-05-22
4 BRBTGPDB0017 BTG Pactual 650000000 0.0798 2029-08-30
5 BRCVCODB0032 Cielo 350000000 0.0815 2027-11-12
# Tabela de mudanças de rating
mudancas_rating <- tribble(
~isin, ~data_evento, ~agencia, ~rating_anterior, ~novo_rating, ~perspectiva,
"BRPETRDBS036", "2023-05-10", "Moody's", "Ba2", "Ba1", "Positiva",
"BRVALEDBF009", "2023-06-22", "S&P", "BBB", "BBB+", "Estável",
"BRVALEDBF009", "2023-08-15", "Fitch", "BBB", "BBB+", "Estável",
"BRITAUDB0025", "2023-07-08", "Moody's", "Ba1", "Baa3", "Estável",
"BRECOPDB0016", "2023-09-14", "S&P", "BB-", "BB", "Positiva"
)
# visualiza o resultado
mudancas_rating
# A tibble: 5 × 6
isin data_evento agencia rating_anterior novo_rating perspectiva
<chr> <chr> <chr> <chr> <chr> <chr>
1 BRPETRDBS036 2023-05-10 Moody's Ba2 Ba1 Positiva
2 BRVALEDBF009 2023-06-22 S&P BBB BBB+ Estável
3 BRVALEDBF009 2023-08-15 Fitch BBB BBB+ Estável
4 BRITAUDB0025 2023-07-08 Moody's Ba1 Baa3 Estável
5 BRECOPDB0016 2023-09-14 S&P BB- BB Positiva
# Inner join: apenas títulos de dívida que tiveram mudanças de rating
analise_rating_impacto <- titulos_divida %>%
inner_join(mudancas_rating, by = "isin")
# Visualizando o resultado
analise_rating_impacto
# A tibble: 4 × 10
isin emissor valor_emissao yield_to_maturity vencimento data_evento agencia
<chr> <chr> <dbl> <dbl> <chr> <chr> <chr>
1 BRPETR… Petrob… 1000000000 0.0785 2030-03-15 2023-05-10 Moody's
2 BRVALE… Vale 750000000 0.0652 2032-10-08 2023-06-22 S&P
3 BRVALE… Vale 750000000 0.0652 2032-10-08 2023-08-15 Fitch
4 BRITAU… Itaú U… 500000000 0.0723 2028-05-22 2023-07-08 Moody's
# ℹ 3 more variables: rating_anterior <chr>, novo_rating <chr>,
# perspectiva <chr>
Observe que:
O título da “Cielo” (ISIN “BRCVCODB0032”) não aparece no resultado pois não teve mudança de rating no período analisado
A mudança de rating do título “BRECOPDB0016” também não aparece no resultado pois este título não está na nossa base de títulos monitorados
O inner_join é apropriado para estudos de evento onde queremos analisar apenas os casos onde ocorreu o evento específico (neste caso, mudança de rating)
Mantém todos os registros de ambas as tabelas
Para registros sem correspondência em qualquer tabela, preenche com NA
Quando usar:
Exemplo: Relatório completo de produtos e vendas
# Full join: todas as vendas e todos os produtos
# Passo 1: Pegamos a tabela 'vendas'
# Passo 2: Combinamos com produtos mantendo TUDO de ambas as tabelas
completo_vendas_produtos <- vendas %>%
full_join(produtos, by = "codigo_produto")
# Visualizando o resultado
completo_vendas_produtos
# A tibble: 7 × 8
id_venda codigo_produto id_cliente data_venda quantidade nome_produto
<dbl> <chr> <chr> <chr> <dbl> <chr>
1 1 P001 C001 2025-04-15 1 Notebook Pro
2 2 P002 C002 2025-04-16 2 Smartphone X
3 3 P003 C001 2025-04-18 2 Monitor 24pol
4 4 P002 C003 2025-04-20 1 Smartphone X
5 5 P006 C002 2025-04-22 3 <NA>
6 6 P004 C004 2025-04-23 4 Mouse Gamer
7 NA P005 <NA> <NA> NA Cadeira Ergonômica
# ℹ 2 more variables: preco_unitario <dbl>, categoria <chr>
Observe que:
A venda do produto “P006” que não existe na tabela de produtos aparece com NAs
O produto “P005” que não tem vendas também aparece com NAs
O full_join é útil para ver “tudo junto” e identificar inconsistências
Mantém todos os registros da tabela da direita (segunda tabela)
Para registros sem correspondência na tabela da esquerda, preenche com NA
Quando usar:
Quando a segunda tabela é sua tabela principal
Quando você precisa garantir que todos os registros da segunda tabela estejam presentes
Na prática, muitas vezes é mais fácil usar left_join invertendo a ordem das tabelas
Exemplo: Ver todos os produtos, mesmo os que não foram vendidos
# Right join: todos os produtos, mesmo sem vendas
# Passo 1: Pegamos a tabela 'vendas'
# Passo 2: Combinamos com TODOS os produtos, mesmo os sem vendas
produtos_vendas_right <- vendas %>%
right_join(produtos, by = "codigo_produto")
# Visualizando o resultado
produtos_vendas_right
# A tibble: 6 × 8
id_venda codigo_produto id_cliente data_venda quantidade nome_produto
<dbl> <chr> <chr> <chr> <dbl> <chr>
1 1 P001 C001 2025-04-15 1 Notebook Pro
2 2 P002 C002 2025-04-16 2 Smartphone X
3 3 P003 C001 2025-04-18 2 Monitor 24pol
4 4 P002 C003 2025-04-20 1 Smartphone X
5 6 P004 C004 2025-04-23 4 Mouse Gamer
6 NA P005 <NA> <NA> NA Cadeira Ergonômica
# ℹ 2 more variables: preco_unitario <dbl>, categoria <chr>
Observe que:
# Tabela de empresas e características de governança
governanca <- tribble(
~codigo_negociacao, ~empresa, ~indice_governanca, ~tipo_controlador, ~comite_auditoria,
"PETR4", "Petrobras", 6.8, "Estatal", TRUE,
"VALE3", "Vale", 8.2, "Pulverizado", TRUE,
"ITUB4", "Itaú Unibanco", 7.9, "Familiar", TRUE,
"BBDC4", "Bradesco", 7.6, "Familiar", TRUE,
"MGLU3", "Magazine Luiza", 7.1, "Familiar", FALSE
)
# visualiza o resultado
governanca
# A tibble: 5 × 5
codigo_negociacao empresa indice_governanca tipo_controlador comite_auditoria
<chr> <chr> <dbl> <chr> <lgl>
1 PETR4 Petrobr… 6.8 Estatal TRUE
2 VALE3 Vale 8.2 Pulverizado TRUE
3 ITUB4 Itaú Un… 7.9 Familiar TRUE
4 BBDC4 Bradesco 7.6 Familiar TRUE
5 MGLU3 Magazin… 7.1 Familiar FALSE
# Tabela de retornos anuais ajustados
retornos <- tribble(
~codigo_negociacao, ~ano, ~retorno_anual, ~volatilidade, ~beta,
"PETR4", 2023, 0.125, 0.285, 1.32,
"VALE3", 2023, 0.084, 0.215, 1.18,
"ITUB4", 2023, 0.152, 0.195, 0.87,
"BBDC4", 2023, 0.138, 0.205, 0.92,
"ABEV3", 2023, 0.062, 0.165, 0.72
)
# visualiza o resultado
retornos
# A tibble: 5 × 5
codigo_negociacao ano retorno_anual volatilidade beta
<chr> <dbl> <dbl> <dbl> <dbl>
1 PETR4 2023 0.125 0.285 1.32
2 VALE3 2023 0.084 0.215 1.18
3 ITUB4 2023 0.152 0.195 0.87
4 BBDC4 2023 0.138 0.205 0.92
5 ABEV3 2023 0.062 0.165 0.72
# Tabela de indicadores contábeis
indicadores <- tribble(
~codigo_negociacao, ~ano, ~roa, ~alavancagem, ~tamanho_ativo,
"PETR4", 2023, 0.089, 0.325, 395120000,
"VALE3", 2023, 0.112, 0.285, 312450000,
"ITUB4", 2023, 0.064, 0.852, 2185620000,
"BBDC4", 2023, 0.058, 0.815, 1924380000,
"MGLU3", 2023, 0.052, 0.368, 28540000
)
# visualiza o resultado
indicadores
# A tibble: 5 × 5
codigo_negociacao ano roa alavancagem tamanho_ativo
<chr> <dbl> <dbl> <dbl> <dbl>
1 PETR4 2023 0.089 0.325 395120000
2 VALE3 2023 0.112 0.285 312450000
3 ITUB4 2023 0.064 0.852 2185620000
4 BBDC4 2023 0.058 0.815 1924380000
5 MGLU3 2023 0.052 0.368 28540000
# Pipeline de análise integrada
analise_integrada <- governanca %>%
# Primeiro, adicionamos dados de retorno e risco
left_join(retornos, by = "codigo_negociacao") %>%
# Depois, adicionamos indicadores contábeis
left_join(indicadores, by = c("codigo_negociacao", "ano")) %>%
# Selecionamos apenas as variáveis relevantes para o estudo
select(
empresa, codigo_negociacao, ano, indice_governanca, tipo_controlador,
retorno_anual, volatilidade, beta,
roa, alavancagem, tamanho_ativo
)
# Visualizando o resultado
analise_integrada
# A tibble: 5 × 11
empresa codigo_negociacao ano indice_governanca tipo_controlador
<chr> <chr> <dbl> <dbl> <chr>
1 Petrobras PETR4 2023 6.8 Estatal
2 Vale VALE3 2023 8.2 Pulverizado
3 Itaú Unibanco ITUB4 2023 7.9 Familiar
4 Bradesco BBDC4 2023 7.6 Familiar
5 Magazine Luiza MGLU3 NA 7.1 Familiar
# ℹ 6 more variables: retorno_anual <dbl>, volatilidade <dbl>, beta <dbl>,
# roa <dbl>, alavancagem <dbl>, tamanho_ativo <dbl>
Observe como:
Implicações metodológicas:
# Tabela com informações básicas das empresas
empresas <- tribble(
~codigo_cvm, ~nome_empresa, ~setor, ~tamanho, ~governanca,
"11592", "Petrobras S.A.", "Petróleo e Gás", "Grande", "Nível 2",
"19615", "Vale S.A.", "Mineração", "Grande", "Novo Mercado",
"14311", "Itaú Unibanco S.A.", "Financeiro", "Grande", "Nível 1",
"18112", "Natura Cosméticos", "Bens de Consumo", "Médio", "Novo Mercado",
"22691", "Magazine Luiza", "Varejo", "Médio", "Novo Mercado"
)
# visualiza o resultado
empresas
# A tibble: 5 × 5
codigo_cvm nome_empresa setor tamanho governanca
<chr> <chr> <chr> <chr> <chr>
1 11592 Petrobras S.A. Petróleo e Gás Grande Nível 2
2 19615 Vale S.A. Mineração Grande Novo Mercado
3 14311 Itaú Unibanco S.A. Financeiro Grande Nível 1
4 18112 Natura Cosméticos Bens de Consumo Médio Novo Mercado
5 22691 Magazine Luiza Varejo Médio Novo Mercado
# Tabela de indicadores financeiros trimestrais
indicadores_financeiros <- tribble(
~codigo_cvm, ~ano, ~trimestre, ~roa, ~alavancagem, ~liquidez_corrente, ~margem_ebitda,
"11592", 2024, 1, 0.032, 0.58, 1.45, 0.28,
"11592", 2024, 2, 0.041, 0.56, 1.52, 0.31,
"19615", 2024, 1, 0.045, 0.32, 2.10, 0.34,
"19615", 2024, 2, 0.048, 0.31, 2.15, 0.36,
"14311", 2024, 1, 0.018, 0.82, 1.28, 0.42,
"14311", 2024, 2, 0.019, 0.81, 1.31, 0.41,
"22691", 2024, 1, 0.028, 0.62, 1.18, 0.12,
"22691", 2024, 2, 0.025, 0.68, 1.12, 0.10
)
# visualiza o resultado
indicadores_financeiros
# A tibble: 8 × 7
codigo_cvm ano trimestre roa alavancagem liquidez_corrente margem_ebitda
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 11592 2024 1 0.032 0.58 1.45 0.28
2 11592 2024 2 0.041 0.56 1.52 0.31
3 19615 2024 1 0.045 0.32 2.1 0.34
4 19615 2024 2 0.048 0.31 2.15 0.36
5 14311 2024 1 0.018 0.82 1.28 0.42
6 14311 2024 2 0.019 0.81 1.31 0.41
7 22691 2024 1 0.028 0.62 1.18 0.12
8 22691 2024 2 0.025 0.68 1.12 0.1
# Combinando dados para análise de desempenho por setor
analise_setorial <- empresas %>%
left_join(indicadores_financeiros, by = "codigo_cvm") %>%
select(nome_empresa, setor, ano, trimestre, roa, alavancagem, margem_ebitda)
# Visualizando o resultado
analise_setorial
# A tibble: 9 × 7
nome_empresa setor ano trimestre roa alavancagem margem_ebitda
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Petrobras S.A. Petróleo … 2024 1 0.032 0.58 0.28
2 Petrobras S.A. Petróleo … 2024 2 0.041 0.56 0.31
3 Vale S.A. Mineração 2024 1 0.045 0.32 0.34
4 Vale S.A. Mineração 2024 2 0.048 0.31 0.36
5 Itaú Unibanco S.A. Financeiro 2024 1 0.018 0.82 0.42
6 Itaú Unibanco S.A. Financeiro 2024 2 0.019 0.81 0.41
7 Natura Cosméticos Bens de C… NA NA NA NA NA
8 Magazine Luiza Varejo 2024 1 0.028 0.62 0.12
9 Magazine Luiza Varejo 2024 2 0.025 0.68 0.1
Aplicação em Pesquisa:
Este tipo de join permite analisar desempenho financeiro controlando por características específicas das empresas
Útil para estudos que investigam:
Nota: Observem que “Natura Cosméticos” (código 18112) não aparece nos resultados porque não há dados financeiros correspondentes - situação comum em pesquisas empíricas
# Tabela de preços diários de ações
precos_acoes <- tribble(
~ticker, ~data, ~preco_fechamento, ~retorno_diario, ~volume,
"PETR4", "2024-04-01", 36.75, 0.0125, 15200000,
"PETR4", "2024-04-02", 37.30, 0.0150, 18500000,
"PETR4", "2024-04-03", 37.05, -0.0067, 14800000,
"PETR4", "2024-04-04", 37.82, 0.0208, 21300000,
"PETR4", "2024-04-05", 37.60, -0.0058, 16900000,
"VALE3", "2024-04-01", 68.45, 0.0087, 22400000,
"VALE3", "2024-04-02", 68.92, 0.0069, 19800000,
"VALE3", "2024-04-03", 70.15, 0.0178, 25600000,
"VALE3", "2024-04-04", 71.20, 0.0150, 28300000,
"VALE3", "2024-04-05", 70.85, -0.0049, 23100000
)
# visualiza o resultado
precos_acoes
# A tibble: 10 × 5
ticker data preco_fechamento retorno_diario volume
<chr> <chr> <dbl> <dbl> <dbl>
1 PETR4 2024-04-01 36.8 0.0125 15200000
2 PETR4 2024-04-02 37.3 0.015 18500000
3 PETR4 2024-04-03 37.0 -0.0067 14800000
4 PETR4 2024-04-04 37.8 0.0208 21300000
5 PETR4 2024-04-05 37.6 -0.0058 16900000
6 VALE3 2024-04-01 68.4 0.0087 22400000
7 VALE3 2024-04-02 68.9 0.0069 19800000
8 VALE3 2024-04-03 70.2 0.0178 25600000
9 VALE3 2024-04-04 71.2 0.015 28300000
10 VALE3 2024-04-05 70.8 -0.0049 23100000
# Tabela de anúncios de eventos corporativos
eventos_corporativos <- tribble(
~ticker, ~data_anuncio, ~tipo_evento, ~valor,
"PETR4", "2024-04-03", "Dividendo Extra", 2.85,
"VALE3", "2024-04-04", "JCP", 1.75
)
# visualiza o resultado
eventos_corporativos
# A tibble: 2 × 4
ticker data_anuncio tipo_evento valor
<chr> <chr> <chr> <dbl>
1 PETR4 2024-04-03 Dividendo Extra 2.85
2 VALE3 2024-04-04 JCP 1.75
# Realizando análise de retornos nos dias de evento
estudo_evento <- precos_acoes %>%
inner_join(eventos_corporativos,
by = c("ticker", "data" = "data_anuncio")) %>%
select(ticker, data, tipo_evento, valor, retorno_diario, volume)
# Visualizando o resultado
estudo_evento
# A tibble: 2 × 6
ticker data tipo_evento valor retorno_diario volume
<chr> <chr> <chr> <dbl> <dbl> <dbl>
1 PETR4 2024-04-03 Dividendo Extra 2.85 -0.0067 14800000
2 VALE3 2024-04-04 JCP 1.75 0.015 28300000
Aplicação em Pesquisa:
Este tipo de join é relevante para estudos de evento que analisam o impacto de anúncios corporativos sobre o preço das ações
Aplicações em pesquisas financeiras incluem:
O inner_join
utilizado garante que apenas os dias com eventos são considerados para a análise de retornos anormais
Conheça seus dados antes de combinar:
Filtre antes de combinar:
Verifique o resultado:
Na dúvida, use left_join:
No mundo ideal, todos os sistemas usariam os mesmos nomes para as mesmas informações…
Mas na prática:
codigo_produto
codigo
cod_prod
id_produto
Resultado: Tentar unir estas tabelas com a sintaxe básica falha:
Como resolver este problema comum?
O dplyr permite especificar explicitamente quais colunas devem ser correspondidas:
Como interpretar:
"nome_na_tabela1"
: Nome da coluna na primeira tabela (esquerda)"nome_na_tabela2"
: Nome da coluna na segunda tabela (direita)=
estabelece a correspondência entre as colunasAnalogia: Você está criando um “dicionário de tradução” entre os sistemas:
codigo_produto
, você entende codigo
”# Sistema de Cadastro de Produtos (departamento de Compras)
produtos_cadastro <- tribble(
~codigo, ~descricao, ~valor_unitario, ~categoria,
"P001", "Notebook Pro", 4500, "Eletrônicos",
"P002", "Smartphone X", 2800, "Eletrônicos",
"P003", "Monitor 24pol", 1200, "Informática"
)
# visualiza o resultado
produtos_cadastro
# A tibble: 3 × 4
codigo descricao valor_unitario categoria
<chr> <chr> <dbl> <chr>
1 P001 Notebook Pro 4500 Eletrônicos
2 P002 Smartphone X 2800 Eletrônicos
3 P003 Monitor 24pol 1200 Informática
# Sistema de Vendas (departamento Comercial)
vendas_sistema <- tribble(
~id_venda, ~cod_produto, ~data_venda, ~qtd,
1, "P001", "2025-04-15", 1,
2, "P002", "2025-04-16", 2,
3, "P003", "2025-04-18", 2
)
# visualiza o resultado
vendas_sistema
# A tibble: 3 × 4
id_venda cod_produto data_venda qtd
<dbl> <chr> <chr> <dbl>
1 1 P001 2025-04-15 1
2 2 P002 2025-04-16 2
3 3 P003 2025-04-18 2
# Integrando os sistemas com diferentes nomenclaturas
relatorio_vendas <- vendas_sistema %>%
left_join(produtos_cadastro, by = c("cod_produto" = "codigo")) %>%
select(id_venda, data_venda, cod_produto, descricao, qtd, valor_unitario) %>%
mutate(valor_total = qtd * valor_unitario) %>%
arrange(data_venda)
# Resultado: um relatório integrado
relatorio_vendas
# A tibble: 3 × 7
id_venda data_venda cod_produto descricao qtd valor_unitario valor_total
<dbl> <chr> <chr> <chr> <dbl> <dbl> <dbl>
1 1 2025-04-15 P001 Notebook Pro 1 4500 4500
2 2 2025-04-16 P002 Smartphone X 2 2800 5600
3 3 2025-04-18 P003 Monitor 24pol 2 1200 2400
Observação: Esta situação é extremamente comum.
Joins unem tabelas que estão separadas
Os tipos mais importantes são:
left_join()
: Mantém todos os registros da tabela principal (o mais usado)inner_join()
: Mantém apenas registros com correspondência em ambas tabelasfull_join()
: Mantém todos os registros de ambas as tabelasNa prática, left_join é o mais comum:
Comece simples e avance gradualmente:
Tipo de Join | Função | Resultado | Quando Usar | Analogia de Negócios |
---|---|---|---|---|
Inner Join | inner_join() |
Apenas registros com correspondência | Análises que exigem dados completos | Relatório com apenas vendas confirmadas |
Left Join | left_join() |
Todos os registros da tabela esquerda | Manter a tabela principal intacta | Relatório de todas as vendas (com ou sem produto cadastrado) |
Right Join | right_join() |
Todos os registros da tabela direita | Quando a 2ª tabela é a principal | Catálogo com todos os produtos (vendidos ou não) |
Full Join | full_join() |
Todos os registros de ambas as tabelas | Análises completas e auditorias | Verificação de inconsistências no sistema |
Dica para lembrar: Pense no “lado” que você quer preservar:
# LEFT JOIN: todos os registros da tabela1
tabela1 %>%
left_join(tabela2, by = "coluna_comum")
# INNER JOIN: apenas registros com correspondência
tabela1 %>%
inner_join(tabela2, by = "coluna_comum")
# FULL JOIN: todos os registros de ambas as tabelas
tabela1 %>%
full_join(tabela2, by = "coluna_comum")
# RIGHT JOIN: todos os registros da tabela2
tabela1 %>%
right_join(tabela2, by = "coluna_comum")
Observe que:
A estrutura básica é idêntica para todos os joins:
%>%
Só muda o nome da função, que indica qual tipo de join realizar:
inner_join
, left_join
, right_join
ou full_join
Quando as colunas têm nomes diferentes, use esta sintaxe:
Finanças Corporativas:
Mercado de Capitais:
Finanças Comportamentais:
Econometria Financeira:
Com os dados organizados (formato longo), podemos facilmente, por exemplo:
Finanças e Controladoria: Análise de tendências financeiras entre períodos, detecção de anomalias em despesas, comparação de desempenho entre unidades de negócio
Marketing: Avaliação de ROI por canal e campanha, análise de comportamento do consumidor, segmentação de clientes baseada em múltiplas variáveis
Operações e Cadeia de Suprimentos: Otimização de estoques baseada em tendências sazonais, previsão de demanda, monitoramento da cadeia de suprimentos
Recursos Humanos: Análise de desempenho ao longo do tempo, identificação de fatores de turnover, planejamento de capacitação
Estratégia de Negócios: Consolidação de KPIs de diversas áreas para tomada de decisão, identificação de correlações entre variáveis de negócio
Na prática: Administradores frequentemente recebem dados em formatos inadequados para análise (relatórios estáticos, planilhas “bonitas”). A capacidade de reorganizar esses dados rapidamente para análise representa uma vantagem competitiva significativa.
# inicia com a df (gapminder) e salva o resultado final
relatorio_expectativa <- gapminder %>%
# Filtra apenas os dados de 2007
filter(year == 2007) %>%
# Agrupa por continente
group_by(continent) %>%
# Calcula estatísticas por continente
summarize(
expectativa_media = mean(lifeExp),
expectativa_minima = min(lifeExp),
expectativa_maxima = max(lifeExp),
) %>%
# Ordena do maior para o menor
arrange(desc(expectativa_media))
# Visualiza o resultado final
relatorio_expectativa
# A tibble: 5 × 4
continent expectativa_media expectativa_minima expectativa_maxima
<fct> <dbl> <dbl> <dbl>
1 Oceania 80.7 80.2 81.2
2 Europe 77.6 71.8 81.8
3 Americas 73.6 60.9 80.7
4 Asia 70.7 43.8 82.6
5 Africa 54.8 39.6 76.4
As data frames produzidas pelos pipelines do dplyr são excelentes para análise, mas não são adequadas para apresentação em relatórios profissionais.
A linguagem R oferece várias soluções para esta limitação:
Estes pacotes permitem transformar dados analíticos em tabelas com qualidade profissional, incluindo:
O pacote kableExtra
estende as funcionalidades da função básica kable
do R, permitindo a criação de tabelas com qualidade de publicação.
Foi desenvolvido para trabalhar com tabelas em documentos HTML e PDF (LaTeX).
Permite formatar tabelas para relatórios profissionais, artigos acadêmicos e apresentações.
É extremamente útil na Fase 6 do CRISP-DM (Implantação), quando precisamos comunicar resultados de forma clara e atrativa.
# inicie com uma data frame
tabela_formatada <- dados %>%
# Transforme a data frame em tabela básica
kable(
caption = "Título da Tabela",
col.names = c("Nome1", "Nome2"), # Renomear colunas
digits = 2, # Casas decimais
format.args = list(decimal.mark = ",", big.mark = ".") # Define vírgula como separador decimal e ponto como separador de milhares
) %>%
# Adicionar estilos
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE,
position = "center"
)
%>%
)Em projetos de análise de dados completos, o fluxo geralmente é:
tidyr
e dplyr
dplyr
(filter, select, group_by, etc.)ggplot2
(gráficos) e kableExtra
(tabelas)Um pipeline completo pode é similar com:
Este fluxo integrado representa as fases 3, 4 e 6 do CRISP-DM.
Para que serve: Transformar tabelas de dados simples em tabelas profissionais para relatórios, apresentações e publicações.
Sintaxe básica:
Funções principais:
kable()
: Converte data frame em tabela basekable_styling()
: Aplica estilos gerais à tabelacolumn_spec()
e row_spec()
: Personalizações específicasfootnote()
: Adiciona notas de rodapéIntegrações estratégicas:
Benefícios em Administração:
# inicia com a df contendo o resultado do pipeline
relatorio_expectativa %>%
# Converte a df em uma tabela kable (tabela básica HTML/LaTeX)
kable(
# Renomeia as colunas para português
col.names = c(
"Continente", "Expectativa Média", "Expectativa Mínima", "Expectativa Máxima"
),
# Formata os números com 1 casa decimal
digits = 1,
# vírgula como separador decimal
format.args = list(decimal.mark = ",")
) %>%
# Adiciona estilo à tabela para melhorar o visual
kable_classic(
# tamanho da fonte
font_size = 25,
# Impede que a tabela ocupe toda a largura disponível
full_width = FALSE,
# # Centraliza a tabela
position = "center"
) %>%
# Aplica formatação específica à coluna da expectativa média
column_spec(
# Aplica a formatação à segunda coluna (Expectativa Média)
2,
# Coloca o texto em negrito para melhor destaque
bold = TRUE,
# Define a cor dos números como branco
color = "white",
# Aplica um gradiente de cores ao fundo das células
background = spec_color(
# A expectativa_media determinar a intensidade das cores
relatorio_expectativa$expectativa_media,
# início do gradiente com intensidade alta
begin = 0.9,
# fim do gradiente com intensidade baixa
end = 0.1,
# paleta de cores "viridis" (azul-verde-amarelo)
option = "viridis",
# 1 = valores mais altos recebem cores mais intensas
direction = 1
)
)
Continente | Expectativa Média | Expectativa Mínima | Expectativa Máxima |
---|---|---|---|
Oceania | 80,7 | 80,2 | 81,2 |
Europe | 77,6 | 71,8 | 81,8 |
Americas | 73,6 | 60,9 | 80,7 |
Asia | 70,7 | 43,8 | 82,6 |
Africa | 54,8 | 39,6 | 76,4 |
# formato típico de planilhas gerenciais
dados_vendas_wide <- tribble(
~produto, ~categoria, ~Jan, ~Fev, ~Mar, ~Abr, ~Mai, ~Jun,
"Notebook Pro", "Eletrônicos", 45000, 38000, 42000, 47000, 52000, 49000,
"Smartphone X", "Eletrônicos", 38000, 41000, 40000, 39000, 45000, 50000,
"Monitor 24pol", "Informática", 22000, 19000, 23000, 25000, 24000, 26000,
"Mouse Gamer", "Informática", 12000, 14000, 13500, 15000, 16000, 17500,
"Mesa Office", "Mobiliário", 28000, 25000, 24000, 26500, 27000, 29000,
"Cadeira Ergo", "Mobiliário", 35000, 32000, 38000, 36000, 39000, 42000
)
# Visualizando os dados no formato amplo (wide)
dados_vendas_wide
# A tibble: 6 × 8
produto categoria Jan Fev Mar Abr Mai Jun
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Notebook Pro Eletrônicos 45000 38000 42000 47000 52000 49000
2 Smartphone X Eletrônicos 38000 41000 40000 39000 45000 50000
3 Monitor 24pol Informática 22000 19000 23000 25000 24000 26000
4 Mouse Gamer Informática 12000 14000 13500 15000 16000 17500
5 Mesa Office Mobiliário 28000 25000 24000 26500 27000 29000
6 Cadeira Ergo Mobiliário 35000 32000 38000 36000 39000 42000
# Transformando os dados para o formato longo (tidy)
dados_vendas_longo <- dados_vendas_wide %>%
pivot_longer(
cols = Jan:Jun, # colunas que serão transformadas em valores de mes
names_to = "mes", # nome da nova coluna
values_to = "valor_vendas" # nome de outra nova coluna para as vendas
)
# Visualizando o resultado
dados_vendas_longo
# A tibble: 36 × 4
produto categoria mes valor_vendas
<chr> <chr> <chr> <dbl>
1 Notebook Pro Eletrônicos Jan 45000
2 Notebook Pro Eletrônicos Fev 38000
3 Notebook Pro Eletrônicos Mar 42000
4 Notebook Pro Eletrônicos Abr 47000
5 Notebook Pro Eletrônicos Mai 52000
6 Notebook Pro Eletrônicos Jun 49000
7 Smartphone X Eletrônicos Jan 38000
8 Smartphone X Eletrônicos Fev 41000
9 Smartphone X Eletrônicos Mar 40000
10 Smartphone X Eletrônicos Abr 39000
# ℹ 26 more rows
Agora os dados estão organizados para análise:
# pipeline de análise
receita_bruta_mes <- dados_vendas_longo %>%
group_by(mes) %>%
summarize(vendas_total = sum(valor_vendas)) %>%
arrange(desc(vendas_total))
# visualiza o resultado
receita_bruta_mes
# A tibble: 6 × 2
mes vendas_total
<chr> <dbl>
1 Jun 213500
2 Mai 203000
3 Abr 188500
4 Mar 180500
5 Jan 180000
6 Fev 169000
# pipeline de análise
vendas_mensais_notebookpro <- dados_vendas_longo %>%
filter(produto == "Notebook Pro") %>%
select(produto, mes, valor_vendas) %>%
arrange(mes)
# visualiza o resultado
vendas_mensais_notebookpro
# A tibble: 6 × 3
produto mes valor_vendas
<chr> <chr> <dbl>
1 Notebook Pro Abr 47000
2 Notebook Pro Fev 38000
3 Notebook Pro Jan 45000
4 Notebook Pro Jun 49000
5 Notebook Pro Mai 52000
6 Notebook Pro Mar 42000
# pipeline de análise
vendas_totais_categoria_mes <- dados_vendas_longo %>%
group_by(categoria, mes) %>%
summarize(vendas_totais = sum(valor_vendas)) %>%
arrange(desc(vendas_totais))
# visualiza o resultado
vendas_totais_categoria_mes
# A tibble: 18 × 3
# Groups: categoria [3]
categoria mes vendas_totais
<chr> <chr> <dbl>
1 Eletrônicos Jun 99000
2 Eletrônicos Mai 97000
3 Eletrônicos Abr 86000
4 Eletrônicos Jan 83000
5 Eletrônicos Mar 82000
6 Eletrônicos Fev 79000
7 Mobiliário Jun 71000
8 Mobiliário Mai 66000
9 Mobiliário Jan 63000
10 Mobiliário Abr 62500
11 Mobiliário Mar 62000
12 Mobiliário Fev 57000
13 Informática Jun 43500
14 Informática Abr 40000
15 Informática Mai 40000
16 Informática Mar 36500
17 Informática Jan 34000
18 Informática Fev 33000
# pipeline
desempenho_mensal_produto <- dados_vendas_longo %>%
group_by(produto) %>%
summarize(
vendas_total = sum(valor_vendas),
vendas_media = mean(valor_vendas),
vendas_min = min(valor_vendas),
vendas_max = max(valor_vendas)
) %>%
arrange(desc(vendas_total))
# visualiza o resultado
desempenho_mensal_produto
# A tibble: 6 × 5
produto vendas_total vendas_media vendas_min vendas_max
<chr> <dbl> <dbl> <dbl> <dbl>
1 Notebook Pro 273000 45500 38000 52000
2 Smartphone X 253000 42167. 38000 50000
3 Cadeira Ergo 222000 37000 32000 42000
4 Mesa Office 159500 26583. 24000 29000
5 Monitor 24pol 139000 23167. 19000 26000
6 Mouse Gamer 88000 14667. 12000 17500
# Formata a tabela de desempenho por produto com kableExtra
desempenho_mensal_produto %>%
kable(
# Renomeia as colunas para melhor apresentação
col.names = c(
"Produto",
"Vendas Totais (R$)",
"Média Mensal (R$)",
"Venda Mínima (R$)",
"Venda Máxima (R$)"
),
# Formata números com 2 casas decimais
digits = 2,
# Define vírgula como separador decimal e ponto como separador de milhares
format.args = list(decimal.mark = ",", big.mark = ".", nsmall = 2)
) %>%
# Aplica um estilo clássico e limpo
kable_classic_2(
# Ajusta o tamanho da fonte
font_size = 18,
# Define largura para se ajustar melhor ao slide
full_width = TRUE,
# Centraliza a tabela
position = "center"
) %>%
# Destaca as colunas de valores em negrito
column_spec(2:5, bold = TRUE) %>%
# Destaca as 3 primeiras linha da tabela
row_spec(1:3, bold = T, color = "white", background = "#011f4b")
Produto | Vendas Totais (R$) | Média Mensal (R$) | Venda Mínima (R$) | Venda Máxima (R$) |
---|---|---|---|---|
Notebook Pro | 273.000,00 | 45.500,00 | 38.000,00 | 52.000,00 |
Smartphone X | 253.000,00 | 42.166,67 | 38.000,00 | 50.000,00 |
Cadeira Ergo | 222.000,00 | 37.000,00 | 32.000,00 | 42.000,00 |
Mesa Office | 159.500,00 | 26.583,33 | 24.000,00 | 29.000,00 |
Monitor 24pol | 139.000,00 | 23.166,67 | 19.000,00 | 26.000,00 |
Mouse Gamer | 88.000,00 | 14.666,67 | 12.000,00 | 17.500,00 |
# Pipeline para identificar mês de melhor desempenho por categoria
meses_pico_categoria <- dados_vendas_longo %>%
# Agrupa por categoria e mês
group_by(categoria, mes) %>%
# Calcula as vendas totais
summarize(vendas_totais = sum(valor_vendas)) %>%
# Filtra para o mês de maior venda
filter(vendas_totais == max(vendas_totais)) %>%
# Ordena o resultado pelas vendas totais
arrange(desc(vendas_totais))
# visualiza o resultado
meses_pico_categoria
# A tibble: 3 × 3
# Groups: categoria [3]
categoria mes vendas_totais
<chr> <chr> <dbl>
1 Eletrônicos Jun 99000
2 Mobiliário Jun 71000
3 Informática Jun 43500
# Pipeline para identificar mês de pior desempenho por categoria
meses_pior_categoria <- dados_vendas_longo %>%
# Agrupa por categoria e mês
group_by(categoria, mes) %>%
# Calcula as vendas totais
summarize(vendas_totais = sum(valor_vendas)) %>%
# Filtra para o mês de menor venda
filter(vendas_totais == min(vendas_totais)) %>%
# Ordena o resultado pelas vendas totais
arrange(desc(vendas_totais))
# visualiza o resultado
meses_pior_categoria
# A tibble: 3 × 3
# Groups: categoria [3]
categoria mes vendas_totais
<chr> <chr> <dbl>
1 Eletrônicos Fev 79000
2 Mobiliário Fev 57000
3 Informática Fev 33000
As funções which.max()
e which.min()
são extremamente úteis em análise de dados:
which.max(x)
: Retorna a posição (índice) do valor máximo no vetor x
which.min(x)
: Retorna a posição (índice) do valor mínimo no vetor x
Exemplo simples:
# Vetor de valores
vendas_mensais <- c(120, 150, 140, 160, 110, 130)
# Qual a posição do valor máximo?
posicao_max <- which.max(vendas_mensais)
posicao_max
[1] 4
[1] 160
# Supondo que temos nomes para os meses
nomes_meses <- c("Jan", "Fev", "Mar", "Abr", "Mai", "Jun")
# Em qual mês ocorreu a venda máxima?
mes_maior_venda <- nomes_meses[which.max(vendas_mensais)]
mes_maior_venda
[1] "Abr"
Estas funções são perfeitas para encontrar quando ocorreram eventos importantes nos seus dados (máximos, mínimos, picos) em vez de apenas quais foram os valores.
# Pipeline de análise para identificar os meses de pico e vale por produto
resumo_comparativo_produto <- dados_vendas_longo %>%
# Agrupa os dados por produto para analisar cada um separadamente
group_by(produto) %>%
# Para cada produto, calculamos:
summarize(
# 1. Qual o mês da maior venda:
# - which.max(valor_vendas) encontra a POSIÇÃO da maior venda
# - mes[which.max(valor_vendas)] seleciona o nome do mês de maior venda
melhor_mes = mes[which.max(valor_vendas)],
# 2. Qual foi o valor da maior venda
maior_venda = max(valor_vendas),
# 3. Qual o mês da menor venda (mesma lógica do melhor mês)
pior_mes = mes[which.min(valor_vendas)],
# 4. Qual foi o valor da menor venda
menor_venda = min(valor_vendas)
)
# Visualiza o resultado
resumo_comparativo_produto
# A tibble: 6 × 5
produto melhor_mes maior_venda pior_mes menor_venda
<chr> <chr> <dbl> <chr> <dbl>
1 Cadeira Ergo Jun 42000 Fev 32000
2 Mesa Office Jun 29000 Mar 24000
3 Monitor 24pol Jun 26000 Fev 19000
4 Mouse Gamer Jun 17500 Jan 12000
5 Notebook Pro Mai 52000 Fev 38000
6 Smartphone X Jun 50000 Jan 38000
Explicação do código:
Primeiro agrupamos por produto para realizar a análise para cada item
A função which.max(valor_vendas)
retorna a posição (índice) do valor máximo
Ao usar mes[which.max(valor_vendas)]
, extraímos o nome do mês na posição com valor máximo
Este tipo de análise é essencial para identificar padrões sazonais de produtos
Este relatório permite identificar rapidamente quais meses foram melhores e piores para cada produto - informação valiosa para planejamento de estoque e promoções.
Assim, esta análise permite otimizar o planejamento de estoque e ações promocionais sazonais.
Produto | Melhor Mês | Maior Venda (R$) | Pior Mês | Menor Venda (R$) |
---|---|---|---|---|
Cadeira Ergo | Jun | 42.000,00 | Fev | 32.000,00 |
Mesa Office | Jun | 29.000,00 | Mar | 24.000,00 |
Monitor 24pol | Jun | 26.000,00 | Fev | 19.000,00 |
Mouse Gamer | Jun | 17.500,00 | Jan | 12.000,00 |
Notebook Pro | Mai | 52.000,00 | Fev | 38.000,00 |
Smartphone X | Jun | 50.000,00 | Jan | 38.000,00 |
Considere os dados com os quais você já trabalha ou espera trabalhar em sua carreira:
Que tipos de dados desorganizados você encontra ou espera encontrar?
Como esses dados poderiam ser melhor organizados para análise?
Quais insights de negócio você poderia extrair se esses dados estivessem organizados adequadamente?
Como você aplicaria o conhecimento desta aula em um exemplo concreto do seu interesse profissional?