hedtorresca commited on
Commit
4342e2d
·
verified ·
1 Parent(s): c11cc73

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +137 -0
app.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import plotly.express as px
3
+ import gradio as gr
4
+
5
+ # -------------------------------
6
+ # Cargar datos
7
+ # -------------------------------
8
+ df = pd.read_excel("Base de Datos Prueba.xlsx", parse_dates=["FECHA_APERTURA"])
9
+ df["MES"] = df["FECHA_APERTURA"].dt.to_period("M").dt.to_timestamp()
10
+
11
+ # -------------------------------
12
+ # Coordenadas de oficinas (hard-code)
13
+ # -------------------------------
14
+ office_coords = {
15
+ "Montería Centro": (8.74733, -75.88145),
16
+ "Monteria": (8.74733, -75.88145),
17
+ "Bucaramanga Centro": (7.119349, -73.122741),
18
+ "Manizales": (5.068887, -75.51739),
19
+ "Caucasia": (7.98666, -75.18959),
20
+ "Pasto": (1.213607, -77.281104),
21
+ "Bello": (6.33734, -75.55835),
22
+ "Fusagasuga": (4.3370, -74.3544),
23
+ "Itagui": (6.1630, -75.6056),
24
+ "Sincelejo": (9.3040, -75.3978),
25
+ "Centro Medellín":(6.2442, -75.5812),
26
+ "Soacha": (4.5833, -74.2167),
27
+ "Principal": (4.7110, -74.0721), # Bogotá – sede principal
28
+ "San Juan": (7.02093, -75.62913),
29
+ "Perdomo": (1.1906, -77.5803),
30
+ "Ibague": (4.4389, -75.2322),
31
+ "Santa Marta Av. Libertador": (11.24079, -74.19904),
32
+ "Valledupar": (10.45924,-73.25321),
33
+ "Funza": (4.7570, -74.1188),
34
+ "Buenos Aires": (2.28889, -76.14583),
35
+ # …añade el resto de oficinas según el dataset…
36
+ }
37
+
38
+ # -------------------------------
39
+ # Funciones de análisis
40
+ # -------------------------------
41
+ def filter_data(start_date, end_date, products, zones, amount_range):
42
+ d = df.copy()
43
+ if start_date:
44
+ d = d[d["FECHA_APERTURA"] >= pd.to_datetime(start_date)]
45
+ if end_date:
46
+ d = d[d["FECHA_APERTURA"] <= pd.to_datetime(end_date)]
47
+ if products:
48
+ d = d[d["TIPO PRODUCTO"].isin(products)]
49
+ if zones:
50
+ d = d[d["OFICINA"].isin(zones)]
51
+ d = d[(d["MONTO_I"] >= amount_range[0]) & (d["MONTO_I"] <= amount_range[1])]
52
+ return d
53
+
54
+ def update_dashboard(start_date, end_date, products, zones, amount_range):
55
+ d = filter_data(start_date, end_date, products, zones, amount_range)
56
+
57
+ # 1. Monto desembolsado por mes
58
+ monthly = d.groupby("MES")["MONTO_I"].sum().reset_index()
59
+ fig1 = px.bar(
60
+ monthly, x="MES", y="MONTO_I",
61
+ labels={"MES":"Mes", "MONTO_I":"Monto (COP)"},
62
+ title="Monto Desembolsado por Mes"
63
+ )
64
+
65
+ # 2. Distribución de aperturas por producto
66
+ counts = d["TIPO PRODUCTO"].value_counts().reset_index()
67
+ counts.columns = ["TIPO PRODUCTO", "CANTIDAD"]
68
+ fig2 = px.pie(
69
+ counts, names="TIPO PRODUCTO", values="CANTIDAD",
70
+ title="Distribución de Aperturas por Tipo de Producto"
71
+ )
72
+
73
+ # 3. Distribución de tasa de interés
74
+ fig3 = px.box(
75
+ d, x="TIPO PRODUCTO", y="TASA",
76
+ labels={"TASA":"Tasa (%)","TIPO PRODUCTO":"Producto"},
77
+ title="Distribución de Tasa de Interés por Producto"
78
+ )
79
+
80
+ # 4. Mapa de aperturas por oficina
81
+ geo = d.copy()
82
+ geo["Latitude"] = geo["OFICINA"].map(lambda x: office_coords.get(x, (None,None))[0])
83
+ geo["Longitude"] = geo["OFICINA"].map(lambda x: office_coords.get(x, (None,None))[1])
84
+ geo = geo.dropna(subset=["Latitude", "Longitude"])
85
+ fig4 = px.scatter_mapbox(
86
+ geo, lat="Latitude", lon="Longitude",
87
+ color="TIPO PRODUCTO", size="MONTO_I", size_max=15,
88
+ hover_name="OFICINA", zoom=4, mapbox_style="open-street-map",
89
+ title="Aperturas por Ubicación de Oficina"
90
+ )
91
+
92
+ return fig1, fig2, fig3, fig4
93
+
94
+ # -------------------------------
95
+ # Interfaz Gradio
96
+ # -------------------------------
97
+ with gr.Blocks() as demo:
98
+ gr.Markdown("## Dashboard Interactivo Bancamía – Q1 2025")
99
+
100
+ with gr.Row():
101
+ with gr.Column(scale=1):
102
+ start_date = gr.DatePicker(label="Fecha inicio")
103
+ end_date = gr.DatePicker(label="Fecha fin")
104
+ products = gr.CheckboxGroup(
105
+ choices=df["TIPO PRODUCTO"].dropna().unique().tolist(),
106
+ label="Tipo de Producto"
107
+ )
108
+ zones = gr.CheckboxGroup(
109
+ choices=list(office_coords.keys()),
110
+ label="Oficina"
111
+ )
112
+ min_amt, max_amt = int(df["MONTO_I"].min()), int(df["MONTO_I"].max())
113
+ amount_range = gr.Slider(
114
+ minimum=min_amt, maximum=max_amt, value=[min_amt, max_amt],
115
+ step=1_000_000, label="Rango de Monto (COP)"
116
+ )
117
+ update_btn = gr.Button("Actualizar")
118
+
119
+ with gr.Column(scale=3):
120
+ with gr.Tabs():
121
+ with gr.TabItem("Monto y Volumen"):
122
+ chart1 = gr.Plot()
123
+ with gr.TabItem("Distribución"):
124
+ chart2 = gr.Plot()
125
+ with gr.TabItem("Tasas"):
126
+ chart3 = gr.Plot()
127
+ with gr.TabItem("Geoespacial"):
128
+ chart4 = gr.Plot()
129
+
130
+ update_btn.click(
131
+ fn=update_dashboard,
132
+ inputs=[start_date, end_date, products, zones, amount_range],
133
+ outputs=[chart1, chart2, chart3, chart4]
134
+ )
135
+
136
+ if __name__ == "__main__":
137
+ demo.launch()