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.comediante 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_territorialeslimpieza_gastos_territorialescolumnas_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.21
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fiscalpy-0.0.21.tar.gz | 42.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fiscalpy-0.0.21-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 81.8 kB
Release files / fiscalpy-0.0.21.tar.gz
| Download URL | fiscalpy-0.0.21.tar.gz |
|---|---|
| Size | 42.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
656bb7ccccfca878829f66c1176f43cc61fa881738a04bb75a9c98de81ba6854
|
|
BLAKE2b-256 checksum How to use checksums |
1c3a8c943306c4e359d0a583d5a8fb0a9ed9f96cbc828b199f2528e50bce84c8
|
| 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.21-py3-none-any.whl
| Download URL | fiscalpy-0.0.21-py3-none-any.whl |
|---|---|
| Size | 39.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3e83951fcfb15b0588d68d774de1bb9f5a961f736311731a23de46db9c587923
|
|
BLAKE2b-256 checksum How to use checksums |
4f0b0f061023c6624ea7444d263762ae8d23469c99b93d403fa99ac79f3cf8a5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.7
|