Skip to main content

FiscalPY

fiscalpy es un paquete de Python para facilitar la extracción, limpieza y análisis de datos fiscales y administrativos de Colombia.

Actualmente incluye herramientas para:

  • limpiar datos del Presupuesto General de la Nación (PGN);
  • limpiar y clasificar información de finanzas territoriales;
  • descargar datos de datos.gov.co mediante la API de Socrata;
  • generar reportes estandarizados de contratación pública a partir de datos de SECOP II.

Instalación

pip install fiscalpy

Para trabajar con la versión local del repositorio durante el desarrollo:

pip install -e .

¿Cómo usarla?

Presupuesto nacional

Para la limpieza del presupuesto nacional se cuenta con las funciones limpieza_gastos_pgn y limpieza_ingresos_pgn.

Los datos deben provenir directamente de los archivos publicados por el Ministerio de Hacienda y Crédito Público de Colombia, y la primera fila del archivo debe contener los nombres de las columnas.

import pandas as pd
from fiscalpy import limpieza_gastos_pgn, limpieza_ingresos_pgn

gastos = pd.read_excel("gastos.xlsx")
rentas = pd.read_excel("rentas.xlsx")

gastos_limpios = limpieza_gastos_pgn(gastos)
rentas_limpias = limpieza_ingresos_pgn(rentas)

El resultado son DataFrame normalizados y preparados para análisis estadístico y gráfico.

Finanzas territoriales

Para información territorial se incluyen las funciones:

  • limpieza_ingresos_territoriales
  • limpieza_gastos_territoriales
  • columnas_ingresos_territoriales

Las dos primeras permiten normalizar datos de ingresos y gastos territoriales, tanto de ejecución como de programación.

import pandas as pd
from fiscalpy import limpieza_ingresos_territoriales

df = pd.read_excel("datos_ejecucion_2025.xlsx")

norm_data = limpieza_ingresos_territoriales(
    df,
    tipo="ejecucion",
)

En el argumento tipo se debe indicar si se trabaja con datos de "ejecucion" o de "programacion".

La función columnas_ingresos_territoriales agrega columnas de clasificación que permiten agrupar los ingresos territoriales con distintos niveles de detalle. Entre las agrupaciones disponibles se encuentran:

  • recursos propios, transferencias y recursos de capital;
  • ingresos tributarios, ingresos no tributarios, transferencias y recursos de capital;
  • principales fuentes de ingreso relevantes para municipios y departamentos.

Extracción de datos abiertos

datos_abiertos

La función datos_abiertos descarga información directamente desde datos.gov.co utilizando la API de Socrata y devuelve el resultado como un pandas.DataFrame.

from fiscalpy import datos_abiertos

La función recibe el identificador Socrata del conjunto de datos, un token de aplicación y, opcionalmente, filtros para limitar la consulta.

from datetime import date
from fiscalpy import datos_abiertos

filtros = {
    "nit_entidad": {"in": ["900948953"]},
    "fecha_de_firma": {
        "gte": date(2022, 1, 1),
        "lt": date(2023, 1, 1),
    },
}

df = datos_abiertos(
    dataset_id="jbjy-vk9h",
    token="TU_TOKEN_SOCRATA",
    filtros=filtros,
)

En este ejemplo se consulta el dataset identificado por jbjy-vk9h y se conservan únicamente los registros que cumplen los filtros especificados.

Filtros simples

Para una igualdad se puede pasar directamente el valor:

df = datos_abiertos(
    dataset_id="jbjy-vk9h",
    token="TU_TOKEN_SOCRATA",
    filtros={"estado_contrato": "En ejecución"},
)

Una lista se interpreta como una condición IN:

filtros = {
    "estado_contrato": ["En ejecución", "Terminado"]
}

También es posible suministrar filtros simples como argumentos adicionales:

df = datos_abiertos(
    "jbjy-vk9h",
    "TU_TOKEN_SOCRATA",
    nit_entidad="900948953",
)

Filtros avanzados

Los operadores disponibles son:

