Auditoria Automàtica de Licitacions de TMB i FGC amb Python: Transparència i Control Públic
Objectiu: Aquest script en Python ha estat dissenyat per ajudar a la Sindicatura de Comptes, l'OLAF o qualsevol entitat de control a auditar automàticament les licitacions i adjudicacions de contractes públics per part de Transports Metropolitans de Barcelona (TMB) i Ferrocarrils de la Generalitat de Catalunya (FGC).
L'script analitza conjunts de dades de contractació pública per detectar patrons sospitosos, com adjudicacions recurrents al mateix proveïdor, imports fraccionats, terminis atípics o processos amb baixa concurrència.
El model pot integrar-se fàcilment amb fonts com Plataforma de Contractació Pública de Catalunya, Gencat Open Data, o portals europeus mitjançant connectors GTFS o APIs obertes. A més, ofereix un informe visual interactiu per identificar riscos, generar alertes i facilitar la presa de decisions per part dels auditors.
Funcionalitats clau:
- Importació i neteja de dades obertes de contractes.
- Anàlisi de concentració d’adjudicacions per empresa.
- Detecció de fraccionament de contractes.
- Control d’imports, terminis i concurrència.
- Visualització gràfica amb mapes i taules interactives.
- Generació automàtica d'informes d'auditoria (PDF/HTML).
Aquest projecte és part d'una iniciativa per fomentar la transparència, la rendició de comptes i la justícia econòmica en la gestió dels recursos públics de mobilitat a Catalunya.
# Script base per a l'auditoria automatitzada de licitacions públiques de TMB i FGC import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns # 1. Importació de dades (des de CSV o API pública) df = pd.read_csv("contractes_tmb_fgc.csv") # Simulació de fitxer real # 2. Neteja i transformació df['Data_adjudicació'] = pd.to_datetime(df['Data_adjudicació']) df['Any'] = df['Data_adjudicació'].dt.year # 3. Anàlisi de concentració top_proveïdors = df['Empresa_adjudicatària'].value_counts().head(10) # 4. Fraccionament: mateix objecte contractat a intervals breus df['clau_contracte'] = df['Objecte_contracte'] + df['Import'].astype(str) fraccionats = df[df.duplicated(['clau_contracte'], keep=False)] # 5. Gràfiques de visualització plt.figure(figsize=(10,5)) sns.countplot(y='Empresa_adjudicatària', data=df, order=top_proveïdors.index) plt.title("Top 10 empreses adjudicatàries") plt.tight_layout() plt.savefig("empreses_top.png") # 6. Exportació d'informe df.to_html("informe_contractes.html") # Opcional: Enviament d’alertes si es detecten anomalies sospitosos = df[df['Import'] > 5000000] # Exemple: imports elevats sense concurrència if not sospitosos.empty: print("Alerta: hi ha contractes potencialment sospitosos.") # auditoria_contractes_tmb_fgc.py import pandas as pd import numpy as np import plotly.express as px from datetime import datetime import os # 1. Carrega de dades des d’un CSV amb dades públiques de contractes df = pd.read_csv("contractes_tmb_fgc.csv") # 2. Neteja bàsica df['Data_adjudicació'] = pd.to_datetime(df['Data_adjudicació'], errors='coerce') df['Import'] = pd.to_numeric(df['Import'], errors='coerce') df.dropna(subset=['Data_adjudicació', 'Import', 'Empresa_adjudicatària'], inplace=True) # 3. Columnes derivades df['Any'] = df['Data_adjudicació'].dt.year df['clau_contracte'] = df['Objecte_contracte'].astype(str) + "_" + df['Import'].astype(str) # 4. Anàlisi de concentració d’adjudicacions ranking_empreses = df['Empresa_adjudicatària'].value_counts().reset_index() ranking_empreses.columns = ['Empresa', 'Nombre_contractes'] # 5. Detecció de fraccionaments sospitosos df['Duplicat'] = df.duplicated(subset=['clau_contracte'], keep=False) fraccionaments = df[df['Duplicat']] # 6. Contractes sense concurrència o d’import elevat anomalies = df[(df['Nombre_ofertes'] <= 1) | (df['Import'] > 1000000)] # 7. Gràfics interactius fig1 = px.bar(ranking_empreses.head(10), x='Nombre_contractes', y='Empresa', title='Top 10 Empreses Adjudicatàries', orientation='h') fig2 = px.histogram(df, x='Any', nbins=10, title='Distribució de Contractes per Any') fig3 = px.scatter(anomalies, x='Data_adjudicació', y='Import', color='Empresa_adjudicatària', hover_data=['Objecte_contracte'], title='Contractes amb anomalies') # 8. Exportació HTML complet html_output = f"""Informe d'Auditoria Automàtica
Data generació: {datetime.now().strftime("%d/%m/%Y %H:%M:%S")}
Comments
Post a Comment