Create an app showing an interactive Shibuya map visualization. Mock data: - Nursery schools locations (25 points) * with business hours * with a number of children * with a type of school (public or private) - Elementary schools locations (20 points) - Bus stops (100 points) and Bus routes Features: - Interactive map centered on Shibuya, Tokyo - Toggle layers: * Nursery schools with popups * Elementary schools * Bus stops * Animated Bus routes Controls: - Time slider - Borough filters - Color schemes - Map style (street/satellite) Include zoom/pan and stats panel showing data summaries.
To upload files, please first save the app
import streamlit as st
import pandas as pd
import numpy as np
import pydeck as pdk
from datetime import datetime, time
import folium
from streamlit_folium import st_folium
import json
# Set page config
st.set_page_config(layout="wide", page_title="Shibuya Interactive Map")
# Helper functions
def generate_nursery_data():
# Generate mock data for nursery schools
np.random.seed(42)
n_points = 25
return pd.DataFrame({
'name': [f'Nursery School {i+1}' for i in range(n_points)],
'lat': np.random.normal(35.6580, 0.01, n_points),
'lon': np.random.normal(139.7016, 0.01, n_points),
'type': np.random.choice(['Public', 'Private'], n_points),
'children': np.random.randint(20, 100, n_points),
'opening_time': [time(7, 0) for _ in range(n_points)],
'closing_time': [time(18, 0) for _ in range(n_points)],
'borough': np.random.choice(['Shibuya', 'Harajuku', 'Ebisu', 'Daikanyama'], n_points)
})
def generate_elementary_data():
# Generate mock data for elementary schools
np.random.seed(43)
n_points = 20
return pd.DataFrame({
'name': [f'Elementary School {i+1}' for i in range(n_points)],
'lat': np.random.normal(35.6580, 0.01, n_points),
'lon': np.random.normal(139.7016, 0.01, n_points),
'borough': np.random.choice(['Shibuya', 'Harajuku', 'Ebisu', 'Daikanyama'], n_points)
})
def generate_bus_data():
# Generate mock data for bus stops and routes
np.random.seed(44)
n_points = 100
stops = pd.DataFrame({
'name': [f'Bus Stop {i+1}' for i in range(n_points)],
'lat': np.random.normal(35.6580, 0.015, n_points),
'lon': np.random.normal(139.7016, 0.015, n_points),
'borough': np.random.choice(['Shibuya', 'Harajuku', 'Ebisu', 'Daikanyama'], n_points)
})
# Generate routes between stops
routes = []
for i in range(5): # 5 different bus routes
route_stops = stops.sample(10) # Each route has 10 stops
for j in range(len(route_stops)-1):
routes.append({
'route_id': i+1,
'from_lat': route_stops.iloc[j]['lat'],
'from_lon': route_stops.iloc[j]['lon'],
'to_lat': route_stops.iloc[j+1]['lat'],
'to_lon': route_stops.iloc[j+1]['lon']
})
return stops, pd.DataFrame(routes)
# Load data
nursery_df = generate_nursery_data()
elementary_df = generate_elementary_data()
bus_stops_df, bus_routes_df = generate_bus_data()
# Sidebar controls
st.sidebar.title("Map Controls")
# Layer toggles
st.sidebar.subheader("Layers")
show_nurseries = st.sidebar.checkbox("Show Nursery Schools", True)
show_elementary = st.sidebar.checkbox("Show Elementary Schools", True)
show_bus_stops = st.sidebar.checkbox("Show Bus Stops", True)
show_bus_routes = st.sidebar.checkbox("Show Bus Routes", True)
# Filters
st.sidebar.subheader("Filters")
selected_boroughs = st.sidebar.multiselect(
"Borough Filter",
['Shibuya', 'Harajuku', 'Ebisu', 'Daikanyama'],
['Shibuya', 'Harajuku', 'Ebisu', 'Daikanyama']
)
# Time slider
time_slider = st.sidebar.slider(
"Time of Day",
min_value=time(6, 0),
max_value=time(20, 0),
value=time(12, 0),
step=datetime.timedelta(minutes=30),
format="HH:mm"
)
# Map style
map_style = st.sidebar.selectbox(
"Map Style",
["streets-v11", "satellite-v9"]
)
# Main content
st.title("Shibuya Interactive Map")
# Create columns for map and stats
col1, col2 = st.columns([7, 3])
with col1:
# Initialize map
initial_view_state = pdk.ViewState(
latitude=35.6580,
longitude=139.7016,
zoom=13,
pitch=45
)
layers = []
# Add nursery schools layer
if show_nurseries:
nursery_layer = pdk.Layer(
"ScatterplotLayer",
data=nursery_df[nursery_df['borough'].isin(selected_boroughs)],
get_position=["lon", "lat"],
get_color=[255, 0, 0, 160],
get_radius=100,
pickable=True
)
layers.append(nursery_layer)
# Add elementary schools layer
if show_elementary:
elementary_layer = pdk.Layer(
"ScatterplotLayer",
data=elementary_df[elementary_df['borough'].isin(selected_boroughs)],
get_position=["lon", "lat"],
get_color=[0, 255, 0, 160],
get_radius=150,
pickable=True
)
layers.append(elementary_layer)
# Add bus stops layer
if show_bus_stops:
bus_stops_layer = pdk.Layer(
"ScatterplotLayer",
data=bus_stops_df[bus_stops_df['borough'].isin(selected_boroughs)],
get_position=["lon", "lat"],
get_color=[0, 0, 255, 160],
get_radius=50,
pickable=True
)
layers.append(bus_stops_layer)
# Add bus routes layer
if show_bus_routes:
bus_routes_layer = pdk.Layer(
"LineLayer",
data=bus_routes_df,
get_source_position=["from_lon", "from_lat"],
get_target_position=["to_lon", "to_lat"],
get_color=[255, 255, 0, 160],
get_width=2,
pickable=True
)
layers.append(bus_routes_layer)
# Render map
st.pydeck_chart(pdk.Deck(
map_style=f"mapbox://{map_style}",
initial_view_state=initial_view_state,
layers=layers,
tooltip={
"html": "<b>Name:</b> {name}<br/>"
"<b>Borough:</b> {borough}<br/>"
"<b>Type:</b> {type}<br/>"
"<b>Children:</b> {children}"
}
))
with col2:
# Stats panel
st.subheader("Statistics")
# Filter data based on selected boroughs
filtered_nursery = nursery_df[nursery_df['borough'].isin(selected_boroughs)]
filtered_elementary = elementary_df[elementary_df['borough'].isin(selected_boroughs)]
filtered_bus_stops = bus_stops_df[bus_stops_df['borough'].isin(selected_boroughs)]
# Display statistics
st.write("Nursery Schools:")
st.write(f"- Total: {len(filtered_nursery)}")
st.write(f"- Public: {len(filtered_nursery[filtered_nursery['type'] == 'Public'])}")
st.write(f"- Private: {len(filtered_nursery[filtered_nursery['type'] == 'Private'])}")
st.write(f"- Total children: {filtered_nursery['children'].sum()}")
st.write("\nElementary Schools:")
st.write(f"- Total: {len(filtered_elementary)}")
st.write("\nBus Network:")
st.write(f"- Bus stops: {len(filtered_bus_stops)}")
st.write(f"- Bus routes: {len(bus_routes_df['route_id'].unique())}")
# Borough breakdown
st.subheader("Borough Breakdown")
borough_stats = filtered_nursery.groupby('borough').agg({
'children': 'sum',
'name': 'count'
}).rename(columns={'name': 'schools'})
st.dataframe(borough_stats)
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?