Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,85 +1,236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
2 |
import pandas as pd
|
3 |
import folium
|
4 |
import gradio as gr
|
|
|
5 |
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
-
# Colores por línea (ajusta si agregas nuevas)
|
12 |
LINE_COLOR = {
|
13 |
"Línea 1": "red",
|
14 |
"Línea 2": "blue",
|
15 |
"BIAC": "green"
|
16 |
}
|
17 |
-
#
|
|
|
|
|
|
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
raise ValueError("El archivo debe contener columnas 'lat' y 'lon' con las coordenadas de cada municipio.")
|
24 |
-
return df
|
25 |
|
26 |
-
|
|
|
27 |
|
28 |
-
|
29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
all_areas.insert(0, "Todas")
|
31 |
-
all_lines = ["Todas"] + sorted(df['
|
32 |
|
33 |
-
|
34 |
-
|
35 |
m = folium.Map(location=[HUB_LAT, HUB_LON], zoom_start=6, tiles="cartodbpositron")
|
36 |
|
37 |
-
# Marcador del hub
|
38 |
folium.Marker(
|
39 |
[HUB_LAT, HUB_LON],
|
40 |
tooltip=f"Hub: {HUB_NAME}",
|
41 |
icon=folium.Icon(color='orange', icon='home')
|
42 |
).add_to(m)
|
43 |
|
44 |
-
# Filtrado
|
45 |
filt = df.copy()
|
46 |
if selected_line != "Todas":
|
47 |
-
filt = filt[filt['
|
48 |
if selected_area != "Todas":
|
49 |
filt = filt[filt['Áreas Únicas'].str.contains(selected_area, case=False, na=False)]
|
50 |
|
51 |
-
# Añadir rutas
|
52 |
for _, row in filt.iterrows():
|
53 |
-
lat, lon = row
|
54 |
if pd.isna(lat) or pd.isna(lon):
|
55 |
continue
|
56 |
folium.Marker(
|
57 |
[lat, lon],
|
58 |
-
tooltip=(f"{row['Ciudad']}
|
59 |
-
|
60 |
-
icon=folium.Icon(color='blue', icon='circle')
|
61 |
).add_to(m)
|
62 |
-
|
63 |
folium.PolyLine(
|
64 |
[[HUB_LAT, HUB_LON], [lat, lon]],
|
65 |
-
color=LINE_COLOR.get(row['
|
66 |
weight=2,
|
67 |
opacity=0.8
|
68 |
).add_to(m)
|
69 |
|
70 |
return m._repr_html_()
|
71 |
|
|
|
72 |
demo = gr.Interface(
|
73 |
fn=make_map,
|
74 |
inputs=[
|
75 |
gr.Dropdown(choices=all_areas, value="Todas", label="Filtrar por Área"),
|
76 |
gr.Dropdown(choices=all_lines, value="Todas", label="Filtrar por Línea")
|
77 |
],
|
78 |
-
outputs=gr.HTML(),
|
79 |
title="Mapa de Rutas: Hub → Municipios",
|
80 |
-
description="
|
|
|
81 |
)
|
82 |
|
83 |
if __name__ == "__main__":
|
84 |
demo.launch()
|
85 |
-
|
|
|
1 |
+
"""
|
2 |
+
Standalone Gradio App: Rutas del Hub a Municipios
|
3 |
+
------------------------------------------------
|
4 |
+
* Datos CSV embebidos (110 filas) con columnas:
|
5 |
+
Departamento, Ciudad, Línea, Áreas Únicas
|
6 |
+
* Si no existen columnas lat/lon, geocodifica con geopy
|
7 |
+
* No necesita archivos externos
|
8 |
+
"""
|
9 |
|
10 |
import pandas as pd
|
11 |
import folium
|
12 |
import gradio as gr
|
13 |
+
import io
|
14 |
|
15 |
+
try:
|
16 |
+
from geopy.geocoders import Nominatim
|
17 |
+
from geopy.extra.rate_limiter import RateLimiter
|
18 |
+
except ImportError:
|
19 |
+
Nominatim = None # geopy no instalada
|
20 |
+
|
21 |
+
# ============ CONFIGURACIÓN =============
|
22 |
+
DATA_CSV = """Departamento,Ciudad,Línea,Áreas Únicas
|
23 |
+
ANTIOQUIA,CAÑASGORDAS,Línea 1,"ARTES VISUALES Y PLÁSTICAS, DANZA, LITERATURA, MÚSICA, OTRA"
|
24 |
+
ANTIOQUIA,LA CEJA,BIAC,Sin información (no registrada en BD)
|
25 |
+
ANTIOQUIA,MEDELLÍN,BIAC,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, CIRCO, DANZA, LITERATURA, OTRA, TEATRO"
|
26 |
+
ANTIOQUIA,MEDELLÍN,Línea 1,
|
27 |
+
ANTIOQUIA,MEDELLÍN,Línea 2,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, DANZA, MÚSICA, TEATRO"
|
28 |
+
"ARCHIPIÉLAGO DE SAN ANDRÉS, PROVIDENCIA Y SANTA CATALINA",SAN ANDRÉS,Línea 1,"ARTES VISUALES Y PLÁSTICAS, LITERATURA, TEATRO"
|
29 |
+
ATLÁNTICO,BARANOA,Línea 1,"DANZA, MÚSICA, TEATRO"
|
30 |
+
ATLÁNTICO,BARRANQUILLA,BIAC,"ARTES VISUALES Y PLÁSTICAS, DANZA, LITERATURA, MÚSICA, TEATRO, TÍTERES"
|
31 |
+
ATLÁNTICO,BARRANQUILLA,Línea 2,
|
32 |
+
ATLÁNTICO,PUERTO COLOMBIA,Línea 2,"ARTES VISUALES Y PLÁSTICAS, CIRCO, DANZA, MÚSICA, TEATRO, TÍTERES"
|
33 |
+
ATLÁNTICO,SABANALARGA,BIAC,Sin información (no registrada en BD)
|
34 |
+
ATLÁNTICO,SANTO TOMÁS,Línea 2,"ARTES VISUALES Y PLÁSTICAS, DANZA, LITERATURA, TÍTERES"
|
35 |
+
ATLÁNTICO,SOLEDAD,BIAC,Sin información (no registrada en BD)
|
36 |
+
"BOGOTÁ, D.C.","BOGOTÁ, D.C.",BIAC,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, DANZA, LITERATURA, MÚSICA, OTRA, TEATRO, TÍTERES"
|
37 |
+
"BOGOTÁ, D.C.","BOGOTÁ, D.C.",Línea 1,
|
38 |
+
"BOGOTÁ, D.C.","BOGOTÁ, D.C.",Línea 2,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, CIRCO, DANZA, LITERATURA, MÚSICA, TEATRO, TÍTERES"
|
39 |
+
BOLÍVAR,CARTAGENA DE INDIAS,Línea 1,"ARTES VISUALES Y PLÁSTICAS, LITERATURA, MÚSICA"
|
40 |
+
BOLÍVAR,CARTAGENA DE INDIAS,Línea 2,"ARTES VISUALES Y PLÁSTICAS, CIRCO, DANZA, LITERATURA, MÚSICA, TEATRO, TÍTERES"
|
41 |
+
BOLÍVAR,MAHATES,Línea 2,"AUDIOVISUALES, DANZA, LITERATURA, MÚSICA, OTRA"
|
42 |
+
BOLÍVAR,SAN JACINTO,Línea 1,"DANZA, MÚSICA, TEATRO"
|
43 |
+
BOLÍVAR,SAN JACINTO,Línea 2,"DANZA, LITERATURA, MÚSICA, TEATRO"
|
44 |
+
BOLÍVAR,SAN JUAN NEPOMUCENO,Línea 2,"CIRCO, DANZA, MÚSICA, TEATRO"
|
45 |
+
BOLÍVAR,SOPLAVIENTO,Línea 1,"ARTES VISUALES Y PLÁSTICAS, DANZA, MÚSICA"
|
46 |
+
BOLÍVAR,TURBACO,Línea 1,"ARTES VISUALES Y PLÁSTICAS, DANZA, MÚSICA"
|
47 |
+
BOYACÁ,CHIQUINQUIRÁ,Línea 1,"ARTES VISUALES Y PLÁSTICAS, LITERATURA, OTRA"
|
48 |
+
BOYACÁ,DUITAMA,Línea 1,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, CIRCO, DANZA, LITERATURA, MÚSICA, TEATRO, TÍTERES"
|
49 |
+
BOYACÁ,GACHANTIVÁ,BIAC,Sin información (no registrada en BD)
|
50 |
+
BOYACÁ,SOGAMOSO,Línea 1,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, DANZA, MÚSICA, TEATRO"
|
51 |
+
BOYACÁ,TUNJA,Línea 2,"ARTES VISUALES Y PLÁSTICAS, TEATRO, TÍTERES"
|
52 |
+
BOYACÁ,VILLA DE LEYVA,Línea 1,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, OTRA"
|
53 |
+
CALDAS,ANSERMA,Línea 2,"ARTES VISUALES Y PLÁSTICAS, DANZA, LITERATURA, MÚSICA, OTRA, TEATRO"
|
54 |
+
CALDAS,MANIZALES,Línea 1,"AUDIOVISUALES, DANZA, LITERATURA, MÚSICA, TEATRO, TÍTERES"
|
55 |
+
CALDAS,SAMANÁ,Línea 1,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, DANZA, TEATRO"
|
56 |
+
CAQUETÁ,CARTAGENA DEL CHAIRÁ,BIAC,Sin información (no registrada en BD)
|
57 |
+
CAQUETÁ,FLORENCIA,Línea 2,"DANZA, LITERATURA, MÚSICA, TEATRO"
|
58 |
+
CAQUETÁ,LA MONTAÑITA,BIAC,"ARTES VISUALES Y PLÁSTICAS, MÚSICA, OTRA, TEATRO"
|
59 |
+
CAQUETÁ,LA MONTAÑITA,Línea 2,
|
60 |
+
CAUCA,INZÁ,Línea 2,"DANZA, MÚSICA, OTRA, TEATRO, TÍTERES"
|
61 |
+
CAUCA,MERCADERES,BIAC,Sin información (no registrada en BD)
|
62 |
+
CAUCA,POPAYÁN,BIAC,"DANZA, LITERATURA, MÚSICA, TEATRO"
|
63 |
+
CAUCA,POPAYÁN,Línea 1,
|
64 |
+
CAUCA,POPAYÁN,Línea 2,"DANZA, LITERATURA, MÚSICA, OTRA"
|
65 |
+
CAUCA,PUERTO TEJADA,BIAC,"ARTES VISUALES Y PLÁSTICAS, DANZA, MÚSICA"
|
66 |
+
CAUCA,PUERTO TEJADA,Línea 1,
|
67 |
+
CAUCA,SAN SEBASTIÁN,Línea 1,"DANZA, MÚSICA, TEATRO"
|
68 |
+
CESAR,LA JAGUA DE IBIRICO,Línea 2,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, DANZA, LITERATURA, MÚSICA, TEATRO, TÍTERES"
|
69 |
+
CHOCÓ,CONDOTO,Línea 1,"MÚSICA, TEATRO"
|
70 |
+
CHOCÓ,ISTMINA,BIAC,Sin información (no registrada en BD)
|
71 |
+
CUNDINAMARCA,CHOACHÍ,Línea 2,"ARTES VISUALES Y PLÁSTICAS, DANZA, LITERATURA, MÚSICA"
|
72 |
+
CUNDINAMARCA,SOACHA,BIAC,Sin información (no registrada en BD)
|
73 |
+
CUNDINAMARCA,SOPÓ,Línea 1,"MÚSICA, TEATRO, TÍTERES"
|
74 |
+
CUNDINAMARCA,TABIO,Línea 1,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, MÚSICA"
|
75 |
+
CUNDINAMARCA,TENJO,Línea 1,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, DANZA, MÚSICA"
|
76 |
+
CÓRDOBA,CERETÉ,BIAC,Sin información (no registrada en BD)
|
77 |
+
CÓRDOBA,MONTERÍA,Línea 1,"ARTES VISUALES Y PLÁSTICAS, LITERATURA, TEATRO"
|
78 |
+
CÓRDOBA,PUERTO LIBERTADOR,BIAC,Sin información (no registrada en BD)
|
79 |
+
CÓRDOBA,SAHAGÚN,Línea 2,"ARTES VISUALES Y PLÁSTICAS, LITERATURA, OTRA, TEATRO"
|
80 |
+
GUAVIARE,SAN JOSÉ DEL GUAVIARE,BIAC,Sin información (no registrada en BD)
|
81 |
+
HUILA,ALGECIRAS,Línea 1,"DANZA, MÚSICA, TEATRO"
|
82 |
+
HUILA,GARZÓN,Línea 1,"DANZA, LITERATURA, MÚSICA"
|
83 |
+
HUILA,NEIVA,Línea 1,"DANZA, LITERATURA, MÚSICA"
|
84 |
+
HUILA,SAN AGUSTÍN,BIAC,Sin información (no registrada en BD)
|
85 |
+
LA GUAJIRA,MAICAO,Línea 1,"DANZA, MÚSICA, TEATRO"
|
86 |
+
LA GUAJIRA,RIOHACHA,Línea 1,"DANZA, MÚSICA, TEATRO"
|
87 |
+
LA GUAJIRA,URUMITA,Línea 2,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, DANZA, MÚSICA, TEATRO, TÍTERES"
|
88 |
+
MAGDALENA,CIÉNAGA,Línea 1,"DANZA, TEATRO, TÍTERES"
|
89 |
+
MAGDALENA,EL BANCO,Línea 1,"ARTES VISUALES Y PLÁSTICAS, MÚSICA, TEATRO"
|
90 |
+
META,SAN MARTÍN,BIAC,Sin información (no registrada en BD)
|
91 |
+
META,VILLAVICENCIO,Línea 2,"ARTES VISUALES Y PLÁSTICAS, LITERATURA, MÚSICA, OTRA"
|
92 |
+
NARIÑO,LA CRUZ,Línea 2,"ARTES VISUALES Y PLÁSTICAS, DANZA, MÚSICA, TEATRO, TÍTERES"
|
93 |
+
NARIÑO,LA TOLA,Línea 1,"DANZA, LITERATURA, MÚSICA"
|
94 |
+
NARIÑO,PASTO,BIAC,"DANZA, LITERATURA, MÚSICA"
|
95 |
+
NARIÑO,PASTO,Línea 1,"CIRCO, DANZA, MÚSICA, TEATRO, TÍTERES"
|
96 |
+
NARIÑO,PASTO,Línea 2,"LITERATURA, MÚSICA, OTRA"
|
97 |
+
NARIÑO,ROBERTO PAYÁN,Línea 1,
|
98 |
+
NARIÑO,SAN ANDRÉS DE TUMACO,Línea 1,"ARTES VISUALES Y PLÁSTICAS, DANZA, MÚSICA"
|
99 |
+
NORTE DE SANTANDER,SAN JOSÉ DE CÚCUTA,Línea 2,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, CIRCO, DANZA, LITERATURA, MÚSICA, OTRA, TEATRO, TÍTERES"
|
100 |
+
PUTUMAYO,SAN FRANCISCO,Línea 1,"DANZA, MÚSICA, OTRA"
|
101 |
+
PUTUMAYO,SIBUNDOY,Línea 1,"AUDIOVISUALES, MÚSICA, OTRA"
|
102 |
+
QUINDÍO,ARMENIA,BIAC,"ARTES VISUALES Y PLÁSTICAS, LITERATURA, MÚSICA"
|
103 |
+
QUINDÍO,ARMENIA,Línea 1,
|
104 |
+
QUINDÍO,BUENAVISTA,Línea 1,"LITERATURA, MÚSICA, TEATRO"
|
105 |
+
QUINDÍO,MONTENEGRO,BIAC,Sin información (no registrada en BD)
|
106 |
+
RISARALDA,PEREIRA,BIAC,"ARTES VISUALES Y PLÁSTICAS, DANZA, LITERATURA, MÚSICA, TEATRO"
|
107 |
+
RISARALDA,PEREIRA,Línea 1,
|
108 |
+
RISARALDA,PEREIRA,Línea 2,"ARTES VISUALES Y PLÁSTICAS, DANZA, LITERATURA, MÚSICA, TEATRO"
|
109 |
+
SANTANDER,BARRANCABERMEJA,Línea 2,"CIRCO, MÚSICA, TEATRO, TÍTERES"
|
110 |
+
SANTANDER,BUCARAMANGA,BIAC,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, DANZA, LITERATURA, MÚSICA, TEATRO"
|
111 |
+
SANTANDER,BUCARAMANGA,Línea 1,
|
112 |
+
SANTANDER,SAN VICENTE DE CHUCURÍ,Línea 1,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, LITERATURA, OTRA"
|
113 |
+
SUCRE,COROZAL,Línea 1,"DANZA, LITERATURA, MÚSICA"
|
114 |
+
SUCRE,SAMPUÉS,Línea 2,"ARTES VISUALES Y PLÁSTICAS, DANZA, LITERATURA, MÚSICA"
|
115 |
+
SUCRE,SAN JOSÉ DE TOLUVIEJO,Línea 1,"DANZA, LITERATURA, MÚSICA"
|
116 |
+
SUCRE,SINCELEJO,Línea 1,"DANZA, LITERATURA, MÚSICA"
|
117 |
+
SUCRE,SINCELEJO,Línea 2,"ARTES VISUALES Y PLÁSTICAS, DANZA, MÚSICA, TEATRO"
|
118 |
+
TOLIMA,IBAGUÉ,Línea 1,"LITERATURA, MÚSICA, TEATRO, TÍTERES"
|
119 |
+
VALLE DEL CAUCA,BUENAVENTURA,Línea 2,"ARTES VISUALES Y PLÁSTICAS, DANZA, LITERATURA, TEATRO"
|
120 |
+
VALLE DEL CAUCA,CAICEDONIA,Línea 1,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, LITERATURA"
|
121 |
+
VALLE DEL CAUCA,CALIMA,Línea 1,"ARTES VISUALES Y PLÁSTICAS, MÚSICA, TEATRO"
|
122 |
+
VALLE DEL CAUCA,FLORIDA,BIAC,Sin información (no registrada en BD)
|
123 |
+
VALLE DEL CAUCA,GUACARÍ,Línea 2,"DANZA, LITERATURA, MÚSICA, TEATRO"
|
124 |
+
VALLE DEL CAUCA,GUADALAJARA DE BUGA,Línea 2,"ARTES VISUALES Y PLÁSTICAS, LITERATURA, TEATRO, TÍTERES"
|
125 |
+
VALLE DEL CAUCA,LA CUMBRE,Línea 2,"ARTES VISUALES Y PLÁSTICAS, DANZA, MÚSICA, TEATRO"
|
126 |
+
VALLE DEL CAUCA,RIOFRÍO,BIAC,Sin información (no registrada en BD)
|
127 |
+
VALLE DEL CAUCA,SAN PEDRO,Línea 1,"ARTES VISUALES Y PLÁSTICAS, DANZA, MÚSICA"
|
128 |
+
VALLE DEL CAUCA,SANTIAGO DE CALI,BIAC,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, DANZA, LITERATURA, MÚSICA, TEATRO"
|
129 |
+
VALLE DEL CAUCA,SANTIAGO DE CALI,Línea 1,
|
130 |
+
VALLE DEL CAUCA,SANTIAGO DE CALI,Línea 2,"ARTES VISUALES Y PLÁSTICAS, DANZA, LITERATURA, MÚSICA, OTRA, TEATRO"
|
131 |
+
VALLE DEL CAUCA,SEVILLA,Línea 1,"ARTES VISUALES Y PLÁSTICAS, AUDIOVISUALES, DANZA, MÚSICA, TEATRO"
|
132 |
+
VALLE DEL CAUCA,TULUÁ,Línea 1,"CIRCO, DANZA, MÚSICA"
|
133 |
+
"""
|
134 |
+
|
135 |
+
HUB_NAME = "Bogotá"
|
136 |
+
HUB_LAT, HUB_LON = 4.7110, -74.0721
|
137 |
|
|
|
138 |
LINE_COLOR = {
|
139 |
"Línea 1": "red",
|
140 |
"Línea 2": "blue",
|
141 |
"BIAC": "green"
|
142 |
}
|
143 |
+
# =========================================
|
144 |
+
|
145 |
+
# Leer DataFrame
|
146 |
+
df = pd.read_csv(io.StringIO(DATA_CSV))
|
147 |
|
148 |
+
# ------------ Geocodificar ---------------
|
149 |
+
def geocode_missing(dframe: pd.DataFrame) -> pd.DataFrame:
|
150 |
+
if {'lat','lon'}.issubset(dframe.columns) and not dframe[['lat','lon']].isna().any().any():
|
151 |
+
return dframe
|
|
|
|
|
152 |
|
153 |
+
if Nominatim is None:
|
154 |
+
raise ImportError("Faltan 'lat' y 'lon' y geopy no está instalado.")
|
155 |
|
156 |
+
geolocator = Nominatim(user_agent="clanes_mapa_app")
|
157 |
+
geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)
|
158 |
+
|
159 |
+
if 'lat' not in dframe.columns:
|
160 |
+
dframe['lat'] = pd.NA
|
161 |
+
dframe['lon'] = pd.NA
|
162 |
+
|
163 |
+
cache = {}
|
164 |
+
for i, row in dframe.iterrows():
|
165 |
+
if not pd.isna(row['lat']) and not pd.isna(row['lon']):
|
166 |
+
continue
|
167 |
+
key = (row['Ciudad'], row['Departamento'])
|
168 |
+
if key in cache:
|
169 |
+
lat, lon = cache[key]
|
170 |
+
else:
|
171 |
+
loc = geocode(f"{row['Ciudad']}, {row['Departamento']}, Colombia")
|
172 |
+
lat, lon = (loc.latitude, loc.longitude) if loc else (pd.NA, pd.NA)
|
173 |
+
cache[key] = (lat, lon)
|
174 |
+
dframe.at[i, 'lat'] = lat
|
175 |
+
dframe.at[i, 'lon'] = lon
|
176 |
+
return dframe
|
177 |
+
|
178 |
+
df = geocode_missing(df)
|
179 |
+
|
180 |
+
# --------- Helpers para filtros ----------
|
181 |
+
def explode_areas(series, sep=','):
|
182 |
+
return {a.strip() for sub in series.dropna() for a in str(sub).split(sep)}
|
183 |
+
|
184 |
+
all_areas = sorted(explode_areas(df['Áreas Únicas']))
|
185 |
all_areas.insert(0, "Todas")
|
186 |
+
all_lines = ["Todas"] + sorted(df['Línea'].dropna().unique().tolist())
|
187 |
|
188 |
+
# -------------- Mapa ---------------------
|
189 |
+
def make_map(selected_area: str, selected_line: str) -> str:
|
190 |
m = folium.Map(location=[HUB_LAT, HUB_LON], zoom_start=6, tiles="cartodbpositron")
|
191 |
|
|
|
192 |
folium.Marker(
|
193 |
[HUB_LAT, HUB_LON],
|
194 |
tooltip=f"Hub: {HUB_NAME}",
|
195 |
icon=folium.Icon(color='orange', icon='home')
|
196 |
).add_to(m)
|
197 |
|
|
|
198 |
filt = df.copy()
|
199 |
if selected_line != "Todas":
|
200 |
+
filt = filt[filt['Línea'] == selected_line]
|
201 |
if selected_area != "Todas":
|
202 |
filt = filt[filt['Áreas Únicas'].str.contains(selected_area, case=False, na=False)]
|
203 |
|
|
|
204 |
for _, row in filt.iterrows():
|
205 |
+
lat, lon = row.get('lat'), row.get('lon')
|
206 |
if pd.isna(lat) or pd.isna(lon):
|
207 |
continue
|
208 |
folium.Marker(
|
209 |
[lat, lon],
|
210 |
+
tooltip=(f"{row['Ciudad']} — {row['Línea']}\nÁreas: {row['Áreas Únicas']}"),
|
211 |
+
icon=folium.Icon(color='blue', icon='user')
|
|
|
212 |
).add_to(m)
|
|
|
213 |
folium.PolyLine(
|
214 |
[[HUB_LAT, HUB_LON], [lat, lon]],
|
215 |
+
color=LINE_COLOR.get(row['Línea'], 'gray'),
|
216 |
weight=2,
|
217 |
opacity=0.8
|
218 |
).add_to(m)
|
219 |
|
220 |
return m._repr_html_()
|
221 |
|
222 |
+
# -------------- Interface -----------------
|
223 |
demo = gr.Interface(
|
224 |
fn=make_map,
|
225 |
inputs=[
|
226 |
gr.Dropdown(choices=all_areas, value="Todas", label="Filtrar por Área"),
|
227 |
gr.Dropdown(choices=all_lines, value="Todas", label="Filtrar por Línea")
|
228 |
],
|
229 |
+
outputs=gr.HTML(label="Mapa"),
|
230 |
title="Mapa de Rutas: Hub → Municipios",
|
231 |
+
description="Filtra por Área artística y/o Línea para visualizar las rutas.",
|
232 |
+
allow_flagging="never"
|
233 |
)
|
234 |
|
235 |
if __name__ == "__main__":
|
236 |
demo.launch()
|
|