Um tutorial de primeiros passos para acessar a execução orçamentária da Secretaria de Educação do município usando Python e a biblioteca de análise de dados Pandas *
A API Console (entre na aba com esse nome neste link aqui) é uma interface que permite testar as diferentes consultas e obter a URL com os parâmetros desejados. Por exemplo, se deseja obter todos os contratos da Secretaria de Educação em 2017, basta entrar no item /consultaContrato e informar "2017" no campo anoContrato e "16" (código da Educação) no campo codOrgao. A URL resultante dessa consulta e que você vai usar nos passos seguintes é https://gatewayapi.prodam.sp.gov.br:443/financas/orcamento/sof/v2.1.0/consultaContrato?anoContrato=2017&codOrgao=16
Este é o script que consulta a API (para qualquer URL gerada acima) e transforma o arquivo obtido em formato json para um Data Frame do Pandas, a partir do qual será possível fazer as análises. Substitua a constante TOKEN pelo seu código de assinatura!
In [2]:
import pandas as pd
import requests
import json
import numpy as np
import matplotlib.pyplot as plt
In [39]:
TOKEN = '198f959a5f39a1c441c7c863423264'
base_url = "https://gatewayapi.prodam.sp.gov.br:443/financas/orcamento/sof/v2.1.0"
headers={'Authorization' : str('Bearer ' + TOKEN)}
anos = [2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018]
#Anos desejados na consulta; é possível consultar informações a partir de 2003
In [5]:
df_lista = []
a = 0
for ano in anos:
"""consulta todos os anos da lista acima"""
url_orcado = '{base_url}/consultarDespesas?anoDotacao={ano}&mesDotacao=12&codOrgao=16'.format(base_url=base_url, ano=ano)
request_orcado = requests.get(url_orcado,
headers=headers,
verify=True).json()
df_orcado = pd.DataFrame(request_orcado['lstDespesas'])
df_lista.append(df_orcado)
df_lista[a].loc[:,'anoExercicio'] = str(ano)
#adiciona uma coluna com o ano de exercício, já que esta informação não vem na API
a += 1
df_total = pd.concat(df_lista, axis=0, ignore_index=True)
In [6]:
df_total
Out[6]:
Uma visão dos valores orçados (valor atualizado no início do ano, após projeção mais adequada das receitas) e o liquidado, nos últimos meses do ano:
In [7]:
series = df_total[['anoExercicio', 'valOrcadoAtualizado','valLiquidado']].set_index('anoExercicio')
In [8]:
series = series[['valOrcadoAtualizado', 'valLiquidado']].divide(1000000000)
In [9]:
grafico1 = series[['valOrcadoAtualizado','valLiquidado']].plot(kind='bar', title ="Orçado x Liquidado", figsize=(15, 7), legend=True, fontsize=12)
grafico1.set_xlabel("Ano", fontsize=12)
grafico1.set_ylabel("Em bilhões de R$", fontsize=12)
plt.show(grafico1)
Empenho é o ato em que autoridade verifica a existência do crédito orçamentário e autoriza a execução da despesa (por exemplo, para realizar uma licitação). A partir daí, os valores vão sendo liquidados e pagos conforme a execução de um contrato.
A API fornece apenas uma página na consulta. O script abaixo checa a quantidade de páginas nos metadados da consulta e itera o número de vezes necessário para obter todas as páginas.
Vamos ver quanto a Secretaria Municipal de Educação empenhou de seu orçamento em 2017.
In [20]:
pagination = '&numPagina={PAGE}'
ano_empenho = 2017
In [ ]:
request_empenhos = requests.get('{base_url}/consultaEmpenhos?anoEmpenho={ano}&mesEmpenho=12&codOrgao=16'.format(base_url=base_url, ano=ano_empenho),
headers=headers, verify=True).json()
number_of_pages = request_empenhos['metadados']['qtdPaginas']
todos_empenhos = []
todos_empenhos = todos_empenhos + request_empenhos['lstEmpenhos']
if number_of_pages>1:
for p in range(2, number_of_pages+1):
request_empenhos = requests.get('{base_url}/consultaEmpenhos?anoEmpenho={ano}&mesEmpenho=12&codOrgao=16'.format(base_url=base_url, ano=ano_empenho) + pagination.format(PAGE=p),
headers=headers, verify=True).json()
todos_empenhos = todos_empenhos + request_empenhos['lstEmpenhos']
df_empenhos = pd.DataFrame(todos_empenhos)
In [4]:
pagination = '&numPagina={PAGE}'
Atenção: as consultas podem demorar horas, a depender da quantidade de anos requerida; verifique se o número de anos acima é realmente necessário; faça apenas isso uma vez, e guarde a base para análises futuras
In [40]:
df_empenhos_lista = []
for ano in anos:
request_empenhos = requests.get('{base_url}/consultaEmpenhos?anoEmpenho={ano}&mesEmpenho=12&codOrgao=16'.format(base_url=base_url, ano=ano),
headers=headers, verify=True).json()
number_of_pages = request_empenhos['metadados']['qtdPaginas']
todos_empenhos = []
todos_empenhos = todos_empenhos + request_empenhos['lstEmpenhos']
if number_of_pages>1:
for p in range(2, number_of_pages+1):
request_empenhos = requests.get('{base_url}/consultaEmpenhos?anoEmpenho={ano}&mesEmpenho=12&codOrgao=16'.format(base_url=base_url, ano=ano) + pagination.format(PAGE=p),
headers=headers, verify=True).json()
todos_empenhos = todos_empenhos + request_empenhos['lstEmpenhos']
df_empenhos = pd.DataFrame(todos_empenhos)
df_empenhos_lista.append(df_empenhos)
df_empenhos_serie = pd.concat(df_empenhos_lista, ignore_index=True)
In [41]:
df_empenhos_serie.columns
Out[41]:
Com os passos acima, fizemos a requisição de todas as páginas e convertemos o arquivo formato json em um DataFrame. Agora podemos trabalhar com a análise desses dado no Pandas. Para checar quantos registros existentes, vamos ver o final da lista (aqui havia apenas 2016-2017):
In [42]:
df_empenhos_serie.tail()
Out[42]:
In [43]:
modalidades = df_empenhos_serie.groupby('txtModalidadeAplicacao')['valTotalEmpenhado', 'valLiquidado'].sum()
In [44]:
modalidades
Out[44]:
In [15]:
# Outra maneira de fazer a mesma operação:
#pd.pivot_table(df_empenhos, values='valTotalEmpenhado', index=['txtModalidadeAplicacao'], aggfunc=np.sum)
In [45]:
despesas = pd.pivot_table(df_empenhos_serie,
values=['valLiquidado', 'valPagoExercicio'],
index=['numCpfCnpj', 'txtRazaoSocial', 'txtDescricaoProjetoAtividade'],
aggfunc=np.sum).sort_values('valPagoExercicio', axis=0, ascending=False, inplace=False, kind='quicksort', na_position='last')
In [46]:
despesas.head(15)
Out[46]:
In [47]:
fonte = pd.pivot_table(df_empenhos_serie,
values=['valLiquidado', 'valPagoExercicio'],
index=['txtDescricaoFonteRecurso'],
aggfunc=np.sum).sort_values('valPagoExercicio', axis=0, ascending=False, inplace=False, kind='quicksort', na_position='last')
In [48]:
fonte
Out[48]:
O objetivo deste tutorial não era fazer uma análise exaustiva da base, mas apenas mostrar o que é possível a partir do consumo da API. Você também pode salvar toda a base de empenhos num arquivo .csv e trabalhar no seu Excel (super te entendo). O Pandas também ajuda nisso! Assim:
In [50]:
df_empenhos_serie.to_csv('serie_empenhos.csv')
Pronto, seu arquivo está lá salvo no mesmo diretório deste jupyter notebook!