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 (10 points) - Bus stops (20 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 pydeck as pdk
import numpy as np
from datetime import datetime, time
import json
st.set_page_config(layout="wide", page_title="Shibuya Education & Transport Map")
# Generate mock data
np.random.seed(42)
# Shibuya coordinates
SHIBUYA_LAT = 35.6580
SHIBUYA_LON = 139.7016
def generate_mock_data():
# Generate nursery schools
nursery_schools = pd.DataFrame({
'name': [f'Nursery School {i}' for i in range(25)],
'latitude': SHIBUYA_LAT + np.random.normal(0, 0.01, 25),
'longitude': SHIBUYA_LON + np.random.normal(0, 0.01, 25),
'open_time': [time(7, 0) for _ in range(25)],
'close_time': [time(18, 0) for _ in range(25)],
'children': np.random.randint(20, 100, 25),
'type': np.random.choice(['public', 'private'], 25),
'borough': np.random.choice(['Shibuya', 'Harajuku', 'Ebisu'], 25)
})
# Generate elementary schools
elementary_schools = pd.DataFrame({
'name': [f'Elementary School {i}' for i in range(10)],
'latitude': SHIBUYA_LAT + np.random.normal(0, 0.008, 10),
'longitude': SHIBUYA_LON + np.random.normal(0, 0.008, 10),
'students': np.random.randint(200, 600, 10),
'borough': np.random.choice(['Shibuya', 'Harajuku', 'Ebisu'], 10)
})
# Generate bus stops
bus_stops = pd.DataFrame({
'name': [f'Bus Stop {i}' for i in range(20)],
'latitude': SHIBUYA_LAT + np.random.normal(0, 0.012, 20),
'longitude': SHIBUYA_LON + np.random.normal(0, 0.012, 20),
'borough': np.random.choice(['Shibuya', 'Harajuku', 'Ebisu'], 20)
})
# Generate bus routes (connect random bus stops)
routes = []
for _ in range(5): # 5 bus routes
stops = bus_stops.sample(n=5) # each route has 5 stops
for i in range(len(stops)-1):
routes.append({
'start_lat': stops.iloc[i]['latitude'],
'start_lon': stops.iloc[i]['longitude'],
'end_lat': stops.iloc[i+1]['latitude'],
'end_lon': stops.iloc[i+1]['longitude'],
'route_id': _
})
bus_routes = pd.DataFrame(routes)
return nursery_schools, elementary_schools, bus_stops, bus_routes
# Generate data
nursery_schools, elementary_schools, bus_stops, bus_routes = generate_mock_data()
# Sidebar controls
st.sidebar.title("Map Controls")
# Time slider
time_selected = st.sidebar.slider(
"Time of day",
min_value=datetime.strptime("06:00", "%H:%M").time(),
max_value=datetime.strptime("20:00", "%H:%M").time(),
value=datetime.strptime("12:00", "%H:%M").time(),
format="HH:mm"
)
# Borough filter
boroughs = ['All'] + list(nursery_schools['borough'].unique())
selected_borough = st.sidebar.selectbox("Select Borough", boroughs)
# 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)
# Map style
map_style = st.sidebar.selectbox(
"Map Style",
["mapbox://styles/mapbox/light-v9",
"mapbox://styles/mapbox/dark-v9",
"mapbox://styles/mapbox/satellite-v9"]
)
# Main content
st.title("Shibuya Education & Transport Map")
# Create layers
layers = []
if show_nurseries:
nursery_layer = pdk.Layer(
"ScatterplotLayer",
nursery_schools,
get_position=["longitude", "latitude"],
get_color=[255, 0, 0, 160],
get_radius=100,
pickable=True,
)
layers.append(nursery_layer)
if show_elementary:
elementary_layer = pdk.Layer(
"ScatterplotLayer",
elementary_schools,
get_position=["longitude", "latitude"],
get_color=[0, 0, 255, 160],
get_radius=150,
pickable=True,
)
layers.append(elementary_layer)
if show_bus_stops:
bus_stop_layer = pdk.Layer(
"ScatterplotLayer",
bus_stops,
get_position=["longitude", "latitude"],
get_color=[0, 255, 0, 160],
get_radius=80,
pickable=True,
)
layers.append(bus_stop_layer)
if show_bus_routes:
bus_route_layer = pdk.Layer(
"ArcLayer",
bus_routes,
get_source_position=["start_lon", "start_lat"],
get_target_position=["end_lon", "end_lat"],
get_source_color=[255, 165, 0, 80],
get_target_color=[255, 165, 0, 80],
get_width=3,
)
layers.append(bus_route_layer)
# Create the map view
view_state = pdk.ViewState(
latitude=SHIBUYA_LAT,
longitude=SHIBUYA_LON,
zoom=13,
pitch=45,
)
# And remove the map_style parameter from the Deck constructor
r = pdk.Deck(
layers=layers,
initial_view_state=view_state,
# remove map_style=map_style,
tooltip={
"text": "{name}\nType: {type}\nChildren: {children}"
}
)
st.pydeck_chart(r)
# Stats panel
col1, col2, col3 = st.columns(3)
with col1:
st.subheader("Nursery Schools")
st.metric("Total Schools", len(nursery_schools))
st.metric("Total Children", nursery_schools['children'].sum())
with col2:
st.subheader("Elementary Schools")
st.metric("Total Schools", len(elementary_schools))
st.metric("Total Students", elementary_schools['students'].sum())
with col3:
st.subheader("Transport")
st.metric("Bus Stops", len(bus_stops))
st.metric("Bus Routes", len(bus_routes['route_id'].unique()))
# Show filtered data tables
if st.checkbox("Show Raw Data"):
st.subheader("Nursery Schools Data")
st.dataframe(nursery_schools)
st.subheader("Elementary Schools Data")
st.dataframe(elementary_schools)
st.subheader("Bus Stops Data")
st.dataframe(bus_stops)
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?