Bases de dados:
Tabela com os PIBs (Produto Interno Bruto) dos estados brasileiros no período de 2002 - 2020
Tabela com a pontuação do IDEB (Índice de Desenvolvimento da Educação Básica) das escolas à nivel nacional
A cada aula, vamos passar por uma base de dados e tecer nossas análises de acordo com as perguntas que forem apresentadas buscando respondê-las por meio da utilização de recursos visuais (gráficos e elementos visuais).
# Definindo a paleta de cores
AZUL1, AZUL2, AZUL3, AZUL4, AZUL5, AZUL6 = '#174A7E', '#4A81BF', "#6495ED", '#2596BE', '#94AFC5', '#CDDBF3'
CINZA1, CINZA2, CINZA3, CINZA4, CINZA5, BRANCO = '#231F20', '#414040', '#555655', '#A6A6A5', '#BFBEBE', '#FFFFFF'
VERMELHO1, VERMELHO2, LARANJA1 = '#C3514E', '#E6BAB7', '#F79747'
VERDE1, VERDE2, VERDE3 = '#0C8040', '#9ABB59', '#9ECCB3'
Você como cientista de dados recebeu um conjunto de dados para analisar a composição do PIB em relação aos estados do Brasil durante o período de 2002-2020. Os dados descrevem os valores do PIB e os valores agregados a ele anualmente por setores como agropecuária, indústria, serviços e outros.
Aqui, vamos focar em investigar a composição dos dados em relação aos estados e regiões e tecer alguns comentários a respeito das perguntas levantadas.
import pandas as pd
# Importando a base de dados com o PIB dos estados brasileiros de 2002 a 2020
df_pib = pd.read_csv("https://raw.githubusercontent.com/afonsosr2/dataviz-graficos-composicao-relacionamento/master/dados/pib_br_2002_2020_estados.csv")
df_pib
| ano | sigla_uf | regiao | pib | impostos_liquidos | va | va_agropecuaria | va_industria | va_servicos | va_adespss | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2002 | RO | Norte | 7467629886 | 839731192 | 6627898698 | 715526872 | 1191090432 | 2484579193 | 2236702207 |
| 1 | 2003 | RO | Norte | 9425010486 | 1108434936 | 8316575548 | 1278658831 | 1216605061 | 3376727040 | 2444584625 |
| 2 | 2004 | RO | Norte | 11004641436 | 1288806654 | 9715834778 | 1288515348 | 1674933817 | 3986529419 | 2765856199 |
| 3 | 2005 | RO | Norte | 12511821181 | 1476144194 | 11035676990 | 1342222120 | 1887932121 | 4603783904 | 3201738843 |
| 4 | 2006 | RO | Norte | 13054713344 | 1613809974 | 11440903374 | 1238006193 | 2210692147 | 4320526746 | 3671678293 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 508 | 2016 | DF | Centro-Oeste | 235540044811 | 29145619376 | 206394425435 | 820754661 | 9662357225 | 103859865830 | 92051447720 |
| 509 | 2017 | DF | Centro-Oeste | 244722249337 | 29120461647 | 215601787690 | 828313642 | 8448768236 | 108322119432 | 98002586380 |
| 510 | 2018 | DF | Centro-Oeste | 254817204692 | 28692287369 | 226124917323 | 1022690641 | 9541298290 | 113768086938 | 101792841454 |
| 511 | 2019 | DF | Centro-Oeste | 273613711477 | 30686607647 | 242927103829 | 992393584 | 9453608031 | 125261853488 | 107219248727 |
| 512 | 2020 | DF | Centro-Oeste | 265847334003 | 25466227775 | 240381106228 | 1623976909 | 10942472569 | 116547655370 | 111267001381 |
513 rows × 10 columns
# Verificando os tipos de dados e se existem dados nulos
df_pib.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 513 entries, 0 to 512 Data columns (total 10 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 ano 513 non-null int64 1 sigla_uf 513 non-null object 2 regiao 513 non-null object 3 pib 513 non-null int64 4 impostos_liquidos 513 non-null int64 5 va 513 non-null int64 6 va_agropecuaria 513 non-null int64 7 va_industria 513 non-null int64 8 va_servicos 513 non-null int64 9 va_adespss 513 non-null int64 dtypes: int64(8), object(2) memory usage: 40.2+ KB
# Criando um df com os dados desejados
df_pib_2002 = df_pib.query("ano == 2002")[["regiao","pib"]]
df_pib_2020 = df_pib.query("ano == 2020")[["regiao","pib"]]
df_pib_2002 = df_pib_2002.groupby("regiao").sum().sort_values("pib", ascending=False)
df_pib_2020 = df_pib_2020.groupby("regiao").sum().sort_values("pib", ascending=False)
display(df_pib_2002, df_pib_2020)
| pib | |
|---|---|
| regiao | |
| Sudeste | 854309793369 |
| Sul | 241564819092 |
| Nordeste | 194847656440 |
| Centro-Oeste | 128162640832 |
| Norte | 69902366306 |
| pib | |
|---|---|
| regiao | |
| Sudeste | 3952694729239 |
| Sul | 1308147455374 |
| Nordeste | 1079331030689 |
| Centro-Oeste | 791250735824 |
| Norte | 478173048893 |
## Configurando o gráfico com parâmetros que potencializam a visualização dos dados
# Importando as bibliotecas
import matplotlib.pyplot as plt
# Área do gráfico e tema da visualização
fig, axs = plt.subplots(1, 2, figsize=(14,6))
# Definindo as cores do gráfico
cores = [AZUL3, LARANJA1, AZUL5 , VERDE1, CINZA5]
# Personalizando o gráfico
plt.suptitle('Produto Interno Bruto (PIB) por região', fontsize=18, color=CINZA1, ha = 'right', x = 0.5, y = 1.05)
# GRÁFICO 1 - PIB de 2002 por região
ptc, text, _ = axs[0].pie(data = df_pib_2002, x = "pib", labels = df_pib_2002.index, autopct="%.1f%%",
pctdistance=0.6, textprops={"size": 12, "fontweight":"bold", "color": BRANCO},
colors = cores)
# Título do Gráfico 1
axs[0].annotate("Em 2002", xy=(50, 350), size =12, xycoords='axes points',
bbox=dict(boxstyle="round", fc=BRANCO, ec=CINZA3))
# Ajustando as cores das regiões relativas as fatias
for i, p in enumerate(ptc):
text[i].set_color(p.get_facecolor())
#######################################
# GRÁFICO 2 - PIB de 2020 por região
ptc, text, _ = axs[1].pie(data = df_pib_2020, x = "pib", labels = df_pib_2020.index, autopct="%.1f%%",
pctdistance=0.6, textprops={"size": 12, "fontweight":"bold", "color": BRANCO},
colors = cores)
# Título do Gráfico 2
axs[1].annotate("Em 2020", xy=(50, 350), size =12, xycoords='axes points',
bbox=dict(boxstyle="round", fc=BRANCO, ec=CINZA3))
# Ajustando as cores das regiões relativas as fatias
for i, p in enumerate(ptc):
text[i].set_color(p.get_facecolor())
#######################################
axs[0].annotate('A Região Sudeste foi a única que\nreduziu a participação no PIB',
xy=(180, 245), xycoords='axes points', xytext=(280, 295), textcoords='axes points',
bbox=dict(boxstyle="round", fc=BRANCO, ec=CINZA3),
size=10, arrowprops=dict(arrowstyle="->", fc=CINZA1, connectionstyle="arc,angleA=-90,angleB=0,armA=30,armB=30,rad=5"))
axs[1].annotate('\n\n', xy=(140, 245), xycoords='axes points', xytext=(-50, 295), textcoords='axes points',
size=10, arrowprops=dict(arrowstyle="->", fc=CINZA1, connectionstyle="arc,angleA=-90,angleB=0,armA=30,armB=-30,rad=5"))
plt.show()
Conclusões:
Aqui notamos um uso correto de gráfico de pizza que trouxemos 5 fatias no total. Tecemos uma comparação entre dois períodos separadamente, visto que o gráfico de pizza representa composições estáticas.
Podemos notar que apenas a região Sudeste recuou em participação no PIB no período que abrange 18 anos (2002 - 2020). Ou seja, foi possível notar que o PIB foi mais distribuído. Podemos perceber esse comportamento sem nem precisar analisar os dados absolutos, apenas os relativos.
Como sugestão, podemos testar adicionando os valores absolutos do PIB das regiões ou fazer essa análise em uma região em específico como por exemplo, a região Sul do Brasil (3 estados apenas).
# Criando um df com os dados desejados
df_mg_2020 = df_pib.query("ano == 2020")[["sigla_uf", "pib"]]
# Renomeando todos os estados como 'Outros' e mudando da sigla MG para Minas Gerais
df_mg_2020.loc[df_mg_2020["sigla_uf"] == "MG", "sigla_uf"] = "Minas Gerais"
df_mg_2020.loc[df_mg_2020["sigla_uf"] != "Minas Gerais", "sigla_uf"] = "Outros"
df_mg_2020 = df_mg_2020.groupby("sigla_uf").sum()
df_mg_2020
| pib | |
|---|---|
| sigla_uf | |
| Minas Gerais | 682786116407 |
| Outros | 6926810883612 |
## Configurando o gráfico com parâmetros que potencializam a visualização dos dados
# Importando as bibliotecas
import matplotlib.pyplot as plt
# Área do gráfico e tema da visualização
fig, ax = plt.subplots(figsize=(6,6))
# Definindo as cores do gráfico
cores = [AZUL3, CINZA5]
# Personalizando o gráfico
plt.suptitle('PIB de Minas Gerais em relação ao Brasil em 2020', fontsize=18, color=CINZA1, ha = 'left', x = 0, y = 0.9)
# Gerando o gráfico do PIB de 2020 de Minas Gerais em relação a todo Brasil
ptc, text, _ = ax.pie(data = df_mg_2020, x="pib", labels=df_mg_2020.index, autopct = "%.1f%%",
startangle = 0, pctdistance = 0.8, wedgeprops=dict(width=0.4),
textprops=dict(size=12, fontweight="bold", color= BRANCO),
colors = cores)
# Ajustando as cores das regiões relativas as fatias
for i, p in enumerate(ptc):
text[i].set_color(p.get_facecolor())
plt.show()
Conclusões:
O gráfico de rosca apresenta a melhor forma de utilizarmos os gráficos de pizza e rosca numa visualização: comparando dados binários ou dicotômicos. Aqui, fizemos a comparação do PIB de Minas Gerais em relação a todo o Brasil no ano de 2020.
Como sugestão, podemos analisar o seu próprio estado ou aquele que tenha interesse em comparar com o Brasil inteiro ou até uma região pelo todo em um dado ano.
bahia = df_pib.query("sigla_uf == 'BA' and ano == 2020")[["pib","impostos_liquidos", "va"]]
bahia.rename(columns = {"pib":"PIB", "impostos_liquidos": "Impostos Líquidos", "va":"Valor Adicionado Bruto"}, inplace=True)
bahia
| PIB | Impostos Líquidos | Valor Adicionado Bruto | |
|---|---|---|---|
| 303 | 305320812691 | 37094030606 | 268226782074 |
# Criando um df com os dados desejados
bahia = bahia.melt(var_name = "Indicadores", value_name = "Valores")
bahia
| Indicadores | Valores | |
|---|---|---|
| 0 | PIB | 305320812691 |
| 1 | Impostos Líquidos | 37094030606 |
| 2 | Valor Adicionado Bruto | 268226782074 |
# Alterando os impostos para descréscimo, criando uma coluna com os valores em string e outra com as medidas
bahia.loc[bahia["Indicadores"] == "Impostos Líquidos", "Valores"] = bahia["Valores"] * -1
bahia["Valores_str"] = (bahia["Valores"]/1e9).map("R$ {:,.2f} Bi".format)
bahia["Medidas"] = ["absolute", "relative", "total"]
bahia
| Indicadores | Valores | Valores_str | Medidas | |
|---|---|---|---|---|
| 0 | PIB | 305320812691 | R$ 305.32 Bi | absolute |
| 1 | Impostos Líquidos | -37094030606 | R$ -37.09 Bi | relative |
| 2 | Valor Adicionado Bruto | 268226782074 | R$ 268.23 Bi | total |
## Configurando o gráfico com parâmetros que potencializam a visualização dos dados
# Importando as bibliotecas
import plotly.graph_objects as go
# Gerando o gráfico de cascata
fig = go.Figure( go.Waterfall(name = "", orientation = "v", measure = bahia["Medidas"],
x = bahia["Indicadores"], y = bahia["Valores"],
text = bahia["Valores_str"], textposition = "outside",
connector_line = dict(color = CINZA3),
totals_marker = dict(color = AZUL3),
decreasing_marker = dict(color = VERMELHO1)
)
)
# Personalizando o gráfico
fig.update_layout(width=1000, height=500, font_family = 'DejaVu Sans', font_size=15,
font_color= CINZA2, title_font_color= CINZA1, title_font_size=24,
title_text='Distribuição do Produto Interno Bruto (PIB) da Bahia em 2020' +
'<br><sup size=1 style="color:#555655">Impostos líquidos e Valores ' +
'Adicionados Brutos de bens e serviços (em bilhões de reais)</sup>',
title_pad_l = 50, plot_bgcolor= BRANCO, yaxis_range=[0,380e9], hovermode="closest")
# Retirando os ticks do eixo y
fig.update_yaxes(showticklabels=False)
# Dados ao passar o mouse
fig.update_traces(hovertemplate = "<b>%{x}</b> = %{text}")
fig.add_annotation(text='Fonte dos dados: <a href="https://sidra.ibge.gov.br/pesquisa/pib-munic/tabelas">Produto Interno Bruto | IBGE</a>',
align="left", xref="paper", yref = "paper", x=1, y=-0.2, showarrow=False)
fig.show()
Conclusões:
Um gráfico de cascata é aplamente utilizado em dados econômicos e financeiros por sua natureza de representar de maneira simples e direta a acumulação e /ou subtração do total em determinado período ou em diferentes categorias.
Como sugestão, podemos analisar esses valores do seu próprio estado ou até separar os valores adicionados por tipo de serviço mostrando a agregação de cada um.
Observação: Para auxiliar na compreensão do gráfico, os bens e serviços finais que compõem o PIB são medidos no preço em que chegam ao consumidor. Dessa forma, levam em consideração também os impostos sobre os produtos comercializados.
# Selecionando os dados do RJ
anos = [x for x in range(2010, 2021)]
rio = df_pib.query("sigla_uf == 'RJ' and ano == @anos")[["ano", "pib"]]
rio = rio.reset_index(drop=True)
rio
| ano | pib | |
|---|---|---|
| 0 | 2010 | 449858101109 |
| 1 | 2011 | 512767904769 |
| 2 | 2012 | 574884973130 |
| 3 | 2013 | 628226069362 |
| 4 | 2014 | 671076844311 |
| 5 | 2015 | 659138951833 |
| 6 | 2016 | 640401206447 |
| 7 | 2017 | 671605668055 |
| 8 | 2018 | 758859046865 |
| 9 | 2019 | 779927917084 |
| 10 | 2020 | 753823710636 |
# Gerando uma coluna com a variação do pib e passando o valor
# do PIB inicial para a 1ª linha da variação pib
rio["variacao_pib"] = rio["pib"].diff().fillna(rio["pib"]).astype("int64")
# Gerando uma coluna com as Medidas para o gráfico de cascata
rio["Medidas"] = ["absolute"] + ["relative"] * 10
rio.head()
| ano | pib | variacao_pib | Medidas | |
|---|---|---|---|---|
| 0 | 2010 | 449858101109 | 449858101109 | absolute |
| 1 | 2011 | 512767904769 | 62909803660 | relative |
| 2 | 2012 | 574884973130 | 62117068361 | relative |
| 3 | 2013 | 628226069362 | 53341096232 | relative |
| 4 | 2014 | 671076844311 | 42850774949 | relative |
# Gerando uma observação com a atualização da última linha com o PIB total de 2020
atualizacao = pd.Series({'ano': 'Total',
'pib': rio["pib"].values[-1],
'variacao_pib': rio["pib"].values[-1],
'Medidas': "total"}).to_frame().T
# Concatenando o df com a atualização e retirando a coluna pib
rio = pd.concat([rio, atualizacao], axis = 0, ignore_index=True)
rio = rio.drop(columns=["pib"])
# Ajustando a formatação do PIB e renomeando colunas
rio["variacao_pib_texto"] = (rio["variacao_pib"]/1e9).map('R$ {:,.2f} Bi'.format)
rio.rename(columns = {"ano":"Ano", "variacao_pib": "Variação do PIB", "variacao_pib_texto":"Variação do PIB (em texto)"}, inplace=True)
rio
| Ano | Variação do PIB | Medidas | Variação do PIB (em texto) | |
|---|---|---|---|---|
| 0 | 2010 | 449858101109 | absolute | R$ 449.86 Bi |
| 1 | 2011 | 62909803660 | relative | R$ 62.91 Bi |
| 2 | 2012 | 62117068361 | relative | R$ 62.12 Bi |
| 3 | 2013 | 53341096232 | relative | R$ 53.34 Bi |
| 4 | 2014 | 42850774949 | relative | R$ 42.85 Bi |
| 5 | 2015 | -11937892478 | relative | R$ -11.94 Bi |
| 6 | 2016 | -18737745386 | relative | R$ -18.74 Bi |
| 7 | 2017 | 31204461608 | relative | R$ 31.20 Bi |
| 8 | 2018 | 87253378810 | relative | R$ 87.25 Bi |
| 9 | 2019 | 21068870219 | relative | R$ 21.07 Bi |
| 10 | 2020 | -26104206448 | relative | R$ -26.10 Bi |
| 11 | Total | 753823710636 | total | R$ 753.82 Bi |
## Configurando o gráfico com parâmetros que potencializam a visualização dos dados
# Importando as bibliotecas
import plotly.graph_objects as go
import numpy as np
# Gerando o gráfico de cascata
fig = go.Figure(
go.Waterfall(name = "", orientation = "v", measure = rio["Medidas"],
y = rio["Variação do PIB"], text = rio["Variação do PIB (em texto)"],
textposition = "outside",
connector_line = dict(color = CINZA3),
totals_marker = dict(color = AZUL3),
increasing_marker = dict(color = VERDE1),
decreasing_marker = dict(color = VERMELHO1)
)
)
# Personalizando o gráfico
fig.update_layout(width=1300, height=600, font_family = 'DejaVu Sans', font_size=15,
font_color= CINZA2, title_font_color= CINZA1, title_font_size=24,
title_text='Variação do Produto Interno Bruto (PIB) do Rio de Janeiro' +
'<br><sup size=1 style="color:#555655">De 2010 a 2020 (em bilhões de reais)</sup>',
plot_bgcolor= BRANCO, yaxis_range=[0,850e9])
# Retirando os ticks do eixo y
fig.update_yaxes(showticklabels=False)
# Ajustando o eixo x para receber o Total
fig.update_xaxes(tickmode='array', tickvals=np.arange(0,12), ticktext=rio["Ano"])
# Dados ao passar o mouse
fig.update_traces(hovertemplate = "<b>%{x}</b> = %{text}")
fig.add_annotation(text="O <b>Rio de Janeiro</b> apresentou recuo no PIB<br>em pelo menos 3 anos no período:<br>2015, 2016 e 2020",
align="left", axref = 'x', ayref='y', x=5, y=600e9, ax=8, ay=450e9,
arrowhead=1, arrowside = "start", showarrow=True, arrowwidth=2, arrowcolor=CINZA3,
bordercolor= CINZA3, borderwidth=1, borderpad=4)
fig.add_annotation(text="", axref = 'x', ayref='y', x=6, y=600e9, ax=8, ay=530e9,
arrowhead=1, arrowside = "start", showarrow=True, arrowwidth=2, arrowcolor=CINZA3)
fig.add_annotation(text="", axref = 'x', ayref='y', x=10, y=710e9, ax=8.5, ay=530e9,
arrowhead=1, arrowside = "start", showarrow=True, arrowwidth=2, arrowcolor=CINZA3)
fig.show()
Conclusões:
Neste exemplo, o gráfico de cascata foi utlilizado para mostrar a evolução do PIB de um estado ano após ano partindo do valor inicial (ano de 2010) até o final (ano de 2020, representado pela coluna Total). É possível notar acréscimos e descréscimos ao longo do tempo, representados pelas cores verde e vermelho, respectivamente.
Como sugestão, podemos analisar a evolução do PIB do seu próprio estado ou de uma região de interesse.
# Selecionando os dados da região Sul do Brasil
anos = [x for x in range(2010, 2021, 5)]
pib_sul = df_pib.query("regiao == 'Sul' and ano == @anos")[["ano", "sigla_uf", "pib"]]
pib_sul["pib"] = (pib_sul["pib"] / 1e9).round(2)
pib_sul = pib_sul.reset_index(drop=True)
pib_sul
| ano | sigla_uf | pib | |
|---|---|---|---|
| 0 | 2010 | PR | 225.21 |
| 1 | 2015 | PR | 376.96 |
| 2 | 2020 | PR | 487.93 |
| 3 | 2010 | SC | 153.73 |
| 4 | 2015 | SC | 249.08 |
| 5 | 2020 | SC | 349.28 |
| 6 | 2010 | RS | 241.25 |
| 7 | 2015 | RS | 381.99 |
| 8 | 2020 | RS | 470.94 |
# Criando uma tabela cruzada (crosstab) com os valores de venda de cada ano por região
pib_sul_cross = pd.crosstab(index = pib_sul.ano, columns = pib_sul.sigla_uf,
values = pib_sul.pib, aggfunc = "sum", normalize = "index")
pib_sul_cross = pib_sul_cross.reset_index()
pib_sul_cross
| sigla_uf | ano | PR | RS | SC |
|---|---|---|---|---|
| 0 | 2010 | 0.363131 | 0.388994 | 0.247876 |
| 1 | 2015 | 0.373957 | 0.378947 | 0.247096 |
| 2 | 2020 | 0.372992 | 0.360005 | 0.267003 |
## Configurando o gráfico com parâmetros que potencializam a visualização dos dados
# Importando as bibliotecas
import matplotlib.pyplot as plt
import seaborn as sns
# Área do gráfico e tema da visualização
fig, axs = plt.subplots(1, 2, figsize=(16,6))
sns.set_theme(style="white")
# Definindo as cores do gráfico
cores = [AZUL6, VERDE3, VERMELHO2]
# Personalizando o Título superior
fig.suptitle("Distribuição do PIB na região Sul do Brasil por quinquênio (2010 - 2020)",
fontsize=18, color=CINZA1, ha = 'right', x = 0.66, y = 1.05)
# GRÁFICO 1 - Gráfico de colunas agrupadas
sns.barplot(data = pib_sul, x = "ano", y = "pib", hue = "sigla_uf", hue_order = ["PR", "RS", "SC"], ax = axs[0], palette = cores)
axs[0].set_title('Em bilhões de reais\n', color = CINZA3, loc = "left")
axs[0].set_xlabel('')
axs[0].set_ylabel('')
axs[0].xaxis.set_tick_params(labelsize=14, color = CINZA2)
axs[0].yaxis.set_tick_params(labelsize=14, color = CINZA2)
axs[0].set_frame_on(False)
# Remover a legenda e colocar grids no eixo y
axs[0].legend().remove()
axs[0].yaxis.grid(linestyle='--', linewidth=1)
#######################################
# GRÁFICO 2 - Gráfico de colunas empilhadas 100 %
pib_sul_cross.plot(x = "ano", kind="bar", stacked = True, color = cores, ax = axs[1])
axs[1].set_title('Em porcentagem\n', color = CINZA3, loc = "left")
axs[1].set_xlabel('')
axs[1].set_ylabel('')
axs[1].set_yticklabels([])
axs[1].xaxis.set_tick_params(labelsize=14, color = CINZA2, labelrotation = 0)
axs[1].set_frame_on(False)
# Adicionar a legenda entre os dois gráficos
axs[1].legend(bbox_to_anchor=(-0.005, 1), title='Estado', title_fontsize = 12, fontsize = 12)
#######################################
# Adicionando os valores dentro da coluna
for container in axs[1].containers:
labels = [f'{valor.get_height()*100:.0f}%' for valor in container]
axs[1].bar_label(container, label_type='center', labels = labels, size = 11, color = CINZA3, fontweight = "bold")
plt.show()
Conclusões:
Neste exemplo, apresentamos as diferenças entre colunas agrupadas e empilhadas. A 1ª reflete os valores absolutos do PIB em cada estado da Região Sul por quinquênio (lustro), já a 2ª representa os valores relativos compilados ano a ano da região como um todo.
# Selecionando os dados desejados
df_va_separado = df_pib.query("ano == 2020")[["regiao", "va_servicos", "va_industria", "va_adespss", "va_agropecuaria"]]
df_va_separado = df_va_separado.reset_index(drop=True)
df_va_separado.head()
| regiao | va_servicos | va_industria | va_adespss | va_agropecuaria | |
|---|---|---|---|---|---|
| 0 | Norte | 19060688172 | 8285675423 | 12000339417 | 6891411669 |
| 1 | Norte | 6590543336 | 1191345379 | 6031050521 | 983531817 |
| 2 | Norte | 34795836262 | 35839810630 | 20210620577 | 5114449144 |
| 3 | Norte | 5278754961 | 1706511471 | 6538065265 | 1000907462 |
| 4 | Norte | 56395092425 | 84173852308 | 37614037902 | 19730656823 |
# Agrupando os dados por região
df_va_separado = df_va_separado.groupby("regiao").agg("sum")
# Normalizando os dados de cada região
df_va_separado = df_va_separado.div(df_va_separado.sum(axis=1), axis=0)
df_va_separado = df_va_separado.sort_values(by="va_servicos", axis=0)
df_va_separado
| va_servicos | va_industria | va_adespss | va_agropecuaria | |
|---|---|---|---|---|
| regiao | ||||
| Norte | 0.338521 | 0.323217 | 0.239485 | 0.098777 |
| Centro-Oeste | 0.435471 | 0.153645 | 0.266185 | 0.144699 |
| Nordeste | 0.459790 | 0.191011 | 0.260121 | 0.089078 |
| Sul | 0.508060 | 0.252751 | 0.139648 | 0.099541 |
| Sudeste | 0.610871 | 0.228032 | 0.133536 | 0.027561 |
# Gerando a função para criar o gráfico de barras empilhadas
def grafico_va():
# Importando as bibliotecas
import matplotlib.pyplot as plt
# Área do gráfico e tema da visualização
fig, ax = plt.subplots(figsize=(10,7))
# Definindo as cores do gráfico
cores = [AZUL3, LARANJA1, CINZA5, VERDE3]
# Gerando o gráfico de barras empilhadas 100%
df_va_separado.plot(kind="barh", stacked=True, color = cores, ax=ax)
## Personalizando o gráfico
plt.suptitle('Valores adicionados de bens e serviços do PIB brasileiro em 2020', size=18, color=CINZA1, ha = 'right', x = 0.8, y = 1.01)
plt.title('Em distribuição dos setores por região (%)\n', fontsize=14, color=CINZA3, pad = 15, ha = "right", x = 0.35)
ax.legend(bbox_to_anchor=(1, 1), bbox_transform=ax.transAxes, fontsize = 10, loc='upper left', )
ax.set_ylabel('')
ax.set_xticklabels([])
ax.yaxis.set_tick_params(labelsize=14, color = CINZA2)
ax.set_frame_on(False)
# Valores das barras
for container in ax.containers:
labels = [f'{valor.get_width()*100:.0f}%' for valor in container]
ax.bar_label(container, label_type='center', labels = labels, size = 10, color = CINZA2, fontweight='bold')
return ax, cores
ax, cores = grafico_va()
Conclusões:
As barras empilhadas são extremamente úteis para representação dos dados em pequenos períodos e quando desejamos comparar diferenças absolutas e relativas ou apenas relativas (como no exemplo acima).
Como sugestão, podemos analisar a composição dos dados em relação aos setores de uma dada região, separada pelos estados.
# Selecionando os dados desejados
df_agro = df_pib.copy()
df_agro = df_agro[["regiao", "ano", "va_agropecuaria"]]
# Agrupando os dados por região
df_agro = pd.crosstab(index = df_agro.ano, columns = df_agro.regiao,
values = df_agro.va_agropecuaria, aggfunc="sum")
df_agro = (df_agro / 1e9).round(2)
df_agro.head()
| regiao | Centro-Oeste | Nordeste | Norte | Sudeste | Sul |
|---|---|---|---|---|---|
| ano | |||||
| 2002 | 12.98 | 17.04 | 6.40 | 22.57 | 22.53 |
| 2003 | 18.70 | 20.98 | 8.14 | 25.71 | 32.42 |
| 2004 | 20.98 | 22.44 | 8.18 | 28.27 | 31.05 |
| 2005 | 17.04 | 22.03 | 8.53 | 28.99 | 24.37 |
| 2006 | 12.15 | 23.42 | 8.91 | 34.44 | 26.37 |
## Configurando o gráfico com parâmetros que potencializam a visualização dos dados
# Importando as bibliotecas
import matplotlib.pyplot as plt
# Área do gráfico e tema da visualização
fig, ax = plt.subplots(figsize=(14,7))
# Definindo as cores do gráfico
cores = [VERDE3, VERMELHO2, AZUL3, LARANJA1, CINZA4]
# Gerando o gráfico de áreas empilhadas
df_agro.plot(kind="area", stacked=True, color = cores, ax = ax, xticks = range(2002, 2021, 2))
## Personalizando o gráfico
ax.set_title('PIB relativo à agropecuária nas regiões do Brasil', fontsize = 18, color = CINZA1, loc='left')
ax.text(0.29, 0.98, "De 2002 a 2020 (em bilhões de reais)", transform=ax.transAxes, color= CINZA3, fontsize=12, ha='right', va='center')
ax.set_ylabel('')
ax.xaxis.set_tick_params(labelsize=14, color = CINZA2)
ax.legend().remove()
ax.set_frame_on(False)
## Anotando os nomes das regiões
reg = list(reversed(df_agro.columns))
cor = list(reversed(cores))
for i in range(len(reg)):
ax.text(0.97, (0.67 - i/7), f'{reg[i]}', fontsize=14, color = cor[i], transform=ax.transAxes)
## Ajustes no eixo y
# Descrevendo o limite mínimo e máximo do eixo y e escondendo o eixo
plt.ylim(0, 500)
ax.get_yaxis().set_visible(False)
# remover todos os ticks do eixo x e y
ax.tick_params(axis='both', which='both', length=0)
# Destacando os valores de 4 em 4 anos e no ano de 2020
agregado_ano = list(df_agro.sum(axis=1).round(2))
for i in range(0, len(df_agro.index), 4):
ax.text(x = df_agro.index[i], y = agregado_ano[i] + 20, s = f"{agregado_ano[i]} Bi", color = CINZA3, weight = "bold", fontsize = 10, ha="center")
ax.text(x = df_agro.index[-1], y = agregado_ano[-1] + 20, s = f"{agregado_ano[-1]} Bi", color = CINZA3, weight = "bold", fontsize = 10, ha="center")
plt.show()
Conclusões:
Os gráficos de áreas são extremamente úteis quando queremos enfatizar a magnitude das mudanças ao longo do período. Ele é uma junção de várias linhas empilhadas preenchidas com a cor de cada categoria para representação dos dados ao longo do período. No exemplo acima, utilizamos o gráfico de áreas em que tanto a diferença absoluta (valores ao longo do tempo) quanto a relativa (espessuras entre elas) são importantes em nossa análise.
Como sugestão, podemos analisar a composição dos dados em relação a outros setores.
Nesta situação-problema, você recebeu um conjunto de dados para analisar as notas do IDEB, divididas por região, das provas realizadas entre 2005 e 2021. Os dados descrevem o desempenho dos alunos em testes de língua portuguesa e matemática, além da taxa de aprovação escolar.
O IDEB é medido em uma escala de 0 a 10 e é uma importante ferramenta para acompanhar o desenvolvimento da educação básica no país, permitindo a avaliação da efetividade das políticas públicas na área e a identificação das regiões que necessitam de maior atenção.
Aqui, vamos focar em investigar as notas em diferentes níveis de ensino (Ensino Fundamental Anos Iniciais e Anos Finais e Ensino Médio) tecendo alguns comentários a respeito das perguntas levantadas.
import pandas as pd
ideb = pd.read_csv("https://raw.githubusercontent.com/afonsosr2/dataviz-graficos-composicao-relacionamento/master/dados/ideb_reg_2005_2021.csv")
ideb.head()
| ano | regiao | rede | ensino | anos_escolares | taxa_aprovacao | indicador_rendimento | nota_saeb_matematica | nota_saeb_lingua_portuguesa | nota_saeb_media_padronizada | ideb | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2005 | Centro-Oeste | estadual | fundamental | EFAF | 72.1 | 0.721828 | 233.50 | 227.88 | 4.356453 | 3.1 |
| 1 | 2005 | Centro-Oeste | estadual | fundamental | EFAI | 83.0 | 0.837081 | 185.38 | 172.13 | 4.631618 | 3.9 |
| 2 | 2005 | Centro-Oeste | estadual | medio | EM | 68.0 | 0.695138 | 261.23 | 251.52 | 4.123654 | 2.9 |
| 3 | 2005 | Centro-Oeste | privada | fundamental | EFAF | 94.4 | 0.943491 | 283.57 | 266.82 | 5.840183 | 5.5 |
| 4 | 2005 | Centro-Oeste | privada | fundamental | EFAI | 97.3 | 0.972388 | 223.64 | 210.36 | 6.057024 | 5.9 |
ideb.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 270 entries, 0 to 269 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 ano 270 non-null int64 1 regiao 270 non-null object 2 rede 270 non-null object 3 ensino 270 non-null object 4 anos_escolares 270 non-null object 5 taxa_aprovacao 270 non-null float64 6 indicador_rendimento 270 non-null float64 7 nota_saeb_matematica 270 non-null float64 8 nota_saeb_lingua_portuguesa 270 non-null float64 9 nota_saeb_media_padronizada 270 non-null float64 10 ideb 270 non-null float64 dtypes: float64(6), int64(1), object(4) memory usage: 23.3+ KB
ideb_em = ideb.query("anos_escolares == 'EM'")[["indicador_rendimento", "ideb"]]
ideb_em = ideb_em.reset_index(drop = True)
ideb_em.head()
| indicador_rendimento | ideb | |
|---|---|---|
| 0 | 0.695138 | 2.9 |
| 1 | 0.943179 | 5.7 |
| 2 | 0.730819 | 2.7 |
| 3 | 0.916831 | 5.2 |
| 4 | 0.737045 | 2.7 |
# Importando a biblioteca
import plotly.express as px
# Gerando o gráfico de dispersão com uma reta representando um modelo de regressão linear (OLS - Mínimos Quadrados Ordinários)
fig = px.scatter(ideb_em, x="ideb", y="indicador_rendimento", trendline = 'ols',
color_discrete_sequence = [AZUL3], trendline_color_override=CINZA3,
labels = {"ideb":"IDEB", "indicador_rendimento":"Indicador de Rendimento"})
# Ajustando o layout do gráfico
fig.update_layout(width=1000, height=500, yaxis_range = [0, 1.1], xaxis_range = [2.5, 7.5],
margin = dict(t=100), font_size=14, font_color= CINZA2,
title_font_color= CINZA1, title_font_size=24,
title_text='Relação entre o IDEB e o indicador de rendimento das escolas' +
'<br><sup size=1 style="color:#555655">Do Ensino Médio (EM) entre os anos de 2005 a 2021</sup>',
xaxis_title='IDEB (0-10)', yaxis_title='Indicador de Rendimento (0-1)')
# Dados ao passar o mouse
fig.update_traces(hovertemplate = "<b>IDEB:</b> %{x} <br><b>Indicador de Rend:</b> %{y}", selector = dict(type='scatter', mode = "markers"))
fig.add_annotation(text='Fonte dos dados: <a href="https://www.gov.br/inep/pt-br/areas-de-atuacao/avaliacao-e-exames-educacionais/saeb">'
'Sistema de Avaliação da Educação Básica (Saeb)</a>',
align="left", xref="paper", yref = "paper", x=1, y=-0.15, showarrow=False, font_size=10)
fig.show()
Conclusões:
O gráfico de dispersão pode ser utilizado para relacionar dados entre duas variáveis numéricas de diferentes naturezas. Essa relação pode ser positiva, negativa ou neutra, linear ou não linear.
Aqui traçamos uma reta em volta dos dados que representam a tendência entre eles, similar ao comoportamento que geramos a trabalhar com modelos de regressão linear.
ideb_efai = ideb.query("anos_escolares == 'EFAI'")[["regiao","nota_saeb_matematica", "nota_saeb_lingua_portuguesa"]]
ideb_efai = ideb_efai.reset_index(drop = True)
ideb_efai.head()
| regiao | nota_saeb_matematica | nota_saeb_lingua_portuguesa | |
|---|---|---|---|
| 0 | Centro-Oeste | 185.38 | 172.13 |
| 1 | Centro-Oeste | 223.64 | 210.36 |
| 2 | Nordeste | 162.61 | 156.61 |
| 3 | Nordeste | 211.16 | 199.88 |
| 4 | Norte | 166.39 | 161.30 |
## Configurando o gráfico com parâmetros que potencializam a visualização dos dados
# Importando as bibliotecas
import matplotlib.pyplot as plt
import seaborn as sns
# Definindo as cores do gráfico
cores = [VERDE3, VERMELHO2, AZUL3, LARANJA1, CINZA4]
# Área do gráfico e tema da visualização
fig, ax = plt.subplots(figsize=(10,5))
sns.set_theme(style="white")
# Gerando o gráfico de dispersão com cores como categorias
ax = sns.scatterplot(data = ideb_efai, x = "nota_saeb_matematica", y="nota_saeb_lingua_portuguesa", hue = "regiao", palette = cores)
## Personalizando o gráfico
plt.suptitle('Relação entre as notas de matemática e língua portuguesa do SAEB', size=18, color=CINZA1, ha = 'right', x = 0.97, y = 1.03)
plt.title('Do Ensino Fudamental Anos Iniciais (EFAI) entre os anos de 2005 a 2021', fontsize=14, color=CINZA3, pad = 15, loc = "left")
ax.legend(bbox_to_anchor=(155, 275), title='Região', title_fontsize = 10, fontsize = 10, loc='upper left', bbox_transform=ax.transData)
ax.set_xlabel('Notas de Matemática (0 - 500)', fontsize = 14)
ax.set_ylabel('Notas de Português (0 - 500)', fontsize = 14)
ax.xaxis.set_tick_params(labelsize=12, color = CINZA2)
ax.set_xlim(150, 280)
ax.yaxis.set_tick_params(labelsize=12, color = CINZA2)
ax.set_ylim(150, 280)
sns.despine()
# Limites das notas em no eixo y (notas de português) - 200 pontos (proficiência)
ax.text(ax.get_xlim()[0] + 1, 202, 'Nível 4 e superior', fontsize=12, color = CINZA3, va = "bottom")
ax.text(ax.get_xlim()[0] + 1 , 198, 'Nível 4 e inferior', fontsize=12, color = CINZA3, va = "top")
plt.axhline(y = 200, color = CINZA5, linestyle='--')
# Limites das notas em no eixo x (notas de matemática) - 225 pontos (proficiência)
ax.text(223, ax.get_ylim()[1] - 10, 'Nível 5\ne inferior', fontsize=12, color = CINZA3, ha="right")
ax.text(227, ax.get_ylim()[1] - 10, 'Nível 5\ne superior', fontsize=12, color = CINZA3, ha="left")
plt.axvline(x = 225, color = CINZA5, linestyle='--')
# Adicionando um texto explicando a divisão de quadrantes e o que significa
ax.annotate("Cada quadrante representa o nível de proficiência\nde estudantes divididas pelo nível 5 (>=225 pontos)\ne 4 (>=200 pontos)\n\n"
"Nota-se que o 2º quadrante (Nível 5 e superior em \nmatemática e Nível 4 e superior em português)\n"
"possuímos as notas com melhores desempenhos \nà nivel nacional", xy=(260, 180), xycoords='data',
bbox=dict(boxstyle="round", fc=BRANCO, ec=CINZA3),
xytext=(0, 0), textcoords='offset points')
plt.show()
Conclusões:
O gráfico de dispersão por cores adiciona uma variável categórica a análise (em nosso exemplo, a região).
Para compreender um pouco mais sobre os níveis de proficiência aessar este link. E para entender sobre o nível de aprendizado proficiente acesse este outro link
Aqui utilizamos dois recursos visuais que é o de acercamento (gerado pela delimitação dos níveis das notas de língua portuguesa e matemática) e o de similaridade por meio das cores, representando as categorias dos pontos representados pelas regiões.