Operador Condición SoQL
eq =
ne !=
gt >
gte >=
lt <
lte <=
in IN (...)
not_in NOT IN (...)
between BETWEEN ... AND ...
not_between NOT BETWEEN ... AND ...
like LIKE
not_like NOT LIKE
is_null IS NULL
not_null IS NOT NULL

Por ejemplo:

filtros = {
    "valor_del_contrato": {"gte": 100_000_000},
    "fecha_de_firma": {
        "between": [date(2024, 1, 1), date(2024, 12, 31)]
    },
    "estado_contrato": {"not_in": ["Borrador"]},
}

La función pagina automáticamente las consultas en bloques de hasta 50.000 registros, por lo que puede descargar resultados que superen ese límite sin que el usuario tenga que manejar manualmente los offset de la API.

Para consultas frecuentes o de mayor tamaño se recomienda utilizar un token de aplicación de Socrata.

Reportes

reporte_contratacion

reporte_contratacion genera un reporte descriptivo de contratación pública a partir de un DataFrame de contratos y una tabla de IPC.

from fiscalpy import reporte_contratacion

La función prepara los datos, expresa los valores monetarios en precios constantes, construye tablas de análisis y, opcionalmente, exporta un archivo Excel y gráficos en formato SVG.

Un flujo típico consiste en descargar primero los contratos con datos_abiertos y luego generar el reporte:

import pandas as pd
from fiscalpy import datos_abiertos, reporte_contratacion

contratos = datos_abiertos(
    dataset_id="jbjy-vk9h",
    token="TU_TOKEN_SOCRATA",
    filtros={
        "nit_entidad": "900948953",
    },
)

ipc = pd.read_excel("datos_macro.xlsx")

resultado = reporte_contratacion(
    contratos,
    ipc,
    salida="salidas_contratacion",
    anio_base=2026,
    crecimiento_ipc_base=0.069,
    verbose=True,
)

Datos requeridos

El DataFrame de contratación debe contener, como mínimo, las siguientes columnas:

id_contrato
fecha_de_firma
valor_del_contrato
duraci_n_del_contrato
dias_adicionados
proveedor_adjudicado
tipo_de_contrato
modalidad_de_contratacion
estado_contrato

Estos nombres corresponden a la estructura utilizada por los datos de contratos electrónicos de SECOP II en datos.gov.co.

La tabla de IPC debe ser un DataFrame con las columnas:

Año
IPC

Por ejemplo:

ipc.head()
    Año      IPC
0  2022   120.27
1  2023   131.35
2  2024   140.12
3  2025   152.27

Año base y precios constantes

El argumento anio_base determina el año al que se llevan todos los valores monetarios.

resultado = reporte_contratacion(
    contratos,
    ipc,
    salida="salidas_contratacion",
    anio_base=2026,
    crecimiento_ipc_base=0.069,
)

Si el IPC del año base ya se encuentra en la tabla de IPC, la función lo utiliza directamente. Si todavía no está disponible, crecimiento_ipc_base permite construirlo a partir del IPC del año inmediatamente anterior.

Por ejemplo, 0.069 representa un crecimiento de 6,9 %.

Archivos generados

Por defecto se crea una estructura similar a:

salidas_contratacion/
├── tablas_analisis_contratacion.xlsx
└── graficos_svg/
    ├── 01_contratos_anio.svg
    ├── 02_monto_anio.svg
    ├── 03_promedio_anio.svg
    ├── ...
    └── 15_dias_adicionados.svg

El archivo Excel contiene tablas sobre, entre otros temas:

  • número y monto de contratos por año y mes;
  • rangos de monto diario;
  • monto diario ajustado por días adicionados;
  • proveedores con mayores montos y mayor número de contratos;
  • tipos y modalidades de contratación;
  • estado de los contratos;
  • distribución de días adicionados;
  • contratos con montos diarios elevados;
  • contratos con más de 100 días adicionados.

Los gráficos se exportan como SVG para conservar elementos vectoriales y texto editable. Si se requiere una copia en PNG, se puede utilizar:

