hedtorresca commited on
Commit
d52c998
Β·
verified Β·
1 Parent(s): b0fe83a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -70
app.py CHANGED
@@ -1,86 +1,106 @@
1
- import os
 
 
 
2
  import pandas as pd
3
  import plotly.express as px
4
  import gradio as gr
 
 
5
 
6
- # ──────────────────────────────────────────────
7
- # Cargar datos
8
- # ──────────────────────────────────────────────
9
- df = pd.read_excel("Base de Datos Prueba.xlsx", parse_dates=["FECHA_APERTURA"])
 
 
 
10
  df["MES"] = df["FECHA_APERTURA"].dt.to_period("M").dt.to_timestamp()
 
 
 
11
 
12
- # Coordenadas mΓ­nimas necesarias (aΓ±ade el resto si las usas)
13
- office_coords = {
14
- "MonterΓ­a Centro": (8.74733, -75.88145),
15
- "Bucaramanga Centro": (7.11935, -73.12274),
16
- "Principal": (4.7110, -74.0721),
17
- }
 
 
 
 
 
 
 
 
18
 
19
- # ──────────────────────────────────────────────
20
- # LΓ³gica
21
- # ──────────────────────────────────────────────
22
- def filtrar(start, end, productos, oficinas, min_amt, max_amt):
23
  d = df.copy()
24
- if start: d = d[d["FECHA_APERTURA"] >= pd.to_datetime(start)]
25
- if end: d = d[d["FECHA_APERTURA"] <= pd.to_datetime(end)]
26
- if productos: d = d[d["TIPO PRODUCTO"].isin(productos)]
27
- if oficinas: d = d[d["OFICINA"].isin(oficinas)]
28
- d = d[(d["MONTO_I"] >= min_amt) & (d["MONTO_I"] <= max_amt)]
29
 
30
- # GrΓ‘fico 1
31
- fig1 = px.bar(d.groupby("MES")["MONTO_I"].sum().reset_index(),
32
- x="MES", y="MONTO_I",
33
- title="Monto desembolsado por mes")
 
34
 
35
- # GrΓ‘fico 2
36
- fig2 = px.pie(d["TIPO PRODUCTO"].value_counts().reset_index(),
37
- names="index", values="TIPO PRODUCTO",
38
- title="DistribuciΓ³n por tipo de producto")
 
39
 
40
- # GrΓ‘fico 3
41
- fig3 = px.box(d, x="TIPO PRODUCTO", y="TASA",
42
- title="DistribuciΓ³n de tasas (%)")
 
43
 
44
- # GrΓ‘fico 4
45
  g = d.copy()
46
- g["lat"] = g["OFICINA"].map(lambda x: office_coords.get(x, (None, None))[0])
47
- g["lon"] = g["OFICINA"].map(lambda x: office_coords.get(x, (None, None))[1])
48
- g = g.dropna(subset=["lat", "lon"])
49
- fig4 = px.scatter_mapbox(g, lat="lat", lon="lon",
50
- hover_name="OFICINA", color="TIPO PRODUCTO",
51
- size="MONTO_I", zoom=4,
52
- mapbox_style="open-street-map",
53
- title="Mapa de aperturas")
54
- return fig1, fig2, fig3, fig4
55
-
56
- # ──────────────────────────────────────────────
57
- # Interfaz (Gradio v2.x)
58
- # ──────────────────────────────────────────────
59
- inputs = [
60
- gr.inputs.Textbox(label="Fecha inicio (YYYY-MM-DD)", default="2025-01-01"),
61
- gr.inputs.Textbox(label="Fecha fin (YYYY-MM-DD)", default="2025-03-31"),
62
- gr.inputs.CheckboxGroup(label="Tipo de Producto",
63
- choices=df["TIPO PRODUCTO"].dropna().unique().tolist()),
64
- gr.inputs.CheckboxGroup(label="Oficina",
65
- choices=list(office_coords.keys())),
66
- gr.inputs.Number(label="Monto mΓ­nimo", default=int(df["MONTO_I"].min())),
67
- gr.inputs.Number(label="Monto mΓ‘ximo", default=int(df["MONTO_I"].max())),
68
- ]
69
-
70
- outputs = [
71
- gr.outputs.Plot(label="Monto y Volumen"),
72
- gr.outputs.Plot(label="DistribuciΓ³n"),
73
- gr.outputs.Plot(label="Tasas"),
74
- gr.outputs.Plot(label="Geoespacial"),
75
- ]
76
 
77
- iface = gr.Interface(
78
- fn=filtrar,
79
- inputs=inputs,
80
- outputs=outputs,
81
- title="Dashboard Interactivo BancamΓ­a – Q1 2025",
82
- description="Filtra por fechas, producto, oficina y rango de montos para explorar aperturas."
83
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
85
  if __name__ == "__main__":
86
- iface.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))
 
 
1
+ ################################################################################
2
+ # DASHBOARD BANCAMÍA – Q1-2025 Β· Gradio v4
3
+ ################################################################################
4
+ import os, json, pathlib, datetime as dt
5
  import pandas as pd
6
  import plotly.express as px
7
  import gradio as gr
8
+ from geopy.geocoders import Nominatim
9
+ from geopy.extra.rate_limiter import RateLimiter
10
 
11
+ DATA_XLSX = "Base de Datos Prueba.xlsx" # <- ponlo junto a app.py
12
+ COORDS_JSON = "office_coords.json" # cachΓ© de coordenadas
13
+
14
+ # ──────────────────────────────────────────────────────────────────────────────
15
+ # 1. Cargar datos
16
+ # ──────────────────────────────────────────────────────────────────────────────
17
+ df = pd.read_excel(DATA_XLSX, parse_dates=["FECHA_APERTURA"])
18
  df["MES"] = df["FECHA_APERTURA"].dt.to_period("M").dt.to_timestamp()
