import gradio as gr import plotly.graph_objects as go import pandas as pd import random import joblib simple_model = joblib.load('modelo_docks.pkl') df_stations = pd.read_csv('Informacio_Estacions_Bicing_2025.csv') def get_station_location(station_id, df): row = df[df['station_id'] == station_id] if not row.empty: latitude = row.iloc[0]['lat'] longitude = row.iloc[0]['lon'] address = row.iloc[0]['address'] return latitude, longitude, address return None, None, None # Return None if the station_id is not found def filter_map(min_availability, selected_day, selected_month, selected_hour, ctx4, ctx3, ctx2, ctx1, tavg, prcp): """Filter stations based on availability, weather conditions, and display them on a map.""" df = df_stations[['station_id']].copy() df['day'] = selected_day df['month'] = selected_month df['hour'] = selected_hour df['ctx-4'] = ctx4 df['ctx-3'] = ctx3 df['ctx-2'] = ctx2 df['ctx-1'] = ctx1 df['temperature_2m (°C)'] = tavg df['precipitation (mm)'] = prcp # Predict availability using the updated model df['availability'] = simple_model.predict(df[['station_id', 'month', 'day', 'hour', 'ctx-4', 'ctx-3', 'ctx-2', 'ctx-1', 'temperature_2m (°C)', 'precipitation (mm)']]) # Filter stations based on availability filtered_df = df[df['availability'] > min_availability].copy() # Fetch latitude, longitude, and address dynamically filtered_df[['latitude', 'longitude', 'address']] = pd.DataFrame( filtered_df['station_id'].apply(lambda sid: get_station_location(sid, df_stations)).tolist(), index=filtered_df.index ) # Remove rows where location is missing filtered_df = filtered_df.dropna(subset=['latitude', 'longitude']) # Format the hover text with HTML line breaks hover_texts = [ f"🚲 Station {id}
" f"🔵 Availability: {avail:.2f}
" f"🏠 Address: {addr}" for id, avail, addr in zip(filtered_df['station_id'], filtered_df['availability'], filtered_df['address']) ] fig = go.Figure(go.Scattermapbox( lat=filtered_df['latitude'], lon=filtered_df['longitude'], mode='markers', marker=go.scattermapbox.Marker(size=8, color='blue'), text=hover_texts, hoverinfo="text" )) fig.update_layout( mapbox_style="open-street-map", hovermode='closest', mapbox=dict( center=dict(lat=41.38, lon=2.17), zoom=13 ) ) return fig # Gradio UI with updated weather variable names with gr.Blocks(css="body {background-color: #070708; font-family: 'Segoe UI', sans-serif;}") as demo: gr.Markdown("### 🗺️ **Bike Availability Map**", elem_id="title") gr.Markdown("Ajusta els filtres per veure les estacions amb disponibilitat predita sobre un mapa interactiu.") with gr.Row(): with gr.Column(scale=2): gr.Markdown("#### 📅 Filtres Principals") min_availability = gr.Slider(0, 1, value=0.2, label="🔵 Mínim de disponibilitat", interactive=True) selected_day = gr.Slider(1, 31, value=1, step=1, label="📅 Dia", interactive=True) selected_month = gr.Slider(1, 12, value=6, step=1, label="🗓️ Mes", interactive=True) selected_hour = gr.Slider(0, 23, value=12, step=1, label="⏰ Hora", interactive=True) with gr.Column(scale=1): with gr.Accordion("⚙️ Filtres Avançats", open=False): selected_ctx4 = gr.Number(value=0.49, label="ctx-4", interactive=True) selected_ctx3 = gr.Number(value=0.38, label="ctx-3", interactive=True) selected_ctx2 = gr.Number(value=0.32, label="ctx-2", interactive=True) selected_ctx1 = gr.Number(value=0.31, label="ctx-1", interactive=True) with gr.Accordion("🌦️ Condicions Meteo", open=False): tavg = gr.Number(value=20.0, label="🌡️ Temperatura Mitjana (°C)", interactive=True) prcp = gr.Number(value=0.0, label="🌧️ Precipitació (mm)", interactive=True) btn = gr.Button("🔍 Filtrar estacions", size="lg") gr.Markdown("---") gr.Markdown("### 🌍 Resultats sobre el mapa") map_plot = gr.Plot() btn.click( filter_map, inputs=[min_availability, selected_day, selected_month, selected_hour, selected_ctx4, selected_ctx3, selected_ctx2, selected_ctx1, tavg, prcp], outputs=map_plot ) if __name__ == "__main__": demo.launch(share=True)