Explorando as despesas da cidade de São Paulo

Um tutorial de primeiros passos para acessar a execução orçamentária do município usando Python e a biblioteca de análise de dados Pandas *

Passo 1. Cadastro na API e token de acesso

  • Acessar a Vitrine de APIs da Prodam:https://api.prodam.sp.gov.br/store/
  • Selecione a API do SOF
  • Clique em "Inscrever-se"
  • Acesse o menu "Minhas assinaturas"
  • Gere uma chave de acesso de produção; coloque um valor de validade negativo, para evitar que expire
  • Copie o Token de Acesso

Passo 2. Teste na API Console

A API Console é 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 é https://gatewayapi.prodam.sp.gov.br:443/financas/orcamento/sof/v2.1.0/consultaContrato?anoContrato=2017&codOrgao=16

Passo 3. Mãos ao Pandas!

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 [168]:
import pandas as pd
import requests
import json
import numpy as np

In [169]:
TOKEN = '198f959a5f39a1c441c7c863423264'
base_url = "https://gatewayapi.prodam.sp.gov.br:443/financas/orcamento/sof/v2.1.0"
headers={'Authorization' : str('Bearer ' + TOKEN)}

Orçamento

Primeiro, vamos ter uma visão geral do que foi orçado para a Secretaria Municipal de Saúde neste ano, bem como os valores congelados e já executados. Isso é possível com a consulta "Despesas"


In [170]:
url_orcado = '{base_url}/consultarDespesas?anoDotacao=2017&mesDotacao=08&codOrgao=84'.format(base_url=base_url)

In [171]:
request_orcado = requests.get(url_orcado,
                                headers=headers,
                                verify=True).json()

In [172]:
df_orcado = pd.DataFrame(request_orcado['lstDespesas'])

In [173]:
df_resumo_orcado = df_orcado[['valOrcadoInicial', 'valOrcadoAtualizado', 'valCongelado', 'valDisponivel', 'valEmpenhadoLiquido', 'valLiquidado']]

In [174]:
df_resumo_orcado


Out[174]:
valOrcadoInicial valOrcadoAtualizado valCongelado valDisponivel valEmpenhadoLiquido valLiquidado
0 8052053545 8.051585e+09 1.633544e+09 7.101136e+09 5.299343e+09 4.849363e+09

Empenhos

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. Vamos ver quanto a Secretaria Municipal de Saúde empenhou de seu orçamento em 2017.


In [175]:
url_empenho = '{base_url}/consultaEmpenhos?anoEmpenho=2017&mesEmpenho=08&codOrgao=84'.format(base_url=base_url)
pagination = '&numPagina={PAGE}'

In [176]:
request_empenhos = requests.get(url_empenho,
                                headers=headers,
                                verify=True).json()

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:


In [177]:
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(url_empenho + pagination.format(PAGE=p), headers=headers, verify=True).json()
        todos_empenhos = todos_empenhos + request_empenhos['lstEmpenhos']

In [178]:
df_empenhos = pd.DataFrame(todos_empenhos)

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:


In [179]:
df_empenhos.tail()


Out[179]:
anoEmpenho codCategoria codElemento codEmpenho codEmpresa codFonteRecurso codFuncao codGrupo codItemDespesa codModalidade ... txtDescricaoUnidade txtGrupoDespesa txtModalidadeAplicacao txtRazaoSocial valAnuladoEmpenho valEmpenhadoLiquido valLiquidado valPagoExercicio valPagoRestos valTotalEmpenhado
16014 2017 3 39 62344 01 00 10 3 01 90 ... Coordenadoria Regional de Saúde Centro Outras Despesas Correntes Aplicações Diretas PROVAC TERCEIRIZAÇÃO DE MÃO DE OBRA LTDA 0.0 235316.08 0.00 0.00 0 235316.08
16015 2017 3 39 64962 01 00 10 3 03 90 ... Coordenadoria Regional de Saúde Centro Outras Despesas Correntes Aplicações Diretas COORDENADORIA REGIONAL DE SAÚDE CENTRO OESTE -... 0.0 9750.00 9750.00 9750.00 0 9750.00
16016 2017 3 39 64945 01 00 10 3 03 90 ... Coordenadoria Regional de Saúde Centro Outras Despesas Correntes Aplicações Diretas COORDENADORIA REGIONAL DE SAÚDE CENTRO OESTE -... 0.0 32463.08 32463.08 32463.08 0 32463.08
16017 2017 3 39 65829 01 00 10 3 03 90 ... Coordenadoria Regional de Saúde Centro Outras Despesas Correntes Aplicações Diretas COORDENADORIA REGIONAL DE SAÚDE CENTRO OESTE -... 0.0 34033.73 34033.73 34033.73 0 34033.73
16018 2017 3 39 65007 01 00 10 3 03 90 ... Coordenadoria Regional de Saúde Centro Outras Despesas Correntes Aplicações Diretas COORDENADORIA REGIONAL DE SAÚDE CENTRO OESTE -... 0.0 4730.52 4730.52 4730.52 0 4730.52

5 rows × 41 columns

Modalidades de Aplicação

Aqui vemos a quantidade de recursos aplicados na Saúde, a título de exemplo, por Modalidade -- se é aplicação na rede direta ou repasse a organizações sociais. Note que o mesmo poderia ser feito para qualquer órgão, ou mesmo para a Prefeitura como um todo:


In [181]:
modalidades = df_empenhos.groupby('txtModalidadeAplicacao')['valTotalEmpenhado', 'valLiquidado'].sum()

In [182]:
modalidades


Out[182]:
valTotalEmpenhado valLiquidado
txtModalidadeAplicacao
Aplicações Diretas 2.682362e+09 2.043195e+09
Transferências a Instituições Privadas sem Fins Lucrativos 3.105583e+09 2.806168e+09

In [183]:
# Outra maneira de fazer a mesma operação:
#pd.pivot_table(df_empenhos, values='valTotalEmpenhado', index=['txtModalidadeAplicacao'], aggfunc=np.sum)

Maiores despesas de 2017

Aqui vamos produzir a lista das 15 maiores despesas da Saúde neste ano:


In [184]:
despesas = pd.pivot_table(df_empenhos, 
                              values=['valLiquidado', 'valPagoExercicio'], 
                              index=['numCpfCnpj', 'txtRazaoSocial', 'txtDescricaoPrograma'], 
                              aggfunc=np.sum).sort_values('valPagoExercicio', axis=0, ascending=False, inplace=False, kind='quicksort', na_position='last')

In [185]:
despesas.head(15)


Out[185]:
valLiquidado valPagoExercicio
numCpfCnpj txtRazaoSocial txtDescricaoPrograma
00000000999962 FOLHA DE PAGAMENTO _ EXECUTIVO Suporte Administrativo 8.205301e+08 8.205301e+08
61699567000273 SPDM ASSOCIAÇÃO PAULISTA PARA O DESENVOLVIMENTO DA MEDICINA Ações e serviços da saúde 5.549547e+08 5.549547e+08
60742616000160 CASA DE SAUDE SANTA MARCELINA Ações e serviços da saúde 4.195546e+08 4.195546e+08
68311216000101 ASSOCIAÇÃO SAUDE DA FAMILIA Ações e serviços da saúde 4.174579e+08 4.174579e+08
66518267000264 CENTRO DE ESTUDOS E PESQUISAS DR.JOAO AMORIM Ações e serviços da saúde 3.384486e+08 3.384486e+08
09652823000176 IABAS - INSTITUTO DE ATENÇÃO BÁSICA E AVANÇADA A SAÚDE Ações e serviços da saúde 1.660016e+08 1.660016e+08
60922168002634 ASSOCIAÇÃO CONGREGACAO DE SANTA CATARINA Ações e serviços da saúde 1.369534e+08 1.369534e+08
61687356000130 SERVIÇO SOCIAL DA CONSTRUÇÃO CIVIL DO ESTADO DE SP - SECONCI - SP Ações e serviços da saúde 1.355018e+08 1.355018e+08
61599908000158 REAL E BENEMERITA ASSOCIAÇÃO PORTUGUESA DE BENEFICENCIA Ações e serviços da saúde 1.158009e+08 1.152467e+08
60765823000130 SOCIEDADE BENEFICENTE ISRAELITA BRAS HOSPITAL ALBERT EINSTEIN Ações e serviços da saúde 9.983917e+07 9.983917e+07
57571275000100 FUNDAÇÃO DO ABC Ações e serviços da saúde 8.802562e+07 8.802562e+07
62779145000190 IRMANDADE DA SANTA CASA DE MISERICORDIA SP Ações e serviços da saúde 7.392324e+07 7.392324e+07
51232221000126 ASSOCIACAO COMUNITARIA MONTE AZUL Ações e serviços da saúde 6.971725e+07 6.971725e+07
61699567000192 SPDM - ASSOCIAÇÃO PAULISTA PARA O DESENVOLVIMENTO DA MEDICINA Ações e serviços da saúde 6.598290e+07 6.598290e+07
66518267000183 CENTRO DE ESTUDOS E PESQUISAS DR JOAO AMORIM Ações e serviços da saúde 5.847394e+07 5.847394e+07

Fontes de recursos

Agrupamento dos empenhos por fonte de recursos:


In [186]:
fonte = pd.pivot_table(df_empenhos, 
                       values=['valLiquidado', 'valPagoExercicio'], 
                       index=['txtDescricaoFonteRecurso'], 
                       aggfunc=np.sum).sort_values('valPagoExercicio', axis=0, ascending=False, inplace=False, kind='quicksort', na_position='last')

In [187]:
fonte


Out[187]:
valLiquidado valPagoExercicio
txtDescricaoFonteRecurso
Tesouro Municipal 3.792365e+09 3.753519e+09
Transferências Federais 1.041841e+09 1.027915e+09
Transferências Estaduais 1.515729e+07 3.743119e+06

Passo 4. Quer salvar um csv?

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 [167]:
df_empenhos.to_csv('empenhos.csv')

Pronto, seu arquivo está lá salvo no mesmo diretório deste jupyter notebook!

Esse foi um panorama. Aos poucos -- e à medida que eu for aprendendo e o tempo permitir, também -- vou explorando outras formas de consulta, análise e visualização.

*Escrito por Fernanda Campagnucci. Agradecimentos especiais ao Fernando Paiva, pelas dicas de código para consumo da API, e aos colegas Eduardo Paiva e Marcelo Cabral, também gestores públicos entusiastas dos dados e do software livre, com quem venho aprendendo bastante