Gráficos em Python

A matplotlib é uma biblioteca de plotagem para a linguagem de programação Python, com sua extensão matemática numérica NumPy. Para sua utilização, instale o pacote através do comando "sudo apt-get install python-pandas". Veja um script com alguns exemplos de uso (testado em Python 2.7.6) para plotar uma série temporal de três sequências numéricas (com o eixo x mostrando datas):

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
import sys
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as md
import dateutil

# Diretorio atual
path = os.path.dirname(os.path.realpath(__file__))
# Dia com os dados a serem plotados
dia = sys.argv[1:][0]
# Arquivo com dados
arquivo = path + '/dados/indices_' + dia + '.txt'
# Arquivo de imagem com grafico
figname = path + '/dados/Indices_' + dia + '.png'

# Ler arquivo e gravar dados em variavel
dados = pd.read_csv(arquivo, delimiter=',')
# Contar quantos numeros sao positivos
count = sum(x > 0 for x in dados.ss)
# Contar numero de linhas da tabela de dados
total = len(dados)
# Calcular percentual de numeros positivos
percentual = (float(count)*100.0)/float(total)

# String para do grafico
titulo = dia + " Estatistica: " + str(count) + "/" + str(total) + " => " + str(round(percentual,1)) + "%"
# Definir DPI
my_dpi=96
# Definir tamanho da imagem em pixeis
plt.figure(figsize=(1200/my_dpi, 800/my_dpi), dpi=my_dpi)
# Formatar eixo x com data: ano-mes-dia hora
dates = [dateutil.parser.parse(i) for i in dados.data]
xfmt = md.DateFormatter('%Y-%m-%d %Hh')
ax=plt.gca()
ax.xaxis.set_major_formatter(xfmt)
plt.xticks(rotation=30)
# Plotar 3 series de dados em funcao da data (cores definidas automaticamente)
plt.plot(dates, dados.obs, label="observado")
plt.plot(dates, dados.prev, label="previsto")
plt.plot(dates, dados.cor, label="correcao")
# Definir label, titulo e quadro com legenda
plt.ylabel("Variavel")
plt.title(estacao,fontsize=30)
plt.legend()
# Abre janela com grafico para visualizacao
plt.show()
# Salva figura em arquivo
plt.savefig(figname)

## Opcao para eixo com strings ##
# Criar vetor com mesmo tamanho do vetor de nomes
#x = range(0,total)
# Vetor de nomes
#my_xticks = dados.estacao
#ax=plt.gca()
# Ligar grid horizontal e vertical
#ax.yaxis.grid(True)
#ax.xaxis.grid(True)
# Plotar duas series de dados em funcao de sequencia numerica (cores definidas no codigo)
#plt.xticks(x, dados.estacao, rotation=30, fontsize=8)
#plt.plot(x, dados.obs, 'bo-', label="observao")
#plt.plot(x, dados.prev, 'go-', label="previsto")
#plt.plot(x, dados.cor, 'ro-', label="corrigido")

Esse script recebe uma data como argumento ao ser executado na linha de comando. Veja um exemplo:

$ python grafico.py 2016-03-03

Também precisa de um arquivo de dados cuja primeira linha tenha um cabeçalho com os nomes de cada coluna (acessada por "nome_da_tabela.nome_da_coluna"). Note, no calculo percentual realizado, como os números utilizados são inteiros, o resultado da conta será um inteiro também. Para resultar em um número real, os números da conta devem ser convertidos para float. A função "round" arredonda o valor para o número de casas decimais informado.

Veja um exemplo de gráfico gerado com o script acima:

grafico_python

A opção comentada mais abaixo no código tem um truque para imprimir o eixo x com strings. Como só dá pra entrar com números nos eixos, cria-se um vetor numérico ordenado de 0 até o mesmo tamanho do vetor de nomes. Depois, basta criar a variável "my_xticks" para receber o vetor de nomes e usar a função "xticks".

Segue outro script para gerar um gráfico de três séries temporais. Nesse caso, serão utilizados dois eixos y (também está comentado no código para usar somente um eixo y).

#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
import sys
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as dates
from datetime import datetime

# Definir arquivos e dados
path = os.path.dirname(os.path.realpath(__file__))
lugar = sys.argv[1:][0]
arquivo = path + '/output/prev_' + lugar + '.csv'
dados = pd.read_csv(arquivo, delimiter=',')

# converter data+hora para formato do matplotlib
x_orig = dados.tempo
x = [datetime.strptime(d, '%Y-%m-%d %H:%M:%S') for d in x_orig]

# Definir tamanho da figura
my_dpi=96
fig = plt.figure(figsize=(1200/my_dpi, 800/my_dpi), dpi=my_dpi)

fig, ax1 = plt.subplots()
plt.gca().xaxis.set_major_formatter(dates.DateFormatter('%d/%m-%Hh'))
plt.gca().xaxis.set_major_locator(dates.DayLocator())

## Opção com 1 eixo y
#plt.plot(x,dados.fsi, marker='o', linestyle='')
#plt.plot(x,dados.vis, marker='o', linestyle='')
#plt.plot(x,dados.h, marker='o', linestyle='')
#plt.minorticks_on()
#plt.grid(which='major', linestyle='--')
#plt.grid(which='minor', linestyle=':')
#plt.gcf().autofmt_xdate()

## Opção com 2 eixos y
ax1.set_ylabel('VIS,H', color='r')
ax1.tick_params('y', colors='r')
lns1 = plt.plot(x,dados.vis, marker='o', linestyle='', color='r')
lns2 = plt.plot(x,dados.h, marker='o', linestyle='', color='y')
plt.minorticks_on()
plt.grid(which='major', linestyle='--')
plt.grid(which='minor', linestyle=':')
plt.gcf().autofmt_xdate()
ax2 = ax1.twinx()
lns3 = ax2.plot(x,dados.fsi, marker='o', linestyle='', color='b')
ax2.set_ylabel('FSI', color='b')
ax2.tick_params('y', colors='b')

## Legenda abaixo do gráfico
#plt.legend(['FSI', 'VIS', 'H'], loc='upper right')
#lns = lns1+lns2+lns3
#labs = [l.get_label() for l in lns]
#ax.legend(lns, labs, loc=0)
ax1.legend(loc='upper left', bbox_to_anchor=(0.1, -0.15), shadow=True, ncol=5)
ax2.legend(loc='upper left', bbox_to_anchor=(0.6, -0.15), shadow=True, ncol=5)

## Título
titulo = lugar + ' - teste'
plt.suptitle(titulo, fontsize=18)

## Salvar figura
figname = path + '/output/prev_' + lugar + '.png'
plt.savefig(figname)

#plt.show()
#sys.exit("fim de teste")

Outra diferença para o gráfico gerado com o outro script é que ele possui grades (principal e secundária), pontos em vez de linhas e a legenda em quadros fora da área de plotagem (está comentada uma opção para colocar todas as variáveis em um mesmo bloco, mas precisa definir um eixo ax comum para todas as séries). Veja a figura gerada:

Mais opções podem ser vistas na documentação do matplotlib.

Compartilhe o link desse texto, mas se for copiar algum trecho, cite a fonte. Valorize nosso trabalho.
Mais informações na licença de uso do site.