19
+ oficinas = sorted(df["OFICINA"].dropna().unique().tolist())
20
+ productos = sorted(df["TIPO PRODUCTO"].dropna().unique().tolist())
21
+ min_amt, max_amt = int(df["MONTO_I"].min()), int(df["MONTO_I"].max())
22
 
23
+ # ──────────────────────────────────────────────────────────────────────────────
24
+ # 2. GeorreferenciaciΓ³n (1Βͺ vez usa Nominatim, luego lee cachΓ©)
25
+ # ──────────────────────────────────────────────────────────────────────────────
26
+ if pathlib.Path(COORDS_JSON).is_file():
27
+ office_coords = json.loads(open(COORDS_JSON).read())
28
+ else:
29
+ geolocator = Nominatim(user_agent="bancamia_dash")
30
+ geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)
31
+ office_coords = {}
32
+ for ofi in oficinas:
33
+ loc = geocode(f"{ofi}, Colombia")
34
+ office_coords[ofi] = (loc.latitude, loc.longitude) if loc else (None, None)
35
+ with open(COORDS_JSON, "w") as fh:
36
+ json.dump(office_coords, fh)
37
 
38
+ # ──────────────────────────────────────────────────────────────────────────────
39
+ # 3. FunciΓ³n principal
40
+ # ──────────────────────────────────────────────────────────────────────────────
41
+ def dashboard(start_date, end_date, tipos, ofis, monto):
42
  d = df.copy()
43
+ if start_date: d = d[d["FECHA_APERTURA"] >= pd.to_datetime(start_date)]
44
+ if end_date: d = d[d["FECHA_APERTURA"] <= pd.to_datetime(end_date)]
45
+ if tipos: d = d[d["TIPO PRODUCTO"].isin(tipos)]
46
+ if ofis: d = d[d["OFICINA"].isin(ofis)]
47
+ d = d[(d["MONTO_I"] >= monto[0]) & (d["MONTO_I"] <= monto[1])]
48
 
49
+ # ── Fig 1: barras mensuales
50
+ f1 = px.bar(d.groupby("MES")["MONTO_I"].sum().reset_index(),
51
+ x="MES", y="MONTO_I",
52
+ labels={"MES":"Mes","MONTO_I":"Monto (COP)"},
53
+ title="Monto desembolsado por mes")
54
 
55
+ # ── Fig 2: pie de distribuciΓ³n
56
+ pie_df = d["TIPO PRODUCTO"].value_counts().reset_index()
57
+ pie_df.columns = ["TIPO PRODUCTO","CANT"]
58
+ f2 = px.pie(pie_df, names="TIPO PRODUCTO", values="CANT",
59
+ title="DistribuciΓ³n por producto")
60
 
61
+ # ── Fig 3: boxplot tasas
62
+ f3 = px.box(d, x="TIPO PRODUCTO", y="TASA",
63
+ labels={"TASA":"Tasa (%)","TIPO PRODUCTO":"Producto"},
64
+ title="Tasas de interΓ©s")
65
 
66
+ # ── Fig 4: mapa
67
  g = d.copy()
68
+ g[["lat","lon"]] = g["OFICINA"].apply(
69
+ lambda x: pd.Series(office_coords.get(x,(None,None))))
70
+ g = g.dropna(subset=["lat","lon"])
71
+ f4 = px.scatter_mapbox(g, lat="lat", lon="lon",
72
+ color="TIPO PRODUCTO", size="MONTO_I", size_max=15,
73
+ hover_name="OFICINA", zoom=4,
74
+ mapbox_style="open-street-map",
75
+ title="Mapa de aperturas")
76
+ return f1, f2, f3, f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
+ # ──────────────────────────────────────────────────────────────────────────────
79
+ # 4. Interfaz Gradio v4
80
+ # ──────────────────────────────────────────────────────────────────────────────
81
+ with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
82
+ gr.Markdown("### Dashboard BancamΓ­a β€” Apertura de Productos Q1-2025")
83
+ with gr.Row():
84
+ with gr.Column(scale=1):
85
+ dp1 = gr.Date(label="Desde", value="2025-01-01")
86
+ dp2 = gr.Date(label="Hasta", value="2025-03-31")
87
+ dd1 = gr.Dropdown(tipos, multiselect=True, label="Producto")
88
+ dd2 = gr.Dropdown(oficinas, multiselect=True, label="Oficina")
89
+ rs = gr.RangeSlider(min_amt, max_amt,
90
+ value=[min_amt, max_amt],
91
+ label="Rango de monto (COP)")
92
+ btn = gr.Button("Actualizar")
93
+ with gr.Column(scale=3):
94
+ with gr.Tab("Monto"):
95
+ out1 = gr.Plot()
96
+ with gr.Tab("DistribuciΓ³n"):
97
+ out2 = gr.Plot()
98
+ with gr.Tab("Tasas"):
99
+ out3 = gr.Plot()
100
+ with gr.Tab("Mapa"):
101
+ out4 = gr.Plot()
102
+ btn.click(dashboard, [dp1, dp2, dd1, dd2, rs], [out1, out2, out3, out4])
103
 
104
  if __name__ == "__main__":
105
+ demo.launch(server_name="0.0.0.0",
106
+ server_port=int(os.environ.get("PORT", 7860)))