Visualização gráfica de dados¶
Intercalando matplotlib e pandas¶
As Series e os DataFrames possuem um método plot de visualização gráfica construído com base no matplotlib que contempla diversos tipos de gráficos, incluindo gráficos estatísticos.
Ao utilizar o método plot em uma Series ou DataFrame, não haverá necessidade de importar o matplotlib.pyplot, uma vez que as funções e métodos utilizados já foram importados pelo pandas.
Primeiramente veremos construções gráficas com base no método plot. Vamos começar importando e construindo os DataFrames a serem utilizados.
import numpy as np
import pandas as pd
serie_Idade = pd.Series({'Ana':20, 'João': 19, 'Maria': 21, 'Pedro': 22, 'Túlio': 20}, name="Idade")
serie_Peso = pd.Series({'Ana':55, 'João': 80, 'Maria': 62, 'Pedro': 67, 'Túlio': 73}, name="Peso")
serie_Altura = pd.Series({'Ana':162, 'João': 178, 'Maria': 162, 'Pedro': 165, 'Túlio': 171}, name="Altura")
dicionario_series_exemplo = {'Idade': serie_Idade, 'Peso': serie_Peso, 'Altura': serie_Altura}
df_dict_series = pd.DataFrame(dicionario_series_exemplo);df_dict_series
| Idade | Peso | Altura | |
|---|---|---|---|
| Ana | 20 | 55 | 162 |
| João | 19 | 80 | 178 |
| Maria | 21 | 62 | 162 |
| Pedro | 22 | 67 | 165 |
| Túlio | 20 | 73 | 171 |
df_exemplo = pd.read_csv('data/exemplo_data.csv', index_col=0);df_exemplo
| coluna_1 | coluna_2 | |
|---|---|---|
| 2020-01-01 | -0.416092 | 1.810364 |
| 2020-01-02 | -0.137970 | 2.578520 |
| 2020-01-03 | 0.575827 | 0.060866 |
| 2020-01-04 | -0.017367 | 1.299587 |
| 2020-01-05 | 1.384279 | -0.381732 |
| 2020-01-06 | 0.549706 | -1.308789 |
| 2020-01-07 | -0.282296 | -1.688979 |
| 2020-01-08 | -0.989730 | -0.028121 |
| 2020-01-09 | 0.275582 | -0.177659 |
| 2020-01-10 | 0.685132 | 0.502535 |
df_exemplo['coluna_3'] = pd.Series([1,2,3,4,5,6,7,8,np.nan,np.nan],index=df_exemplo.index);df_exemplo
| coluna_1 | coluna_2 | coluna_3 | |
|---|---|---|---|
| 2020-01-01 | -0.416092 | 1.810364 | 1.0 |
| 2020-01-02 | -0.137970 | 2.578520 | 2.0 |
| 2020-01-03 | 0.575827 | 0.060866 | 3.0 |
| 2020-01-04 | -0.017367 | 1.299587 | 4.0 |
| 2020-01-05 | 1.384279 | -0.381732 | 5.0 |
| 2020-01-06 | 0.549706 | -1.308789 | 6.0 |
| 2020-01-07 | -0.282296 | -1.688979 | 7.0 |
| 2020-01-08 | -0.989730 | -0.028121 | 8.0 |
| 2020-01-09 | 0.275582 | -0.177659 | NaN |
| 2020-01-10 | 0.685132 | 0.502535 | NaN |
covid_PB = pd.read_csv('https://superset.plataformatarget.com.br/superset/explore_json/?form_data=%7B%22slice_id%22%3A1550%7D&csv=true',
sep=',', index_col=0)
covid_PB.head()
| casosAcumulados | casosNovos | descartados | recuperados | obitosAcumulados | obitosNovos | Letalidade | |
|---|---|---|---|---|---|---|---|
| data | |||||||
| 2021-02-09 | 199706 | 971 | 237369 | 152779 | 4171 | 13 | 0.0209 |
| 2021-02-08 | 198735 | 611 | 237189 | 151879 | 4158 | 12 | 0.0209 |
| 2021-02-07 | 198124 | 664 | 237072 | 151535 | 4146 | 11 | 0.0209 |
| 2021-02-06 | 197460 | 918 | 236774 | 150175 | 4135 | 12 | 0.0209 |
| 2021-02-05 | 196542 | 1060 | 236216 | 150169 | 4123 | 13 | 0.0210 |
covid_BR = pd.read_excel("data/HIST_PAINEL_COVIDBR_18jul2020.xlsx")
covid_BR.head()
| Unnamed: 0 | regiao | estado | municipio | coduf | codmun | codRegiaoSaude | nomeRegiaoSaude | data | semanaEpi | populacaoTCU2019 | casosAcumulado | casosNovos | obitosAcumulado | obitosNovos | Recuperadosnovos | emAcompanhamentoNovos | interior/metropolitana | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | Brasil | NaN | NaN | 76 | NaN | NaN | NaN | 2020-02-25 | 9 | 210147125 | 0 | 0 | 0 | 0 | NaN | NaN | NaN |
| 1 | 1 | Brasil | NaN | NaN | 76 | NaN | NaN | NaN | 2020-02-26 | 9 | 210147125 | 1 | 1 | 0 | 0 | NaN | NaN | NaN |
| 2 | 2 | Brasil | NaN | NaN | 76 | NaN | NaN | NaN | 2020-02-27 | 9 | 210147125 | 1 | 0 | 0 | 0 | NaN | NaN | NaN |
| 3 | 3 | Brasil | NaN | NaN | 76 | NaN | NaN | NaN | 2020-02-28 | 9 | 210147125 | 1 | 0 | 0 | 0 | NaN | NaN | NaN |
| 4 | 4 | Brasil | NaN | NaN | 76 | NaN | NaN | NaN | 2020-02-29 | 9 | 210147125 | 2 | 1 | 0 | 0 | NaN | NaN | NaN |
Gráfico de Linhas¶
O gráfico de linhas é formado por pontos no plano a partir de duas variáveis e, em seguida, estes pontos são ligados por segmentos de retas. Este é o gráfico padrão construído pelo método plot. Para construí-lo basta “chamar” o método plot sem argumentos adicionais.
df_exemplo.plot();
covid_PB_casos_obitos = covid_PB[['casosAcumulados', 'obitosAcumulados']].sort_index()
covid_PB_casos_obitos.plot();
Obs.: Note que houve uma sobreposição dos valores no eixo x.
Se convertermos o index para data, isto será corrigido, pois se o tipo do dado for data, o pandas implementa o método autofmt_xdate que corrige a sobreposição:
covid_PB.index = pd.to_datetime(covid_PB.index)
covid_PB_casos_obitos = covid_PB[['casosAcumulados', 'obitosAcumulados']].sort_index()
covid_PB_casos_obitos.plot();
covid_regioes = pd.DataFrame()
regioes = covid_BR.query('regiao != "Brasil"')['regiao'].drop_duplicates().array
for regiao in regioes:
temp_series = covid_BR.set_index('data').query('regiao == @regiao')['obitosAcumulado'].groupby('data').sum()/2
#Obs.: Utilizamos @ na frente do nome da variável para utilizar o valor da variável no query.
temp_series.name = 'obitos_' + regiao
covid_regioes = pd.concat([covid_regioes, temp_series], axis=1)
covid_regioes.index = pd.to_datetime(covid_regioes.index)
covid_regioes
| obitos_Norte | obitos_Nordeste | obitos_Sudeste | obitos_Sul | obitos_Centro-Oeste | |
|---|---|---|---|---|---|
| data | |||||
| 2020-02-25 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2020-02-26 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2020-02-27 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2020-02-28 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2020-02-29 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| ... | ... | ... | ... | ... | ... |
| 2020-07-14 | 10628.0 | 23925.0 | 33718.0 | 2740.0 | 3122.0 |
| 2020-07-15 | 10693.0 | 24272.0 | 34246.0 | 2870.0 | 3285.0 |
| 2020-07-16 | 10790.0 | 24645.0 | 34857.0 | 2975.0 | 3421.0 |
| 2020-07-17 | 10911.0 | 24902.0 | 35374.0 | 3104.0 | 3560.0 |
| 2020-07-18 | 10972.0 | 25194.0 | 35732.0 | 3199.0 | 3675.0 |
145 rows × 5 columns
O argumento figsize permite inserir uma tupla para definir as dimensões horizontais e verticais, respectivamente, em polegadas.
covid_regioes.plot(figsize=(12,7));
Gráfico de Colunas¶
O gráfico de colunas é formado por uma coleção de colunas, com bases de mesmo comprimento, e igualmente espaçados. O eixo horizontal do gráfico consiste das diferentes categorias consideradas, e o eixo vertical é proporcional ao valor do dado. Podemos criar gráficos em colunas utilizando o argument kind do método plot. Assim, para criar um gráfico de colunas, basta utilizar plot(kind = 'bar'). Também podemos criar estes gráficos utilizando o método plot.bar(). As duas formas são equivalentes.
df_dict_series.plot(kind = 'bar');
df_dict_series.plot.bar();
Também podemos “empilhar” as barras para cada index utilizando o argumento stacked=True:
df_dict_series.plot.bar(stacked=True);
covid_Regioes = covid_BR[['regiao','obitosNovos']].groupby('regiao').sum().query('regiao != "Brasil"')
covid_Regioes.plot.bar();
Vamos agora considerar os óbitos como index:
covid_Regioes_casos_obitos = covid_BR[['regiao',
'obitosNovos']].groupby('regiao').sum().query('regiao != "Brasil"')/2
covid_Regioes_casos_obitos.transpose().plot.bar();
covid_Regioes_casos_obitos.transpose().plot.bar(stacked=True);
Gráfico de Barras¶
O gráfico de barras é construído da mesma forma do gráfico em colunas, entretanto, muda-se a orientação. Neste caso, o eixo horizontal do gráfico é proporcional ao valor do dado, e o eixo vertical consiste das diferentes categorias consideradas. Para criar um gráfico de barras, basta utilizar plot(kind = 'barh'). Também podemos criar estes gráficos utilizando o método plot.barh(). As duas formas são equivalentes.
df_dict_series.plot(kind = 'barh');
df_dict_series.plot.barh();
Também podemos “empilhar” as barras para cada índice utilizando o argumento stacked=True:
df_dict_series.plot.barh(stacked=True);
covid_Regioes = covid_BR[['regiao','obitosNovos']].groupby('regiao').sum().query('regiao != "Brasil"')/2
covid_Regioes.plot.barh();
Vamos agora considerar as óbitos como index:
covid_Regioes_casos_obitos = covid_BR[['regiao',
'obitosNovos']].groupby('regiao').sum().query('regiao != "Brasil"')/2
covid_Regioes_casos_obitos.transpose().plot.barh();
covid_Regioes_casos_obitos.transpose().plot.barh(stacked=True);
Gráfico de Setores¶
O gráfico de setores, que também é popularmente conhecido como gráfico pizza, é um gráfico em que um círculo é dividido em setores, onde cada setor representa uma categoria considerada pelo conjunto de dados, e os ângulos dos setores são proporcionais aos valores dos dados em cada categoria.
Podemos criar gráficos de setores utilizando o argumento kind do método plot. Assim, para criar um gráfico de setores, basta utilizar plot(kind = 'pie'). Também podemos criar estes gráficos utilizando o método plot.pie(). As duas formas são equivalentes. Para este gráfico é conveniente utilizar o argumento figsize já que o tamanho padrão tende a ser muito pequeno.
Além disso, tipicamente é necessário acrescentar subplots=True para a criação de uma “pizza” para cada coluna numérica.
Em uma Series do pandas, não é necessário o argumento subplots=True.
df_dict_series.plot.pie(subplots=True,figsize=(22,7));
Aqui temos um gráfico acerca da mortalidade de COVID-19 através das diferentes regiões do Brasil.
covid_Regioes_casos_obitos.obitosNovos.plot.pie(figsize=(7,7));
Gráfico de Dispersão¶
O gráfico de dispersão representa dados de duas (ou mais) variáveis utilizando as coordenadas cartesianas para exibir valores de um conjunto de dados. Os dados são exibidos como uma coleção de pontos, cada um com o valor de uma variável determinando a posição no eixo horizontal e o valor da outra variável determinando a posição no eixo vertical. Quando há mais de duas variáveis, utilizam-se recursos adicionais como tamanhos dos pontos e/ou cores dos pontos.
Para criar um gráfico de dispersão, basta utilizar plot(kind = 'scatter'). Também podemos criar estes gráficos utilizando o método plot.scatter(). As duas formas são equivalentes.
Neste caso, devemos incluir dois argumentos: x e y, representando a abscissa e a ordenada, respectivamente. Para utilizar o index como eixo x é preciso que o index seja uma coluna, para tanto pode-se utilizar o método reset_index(). Assim, como nos outros métodos, podemos utilizar o argumento rot para rotacionar os rótulos do eixo x.
df_exemplo.reset_index().plot.scatter(x = 'index', y ='coluna_1' , rot = 45);
Podemos utilizar o argumento s para inserir o tamanho como uma variável gráfica (lembrando que o tamanho deve ser positivo):
df_exemplo.reset_index().plot.scatter(x = 'index', y = 'coluna_1', rot = 45, s = np.abs(df_exemplo['coluna_2'])*100);
Podemos utilizar o argumento c para definir uma variável inserir a cor como uma variável gráfica:
covid_PB_casos_obitos = covid_PB[['obitosNovos', 'casosNovos']].sort_index()
covid_PB_casos_obitos.reset_index().plot.scatter(x = 'data', y = 'casosNovos', c = 'obitosNovos');
O tamanho e cores também podem ser fixados para fins estéticos:
df_exemplo.reset_index().plot.scatter(x = 'index', y = 'coluna_1', rot = 45, c = 'black', s = 100);
Para criar múltiplos gráficos de dispersão sobrepostos, utilizamos o argumento ax.
Para definir o rótulo do eixo y utilizamos: ax.set_ylabel("Valor").
Para definir o rótulo do eixo x utilizamos: ax.set_xlabel("Data").
ax = df_exemplo.reset_index().plot.scatter(x = 'index', y = 'coluna_1', label = 'coluna_1',
color = 'black', rot = 45)
df_exemplo.reset_index().plot.scatter(x = 'index', y = 'coluna_2', label = 'coluna_2', color = 'red',
rot = 45, ax = ax)
ax.set_ylabel("Valor")
ax.set_xlabel("Data")
Text(0.5, 0, 'Data')
Para sobrepor mais de dois gráficos, basta repetir o método anterior mais de uma vez:
ax = df_exemplo.reset_index().plot.scatter(x = 'index', y = 'coluna_1', label = 'coluna_1',
color = 'black', rot = 45)
df_exemplo.reset_index().plot.scatter(x = 'index', y = 'coluna_2', label = 'coluna_2', color = 'red',
rot = 45, ax = ax)
df_exemplo.reset_index().plot.scatter(x = 'index', y = 'coluna_3', label = 'coluna_3', color = 'green',
rot = 45, ax = ax)
ax.set_ylabel("Valor")
ax.set_xlabel("Data")
Text(0.5, 0, 'Data')
Histograma¶
O histograma é formado por uma justaposição de retângulos de bases com o mesmo comprimento. O comprimento da base é justamente a amplitude do intervalo e a altura do retângulo é dada pela frequência absoluta do intervalo. O histograma é a representação gráfica de distribuição de frequência.
Para criar um histograma, basta utilizar plot(kind = 'hist'). Também podemos criar histogramas utilizando o método plot.hist(). As duas formas são equivalentes.
Um parâmetro comumente utilizado é alpha que define a transparência dos histogramas e é dado por um número entre 0 e 1. Outro parâmetro comumente utilizado é bins que determina o número de intervalos a serem considerados. Se quisermos que os histogramas sejam “plotados” separadamente, utilizamos o método hist() diretamente.
covid_BR_regioes = covid_BR.copy().set_index('data').query('regiao != "Brasil"')
covid_BR_regioes = covid_BR_regioes[['regiao','obitosNovos']].groupby(['regiao','data']).sum()/2
covid_BR_reg = pd.DataFrame()
for regiao in covid_BR_regioes.index.get_level_values(0).drop_duplicates():
covid_BR_reg = pd.concat([covid_BR_reg, covid_BR_regioes.loc[regiao]],
axis=1).rename({'obitosNovos':'obitos_'+regiao},axis=1)
covid_BR_reg
| obitos_Centro-Oeste | obitos_Nordeste | obitos_Norte | obitos_Sudeste | obitos_Sul | |
|---|---|---|---|---|---|
| data | |||||
| 2020-02-25 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2020-02-26 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2020-02-27 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2020-02-28 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2020-02-29 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| ... | ... | ... | ... | ... | ... |
| 2020-07-14 | 88.0 | 315.0 | 76.0 | 682.0 | 139.0 |
| 2020-07-15 | 163.0 | 347.0 | 65.0 | 528.0 | 130.0 |
| 2020-07-16 | 136.0 | 373.0 | 97.0 | 611.0 | 105.0 |
| 2020-07-17 | 139.0 | 257.0 | 121.0 | 517.0 | 129.0 |
| 2020-07-18 | 115.0 | 292.0 | 61.0 | 358.0 | 95.0 |
145 rows × 5 columns
covid_BR_NE = covid_BR.set_index('data').query('regiao == "Nordeste"')['obitosNovos'].groupby('data').sum()/2
covid_BR_NE.name = 'obitos_NE'
covid_BR_SE = covid_BR.set_index('data').query('regiao == "Sudeste"')['obitosNovos'].groupby('data').sum()/2
covid_BR_SE.name = 'obitos_SE'
covid_BR_NE_SE = pd.concat([covid_BR_NE,covid_BR_SE], axis=1)
covid_BR_NE_SE
| obitos_NE | obitos_SE | |
|---|---|---|
| data | ||
| 2020-02-25 | 0.0 | 0.0 |
| 2020-02-26 | 0.0 | 0.0 |
| 2020-02-27 | 0.0 | 0.0 |
| 2020-02-28 | 0.0 | 0.0 |
| 2020-02-29 | 0.0 | 0.0 |
| ... | ... | ... |
| 2020-07-14 | 315.0 | 682.0 |
| 2020-07-15 | 347.0 | 528.0 |
| 2020-07-16 | 373.0 | 611.0 |
| 2020-07-17 | 257.0 | 517.0 |
| 2020-07-18 | 292.0 | 358.0 |
145 rows × 2 columns
covid_BR_reg.hist(figsize = (10,8), bins=30);
covid_BR_NE_SE.hist(figsize = (14,7));
covid_BR_NE_SE.plot.hist(bins=30, figsize = (10,8));
covid_BR_NE_SE.plot.hist(alpha=0.5, bins=30, figsize = (10,8));
covid_BR_reg.plot.hist(alpha=0.5, bins=30);
covid_BR_reg.plot.hist(bins=30);
BoxPlot¶
O boxplot representa a variação dos dados de uma variável, por meio de uma caixa, onde são apresentados os quartis, e retas apresentando os limites inferior e superior dos dados. Os valores discrepantes ou outliers são plotados como pontos individuais.
Para criar um BoxPlot, basta utilizar plot(kind = 'box'). Também podemos criar BoxPlots utilizando o método plot.box(). As duas formas são equivalentes. O argumento vert=False faz com que os BoxPlots fiquem horizontais.
covid_regioes_obitosDiarios = pd.DataFrame()
regioes = covid_BR.query('regiao != "Brasil"')['regiao'].drop_duplicates().array
for regiao in regioes:
temp_series = covid_BR.set_index('data').query('regiao == @regiao')['obitosNovos'].groupby('data').sum()/2
#Obs.: Utilizamos @ na frente do nome da variável para utilizar o valor da variável no query.
temp_series.name = 'obitos_' + regiao
covid_regioes_obitosDiarios = pd.concat([covid_regioes_obitosDiarios, temp_series], axis=1)
covid_regioes_obitosDiarios.index = pd.to_datetime(covid_regioes_obitosDiarios.index)
covid_regioes_obitosDiarios.tail()
| obitos_Norte | obitos_Nordeste | obitos_Sudeste | obitos_Sul | obitos_Centro-Oeste | |
|---|---|---|---|---|---|
| data | |||||
| 2020-07-14 | 76.0 | 315.0 | 682.0 | 139.0 | 88.0 |
| 2020-07-15 | 65.0 | 347.0 | 528.0 | 130.0 | 163.0 |
| 2020-07-16 | 97.0 | 373.0 | 611.0 | 105.0 | 136.0 |
| 2020-07-17 | 121.0 | 257.0 | 517.0 | 129.0 | 139.0 |
| 2020-07-18 | 61.0 | 292.0 | 358.0 | 95.0 | 115.0 |
covid_regioes_obitosDiarios.plot.box(figsize=(10,10));
covid_regioes_obitosDiarios.plot.box(figsize=(10,10), vert=False);