Nico612/Data_Visualization_Project_World_Map_Visualization
0
1 2 3import marimo4 5__generated_with = "0.13.1-dev16"6app = marimo.App()7 8 9@app.cell10def _():11 import marimo as mo12 13 view_selector = mo.ui.dropdown(14 options=["Winners", "Stages"],15 value="Winners",16 label="Choose a view:"17 )18 19 view_selector20 return (view_selector,)21 22 23@app.cell24def _():25 import pandas as pd26 27 # Load & process winners dataset28 geocoded_df = pd.read_csv("winner_locations_geocoded.csv")29 winners_df = pd.read_csv("tdf_winners.csv")30 winners_df = winners_df.dropna(subset=["birth_town", "birth_country"])31 winners_df["location"] = winners_df["birth_town"] + ", " + winners_df["birth_country"]32 winners_df["birth_year"] = pd.to_datetime(winners_df["born"], errors="coerce").dt.year33 winners_df["hover_text"] = winners_df["winner_name"] + ", " + winners_df["birth_year"].astype(str)34 35 # Group by town for hover aggregation36 winners_grouped = (37 winners_df[["location", "hover_text"]]38 .drop_duplicates()39 .groupby("location")["hover_text"]40 .apply(lambda x: "<br>".join(x))41 .reset_index()42 )43 44 # Merge with geocoded lat/lon45 winners_map_df = pd.merge(geocoded_df, winners_grouped, on="location", how="left")46 winners_map_df["town"] = winners_map_df["location"].apply(lambda x: x.split(",")[0])47 winners_map_df["lat_offset"] = winners_map_df["lat"] + 0.148 return pd, winners_map_df49 50 51@app.cell52def _(pd, winners_map_df):53 import plotly.graph_objects as go54 55 def create_winners_map():56 fig = go.Figure()57 58 fig.add_trace(go.Scattergeo(59 lon=winners_map_df["lon"],60 lat=winners_map_df["lat"],61 mode='markers',62 marker=dict(size=8, color='blue', opacity=0.7),63 text=winners_map_df["hover_text"],64 hovertemplate="<b>%{text}</b><extra></extra>",65 name="Winners"66 ))67 68 fig.add_trace(go.Scattergeo(69 lon=winners_map_df["lon"],70 lat=winners_map_df["lat_offset"],71 mode="text",72 text=winners_map_df["town"],73 textfont=dict(color="#003366", size=11),74 textposition="top center",75 showlegend=False,76 opacity=0.95,77 hoverinfo="skip"78 ))79 80 fig.update_layout(81 title="Tour de France Stage Winners' Birthplaces",82 geo=dict(83 scope='world',84 showland=True,85 showcountries=True,86 countrycolor="Black",87 showcoastlines=True,88 showframe=True,89 framecolor="gray",90 projection_type="natural earth"91 ),92 hoverlabel=dict(93 bgcolor="#e6f0ff",94 bordercolor="#003366",95 font=dict(color="#003366", family="Arial", size=13)96 ),97 showlegend=False98 )99 return fig100 101 def create_stages_map():102 df = pd.read_csv("aggregated_stage_routes.csv")103 104 # Define stage colors105 stage_type_colors = {106 "Flat stage": "blue",107 "Plain stage": "royalblue",108 "Mountain stage": "crimson",109 "Medium mountain stage": "orange",110 "Stage with mountain(s)": "darkred",111 "Individual time trial": "green",112 "Team time trial": "purple",113 "Hilly stage": "darkorange",114 "Transition stage": "teal",115 "High mountain stage": "firebrick"116 }117 118 fig = go.Figure()119 120 # Add stage route lines121 for _, row in df.iterrows():122 fig.add_trace(go.Scattergeo(123 lon=[row["origin_lon"], row["dest_lon"]],124 lat=[row["origin_lat"], row["dest_lat"]],125 mode="lines",126 line=dict(127 width=max(1, min(row["count"], 8)),128 color=stage_type_colors.get(row["Type"], "gray")129 ),130 showlegend=False131 ))132 133 # Add city markers (after lines, so they appear on top)134 for _, row in df.iterrows():135 origin_city = row["route_key"].split(" → ")[0]136 dest_city = row["route_key"].split(" → ")[1].split(" (")[0]137 138 # Origin city marker139 fig.add_trace(go.Scattergeo(140 lon=[row["origin_lon"]],141 lat=[row["origin_lat"]],142 mode="markers",143 marker=dict(size=3, color="black"),144 text=[origin_city],145 hovertemplate="%{text}<extra></extra>",146 showlegend=False147 ))148 149 # Destination city marker150 fig.add_trace(go.Scattergeo(151 lon=[row["dest_lon"]],152 lat=[row["dest_lat"]],153 mode="markers",154 marker=dict(size=3, color="black"),155 text=[dest_city],156 hovertemplate="%{text}<extra></extra>",157 showlegend=False158 ))159 160 # Add dummy traces to create a legend for stage types161 for stage_type, color in stage_type_colors.items():162 fig.add_trace(go.Scattergeo(163 lon=[None], # no real point164 lat=[None],165 mode='lines',166 line=dict(color=color, width=4),167 name=stage_type,168 showlegend=True169 ))170 171 172 # Final layout173 fig.update_layout(174 title="Tour de France Stage Routes",175 geo=dict(176 scope="europe",177 projection_type="natural earth",178 showland=True,179 showcountries=True,180 countrycolor="black",181 showcoastlines=True,182 ),183 hoverlabel=dict(184 bgcolor="#e6f0ff",185 bordercolor="#003366",186 font=dict(color="#003366", family="Arial", size=13)187 ),188 margin=dict(l=0, r=0, t=40, b=0),189 legend=dict(190 title="Stage Types",191 x=0.95, # just outside the plot to the right192 y=1,193 bgcolor="white",194 bordercolor="black",195 borderwidth=1196 )197 )198 199 return fig200 return create_stages_map, create_winners_map201 202 203@app.cell204def _(create_stages_map, create_winners_map, view_selector):205 fig = create_winners_map() if view_selector.value == "Winners" else create_stages_map()206 fig # Marimo will render this207 return view_selector, fig208 209 210if __name__ == "__main__":211 app.run()212 213 