knitr::opts_chunk$set(echo = TRUE, warning = F, message = F)
options(encoding = 'UTF-8')
O Ministério do Desenvolvimento, Indústria, Comércio e Serviços (MDIC) mantém um Observatório do Comércio Eletrônico Nacional.
O produto final consiste em um dashboard que compila as informações do comércio realizado por intermédio de plataformas digitais.
Conforme delimitado pelo projeto, tratam-se de transações de B2C (CNPJ para CPF) (empresa para cliente) obtidas via Notas Fiscais Eletrônicas (NFe)
O dashboard pode ser acessado em https://app.powerbi.com/view?r=eyJrIjoiOTdmOTE4MmUtMGM5OC00Yzk3LTljYTctN2I4YTEwODhlMDlkIiwidCI6IjNlYzkyOTY5LTVhNTEtNGYxOC04YWM5LWVmOThmYmFmYTk3OCJ9
As bases de dados, por sua vez, estão disponíveis em arquivos .xlsx na página https://www.gov.br/mdic/pt-br/assuntos/observatorio-do-comercio-eletronico/perguntas-frequentes
O objetivo dessa análise é o de apresentar os dados em formato de gráficos do tipo Sankey para que sirva como tutorial ou para referência de pesquisa posterior.
As tabelas mais recentes disponíveis são do ano de 2023. São duas bases em .xlsx A primeira até o capítulo 69 e outra dos capítulos 70 em diante.
library(readxl)
library(dplyr)
library(tidyverse)
library(networkD3) #sankey
library(htmltools) #titulos dos gráficos
library(scales) #para valores em reais
dados1 = read_excel("C:/Users/raphael.rsl/Desktop/R/ecommerce_mdic/2023atcaptulo69.xlsx")
dados2 = read_excel("C:/Users/raphael.rsl/Desktop/R/ecommerce_mdic/2023captulos70a97.xlsx")
colnames(dados1)
## [1] "Ano" "NCM" "Descricao"
## [4] "CFOP_1_Digito" "UF_Emitente" "UF_Destinatario"
## [7] "quant_comercial" "Valor_Total_Bruto"
colnames(dados2)
## [1] "Ano" "NCM" "Descricao"
## [4] "CFOP_1_Digito" "UF_Emitente" "UF_Destinatario"
## [7] "quant_comercial" "Valor_Total_Bruto"
#Considerando nomes de colunas iguais, basta fazer um mescla de adição de linhas em um mesmo dataset
dados = rbind (dados1, dados2)
rm(dados1, dados2)
colnames(dados)
## [1] "Ano" "NCM" "Descricao"
## [4] "CFOP_1_Digito" "UF_Emitente" "UF_Destinatario"
## [7] "quant_comercial" "Valor_Total_Bruto"
nrow(dados) #número de linhas
## [1] 874133
glimpse(dados)
## Rows: 874,133
## Columns: 8
## $ Ano <dbl> 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023…
## $ NCM <chr> "01011090", "01011090", "01011090", "01011100", "010…
## $ Descricao <chr> "Animais da espécie asinina/muar, reprodutores, raça…
## $ CFOP_1_Digito <dbl> 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5…
## $ UF_Emitente <chr> "GO", "GO", "GO", "GO", "BA", "DF", "ES", "GO", "MA"…
## $ UF_Destinatario <chr> "MT", "PA", "TO", "GO", "BA", "DF", "ES", "GO", "MA"…
## $ quant_comercial <dbl> 292.00, 13.00, 157.00, 11.00, 405.00, 3.00, 44.00, 8…
## $ Valor_Total_Bruto <dbl> 1999.99, 306.00, 3007.00, 272.80, 1241.20, 20200.00,…
summary(dados)
## Ano NCM Descricao CFOP_1_Digito
## Min. :2023 Length:874133 Length:874133 Min. :5.000
## 1st Qu.:2023 Class :character Class :character 1st Qu.:6.000
## Median :2023 Mode :character Mode :character Median :6.000
## Mean :2023 Mean :5.813
## 3rd Qu.:2023 3rd Qu.:6.000
## Max. :2023 Max. :6.000
## UF_Emitente UF_Destinatario quant_comercial Valor_Total_Bruto
## Length:874133 Length:874133 Min. : 0 Min. :0.000e+00
## Class :character Class :character 1st Qu.: 4 1st Qu.:3.240e+02
## Mode :character Mode :character Median : 25 Median :2.160e+03
## Mean : 4325 Mean :2.243e+05
## 3rd Qu.: 218 3rd Qu.:1.746e+04
## Max. :146123540 Max. :1.969e+09
São 8 colunas com as seguintes informações:
Vamos fazer alguns testes para comparar os resultados do dataframe importado e o dashboard
total_bruto_geral <- sum(dados$Valor_Total_Bruto, na.rm = TRUE)
valor_formatado <- format(total_bruto_geral, big.mark = ".", decimal.mark = ",", nsmall = 2)
valor_formatado <- paste0("R$ ", valor_formatado)
valor_formatado
## [1] "R$ 196.100.457.196,71"
#Há uma diferença de cerca de R$ 212 mil. Creio que tenha relação com o UF_Destinatario que contém uma entrada de EX. Vamos testar
total_bruto_geral2 <- dados %>%
filter(UF_Destinatario != "EX") %>%
summarise(Valor = sum(Valor_Total_Bruto, na.rm = TRUE)) %>%
mutate(Valor_Formatado = paste0("R$ ",
format(Valor, big.mark = ".", decimal.mark = ",", nsmall = 2)))
total_bruto_geral2
## # A tibble: 1 × 2
## Valor Valor_Formatado
## <dbl> <chr>
## 1 196100437409. R$ 196.100.437.408,74
#O valor veio próximo. Tendo em vista o valor baixo na comparação, podemos seguir.
#O valor veio exato ao somatório do arquivo em excel, mas um pouco diferente do valor do dashboard.
#A diferença é de cerca de 212 mil a menos no dashboard
Vamos fazer a checagem por UF
total_bruto_por_uf <- dados %>%
group_by(UF_Emitente) %>%
summarise(Valor_Total = sum(Valor_Total_Bruto, na.rm = TRUE)) %>%
arrange(desc(Valor_Total)) %>%
mutate(Valor_Formatado = paste0(
"R$ ",
format(Valor_Total, big.mark = ".", decimal.mark = ",", nsmall = 2)
))
total_bruto_por_uf
## # A tibble: 27 × 3
## UF_Emitente Valor_Total Valor_Formatado
## <chr> <dbl> <chr>
## 1 SP 95097186015. R$ 95.097.186.015,29
## 2 MG 24177864893. R$ 24.177.864.892,84
## 3 ES 14197989847. R$ 14.197.989.847,46
## 4 SC 13181370126. R$ 13.181.370.125,65
## 5 PR 10735256562. R$ 10.735.256.562,09
## 6 RJ 10661383456. R$ 10.661.383.455,77
## 7 RS 5894393942. R$ 5.894.393.942,35
## 8 PE 4551112546. R$ 4.551.112.546,32
## 9 PB 3068661436. R$ 3.068.661.435,53
## 10 GO 2670341534. R$ 2.670.341.533,93
## # ℹ 17 more rows
total_bruto_por_uf_dest <- dados %>%
group_by(UF_Destinatario) %>%
summarise(Valor_Total = sum(Valor_Total_Bruto, na.rm = TRUE)) %>%
arrange(desc(Valor_Total)) %>%
mutate(Valor_Formatado = paste0(
"R$ ",
format(Valor_Total, big.mark = ".", decimal.mark = ",", nsmall = 2)
))
total_bruto_por_uf_dest
## # A tibble: 28 × 3
## UF_Destinatario Valor_Total Valor_Formatado
## <chr> <dbl> <chr>
## 1 SP 64102683504 R$ 6,410268e+10
## 2 MG 22088791421. R$ 2,208879e+10
## 3 RJ 19047881882. R$ 1,904788e+10
## 4 PR 11879685840. R$ 1,187969e+10
## 5 RS 11530569563. R$ 1,153057e+10
## 6 SC 9527098516. R$ 9,527099e+09
## 7 BA 9178477020. R$ 9,178477e+09
## 8 GO 5990127840. R$ 5,990128e+09
## 9 PE 5668294099. R$ 5,668294e+09
## 10 CE 4493116598. R$ 4,493117e+09
## # ℹ 18 more rows
#As diferenças existem, mas não são significativas. Podemos seguir.
No primeiro momento, vamos olhar para os dados de Valor Bruto transacionados
fluxo <- dados %>%
group_by(UF_Emitente, UF_Destinatario) %>%
summarise(Valor = sum(Valor_Total_Bruto, na.rm = TRUE)) %>%
ungroup()
glimpse(fluxo)
## Rows: 732
## Columns: 3
## $ UF_Emitente <chr> "AC", "AC", "AC", "AC", "AC", "AC", "AC", "AC", "AC", …
## $ UF_Destinatario <chr> "AC", "AL", "AM", "AP", "BA", "CE", "DF", "ES", "GO", …
## $ Valor <dbl> 13558716.53, 3826.55, 125296.11, 219.03, 1629.80, 8101…
nodes <- data.frame(name = unique(c(fluxo$UF_Emitente, fluxo$UF_Destinatario)))
fluxo$source <- match(fluxo$UF_Emitente, nodes$name) - 1 # -1 pq networkD3 usa index começando do zero
fluxo$target <- match(fluxo$UF_Destinatario, nodes$name) - 1
sankeyNetwork(Links = fluxo,
Nodes = nodes,
Source = "source",
Target = "target",
Value = "Valor",
NodeID = "name",
fontSize = 12,
nodeWidth = 30)
A visualização fica prejudicada sem uma ordenação mais restrita dos nós, especialmente por conta do fluxo a partir de SP
Uma solução é fazer uma coluna de saída e outra de chegada, ou seja, duas colunas fixas.
unique(fluxo$UF_Destinatario)
## [1] "AC" "AL" "AM" "AP" "BA" "CE" "DF" "ES" "GO" "MA" "MG" "MS" "MT" "PA" "PB"
## [16] "PE" "PI" "PR" "RJ" "RN" "RO" "RR" "RS" "SC" "SE" "SP" "TO" "EX"
unique(fluxo$UF_Emitente)
## [1] "AC" "AL" "AM" "AP" "BA" "CE" "DF" "ES" "GO" "MA" "MG" "MS" "MT" "PA" "PB"
## [16] "PE" "PI" "PR" "RJ" "RN" "RO" "RR" "RS" "SC" "SE" "SP" "TO"
# Em UF_Destinatário há um indicador de EX (indicando exterior). Vamos retirar.
fluxo2 <- dados %>%
filter(UF_Destinatario != "EX") %>%
group_by(UF_Emitente, UF_Destinatario) %>%
summarise(Valor = sum(Valor_Total_Bruto, na.rm = TRUE)) %>%
ungroup()
# criando os indicadores de emitente e destinatário
nodes2 <- data.frame(name = c(paste0("E: ", unique(fluxo2$UF_Emitente)),
paste0("D: ", unique(fluxo2$UF_Destinatario))))
fluxo2$source <- match(paste0("E: ", fluxo2$UF_Emitente), nodes2$name) - 1
fluxo2$target <- match(paste0("D: ", fluxo2$UF_Destinatario), nodes2$name) - 1
sankey_2col <- sankeyNetwork(Links = fluxo2,
Nodes = nodes2,
Source = "source",
Target = "target",
Value = "Valor",
NodeID = "name",
fontSize = 12,
nodeWidth = 30,
height = 800,
width = "100%")
#Para adicionar título em gráfico sankey é necessário tratar direto no HTML com o pacote htmltools
browsable(tagList(tags$h2("Fluxos de valor transacionado por e-commerce",
style = "text-align:center; font-family:Arial; font-size:20px"),
tags$h4("por UFs - Unidades da Federação",
style = "text-align:center; font-family:Arial; font-size:14px; font-weight:normal;
color:gray;"),
sankey_2col,
tags$p("Fonte: MDIC",
style = "text-align:left; font-style:italic; font-size:12px; font-family:Arial;")))
Fonte: MDIC
# descrescente por emitente
rank_emitente <- fluxo2 %>%
group_by(UF_Emitente) %>%
summarise(Total = sum(Valor)) %>%
arrange(desc(Total)) %>%
mutate(name = paste0("E: ", UF_Emitente))
destinatarios <- fluxo2 %>%
distinct(UF_Destinatario) %>%
mutate(name = paste0("D: ", UF_Destinatario))
nodes3 <- bind_rows(rank_emitente %>% select(name),
destinatarios %>% select(name)) %>%
distinct() %>%
mutate(group = "neutro")
fluxo3 <- fluxo2 %>%
mutate(source = match(paste0("E: ", UF_Emitente), nodes3$name) - 1,
target = match(paste0("D: ", UF_Destinatario), nodes3$name) - 1,
group = UF_Emitente)
sankey_2col_desc <- sankeyNetwork(Links = fluxo3,
Nodes = nodes3,
Source = "source",
Target = "target",
Value = "Valor",
NodeID = "name",
fontSize = 12,
nodeWidth = 30,
LinkGroup = "group",
NodeGroup = "group",
height = 800,
width = "100%")
browsable(tagList(tags$h2("Fluxos de valor transacionado por e-commerce",
style = "text-align:center; font-family:Arial; font-size:20px"),
tags$h4("por UFs - Unidades da Federação - Decrescente",
style = "text-align:center; font-family:Arial; font-size:14px; font-weight:normal;
color:gray;"),
sankey_2col_desc,
tags$p("Fonte: MDIC",
style = "text-align:left; font-size:12px; font-family:Arial;")))
Fonte: MDIC
Nem sempre a visualização decrescente funciona, pois o pacote networdD3 prioriza as sobreposições. Ou seja, busca minimizar o número de sobreposições.
Tendo em vista que a visualização não fica tão interessante, vamos fazer por regiões político-administrativas
Uma primeira opção é a de fazer um filtro para as 3 UFs com maior valor transacionado. Desse modo a quantidade máxima de nós diminuirá de 729 para 81.
Vamos seguir com a primeira opção de verificar os 3 maiores destinos por UF emitente, reduzindo a quantidade de nós para 81.
fluxo_top3 <- dados %>%
filter(UF_Destinatario != "EX") %>%
group_by(UF_Emitente, UF_Destinatario) %>%
summarise(Valor = sum(Valor_Total_Bruto, na.rm = TRUE), .groups = "drop") %>%
group_by(UF_Emitente) %>%
slice_max(order_by = Valor, n = 3, with_ties = FALSE) %>%
ungroup()
nodes_top3 <- data.frame(name = c(paste0("E: ", unique(fluxo_top3$UF_Emitente)),
paste0("D: ", unique(fluxo_top3$UF_Destinatario)))) %>%
distinct() %>%
mutate(group = "neutro")
fluxo_top3 <- fluxo_top3 %>%
mutate(source = match(paste0("E: ", UF_Emitente), nodes_top3$name) - 1,
target = match(paste0("D: ", UF_Destinatario), nodes_top3$name) - 1,
group = UF_Emitente)
# 4. Gráfico Sankey
sankey_top3 <- sankeyNetwork(Links = fluxo_top3,
Nodes = nodes_top3,
Source = "source",
Target = "target",
Value = "Valor",
NodeID = "name",
fontSize = 13,
nodeWidth = 30,
LinkGroup = "group",
NodeGroup = "group",
height = 800,
width = "100%")
browsable(tagList(tags$h2("Fluxos de valor transacionado por e-commerce",
style = "text-align:center; font-family:Arial; font-size:20px"),
tags$h4("3 maiores destinos de cada UF",
style = "text-align:center; font-family:Arial; font-size:14px; font-weight:normal;
color:gray;"),
sankey_top3,
tags$p("Fonte: MDIC",
style = "text-align:left; font-size:12px; font-family:Arial;")))
Fonte: MDIC
#Tabela
library(reactable)
reactable(fluxo_top3 %>%
select(UF_Emitente, UF_Destinatario, Valor) %>%
arrange(desc(Valor)),
columns = list(
UF_Destinatario = colDef(name = "UF Emitente"),
UF_Destinatario = colDef(name = "UF Destinatária"),
Valor = colDef(
name = "Valor Transacionado (R$)",
format = colFormat(prefix = "R$ ", separators = TRUE, digits = 0))),
defaultPageSize = 25,
bordered = TRUE,
highlight = TRUE,
striped = TRUE,
theme = reactableTheme(
headerStyle = list(backgroundColor = "#f7f7f8", fontWeight = "bold"),
rowSelectedStyle = list(backgroundColor = "#e6f2ff")),
searchable = TRUE,
sortable = TRUE,
filterable = TRUE)
Conforme é possível visualizar do gráfico, os três princiais destinos de produtos emitidos por São Paulo são: o próprio estado de São Paulo, Rio de Janeiro e Minas Gerais.
Minas Gerais, por sua vez, transaciona com o próprio estado, São Paulo e Rio de Janeiro.
E o Rio de Janeiro fecha a mesma tríade com si mesmo, Minas Gerais e São Paulo.
Para o gráfico há uma distorção por conta dos dados de SP. Talvez seja interessante gerar novamente o mesmo gráfico, agora retirando SP.
fluxo_top3_semSP <- dados %>%
filter(UF_Destinatario != "EX",
UF_Emitente != "SP",) %>%
group_by(UF_Emitente, UF_Destinatario) %>%
summarise(Valor = sum(Valor_Total_Bruto, na.rm = TRUE), .groups = "drop") %>%
group_by(UF_Emitente) %>%
slice_max(order_by = Valor, n = 3, with_ties = FALSE) %>% # top‑3 por emitente
ungroup()
nodes_top3_semSP <- data.frame(name = c(paste0("E: ", unique(fluxo_top3_semSP$UF_Emitente)),
paste0("D: ", unique(fluxo_top3_semSP$UF_Destinatario)))) %>%
distinct() %>%
mutate(group = "neutro")
fluxo_top3_semSP <- fluxo_top3_semSP %>%
mutate(source = match(paste0("E: ", UF_Emitente), nodes_top3_semSP$name) - 1,
target = match(paste0("D: ", UF_Destinatario), nodes_top3_semSP$name) - 1,
group = UF_Emitente)
sankey_top3_semSP <- sankeyNetwork(Links = fluxo_top3_semSP,
Nodes = nodes_top3_semSP,
Source = "source",
Target = "target",
Value = "Valor",
NodeID = "name",
LinkGroup = "group", # cores nos fluxos
NodeGroup = "group", # nós neutros (todos "neutro")
fontSize = 12,
nodeWidth = 30,
height = 800,
width = "100%")
browsable(tagList(tags$h2("Fluxos de valor transacionado por e-commerce",
style = "text-align:center; font-family:Arial; font-size:20px"),
tags$h4("3 maiores destinos de cada UF - Sem SP",
style = "text-align:center; font-family:Arial; font-size:14px; font-weight:normal;
color:gray;"),
sankey_top3_semSP,
tags$p("Fonte: MDIC",
style = "text-align:left; font-size:12px; font-family:Arial;")))
Fonte: MDIC
Uma segunda opção, para melhorar a visualização, é a divisão por paineis a partir das regiões
uf_regiao <- data.frame(UF_Emitente = c("AC","AL","AM","AP","BA","CE","DF","ES","GO","MA","MG",
"MS","MT","PA","PB","PE","PI","PR","RJ","RN","RO","RR",
"RS","SC","SE","SP","TO"),
Regiao = c("Norte","Nordeste","Norte","Norte","Nordeste","Nordeste",
"Centro-Oeste","Sudeste","Centro-Oeste","Nordeste","Sudeste",
"Centro-Oeste","Centro-Oeste","Norte","Nordeste","Nordeste",
"Nordeste","Sul","Sudeste","Nordeste","Norte","Norte",
"Sul","Sul","Nordeste","Sudeste","Norte"))
dados_regiao <- dados %>%
filter(UF_Destinatario != "EX") %>%
left_join(uf_regiao, by = "UF_Emitente")
# Top 3 fluxos por UF (por região)
fluxo_top3_regiao <- dados_regiao %>%
group_by(Regiao, UF_Emitente, UF_Destinatario) %>%
summarise(Valor = sum(Valor_Total_Bruto, na.rm = TRUE), .groups = "drop") %>%
group_by(Regiao, UF_Emitente) %>%
slice_max(Valor, n = 3, with_ties = FALSE) %>%
ungroup()
#Função para gerar sankey
gerar_sankey_por_regiao <- function(regiao_nome) {
fluxo_reg <- fluxo_top3_regiao %>% filter(Regiao == regiao_nome)
nodes <- data.frame(
name = c(paste0("E: ", unique(fluxo_reg$UF_Emitente)),
paste0("D: ", unique(fluxo_reg$UF_Destinatario)))) %>%
distinct() %>%
mutate(group = "neutro")
fluxo <- fluxo_reg %>%
mutate(source = match(paste0("E: ", UF_Emitente), nodes$name) - 1,
target = match(paste0("D: ", UF_Destinatario), nodes$name) - 1,
group = UF_Emitente)
sankey_regiao_UF <- sankeyNetwork(Links = fluxo,
Nodes = nodes,
Source = "source",
Target = "target",
Value = "Valor",
NodeID = "name",
LinkGroup = "group",
NodeGroup = "group",
fontSize = 12,
nodeWidth = 15,
height = 800,
width = "100%")
tagList(tags$h3(paste0("Fluxos de valor transacionado por e-commerce - Região: ", regiao_nome),
style = "text-align:center; font-family:Arial; margin-bottom:5px;"),
tags$h4("3 maiores destinos de cada UF",
style = "text-align:center; font-family:Arial; font-size:14px; font-weight:normal;
color:gray;"),
sankey_regiao_UF,
tags$p("Fonte: MDIC",
style = "text-align:left; font-size:12px; font-family:Arial; margin-bottom:40px;"))
}
gerar_sankey_por_regiao("Norte")
Fonte: MDIC
gerar_sankey_por_regiao("Nordeste")
Fonte: MDIC
gerar_sankey_por_regiao("Centro-Oeste")
Fonte: MDIC
gerar_sankey_por_regiao("Sudeste")
Fonte: MDIC
gerar_sankey_por_regiao("Sul")
Fonte: MDIC
regioes <- c(AC = "Norte", AL = "Nordeste", AM = "Norte", AP = "Norte", BA = "Nordeste",
CE = "Nordeste", DF = "Centro-Oeste", ES = "Sudeste", GO = "Centro-Oeste",
MA = "Nordeste", MG = "Sudeste", MS = "Centro-Oeste", MT = "Centro-Oeste",
PA = "Norte", PB = "Nordeste", PE = "Nordeste", PI = "Nordeste", PR = "Sul",
RJ = "Sudeste", RN = "Nordeste", RO = "Norte", RR = "Norte", RS = "Sul",
SC = "Sul", SE = "Nordeste", SP = "Sudeste", TO = "Norte")
# Agregando por região
fluxo_regiao <- dados %>%
filter(UF_Destinatario != "EX") %>%
mutate(Regiao_Emitente = recode(UF_Emitente, !!!regioes), #!!! descompactação do list. Por isso não foi usado uf_região. Para testar a função.
Regiao_Destinatario = recode(UF_Destinatario, !!!regioes)) %>%
group_by(Regiao_Emitente, Regiao_Destinatario) %>%
summarise(Valor = sum(Valor_Total_Bruto, na.rm = TRUE), .groups = "drop")
regioes_ordenadas <- fluxo_regiao %>%
group_by(Regiao_Emitente) %>%
summarise(Total = sum(Valor)) %>%
arrange(desc(Total)) %>%
mutate(name = paste0("E: ", Regiao_Emitente))
destinos_regiao <- fluxo_regiao %>%
distinct(Regiao_Destinatario) %>%
mutate(name = paste0("D: ", Regiao_Destinatario))
nodes_regiao <- bind_rows(regioes_ordenadas %>% select(name),
destinos_regiao %>% select(name)) %>%
distinct() %>%
mutate(group = "neutro")
fluxo_regiao <- fluxo_regiao %>%
mutate(source = match(paste0("E: ", Regiao_Emitente), nodes_regiao$name) - 1,
target = match(paste0("D: ", Regiao_Destinatario), nodes_regiao$name) - 1,
group = Regiao_Emitente)
glimpse(fluxo_regiao)
## Rows: 25
## Columns: 6
## $ Regiao_Emitente <chr> "Centro-Oeste", "Centro-Oeste", "Centro-Oeste", "C…
## $ Regiao_Destinatario <chr> "Centro-Oeste", "Nordeste", "Norte", "Sudeste", "S…
## $ Valor <dbl> 4181133880, 310941085, 177111610, 932794741, 27445…
## $ source <dbl> 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 0, 0,…
## $ target <dbl> 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 5, 6,…
## $ group <chr> "Centro-Oeste", "Centro-Oeste", "Centro-Oeste", "C…
sankey_regiao <- sankeyNetwork(Links = fluxo_regiao,
Nodes = nodes_regiao,
Source = "source",
Target = "target",
Value = "Valor",
NodeID = "name",
fontSize = 12,
fontFamily = "Arial",
nodeWidth = 10,
NodeGroup = "group",
LinkGroup = "group",
colourScale = JS("d3.scaleOrdinal()
.domain(['Norte', 'Nordeste', 'Centro-Oeste', 'Sudeste', 'Sul'])
.range(['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd'])"))
browsable(tagList(tags$h2("Fluxos de valor transacionado por e-commerce",
style = "text-align:center; font-family:Arial; font-size:20px"),
tags$h4("Agregador por Regiões",
style = "text-align:center; font-family:Arial; font-size:14px; font-weight:normal;
color:gray;"),
sankey_regiao,
tags$p("Fonte: MDIC",
style = "text-align:left; font-size:12px; font-family:Arial;")))
Fonte: MDIC
Inserir uma tabela
library(reactable)
library(scales)
reactable(fluxo_regiao %>%
select(Regiao_Emitente, Regiao_Destinatario, Valor) %>%
arrange(desc(Valor)),
columns = list(Regiao_Emitente = colDef(name = "Região Emitente"),
Regiao_Destinatario = colDef(name = "Região Destinatária"),
Valor = colDef(name = "Valor Transacionado (R$)",
format = colFormat(prefix = "R$ ", separators = TRUE, digits = 0))),
defaultPageSize = 25,
bordered = TRUE,
highlight = TRUE,
striped = TRUE,
theme = reactableTheme(headerStyle = list(backgroundColor = "#f7f7f8", fontWeight = "bold"),
rowSelectedStyle = list(backgroundColor = "#e6f2ff")),
searchable = TRUE,
sortable = TRUE,
filterable = TRUE)
Um potencial indicador acerca das movimentações a partir do e-commerce pode ser realizada na razão entre valores transacionados de maneira intra e interestadual
Antes, vamos verificar os valores separados por interestadual e dentro do estado na comparação com o dashboard
resumo_geral <- dados %>%
filter(UF_Destinatario != "EX") %>%
mutate(Tipo_Venda = ifelse(CFOP_1_Digito == 5, "Dentro do Estado",
ifelse(CFOP_1_Digito == 6, "Interestadual", "NA"))) %>%
group_by(Tipo_Venda) %>%
summarise(Valor_Total = sum(Valor_Total_Bruto, na.rm = TRUE)) %>%
arrange(desc(Valor_Total))
resumo_geral
## # A tibble: 2 × 2
## Tipo_Venda Valor_Total
## <chr> <dbl>
## 1 Interestadual 121497653560.
## 2 Dentro do Estado 74602783849.
resumo_por_uf <- dados %>%
filter(CFOP_1_Digito %in% c(5, 6)) %>%
mutate(Tipo_Venda = ifelse(CFOP_1_Digito == 5, "Dentro", "Fora")) %>%
group_by(UF_Emitente, Tipo_Venda) %>%
summarise(Valor = sum(Valor_Total_Bruto, na.rm = TRUE), .groups = "drop") %>%
tidyr::pivot_wider(names_from = Tipo_Venda, values_from = Valor, values_fill = 0) %>%
mutate(Razao_Fora_Dentro = ifelse(Dentro == 0, NA, Fora / Dentro),
Dentro_formatado = paste0("R$ ", format(Dentro, big.mark = ".", decimal.mark = ",", nsmall = 2, scientific = FALSE)),
Fora_formatado = paste0("R$ ", format(Fora, big.mark = ".", decimal.mark = ",", nsmall = 2, scientific = FALSE)),
Razao_formatado = format(Razao_Fora_Dentro, big.mark = ".", decimal.mark = ",", nsmall = 2)) %>%
mutate(Razao_num = Razao_Fora_Dentro) %>% # manter para ordenação
select(UF_Emitente, Dentro = Dentro_formatado, Fora = Fora_formatado, Razao = Razao_formatado, Razao_num) %>%
arrange(desc(Razao_num))
reactable(
resumo_por_uf,
columns = list(UF_Emitente = colDef(name = "UF"),
Dentro = colDef(name = "Venda Dentro do Estado"),
Fora = colDef(name = "Venda Fora do Estado"),
Razao = colDef(name = "Razão (Fora / Dentro)", sortNALast = TRUE, align = "right"),
Razao_num = colDef(show = FALSE) # Oculta a coluna usada para ordenação
),
defaultSorted = "Razao_num", # Usa a coluna numérica oculta para ordenar
defaultSortOrder = "asc",
striped = TRUE,
highlight = TRUE,
defaultPageSize = 10)
A partir desse índice é possível observar que as UFs que menos comercializam para fora do estado, proporcionalmente aos valores internos, são Roraima, Rondônia e Amapá. Essa proporção pode apontar para desafios de logística, do tipo de produto transacionado, dentre outros possíveis aspectos.
Por outro lado, as UFs que mais mandam para fora do Estado são, respectivamente, o Espírito Santo, o Amazonas e Santa Catarina.
Isso nos leva a explorar os dados agora para verificar os produtos transacionados