Create an app showing an interactive NYC map visualization. Mock data: - Food truck locations (100 points) - Pedestrian activity heatmap Features: - Interactive map centered on NYC - Toggle layers: * Food trucks with popups * Pedestrian heatmap * Animated routes * Taxi clusters Controls: - Time slider - Borough filters - Color schemes - Map style (street/satellite) - Heatmap and cluster settings Include zoom/pan and stats panel showing data summaries.
Drop files here
or click to upload
import streamlit as st
import pandas as pd
import numpy as np
import pydeck as pdk
import plotly.express as px
from datetime import datetime, timedelta
# Configure page
st.set_page_config(
page_title="NYC Interactive Map Visualization",
page_icon="π½",
layout="wide"
)
# NYC coordinates
NYC_CENTER = [40.7831, -73.9712]
# Generate mock data
@st.cache_data
def generate_food_truck_data():
np.random.seed(42)
# Define NYC boroughs with their approximate boundaries
boroughs = {
'Manhattan': {'lat_center': 40.7831, 'lon_center': -73.9712, 'spread': 0.02},
'Brooklyn': {'lat_center': 40.6782, 'lon_center': -73.9442, 'spread': 0.04},
'Queens': {'lat_center': 40.7282, 'lon_center': -73.7949, 'spread': 0.05},
'Bronx': {'lat_center': 40.8448, 'lon_center': -73.8648, 'spread': 0.03},
'Staten Island': {'lat_center': 40.5795, 'lon_center': -74.1502, 'spread': 0.02}
}
food_trucks = []
truck_types = ['Pizza', 'Tacos', 'Burgers', 'Hot Dogs', 'Ice Cream', 'Coffee', 'Asian Fusion', 'Sandwiches']
for i in range(100):
borough = np.random.choice(list(boroughs.keys()))
borough_info = boroughs[borough]
lat = np.random.normal(borough_info['lat_center'], borough_info['spread'])
lon = np.random.normal(borough_info['lon_center'], borough_info['spread'])
food_trucks.append({
'id': f'truck_{i}',
'name': f"{np.random.choice(truck_types)} Truck {i+1}",
'lat': lat,
'lon': lon,
'borough': borough,
'type': np.random.choice(truck_types),
'rating': np.random.uniform(3.5, 5.0),
'avg_wait': np.random.randint(5, 25),
'price_range': np.random.choice(['$', '$$', '$$$']),
'hour': np.random.randint(0, 24)
})
return pd.DataFrame(food_trucks)
@st.cache_data
def generate_pedestrian_data():
np.random.seed(123)
# Generate heatmap data for pedestrian activity
pedestrian_data = []
# Focus on Manhattan and parts of Brooklyn for high pedestrian activity
for _ in range(500):
# Create clusters around popular areas
center_choice = np.random.choice([
[40.7589, -73.9851], # Times Square
[40.7505, -73.9934], # Empire State Building
[40.7061, -74.0087], # World Trade Center
[40.7812, -73.9665], # Central Park
[40.6892, -73.9442], # Brooklyn Heights
])
lat = np.random.normal(center_choice[0], 0.005)
lon = np.random.normal(center_choice[1], 0.005)
pedestrian_data.append({
'lat': lat,
'lon': lon,
'count': np.random.randint(10, 100),
'hour': np.random.randint(0, 24)
})
return pd.DataFrame(pedestrian_data)
@st.cache_data
def generate_taxi_data():
np.random.seed(456)
taxi_data = []
for _ in range(200):
lat = np.random.normal(40.7589, 0.03)
lon = np.random.normal(-73.9851, 0.03)
taxi_data.append({
'lat': lat,
'lon': lon,
'trips': np.random.randint(1, 50),
'hour': np.random.randint(0, 24)
})
return pd.DataFrame(taxi_data)
@st.cache_data
def generate_route_data():
np.random.seed(789)
routes = []
for i in range(10):
# Create random routes across NYC
start_lat = np.random.normal(40.7589, 0.02)
start_lon = np.random.normal(-73.9851, 0.02)
# Generate waypoints for each route
waypoints = []
for j in range(5):
lat = start_lat + (j * 0.005 * np.random.choice([-1, 1]))
lon = start_lon + (j * 0.005 * np.random.choice([-1, 1]))
waypoints.append([lon, lat])
routes.append({
'route_id': i,
'path': waypoints,
'color': [np.random.randint(100, 255), np.random.randint(100, 255), np.random.randint(100, 255)]
})
return routes
# Load data
food_trucks_df = generate_food_truck_data()
pedestrian_df = generate_pedestrian_data()
taxi_df = generate_taxi_data()
routes_data = generate_route_data()
# Title and description
st.title("π½ NYC Interactive Map Visualization")
st.markdown("Explore New York City through interactive data layers showing food trucks, pedestrian activity, taxi clusters, and animated routes.")
# Sidebar controls
st.sidebar.header("Map Controls")
# Time slider
st.sidebar.subheader("β° Time Filter")
selected_hour = st.sidebar.slider("Hour of Day", 0, 23, 12)
# Borough filter
st.sidebar.subheader("ποΈ Borough Filter")
boroughs = ['All'] + list(food_trucks_df['borough'].unique())
selected_boroughs = st.sidebar.multiselect("Select Boroughs", boroughs, default=['All'])
if 'All' in selected_boroughs or len(selected_boroughs) == 0:
selected_boroughs = list(food_trucks_df['borough'].unique())
# Layer toggles
st.sidebar.subheader("πΊοΈ Map Layers")
show_food_trucks = st.sidebar.checkbox("Food Trucks", value=True)
show_pedestrian = st.sidebar.checkbox("Pedestrian Heatmap", value=True)
show_routes = st.sidebar.checkbox("Animated Routes", value=False)
show_taxi_clusters = st.sidebar.checkbox("Taxi Clusters", value=False)
# Map style
st.sidebar.subheader("π¨ Map Style")
map_style = st.sidebar.selectbox("Map Style", ["mapbox://styles/mapbox/streets-v11", "mapbox://styles/mapbox/satellite-v9"])
# Color scheme
color_scheme = st.sidebar.selectbox("Color Scheme", ["viridis", "plasma", "inferno", "magma"])
# Heatmap settings
st.sidebar.subheader("π₯ Heatmap Settings")
heatmap_radius = st.sidebar.slider("Heatmap Radius", 10, 100, 50)
heatmap_intensity = st.sidebar.slider("Heatmap Intensity", 0.1, 2.0, 1.0)
# Cluster settings
st.sidebar.subheader("π Cluster Settings")
cluster_radius = st.sidebar.slider("Cluster Radius", 10, 200, 50)
# Filter data based on controls
filtered_trucks = food_trucks_df[
(food_trucks_df['borough'].isin(selected_boroughs)) &
(food_trucks_df['hour'] == selected_hour)
]
filtered_pedestrian = pedestrian_df[pedestrian_df['hour'] == selected_hour]
filtered_taxi = taxi_df[taxi_df['hour'] == selected_hour]
# Create map layers
layers = []
# Food truck layer
if show_food_trucks and len(filtered_trucks) > 0:
layers.append(
pdk.Layer(
"ScatterplotLayer",
data=filtered_trucks,
get_position=["lon", "lat"],
get_color=[255, 140, 0, 160],
get_radius=50,
pickable=True,
)
)
# Pedestrian heatmap layer
if show_pedestrian and len(filtered_pedestrian) > 0:
layers.append(
pdk.Layer(
"HeatmapLayer",
data=filtered_pedestrian,
get_position=["lon", "lat"],
get_weight="count",
radius_pixels=heatmap_radius,
intensity=heatmap_intensity,
threshold=0.3,
)
)
# Route layer
if show_routes:
layers.append(
pdk.Layer(
"PathLayer",
data=routes_data,
get_path="path",
get_color="color",
width_scale=20,
width_min_pixels=2,
pickable=True,
)
)
# Taxi cluster layer
if show_taxi_clusters and len(filtered_taxi) > 0:
layers.append(
pdk.Layer(
"HexagonLayer",
data=filtered_taxi,
get_position=["lon", "lat"],
get_elevation_weight="trips",
radius=cluster_radius,
elevation_scale=4,
elevation_range=[0, 1000],
pickable=True,
extruded=True,
)
)
# Create the deck
deck = pdk.Deck(
map_style=map_style,
initial_view_state=pdk.ViewState(
latitude=NYC_CENTER[0],
longitude=NYC_CENTER[1],
zoom=11,
pitch=50,
),
layers=layers,
tooltip={
"html": "<b>{name}</b><br/>Type: {type}<br/>Rating: {rating:.1f}/5<br/>Wait: {avg_wait} min<br/>Price: {price_range}",
"style": {"backgroundColor": "steelblue", "color": "white"}
}
)
# Layout: Map and Stats
col1, col2 = st.columns([3, 1])
with col1:
st.subheader("πΊοΈ Interactive Map")
st.pydeck_chart(deck, use_container_width=True)
with col2:
st.subheader("π Data Summary")
# Current time stats
st.metric("Current Hour", f"{selected_hour:02d}:00")
# Food truck stats
if show_food_trucks:
st.markdown("**π Food Trucks**")
st.metric("Active Trucks", len(filtered_trucks))
if len(filtered_trucks) > 0:
avg_rating = filtered_trucks['rating'].mean()
st.metric("Avg Rating", f"{avg_rating:.1f}/5")
avg_wait = filtered_trucks['avg_wait'].mean()
st.metric("Avg Wait Time", f"{avg_wait:.0f} min")
# Pedestrian stats
if show_pedestrian:
st.markdown("**πΆ Pedestrian Activity**")
total_pedestrians = filtered_pedestrian['count'].sum()
st.metric("Total Activity", f"{total_pedestrians:,}")
if len(filtered_pedestrian) > 0:
avg_activity = filtered_pedestrian['count'].mean()
st.metric("Avg per Location", f"{avg_activity:.0f}")
# Taxi stats
if show_taxi_clusters:
st.markdown("**π Taxi Activity**")
total_trips = filtered_taxi['trips'].sum()
st.metric("Total Trips", f"{total_trips:,}")
if len(filtered_taxi) > 0:
avg_trips = filtered_taxi['trips'].mean()
st.metric("Avg per Cluster", f"{avg_trips:.0f}")
# Borough breakdown
st.markdown("**ποΈ Borough Distribution**")
borough_counts = filtered_trucks['borough'].value_counts()
for borough, count in borough_counts.items():
st.text(f"{borough}: {count}")
# Additional analytics
st.markdown("---")
st.subheader("π Analytics Dashboard")
col1, col2 = st.columns(2)
with col1:
# Hourly activity chart
if show_pedestrian:
hourly_pedestrian = pedestrian_df.groupby('hour')['count'].sum().reset_index()
fig_hourly = px.line(
hourly_pedestrian,
x='hour',
y='count',
title='Pedestrian Activity by Hour',
color_discrete_sequence=[px.colors.qualitative.Set1[0]]
)
fig_hourly.add_vline(x=selected_hour, line_dash="dash", line_color="red")
st.plotly_chart(fig_hourly, use_container_width=True)
with col2:
# Borough distribution
borough_dist = food_trucks_df['borough'].value_counts().reset_index()
borough_dist.columns = ['Borough', 'Count']
fig_borough = px.pie(
borough_dist,
values='Count',
names='Borough',
title='Food Truck Distribution by Borough'
)
st.plotly_chart(fig_borough, use_container_width=True)
# Data tables
with st.expander("π View Raw Data"):
tab1, tab2, tab3 = st.tabs(["Food Trucks", "Pedestrian Data", "Taxi Data"])
with tab1:
st.dataframe(filtered_trucks, use_container_width=True)
with tab2:
st.dataframe(filtered_pedestrian, use_container_width=True)
with tab3:
st.dataframe(filtered_taxi, use_container_width=True)
# Instructions
st.markdown("---")
st.markdown("""
### π― How to Use
1. **Time Control**: Use the hour slider to see data for different times of day
2. **Borough Filter**: Select specific boroughs to focus on particular areas
3. **Layer Toggles**: Turn different data layers on/off to customize your view
4. **Map Style**: Switch between street and satellite views
5. **Settings**: Adjust heatmap and cluster visualization parameters
6. **Interactive Elements**: Click on map elements to see detailed information
### πΊοΈ Layer Information
- **Food Trucks**: Orange dots showing truck locations with popup details
- **Pedestrian Heatmap**: Heat visualization of foot traffic density
- **Animated Routes**: Colored paths showing movement patterns
- **Taxi Clusters**: 3D hexagonal clusters showing trip concentrations
""")
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?