Manipulação de Dados no R
A manipulação de bases de dados consiste em um conjunto de funções/procedimentos que nos permite tornar essas informações estruturadas em bases analíticas, isto é, capazes de responder aos questionamentos que são objeto de análise.
Essas funções e procedimentos consistem no relacionamento de diferentes bases, agregação de informações, realização de filtros, conversão de unidades, cálculo de medidas baseado nas informações consultadas, etc.
Diversas ferramentas auxiliam nesses tratamentos. Os Sistemas Gerenciadores de Banco de Dados (SGBD) são um exemplo de ferramenta com alta competência nessa tarefa. Os SGBD utilizam a linguagem de programação conhecida como SQL (Structure Query Language) para manipulação dos dados.
Dentre os comandos mais conhecidos dessa linguagem temos junções (joins), seleções (select), filtros (cláusulas where e having), agregações (cláusula group by), entre outras. O R possui recursos para realizar, de forma semelhante, esses procedimentos. O objetivo desse tutorial é apresentar essas funcionalidades e criar um paralelismo para com a linguagem SQL.
key words: Manipulação de Dados, SQL, dplyr, tidyr
Manipulando dados com o dplyr
e tidyr
Os pacotes tidyr
e dplyr
são, atualmente, os instrumentos mais sofisticados para manipulação de dados no R. O tidyr
permite que trabalhemos com estruturas de dados conhecidas como tibbles, que são uma espécie particular de data frame que traz algumas facilidades para o analista de dados. O pacote dplyr
permite a manipulação dessas estruturas pela execução de procedimentos como filtros, agregações, junções e criação de novas medidas.
Os dados que utilizaremos nesse tutorial foram extraídos do banco AdventureWorks. Esse que foi criado pela Microsoft e representa as operações de uma empresa de manufatura e varejo fictícia. utilizamos as tabelas do diagrama Reseller Sales e as funções do pacote dplyr
e tidyr
para manipulação dos dados.
Você pode fazer download dos dados clicando aqui. As tabelas utilizadas são:
FactResellerSales: Possui informações como valor das vendas, custos, fretes, código da ordem de venda, código do produto vendido, código do revendedor comprador, entre outras.
DimDate: Tabela com informações de dimensão de tempo.
DimProduct: Tabela com informações de dimensão dos produtos, como descrição, código da subcategoria, entre outros.
DimProductSubcategory: Tabela com informações de dimensão de subcategoria dos produtos.
DimProductCategory: Tabela com informações de dimensão de categoria dos produtos.
A Figura 1 apresenta o diagramada que sintetiza a natureza dos relacionamentos entre as tabelas assim como as respectivas chaves.
Fig.1: Diagrama de relacionamento das tabelas utilizadas
Vamos fazer o carregamento dessas tabelas para o R. Para isso, faça o download dos dados e salve-os no mesmo diretório em que está trabalhando com seu arquivo no R.
library(readxl)
library(dplyr)
library(tidyr)
TB_FR<-read_excel("ADVWorks Reseller (Tutorial).xlsx", sheet = "FactResellerSales") %>% as_tibble()
TB_Data<-read_excel("ADVWorks Reseller (Tutorial).xlsx", sheet = "DimDate") %>% as_tibble()
TB_Prod<-read_excel("ADVWorks Reseller (Tutorial).xlsx", sheet = "DimProduct") %>% as_tibble()
TB_SubCat<-read_excel("ADVWorks Reseller (Tutorial).xlsx", sheet = "DimProductSubcategory") %>% as_tibble()
TB_Cat<-read_excel("ADVWorks Reseller (Tutorial).xlsx", sheet = "DimProductCategory") %>% as_tibble()
O código acima carrega os dados para nosso ambiente e os armazena como um objeto tibble. Vejamos como esses dados são exibidos pelo R.
TB_FR
## # A tibble: 60,855 x 27
## ProductKey OrderDateKey DueDateKey ShipDateKey ResellerKey EmployeeKey
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 349 20050701 20050713 20050708 676 285
## 2 350 20050701 20050713 20050708 676 285
## 3 351 20050701 20050713 20050708 676 285
## 4 344 20050701 20050713 20050708 676 285
## 5 345 20050701 20050713 20050708 676 285
## 6 346 20050701 20050713 20050708 676 285
## 7 347 20050701 20050713 20050708 676 285
## 8 229 20050701 20050713 20050708 676 285
## 9 235 20050701 20050713 20050708 676 285
## 10 218 20050701 20050713 20050708 676 285
## # ... with 60,845 more rows, and 21 more variables: PromotionKey <dbl>,
## # CurrencyKey <dbl>, SalesTerritoryKey <dbl>, SalesOrderNumber <chr>,
## # SalesOrderLineNumber <dbl>, RevisionNumber <dbl>, OrderQuantity <dbl>,
## # UnitPrice <dbl>, ExtendedAmount <dbl>, UnitPriceDiscountPct <dbl>,
## # DiscountAmount <dbl>, ProductStandardCost <dbl>, TotalProductCost <dbl>,
## # SalesAmount <dbl>, TaxAmt <dbl>, Freight <dbl>,
## # CarrierTrackingNumber <chr>, CustomerPONumber <chr>, OrderDate <dttm>,
## # DueDate <dttm>, ShipDate <dttm>
Aqui temos algumas diferenças para com os data frames. A exibição de tibbles contempla, por padrão, apenas 10 linhas, o número de colunas exibido é definido de modo a não transpassar a largura disponível no console e a tipagem dos dados é apresentada logo abaixo do nome da coluna.
Vamos tratar algumas das principais funções do SQL em uma roupagem que utiliza o dplyr
para tanto.
Seleções (Select) e Junções (Joins)
Os comandos Select permitem a filtragem de colunas de uma tabela baseada em seus nomes. As joins utilizam as chaves que definem os relacionamento entre as tabelas para gerar uma nova base de dados que contempla as informações de 2 ou mais tabelas diferentes. Essas são, possivelmente, os comandos mais usuais da linguagem SQL.
## Tomamos a TB_FR e realizamos uma junção com a TB_Data.
## Tomando a tabela resultante da join anterior selecionamos o conjunto de colunas ProductKey, CurrencyKey, FiscalYear e OrderQuantity. Em seguida, tomamos todas as colunas que iniciam com o texto SalesOrder e, por fim, tomamos a sequência de colunas iniciando em TotalProductCost até Freight.
View_1<-TB_FR %>%
inner_join(TB_Data, by = c("OrderDateKey" = "DateKey")) %>%
inner_join(TB_Prod, by = c("ProductKey" = "ProductKey")) %>%
select(c(ProductKey,EnglishProductName, OrderDateKey, FiscalYear, OrderQuantity), starts_with("SalesOrder"),
TotalProductCost:Freight)
View_1
## # A tibble: 60,855 x 11
## ProductKey EnglishProductName OrderDateKey FiscalYear OrderQuantity
## <dbl> <chr> <dbl> <dbl> <dbl>
## 1 349 Mountain-100 Black, 42 20050701 2006 1
## 2 350 Mountain-100 Black, 44 20050701 2006 3
## 3 351 Mountain-100 Black, 48 20050701 2006 1
## 4 344 Mountain-100 Silver, 38 20050701 2006 1
## 5 345 Mountain-100 Silver, 42 20050701 2006 1
## 6 346 Mountain-100 Silver, 44 20050701 2006 2
## 7 347 Mountain-100 Silver, 48 20050701 2006 1
## 8 229 Long-Sleeve Logo Jersey, M 20050701 2006 3
## 9 235 Long-Sleeve Logo Jersey, XL 20050701 2006 1
## 10 218 Mountain Bike Socks, M 20050701 2006 6
## # ... with 60,845 more rows, and 6 more variables: SalesOrderNumber <chr>,
## # SalesOrderLineNumber <dbl>, TotalProductCost <dbl>, SalesAmount <dbl>,
## # TaxAmt <dbl>, Freight <dbl>
O dplyr
possui muito recursos que aumentam a praticidade das funções. As rights, lefts, full e natural joins também estão disponíveis. O parâmetro by determina a chave da relação entre as tabelas que, inclusive, podem possuir chaves compostas. Utilizando o pipe (%>%) ganhamos organização e agilidade no código. Veja-o sempre como um operador que determina a sequência em que um objeto é transformado em outro.
Por fim, a função select possui diversos recursos para facilitar a seleção dos campos. É possível realizar filtros baseado no texto de início ou fim do nome das colunas (starts_with
ou ends_with
), na existência de uma certa sequência textual (contains
), em um filtro reverso (isto é, na exclusão de um certo conjunto de variáveis), entre outras possibilidades. Utilize a função help(inner_join) para ver mais detalhes.
Agregação (Group by) e Ordenação (Order by)
As operações de agregação, conhecida no SQL como cláusula group by, servem para retrair alguma dimensão de uma base de dados, agregando-a nas dimensões restantes. Por exemplo, na consulta anterior poderíamos optar por retirar a dimensão de ordem das vendas, agregando o valor total, o custo, quantidade e o número de pedidos por produto e ano. Para isso, o seguinte comando é executado.
View_2<-View_1 %>%
group_by(FiscalYear, ProductKey, EnglishProductName) %>%
summarise("Custo"=sum(TotalProductCost), "Vendas"=sum(SalesAmount), "Qtd"=sum(OrderQuantity),
"Num Ordens"=n())
No dplyr
as agregações ocorrem em duas etapas. Primeiro deve-se indicar as dimensões de agregação por meio da função group_by
. Na sequência, deve-se apontar quais colunas serão agregadas e qual a função de agregação a ser aplicada. Isso ocorre por meio da função summarise
.
Um caso especial da agregação ocorre quando desejamos apenas retirar a duplicidade de valores de uma coluna. Podemos realizar essa operação por meio da função distinct
.
## Tomando todos os códigos de produtos presentes na base de dados View_1
View_1 %>%
select(ProductKey) %>%
distinct()
## # A tibble: 334 x 1
## ProductKey
## <dbl>
## 1 349
## 2 350
## 3 351
## 4 344
## 5 345
## 6 346
## 7 347
## 8 229
## 9 235
## 10 218
## # ... with 324 more rows
A função arrange
é útil para a tarefa de ordenação da visulização de dados criada, conforme algum critério. Nesse exemplo, vamos ordenar os produtos por ordem decrescente do valor das vendas e número de ordens de venda.
View_2 %>%
arrange(desc(Vendas), desc(`Num Ordens`), .by_group = FALSE)
## # A tibble: 334 x 7
## # Groups: FiscalYear, ProductKey [334]
## FiscalYear ProductKey EnglishProductName Custo Vendas Qtd `Num Ordens`
## <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <int>
## 1 2008 359 Mountain-200 Black,~ 1.50e6 1.63e6 1197 327
## 2 2007 358 Mountain-200 Black,~ 1.32e6 1.47e6 1198 343
## 3 2008 583 Road-350-W Yellow, ~ 1.50e6 1.38e6 1390 334
## 4 2008 576 Touring-1000 Blue, ~ 1.44e6 1.37e6 973 292
## 5 2007 360 Mountain-200 Black,~ 1.23e6 1.36e6 1110 319
## 6 2008 361 Mountain-200 Black,~ 1.18e6 1.29e6 940 244
## 7 2008 580 Road-350-W Yellow, ~ 1.33e6 1.24e6 1231 327
## 8 2008 564 Touring-1000 Yellow~ 1.44e6 1.18e6 974 293
## 9 2008 353 Mountain-200 Silver~ 1.08e6 1.18e6 853 219
## 10 2007 354 Mountain-200 Silver~ 1.06e6 1.18e6 948 273
## # ... with 324 more rows
O parâmetro .by_group
indica se a ordenação deve ou não considerar grupos de agregação no processo de ordenação. Neste exemplo, se alterarmos para TRUE
o valor desse parâmetro a ordenação ocorrerá por produto dentro de cada ano fiscal. Vejamos o resultado abaixo.
View_2 %>%
arrange(desc(Vendas), desc(`Num Ordens`), .by_group = TRUE)
## # A tibble: 334 x 7
## # Groups: FiscalYear, ProductKey [334]
## FiscalYear ProductKey EnglishProductName Custo Vendas Qtd `Num Ordens`
## <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <int>
## 1 2006 212 Sport-100 Helmet, Red 6784. 11385. 564 200
## 2 2006 215 Sport-100 Helmet, Bla~ 7217. 12098. 600 201
## 3 2006 218 Mountain Bike Socks, M 3760. 6060. 1107 188
## 4 2006 219 Mountain Bike Socks, L 306. 513 90 44
## 5 2006 220 Sport-100 Helmet, Blue 7950. 13332. 661 215
## 6 2006 223 AWC Logo Cap 5620. 5081. 985 290
## 7 2006 229 Long-Sleeve Logo Jers~ 13864. 12603. 437 178
## 8 2006 232 Long-Sleeve Logo Jers~ 31439. 28399. 991 296
## 9 2006 235 Long-Sleeve Logo Jers~ 15037. 13670. 474 192
## 10 2006 238 HL Road Frame - Red, ~ 22439. 22742. 30 18
## # ... with 324 more rows
Por último, ainda nesse tópico, vamos utilizar a função rename
para alterar o nome de algumas colunas na visualização criada.
## Altera o nome das colunas FiscalYear e ProductKey para AnoFiscal e ChaveProduto, respectivamente.
View_2<-View_2 %>%
rename(AnoFiscal=FiscalYear, ChaveProduto=ProductKey, NomeProduto=EnglishProductName)
Filtros e inclusão de novas colunas
Na linguagem SQL os filtros são performados utilizando a cláusula where ou having. No dplyr
ambas utilizam a mesma função, chamada filter
.
## Filtra apenas o ano fiscal de 2008
View_2 %>%
filter(AnoFiscal==2008)
## # A tibble: 167 x 7
## # Groups: AnoFiscal, ChaveProduto [167]
## AnoFiscal ChaveProduto NomeProduto Custo Vendas Qtd `Num Ordens`
## <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <int>
## 1 2008 214 Sport-100 Helmet, R~ 25898. 3.93e4 1979 336
## 2 2008 217 Sport-100 Helmet, B~ 28947. 4.40e4 2212 381
## 3 2008 222 Sport-100 Helmet, B~ 29025. 4.39e4 2218 378
## 4 2008 225 AWC Logo Cap 19604. 1.48e4 2832 460
## 5 2008 231 Long-Sleeve Logo Je~ 58470. 4.50e4 1519 311
## 6 2008 234 Long-Sleeve Logo Je~ 107894. 8.16e4 2803 451
## 7 2008 237 Long-Sleeve Logo Je~ 38184. 2.97e4 992 203
## 8 2008 240 HL Road Frame - Red~ 180676. 1.79e5 208 98
## 9 2008 243 HL Road Frame - Red~ 181545. 1.80e5 209 96
## 10 2008 246 HL Road Frame - Red~ 52987. 5.24e4 61 23
## # ... with 157 more rows
## Filtra apenas o ano fiscal de 2008
View_2 %>%
filter(NomeProduto %in% c("Helmet", "Bike"))
## # A tibble: 0 x 7
## # Groups: AnoFiscal, ChaveProduto [0]
## # ... with 7 variables: AnoFiscal <dbl>, ChaveProduto <dbl>, NomeProduto <chr>,
## # Custo <dbl>, Vendas <dbl>, Qtd <dbl>, Num Ordens <int>
## Filtra apenas o ano fiscal de 2008 e produtos com vendas acima de US$ 1.000.000
View_2 %>%
filter(AnoFiscal==2008 & Vendas>=1000000)
## # A tibble: 10 x 7
## # Groups: AnoFiscal, ChaveProduto [10]
## AnoFiscal ChaveProduto NomeProduto Custo Vendas Qtd `Num Ordens`
## <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <int>
## 1 2008 353 Mountain-200 Silve~ 1.08e6 1.18e6 853 219
## 2 2008 355 Mountain-200 Silve~ 9.19e5 1.01e6 726 207
## 3 2008 359 Mountain-200 Black~ 1.50e6 1.63e6 1197 327
## 4 2008 361 Mountain-200 Black~ 1.18e6 1.29e6 940 244
## 5 2008 561 Touring-1000 Yello~ 1.23e6 1.02e6 833 268
## 6 2008 564 Touring-1000 Yello~ 1.44e6 1.18e6 974 293
## 7 2008 573 Touring-1000 Blue,~ 1.22e6 1.16e6 825 265
## 8 2008 576 Touring-1000 Blue,~ 1.44e6 1.37e6 973 292
## 9 2008 580 Road-350-W Yellow,~ 1.33e6 1.24e6 1231 327
## 10 2008 583 Road-350-W Yellow,~ 1.50e6 1.38e6 1390 334
## Filtra apenas as observações que OU são do ano fiscal 2008, OU tem as vendas entre 100.000 e 1.000.000, não incluindo a intersecção entre os dois conjuntos de observações.
View_2 %>%
filter(xor(AnoFiscal==2008 , between(Vendas,100000,1000000)))
## # A tibble: 172 x 7
## # Groups: AnoFiscal, ChaveProduto [172]
## AnoFiscal ChaveProduto NomeProduto Custo Vendas Qtd `Num Ordens`
## <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <int>
## 1 2006 292 HL Mountain Frame - ~ 1.22e5 1.42e5 173 94
## 2 2006 296 HL Mountain Frame - ~ 1.09e5 1.27e5 177 98
## 3 2006 300 HL Mountain Frame - ~ 9.16e4 1.06e5 131 76
## 4 2006 307 HL Mountain Frame - ~ 1.13e5 1.31e5 181 102
## 5 2006 310 Road-150 Red, 62 5.73e5 5.67e5 264 134
## 6 2006 311 Road-150 Red, 44 3.39e5 3.35e5 156 77
## 7 2006 312 Road-150 Red, 48 3.39e5 3.35e5 156 72
## 8 2006 313 Road-150 Red, 52 3.39e5 3.35e5 156 76
## 9 2006 314 Road-150 Red, 56 8.01e5 7.92e5 369 180
## 10 2006 315 Road-450 Red, 58 5.15e5 5.08e5 582 226
## # ... with 162 more rows
Utilize o help(filter)
para veirifcar operadores úteis que podem ser utilizados em conjunto a função filter
. Por fim, a inclusão, modificação ou exclusão de colunas utilizando o dplyr
ocorre por meio da função mutate
. Vejamos um exemplo abaixo.
## Cria colunas contendo o lucro e margem de lucratividade por produto
View_3<- View_2 %>%
mutate("Lucro"=Vendas-Custo, "Margem"=(Vendas-Custo)/Custo)
Desafio: Juntando todos os conhecimentos
Como exercício final iremos unir todas as funções vistas anteriormente a fim de executar uma consulta que nos retorne as seguintes informações:
- Uma tabela com um ranking das categorias dos produtos com maior margem de lucro no ano de 2008.
TB_FR %>%
inner_join(TB_Data, by = c("OrderDateKey" = "DateKey")) %>%
inner_join(TB_Prod, by = c("ProductKey" = "ProductKey")) %>%
inner_join(TB_SubCat, by = c("ProductSubcategoryKey" = "ProductSubcategoryKey")) %>%
inner_join(TB_Cat, by = c("ProductCategoryKey" = "ProductCategoryKey")) %>%
select(c(FiscalYear, EnglishProductCategoryName, OrderQuantity), TotalProductCost:SalesAmount,
starts_with("SalesOrder")) %>%
rename(AnoFiscal=FiscalYear, Categoria=EnglishProductCategoryName, Qtd=OrderQuantity,
Custo=TotalProductCost, Vendas=SalesAmount) %>%
group_by(AnoFiscal, Categoria) %>%
summarise("Qtd"=sum(Qtd), "Custo"=sum(Custo),"Vendas"=sum(Vendas), "Num Pedidos"=n()) %>%
filter(AnoFiscal==2008) %>%
mutate("Lucro"=Vendas-Custo, "Margem"=(Vendas-Custo)/Custo,
"Rank"=min_rank(desc((Vendas-Custo)/Custo))) %>%
arrange(Rank)
## # A tibble: 4 x 9
## # Groups: AnoFiscal [1]
## AnoFiscal Categoria Qtd Custo Vendas `Num Pedidos` Lucro Margem Rank
## <dbl> <chr> <dbl> <dbl> <dbl> <int> <dbl> <dbl> <int>
## 1 2008 Accessori~ 16931 2.65e5 4.10e5 2930 1.45e5 0.544 1
## 2 2008 Clothing 35533 9.01e5 9.61e5 5894 6.00e4 0.0666 2
## 3 2008 Components 26965 5.65e6 6.00e6 10318 3.55e5 0.0628 3
## 4 2008 Bikes 34100 3.01e7 2.89e7 11584 -1.23e6 -0.0410 4
Cada etapa de manipulação é separada pelo operador %>% que facilita a depuração do código e cria uma lógica sequêncial de fácil entendimento.
Colunas dinâmicas (pivoting)
O uso de colunas dinâmicas é outra funcionalidade muito utilizada quando se deseja visualizar, por meio de uma tabela, um conjunto de dados em duas dimensões distintas. É possível utilizar as funções do tidyr
conhecidas como pivot_wider
e pivot_longer
. Enquanto a primeira realiza a operação de avaliar um dado em uma matriz dinâmica, fazendo com que os rótulos de várias linhas de observações se tornem diferentes colunas, a segunda realiza a operação inversa. Isto é, transforma colunas em várias linhas, rotulando as observações. Um exemplo pode descomplicar:
TB_VENDAS <- TB_FR %>%
inner_join(TB_Data, by = c("OrderDateKey" = "DateKey")) %>%
inner_join(TB_Prod, by = c("ProductKey" = "ProductKey")) %>%
inner_join(TB_SubCat, by = c("ProductSubcategoryKey" = "ProductSubcategoryKey")) %>%
inner_join(TB_Cat, by = c("ProductCategoryKey" = "ProductCategoryKey")) %>%
select(c(FiscalYear, EnglishProductCategoryName, SalesAmount)) %>%
rename(AnoFiscal=FiscalYear, Categoria=EnglishProductCategoryName, Vendas=SalesAmount)
TB_VENDAS
## # A tibble: 60,855 x 3
## AnoFiscal Categoria Vendas
## <dbl> <chr> <dbl>
## 1 2006 Bikes 2025.
## 2 2006 Bikes 6075.
## 3 2006 Bikes 2025.
## 4 2006 Bikes 2040.
## 5 2006 Bikes 2040.
## 6 2006 Bikes 4080.
## 7 2006 Bikes 2040.
## 8 2006 Clothing 86.5
## 9 2006 Clothing 28.8
## 10 2006 Clothing 34.2
## # ... with 60,845 more rows
A tabela acima possui o dado de Vendas (também chamado de fato) avaliado sobre as dimensões de tempo (AnoFiscal) e a dimensão Categoria do produto. Desejamos fazer com que os rótulos da coluna Categoria sejam transformados em várias colunas e, dessa forma, avaliar dinamicamente a métrica de vendas sobre a dimensão Categoria. Utilizando a pivot_wider
:
TB_VENDAS_PIVOT <- TB_VENDAS %>%
pivot_wider(names_from = Categoria, values_from = Vendas, values_fn = sum)
#names_from diz qual dimensão deve ser utilizada para criar as colunas dinâmicas
#values_from diz qual coluna contém a métrica (fato) a ser avaliado na matriz dinâmica
#values_fn diz qual a função deve ser utilizada para agregar os dados
TB_VENDAS_PIVOT
## # A tibble: 3 x 5
## AnoFiscal Bikes Clothing Accessories Components
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2006 15018534. 66328. 36815. 1166765.
## 2 2007 22417420. 750716. 124433. 4629101.
## 3 2008 28866428. 960797. 410050. 6003210.
Por fim, se desejássemos retornar ao estado anterior, poderíamos utilizar a pivot_longer
.
TB_VENDAS_UNPIVOT <- TB_VENDAS_PIVOT %>%
pivot_longer(cols=2:5, names_to = "Categoria", values_to = "Vendas")
#cols diz quais as colunas devem ser convertidas em rótulos de linha
#names_to diz qual o nome da nova coluna a ser criada com os rótulos
#values_to diz qual o nome da nova coluna a ser criada com os dados (fato)
TB_VENDAS_UNPIVOT
## # A tibble: 12 x 3
## AnoFiscal Categoria Vendas
## <dbl> <chr> <dbl>
## 1 2006 Bikes 15018534.
## 2 2006 Clothing 66328.
## 3 2006 Accessories 36815.
## 4 2006 Components 1166765.
## 5 2007 Bikes 22417420.
## 6 2007 Clothing 750716.
## 7 2007 Accessories 124433.
## 8 2007 Components 4629101.
## 9 2008 Bikes 28866428.
## 10 2008 Clothing 960797.
## 11 2008 Accessories 410050.
## 12 2008 Components 6003210.
A função pivot_longer
é extremamente útil para arrumar bancos de dados que já passaram por algum processo de análise (isto é, foram pivotados anteriormente). Muitos dados públicos estão disponíveis no formato pivot o que é mais ineficiente quando se deseja utilizar várias ferramentas de análise de dados.