resultado = reporte_contratacion(
    contratos,
    ipc,
    salida="salidas_contratacion",
    exportar_png=True,
)

Resultado en Python

Además de escribir archivos, la función devuelve un diccionario con los resultados del análisis:

resultado.keys()
dict_keys(['datos', 'ipc', 'tablas', 'graficos', 'excel', 'metadata'])

Los principales componentes son:

  • resultado["datos"]: base de contratación preparada y enriquecida;
  • resultado["ipc"]: tabla de IPC utilizada en el cálculo;
  • resultado["tablas"]: diccionario con todas las tablas analíticas;
  • resultado["graficos"]: rutas de los gráficos generados;
  • resultado["excel"]: ruta del archivo Excel generado;
  • resultado["metadata"]: información general del reporte.

Por ejemplo, las tablas pueden consultarse directamente sin abrir el Excel:

resultado["tablas"]["resumen_general"]
resultado["tablas"]["por_anio"]
resultado["tablas"]["proveedores"]
resultado["tablas"]["contratos_mas_100_dias"]

Opciones de exportación

La generación de archivos puede controlarse con los siguientes argumentos:

resultado = reporte_contratacion(
    contratos,
    ipc,
    salida="salidas_contratacion",
    exportar_excel=True,
    exportar_graficos=True,
    exportar_png=False,
)

Esto permite utilizar reporte_contratacion tanto como generador de entregables como dentro de otros flujos de análisis en Python.

Reporte de ejecución presupuestal

reporte_ejecucion permite homologar la ejecución presupuestal del año corriente con la serie histórica y generar un conjunto estandarizado de gráficos de ejecución del PGN.

Ejemplo

import pandas as pd
from fiscalpy import reporte_ejecucion

historico = pd.read_excel(
    "ejecucion_2019_2025.xlsx"
)

actual = pd.read_excel(
    "ejecucion_2026.xlsx",
    sheet_name="Vigencia",
    skiprows=3,
)

macro = pd.read_csv(
    "datos_macro.csv"
)

resultado = reporte_ejecucion(
    historico=historico,
    actual=actual,
    macro=macro,
    salida="salidas_ejecucion",
    entidades=[4106, 4602],
    anio_actual=2026,
    mes_corte="agosto",
)

## Licencia

Este proyecto se distribuye bajo la licencia incluida en el repositorio.

Metadata

Release files for fiscalpy 0.0.20

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fiscalpy 0.0.20
File Size Uploaded
fiscalpy-0.0.20.tar.gz 41.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fiscalpy 0.0.20
File Interpreter ABI Platform
fiscalpy-0.0.20-py3-none-any.whl Python 3 none any Details

Total release size: 80.8 kB

Release files / fiscalpy-0.0.20.tar.gz

Download URL fiscalpy-0.0.20.tar.gz
Size 41.5 kB
Tags Source
SHA-256 checksum
How to use checksums
a12db82dd8b33914855ec4ae96cb45a186c604dc6a3fcba69d9a6abef8d5109a
BLAKE2b-256 checksum
How to use checksums
bf020769b3ff8ddee4ab696688a76332f59dfd7c67a49822922d465d6d245886
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.7

Release files / fiscalpy-0.0.20-py3-none-any.whl

Download URL fiscalpy-0.0.20-py3-none-any.whl
Size 39.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
93da073c47f910f438c64383a5fb2a25a03feece72ea8ba251979efd1bf85eec
BLAKE2b-256 checksum
How to use checksums
81d374d3b09f78d71298e5055ccd0efa8ee50f91deca1af228a787a3d1009cb6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.7

Release history Release notifications | RSS feed

0.0.22

2 release files

0.0.21

2 release files

This release

0.0.20 This release

2 release files

0.0.19

2 release files

0.0.18

2 release files

0.0.17

2 release files

0.0.16

2 release files

0.0.15

2 release files

0.0.14

2 release files

0.0.13

2 release files

0.0.12

2 release files

0.0.11

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page