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.
To upload files, please first save the app
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
import folium
from streamlit_folium import st_folium
from datetime import datetime, timedelta
import random
# Set page config
st.set_page_config(
page_title="NYC Interactive Map Visualization",
page_icon="š½",
layout="wide",
initial_sidebar_state="expanded"
)
# Generate mock data
@st.cache_data
def generate_food_trucks():
"""Generate mock food truck data"""
np.random.seed(42)
# NYC bounding box
lat_min, lat_max = 40.4774, 40.9176
lon_min, lon_max = -74.2591, -73.7004
trucks = []
truck_types = ['Taco', 'Burger', 'Pizza', 'Hot Dog', 'Ice Cream', 'Halal', 'BBQ', 'Coffee']
boroughs = ['Manhattan', 'Brooklyn', 'Queens', 'Bronx', 'Staten Island']
for i in range(100):
trucks.append({
'id': i,
'name': f"{random.choice(truck_types)} Truck #{i+1}",
'type': random.choice(truck_types),
'lat': np.random.uniform(lat_min, lat_max),
'lon': np.random.uniform(lon_min, lon_max),
'borough': random.choice(boroughs),
'rating': round(np.random.uniform(3.0, 5.0), 1),
'price_range': random.choice(['$', '$$', '$$$']),
'hours': f"{random.randint(6, 11)}AM - {random.randint(6, 11)}PM"
})
return pd.DataFrame(trucks)
@st.cache_data
def generate_pedestrian_data():
"""Generate mock pedestrian activity data"""
np.random.seed(43)
# NYC bounding box with focus on Manhattan
lat_min, lat_max = 40.7000, 40.7831
lon_min, lon_max = -74.0479, -73.9441
pedestrians = []
for i in range(200):
pedestrians.append({
'lat': np.random.uniform(lat_min, lat_max),
'lon': np.random.uniform(lon_min, lon_max),
'activity': np.random.randint(10, 1000),
'hour': np.random.randint(0, 24)
})
return pd.DataFrame(pedestrians)
@st.cache_data
def generate_taxi_data():
"""Generate mock taxi data"""
np.random.seed(44)
# NYC bounding box
lat_min, lat_max = 40.4774, 40.9176
lon_min, lon_max = -74.2591, -73.7004
taxis = []
for i in range(150):
taxis.append({
'lat': np.random.uniform(lat_min, lat_max),
'lon': np.random.uniform(lon_min, lon_max),
'pickup_count': np.random.randint(1, 50),
'hour': np.random.randint(0, 24)
})
return pd.DataFrame(taxis)
@st.cache_data
def generate_routes():
"""Generate mock animated routes"""
np.random.seed(45)
routes = []
for i in range(10):
start_lat = np.random.uniform(40.7000, 40.7831)
start_lon = np.random.uniform(-74.0479, -73.9441)
# Generate route points
route_points = []
current_lat, current_lon = start_lat, start_lon
for j in range(20):
current_lat += np.random.uniform(-0.01, 0.01)
current_lon += np.random.uniform(-0.01, 0.01)
route_points.append([current_lat, current_lon])
routes.append({
'route_id': i,
'points': route_points,
'type': random.choice(['Bus', 'Delivery', 'Emergency'])
})
return routes
# Load data
food_trucks = generate_food_trucks()
pedestrian_data = generate_pedestrian_data()
taxi_data = generate_taxi_data()
routes_data = generate_routes()
# Sidebar controls
st.sidebar.title("š½ NYC 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")
selected_boroughs = st.sidebar.multiselect(
"Select Boroughs",
options=food_trucks['borough'].unique(),
default=food_trucks['borough'].unique()
)
# Layer toggles
st.sidebar.subheader("šļø Map Layers")
show_food_trucks = st.sidebar.checkbox("Food Trucks", True)
show_pedestrian_heatmap = st.sidebar.checkbox("Pedestrian Heatmap", True)
show_animated_routes = st.sidebar.checkbox("Animated Routes", False)
show_taxi_clusters = st.sidebar.checkbox("Taxi Clusters", True)
# Color scheme
st.sidebar.subheader("šØ Styling")
color_scheme = st.sidebar.selectbox(
"Color Scheme",
["viridis", "plasma", "inferno", "magma", "cividis"]
)
# Map style
map_style = st.sidebar.selectbox(
"Map Style",
["OpenStreetMap", "Stamen Terrain", "Stamen Toner", "CartoDB positron"]
)
# Heatmap settings
st.sidebar.subheader("š„ Heatmap Settings")
heatmap_radius = st.sidebar.slider("Heatmap Radius", 10, 50, 25)
heatmap_blur = st.sidebar.slider("Heatmap Blur", 10, 50, 25)
# Cluster settings
st.sidebar.subheader("šÆ Cluster Settings")
cluster_size = st.sidebar.slider("Cluster Size", 5, 50, 20)
# Main content
st.title("š½ NYC Interactive Map Visualization")
st.markdown("Explore New York City through interactive data layers")
# Create main map
col1, col2 = st.columns([3, 1])
with col1:
# Filter data based on selections
filtered_trucks = food_trucks[food_trucks['borough'].isin(selected_boroughs)]
filtered_pedestrians = pedestrian_data[pedestrian_data['hour'] == selected_hour]
filtered_taxis = taxi_data[taxi_data['hour'] == selected_hour]
# Create base map
m = folium.Map(
location=[40.7831, -73.9712], # NYC center
zoom_start=11,
tiles=map_style if map_style != "OpenStreetMap" else None
)
# Add food trucks layer
if show_food_trucks and not filtered_trucks.empty:
truck_colors = {
'Taco': 'red', 'Burger': 'blue', 'Pizza': 'green', 'Hot Dog': 'orange',
'Ice Cream': 'pink', 'Halal': 'purple', 'BBQ': 'darkred', 'Coffee': 'brown'
}
for _, truck in filtered_trucks.iterrows():
popup_text = f"""
<b>{truck['name']}</b><br>
Type: {truck['type']}<br>
Borough: {truck['borough']}<br>
Rating: {truck['rating']} ā<br>
Price: {truck['price_range']}<br>
Hours: {truck['hours']}
"""
folium.Marker(
[truck['lat'], truck['lon']],
popup=folium.Popup(popup_text, max_width=200),
tooltip=truck['name'],
icon=folium.Icon(
color=truck_colors.get(truck['type'], 'gray'),
icon='cutlery',
prefix='fa'
)
).add_to(m)
# Add pedestrian heatmap
if show_pedestrian_heatmap and not filtered_pedestrians.empty:
from folium.plugins import HeatMap
heat_data = [[row['lat'], row['lon'], row['activity']]
for _, row in filtered_pedestrians.iterrows()]
HeatMap(
heat_data,
radius=heatmap_radius,
blur=heatmap_blur,
max_zoom=1,
gradient={0.2: 'blue', 0.4: 'lime', 0.6: 'orange', 1: 'red'}
).add_to(m)
# Add taxi clusters
if show_taxi_clusters and not filtered_taxis.empty:
from folium.plugins import MarkerCluster
taxi_cluster = MarkerCluster(name='Taxi Pickups')
for _, taxi in filtered_taxis.iterrows():
folium.CircleMarker(
[taxi['lat'], taxi['lon']],
radius=max(5, taxi['pickup_count'] / 5),
popup=f"Pickups: {taxi['pickup_count']}",
color='yellow',
fill=True,
weight=2
).add_to(taxi_cluster)
taxi_cluster.add_to(m)
# Add animated routes
if show_animated_routes:
colors = ['red', 'blue', 'green', 'purple', 'orange']
for i, route in enumerate(routes_data[:5]): # Show only first 5 routes
folium.PolyLine(
route['points'],
color=colors[i % len(colors)],
weight=4,
opacity=0.7,
popup=f"{route['type']} Route {route['route_id']}"
).add_to(m)
# Add layer control
folium.LayerControl().add_to(m)
# Display map
map_data = st_folium(m, width=800, height=600, returned_objects=["last_clicked"])
with col2:
st.subheader("š Statistics Panel")
# Current filters info
st.info(f"š
Time: {selected_hour}:00\nšļø Boroughs: {len(selected_boroughs)}")
# Food truck stats
if show_food_trucks:
st.metric("š Food Trucks", len(filtered_trucks))
if not filtered_trucks.empty:
avg_rating = filtered_trucks['rating'].mean()
st.metric("ā Avg Rating", f"{avg_rating:.1f}")
# Top truck types
st.subheader("Top Truck Types")
truck_counts = filtered_trucks['type'].value_counts().head(3)
for truck_type, count in truck_counts.items():
st.write(f"⢠{truck_type}: {count}")
# Pedestrian stats
if show_pedestrian_heatmap:
st.metric("š¶ Pedestrian Points", len(filtered_pedestrians))
if not filtered_pedestrians.empty:
avg_activity = filtered_pedestrians['activity'].mean()
st.metric("š Avg Activity", f"{avg_activity:.0f}")
# Taxi stats
if show_taxi_clusters:
st.metric("š Taxi Points", len(filtered_taxis))
if not filtered_taxis.empty:
total_pickups = filtered_taxis['pickup_count'].sum()
st.metric("š Total Pickups", total_pickups)
# Route stats
if show_animated_routes:
st.metric("š£ļø Active Routes", len(routes_data))
# Data summary by borough
if not filtered_trucks.empty:
st.subheader("Borough Breakdown")
borough_stats = filtered_trucks.groupby('borough').agg({
'rating': 'mean',
'name': 'count'
}).round(1)
borough_stats.columns = ['Avg Rating', 'Count']
st.dataframe(borough_stats, use_container_width=True)
# Additional visualizations
st.subheader("š Data Analytics")
col3, col4 = st.columns(2)
with col3:
# Hourly activity chart
hourly_pedestrians = pedestrian_data.groupby('hour')['activity'].sum().reset_index()
fig_hourly = px.line(
hourly_pedestrians,
x='hour',
y='activity',
title='Pedestrian Activity by Hour',
color_discrete_sequence=[px.colors.qualitative.Set1[0]]
)
fig_hourly.update_layout(height=300)
st.plotly_chart(fig_hourly, use_container_width=True)
with col4:
# Food truck types distribution
truck_type_counts = food_trucks['type'].value_counts()
fig_pie = px.pie(
values=truck_type_counts.values,
names=truck_type_counts.index,
title='Food Truck Types Distribution'
)
fig_pie.update_layout(height=300)
st.plotly_chart(fig_pie, use_container_width=True)
# Map interaction feedback
if map_data['last_clicked']:
st.subheader("šÆ Last Clicked Location")
clicked_lat = map_data['last_clicked']['lat']
clicked_lng = map_data['last_clicked']['lng']
st.write(f"Latitude: {clicked_lat:.4f}")
st.write(f"Longitude: {clicked_lng:.4f}")
# Footer
st.markdown("---")
st.markdown("š½ **NYC Interactive Map Visualization** - Built with Streamlit, Folium, and Plotly")
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?