Getting Started Tutorial¶
This tutorial introduces the fundamental concepts of SocialMapper through a practical example analyzing library accessibility in Wake County, North Carolina.
What You'll Learn¶
- How to search for Points of Interest (POIs) from OpenStreetMap
- How to generate travel time isochrones
- How to analyze census demographics within reachable areas
- How to export and interpret results
Prerequisites¶
Before starting this tutorial, ensure you have:
-
SocialMapper installed:
-
Census API key (optional but recommended):
!!! tip "Getting a Census API Key" You can obtain a free API key from the U.S. Census Bureau. While optional, having a key prevents rate limiting.
Tutorial Overview¶
This tutorial analyzes access to public libraries in Wake County, NC, demonstrating how residents can reach these important community resources within a 15-minute walk.
Step-by-Step Guide¶
Step 1: Import Required Libraries¶
The tutorial uses SocialMapper's modern API with two key components:
- SocialMapperClient
: Manages the analysis session
- SocialMapperBuilder
: Helps construct analysis configurations
Step 2: Define Search Parameters¶
geocode_area = "Wake County"
state = "North Carolina"
poi_type = "amenity" # OpenStreetMap category
poi_name = "library" # Specific type within category
travel_time = 15 # minutes
Key parameters explained: - geocode_area: The geographic area to analyze (county, city, or specific address) - state: Helps disambiguate location names - poi_type/poi_name: OpenStreetMap tags for finding specific place types - travel_time: Maximum walking time in minutes
OpenStreetMap Tags
Common POI combinations include:
- amenity=school
for schools
- amenity=hospital
for hospitals
- leisure=park
for parks
- shop=supermarket
for grocery stores
Step 3: Select Census Variables¶
These variables help understand the demographics of people who can access the libraries. SocialMapper supports many census variables including income, age, race, education, and housing characteristics.
Step 4: Build and Run the Analysis¶
with SocialMapperClient() as client:
# Build configuration using fluent interface
config = (SocialMapperBuilder()
.with_location(geocode_area, state)
.with_osm_pois(poi_type, poi_name)
.with_travel_time(travel_time)
.with_census_variables(*census_variables)
.with_exports(csv=True, isochrones=False, maps=True)
.build()
)
# Run analysis
result = client.run_analysis(config)
The builder pattern makes it easy to configure analyses:
- .with_location()
: Sets the geographic area
- .with_osm_pois()
: Configures POI search
- .with_travel_time()
: Sets travel time limit
- .with_census_variables()
: Selects demographic data
- .with_exports()
: Controls output formats (CSV data, isochrone boundaries, choropleth maps)
Step 5: Handle Results¶
if result.is_err():
error = result.unwrap_err()
print(f"Error: {error.message}")
else:
analysis_result = result.unwrap()
print(f"Found {analysis_result.poi_count} libraries")
print(f"Analyzed {analysis_result.census_units_analyzed} block groups")
SocialMapper uses Result types for robust error handling. The analysis returns: - poi_count: Number of libraries found - census_units_analyzed: Number of census block groups within reach - files_generated: Dictionary of output file paths
Understanding the Output¶
The tutorial generates multiple outputs:
1. CSV Data File¶
Located in output/csv/
, containing:
- POI Information: Name, address, and coordinates of each library
- Demographics: Population characteristics within walking distance
- Aggregated Statistics: Summary metrics across all reachable areas
2. Choropleth Maps¶
Located in output/maps/
, visualizing:
- Demographic Maps: Population density, income distribution, age patterns
- Distance Map: Travel distance to nearest library by census block group
- Accessibility Map: Combined view showing demographics within isochrones
Each map includes: - Color-coded census block groups showing data intensity - Library locations marked with symbols - Legend explaining the color scale - Scale bar and north arrow for reference
Sample Output Structure¶
The CSV file contains detailed demographic data for each library. Let's first look at the raw output:
import pandas as pd
# Read the generated CSV file
df = pd.read_csv('output/csv/wake_county_north_carolina_library_analysis.csv')
# Show raw data
print(df.head())
Raw output (hard to read):
poi_name poi_lat poi_lon total_population median_household_income median_age percent_poverty ...
0 Wake County Public Library - Main 35.779623 -78.638245 15420 65000 34.5 12.3 ...
1 Eva H. Perry Regional Library 35.723412 -78.856732 12300 58000 36.2 15.7 ...
2 Green Road Library 35.903234 -78.567891 18750 72500 32.1 8.9 ...
3 Apex Library 35.732156 -78.850234 22100 85000 35.8 5.2 ...
Creating a Readable Table¶
Now let's transform this into a clean, readable table using the tabulate
package:
from tabulate import tabulate
# Select and format key columns for display
display_df = pd.DataFrame({
'Library': df['poi_name'],
'Population Served': df['total_population'].astype(int).map('{:,}'.format),
'Median Income': df['median_household_income'].astype(int).map('${:,}'.format),
'Median Age': df['median_age'].round(1)
})
# Display using tabulate with GitHub-flavored markdown style
print(tabulate(display_df, headers='keys', tablefmt='github', showindex=False))
Clean, formatted table:
| Library | Population Served | Median Income | Median Age |
|-----------------------------------|-------------------|---------------|------------|
| Wake County Public Library - Main | 15,420 | $65,000 | 34.5 |
| Eva H. Perry Regional Library | 12,300 | $58,000 | 36.2 |
| Green Road Library | 18,750 | $72,500 | 32.1 |
| Apex Library | 22,100 | $85,000 | 35.8 |
Quick Summary Statistics¶
You can also use pandas to calculate summary statistics and display them in a clean table:
# Calculate summary statistics using pandas
summary_stats = pd.DataFrame({
'Metric': [
'Total Libraries',
'Total Population Reach',
'Average Population per Library',
'Average Median Income',
'Lowest Income Area',
'Highest Income Area',
'Average Age'
],
'Value': [
f"{len(df)}",
f"{df['total_population'].sum():,}",
f"{df['total_population'].mean():,.0f}",
f"${df['median_household_income'].mean():,.0f}",
f"${df['median_household_income'].min():,}",
f"${df['median_household_income'].max():,}",
f"{df['median_age'].mean():.1f} years"
]
})
print("\nSummary Statistics:")
print(tabulate(summary_stats, headers='keys', tablefmt='simple', showindex=False))
Output:
Summary Statistics:
Metric Value
------------------------------- -------------
Total Libraries 12
Total Population Reach 198,470
Average Population per Library 16,539
Average Median Income $68,750
Lowest Income Area $45,000
Highest Income Area $95,000
Average Age 34.8 years
Customizing the Analysis¶
Try Different POI Types¶
Replace the library search with other community resources:
# Parks
poi_type = "leisure"
poi_name = "park"
# Schools
poi_type = "amenity"
poi_name = "school"
# Healthcare
poi_type = "amenity"
poi_name = "hospital"
Adjust Travel Parameters¶
# Shorter walk (5 minutes)
travel_time = 5
# Longer walk (30 minutes)
travel_time = 30
# Different travel mode (requires mode support)
travel_mode = "drive" # or "bike"
Add More Census Variables¶
census_variables = [
"total_population",
"median_household_income",
"median_age",
"percent_poverty",
"percent_no_vehicle",
"percent_seniors"
]
Export Options¶
# Default (CSV + maps)
.with_exports(csv=True, isochrones=False, maps=True)
# All outputs
.with_exports(csv=True, isochrones=True, maps=True)
# Data only (no visualizations)
.with_exports(csv=True, isochrones=False, maps=False)
Common Issues and Solutions¶
No POIs Found¶
- Verify the location name is correct
- Try a larger geographic area
- Check POI type/name combination
Census Data Missing¶
- Ensure Census API key is set
- Some rural areas may have limited data
- Try different census variables
Slow Performance¶
- First run downloads street network data (cached for future use)
- Reduce travel time for faster analysis
- Use smaller geographic areas
Next Steps¶
After completing this tutorial, explore:
- Custom POIs Tutorial: Use your own location data
- Travel Modes Tutorial: Compare walk, bike, and drive access
- ZCTA Analysis Tutorial: Analyze by ZIP code
Full Code¶
The complete tutorial script is available at:
examples/tutorials/01_getting_started.py
Key Takeaways¶
- SocialMapper makes it easy to analyze community accessibility
- The builder pattern provides a clean API for configuration
- Results include both geographic and demographic insights
- Caching speeds up repeated analyses
- Error handling helps diagnose issues