Appendix A — Datasets

A.1 What This Appendix Covers

This appendix is the reference you come back to whenever you need to remember how a dataset is structured or what its known quirks are. For every dataset used in the book, the entry below lists:

  • Source (publishing agency) and URL
  • Filename in the course repository
  • Chapters where the dataset is used
  • Structure — what each row represents and the full column list with types
  • Known quirks — the gotchas you need to handle before analysis

The “Known quirks” block for each dataset is your per-dataset troubleshooting guide. Read it before loading the file for the first time; return to it whenever a new error surprises you.

All datasets are available in the accompanying GitHub repository.

A.2 Colorado Cannabis Sales by County

Source: Colorado Department of Revenue, Marijuana Enforcement Division
URL: https://cdor.colorado.gov/data-and-reports/marijuana-data/marijuana-sales-reports
File: colorado_cannabis_sales_by_county.csv
Used in: Chapter 5, Chapter 9

This file contains monthly medical and retail cannabis sales totals for each Colorado county from 2014 to 2024. The original file is an Excel export with a two-row title block at the top and an eight-row footnote section at the bottom.

Structure: Each row represents one county’s sales for one month.

Column Type Description
Month integer Calendar month (1–12)
Year integer Calendar year (2014–2024)
County text Colorado county name
Medical Sales currency string Medical cannabis sales in dollars
Retail Sales currency string Retail cannabis sales in dollars

Known quirks:

  • Header row is on row 2 (zero-indexed), not row 0. Use header=2 in read_csv.
  • Eight footer rows contain footnotes and source information. Use skipfooter=8.
  • Sales columns are formatted as currency strings ($1,234,567) and must be stripped of $ and , before numeric conversion.
  • NR (Not Reported) appears in sales columns for counties with fewer than three licensees. Treat as missing with na_values=['NR'].
  • Rows with County == 'Total' are monthly statewide aggregates and should be removed before county-level analysis.
  • County names may contain leading or trailing whitespace.

A.3 Boulder County Voter Registration Data

Source: Boulder County Clerk and Recorder
URL: https://bouldercounty.gov/elections/maps-and-data/data-access/
File: boco_voter_data.txt
Used in: Chapter 6

A pipe-delimited text file containing voter registration records for Boulder County. Each row represents one registered voter.

Column Type Description
VOTER_ID text Unique voter identifier (has leading zeros)
VOTER_NAME text Full name
RES_ADDRESS text Residential address
RES_CITY text City of residence
RES_ZIP_CODE text 5-digit ZIP code (has leading zeros)
PARTY text Party affiliation code
YOB integer Year of birth
PRECINCT text Precinct number

Known quirks:

  • Delimiter is | (pipe), not comma. Use sep='|' in read_csv.
  • VOTER_ID, RES_ZIP_CODE, BALLOT_ZIP, and PRECINCT contain leading zeros and should be loaded as strings using the dtype parameter.
  • Party affiliation codes are inconsistent — multiple abbreviations for the same party (e.g., DEM, Dem, D, Democrat).
  • Some text fields contain extra whitespace, non-breaking spaces, or inconsistent capitalization.

A.4 Lahman Baseball Database

Source: Sean Lahman’s Baseball Archive
URL: https://www.seanlahman.com/baseball-archive/statistics/
Files: Batting.csv, Salaries.csv, People.csv, Teams.csv
Used in: Chapter 7, Chapter 8

A comprehensive historical database of Major League Baseball statistics. The book uses four tables from this database.

A.4.1 Batting.csv

Each row represents one player’s statistics for one team in one season. Players traded mid-season have multiple rows (one per “stint”).

Column Type Description
playerID text Unique player identifier
yearID integer Season year
teamID text Team abbreviation
stint integer Order of appearance with team that season
AB integer At bats
H integer Hits
2B integer Doubles
3B integer Triples
HR integer Home runs
BB integer Bases on balls (walks)
HBP integer Hit by pitch (NULL before this stat was tracked)
SF integer Sacrifice flies (NULL before this stat was tracked)

Known quirks:

  • HBP and SF are NULL for early seasons when these statistics were not recorded. Filling with 0 is a common choice but should be documented.
  • Players traded mid-season appear as multiple rows. Aggregate to one row per (playerID, yearID) before computing season-level metrics or merging with other tables.

A.4.2 Salaries.csv

One row per player per season. Salary data begins in 1985.

Column Type Description
playerID text Unique player identifier
yearID integer Season year
teamID text Team abbreviation
salary integer Annual salary in dollars

A.4.3 People.csv

One row per player. Biographical information.

Column Type Description
playerID text Unique player identifier
nameFirst text First name
nameLast text Last name
birthYear integer Year of birth
birthState text State/province of birth
birthCountry text Country of birth

A.4.4 Teams.csv

One row per team per season. Franchise-level information.

Column Type Description
teamID text Team abbreviation
yearID integer Season year
franchID text Franchise identifier
name text Full team name
W integer Wins
L integer Losses
attendance integer Season attendance

A.5 Colorado State Demography Office — Single Year of Age Estimates

Source: Colorado Department of Local Affairs (DOLA), State Demography Office
URL: https://demography.dola.colorado.gov/assets/html/sdodata.html
File: sya-county.csv
Used in: Chapter 7, Chapter 8, Chapter 10, Chapter 12

Population estimates by county, year, and single year of age (0 through 100). Includes both historical estimates and future forecasts.

Column Type Description
countyfips text FIPS county code (with leading zeros)
county text County name
year integer Calendar year
age integer Single year of age (0–100)
malepopulation integer Male population count
femalepopulation integer Female population count
totalpopulation integer Total population count
datatype text Estimate (historical) or Forecast (projected)

Known quirks:

  • The first row of the CSV is a metadata header. Use skiprows=1 in read_csv.
  • countyfips has leading zeros and should be loaded as a string.
  • The datatype column distinguishes historical estimates from projections. Filter to Estimate rows for historical analysis.
  • County names use bare names (e.g., Adams, not Adams County). This format differs from the CDC and CBI datasets and must be standardized before joining. The standardization process and its consequences are demonstrated in Chapter 10 and Chapter 12.
  • Contains a DtypeWarning on some columns due to mixed types.

A.6 CDC WONDER — Underlying Cause of Death

Source: Centers for Disease Control and Prevention, WONDER database
URL: https://wonder.cdc.gov/ucd-icd10.html
File: cdc_deaths.csv
Used in: Chapter 10, Chapter 12

Colorado mortality counts by county, year, age group, and ICD-10 chapter (broad cause of death category).

Column Type Description
County text County name (format: Adams County, CO)
Year integer Calendar year
Age Group text Age band
ICD Chapter text Broad cause of death category
Deaths integer Number of deaths

Known quirks:

  • County names are in the format 'Adams County, CO'. This must be standardized to match other datasets; see Chapter 10 for the cleaning workflow.
  • Death counts below 10 may be suppressed for privacy. The value appears as Suppressed rather than a number.
  • Unreliable flags appear for counts based on small numbers.

A.7 Colorado Bureau of Investigation — Crime Statistics

Source: Colorado Bureau of Investigation
URL: https://coloradocrimestats.state.co.us/
File: cbi_crime.csv
Used in: Chapter 10, Chapter 12

Reported criminal offenses by jurisdiction, date, and offense type.

Column Type Description
jurisdiction text Reporting agency (format: Adams County)
offense_date text Date of offense
offense_type text Type of offense
county text County (may differ from jurisdiction)

Known quirks:

  • County names use the format 'Adams County' (with ” County” suffix but without state abbreviation). Must be standardized before joining with other sources; see Chapter 10 and Chapter 12.
  • Jurisdiction names do not always map cleanly to county names — some jurisdictions are municipal police departments rather than county sheriff offices.
  • Multiple NULL patterns across columns; different columns use different conventions for missing data.

A.8 Boulder County Assessor

A.8.1 Buildings

Source: Boulder County Assessor’s Office
URL: https://bouldercounty.gov/property-and-land/assessor/data-download/
File: buildings.csv
Used in: Chapter 11

One row per improvement section recorded for each parcel. Contains detailed building characteristics.

Column Type Description
strap text Parcel account number
bld_num integer Building number on parcel
section_num integer Section within building
bldg_class text Building class (R = residential, C = commercial)
quality_grade text Construction quality rating
year_built integer Year of construction
above_ground_sqft integer Above-ground square footage
heating_type text Heating system type
roof_type text Roof material

Known quirks:

  • Some text columns have trailing whitespace.
  • Placeholder zeros in categorical columns should be treated as missing.
  • Multiple rows per parcel account number (one per building section).

A.8.2 Residential Sales

Source: Boulder County Assessor’s Office
URL: https://bouldercounty.gov/property-and-land/assessor/sales/
File: ar-rec-2025-residential.xlsx
Used in: Chapter 6

Residential property sales records.

Column Type Description
ACCOUNTNO text Property account number (has trailing whitespace)
PROPERTY_ADDRESS text Street address
LOCCITY text City
SALE_DATE datetime Date of sale
SALE_PRICE mixed Sale price (contains $, commas, and text like PRIVATE SALE)

Known quirks:

  • ACCOUNTNO has trailing whitespace that must be stripped.
  • SALE_PRICE contains currency formatting and non-numeric values like PRIVATE SALE.
  • Multiple rows per ACCOUNTNO (representing different sale transactions over time).

A.9 Non-Tabular Data Sources

The five chapters in Part IV use specialized datasets — shapefiles, edge lists, text corpora, time series, and API responses. Each chapter’s examples assume one or more of the sources listed below.

A.9.1 Census TIGER/Line Shapefiles (Chapter 13)

Source: US Census Bureau URL: https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html Files: tl_2023_08_county.shp (Colorado counties) and companion .shx, .dbf, .prj files Used in: Chapter 13

County and state boundary polygons for the entire United States, republished annually. The Colorado-specific file (08 = state FIPS) is a good default for the book’s spatial examples.

Known quirks:

  • A shapefile is actually several files (.shp, .shx, .dbf, .prj). Keep them together in the same folder.
  • Default CRS is EPSG:4269 (NAD83 latitude/longitude). Reproject to EPSG:3857 for overlays on web basemaps.
  • Each county has a GEOID / COUNTYFP that matches the countyfips column in the State Demography Office data.

A.9.2 ICON / KONECT / Network Repository Edge Lists (Chapter 14)

Sources: ICON (CU Boulder), KONECT (Koblenz), Network Repository Example files: soc-karate.edges (Zachary’s karate club), soc-dolphins.edges (dolphin social network) Used in: Chapter 14

Small, curated network datasets suitable for teaching. Zachary’s karate club (34 nodes, 78 edges) is the single most common beginner example.

Known quirks:

  • Edge-list files often start with comment lines prefixed by % (KONECT) or #. Use comment='%' in pd.read_csv to skip them.
  • Many datasets ship as whitespace-delimited .edges files, not .csv. Pass sep=r'\s+' or sep=' ' to pd.read_csv.
  • Node IDs are typically integers. Cast consistently before building a graph to avoid “node not in graph” errors.

A.9.3 Project Gutenberg and NLTK Corpora (Chapter 15)

Sources: Project Gutenberg, NLTK built-in corpora Example files: 2021-biden.txt (Project Gutenberg), inaugural corpus (NLTK built-in) Used in: Chapter 15

The NLTK inaugural corpus contains every US presidential inaugural address (1789–present) as plain text, accessible via nltk.corpus.inaugural. Project Gutenberg distributes public-domain literature in UTF-8 text.

Known quirks:

  • Project Gutenberg files include a boilerplate header and footer that must be stripped before analysis.
  • NLTK corpora require a one-time nltk.download('inaugural') (and similar for other corpora and resources like punkt, stopwords, wordnet, vader_lexicon).
  • Encoding is UTF-8 for recent files; older Gutenberg texts may arrive as Latin-1. Pass encoding= explicitly.

A.9.4 FRED / World Bank / IMF Time Series (Chapter 16)

Sources: FRED, World Bank Open Data, IMF Data Example files: UNRATE.csv (US unemployment rate, monthly), CPIAUCSL.csv (CPI, monthly), HOUST.csv (housing starts, monthly) Used in: Chapter 16

FRED publishes thousands of US macroeconomic series as downloadable CSVs with two columns: DATE and the series value. World Bank data arrives in wide format (one column per year) and requires melt to reshape into long.

Known quirks:

  • FRED files use DATE as an ISO date column. Parse with pd.to_datetime(df['DATE']) and set as the index.
  • Some series have “.” or blank rows for missing observations (e.g., during data-collection gaps). Treat these as NaN via na_values=['.', ''].
  • World Bank CSVs include 4 metadata rows at the top. Use skiprows=4.
  • IMF files sometimes require joining a separate country-code reference file before they are usable.

A.9.5 Public APIs for Structured Data (Chapter 17)

Sources: FRED API, Census Bureau API, OpenAlex API, Wikipedia/MediaWiki API, Open Library API Example file: example_openalex_response.json (cached API response), any static Wikipedia page for HTML scraping Used in: Chapter 17

All five APIs above are free; most require only a User-Agent header (or, for the OpenAlex “polite pool,” a mailto query parameter). The chapter includes worked examples against OpenAlex.

Known quirks:

  • FRED, Census, and Open Library require registration for an API key. OpenAlex and Wikipedia are unauthenticated.
  • Every API paginates differently — some use page=N, some use a cursor token, some use Link: headers. Read the docs before looping.
  • Rate limits are real. Respect them with time.sleep() between requests, and cache responses to disk during development.
  • API responses are JSON; flatten with pd.json_normalize() to get a clean DataFrame.

NotePublic Interest Context: Exemption

The datasets described in this appendix represent what is publicly available — what agencies have chosen to publish, in the formats they chose to publish it. That is a narrower set than what exists or what would be useful for public accountability.

Noticeably absent from what is publicly available at a useful granularity:

  • Housing displacement records at the parcel level — public records exist, but parcel-level linkage to eviction or code enforcement actions is rarely published.
  • Policing data at the incident level — Colorado requires some reporting, but stop-and-frisk data, use-of-force details, and officer-level records are inconsistently available across jurisdictions.
  • Detention and incarceration populations — county jail populations are not systematically published in machine-readable form.
  • Environmental health data — air quality monitoring stations cover urban centers but are sparse in rural counties and on Tribal lands.

Exemption — data that does not exist publicly, or is not released — is itself a data quality problem. The questions you cannot answer because the data is missing are often the most important ones to ask.

When you finish an analysis, it is worth asking: what would you study if you had access to data that is not currently available? That question is as analytically important as what you did study. See Chapter 4 for the broader framework.

A.10 Further Reading

Finding new datasets: Data.gov aggregates federal sources, CO Information Marketplace publishes Colorado state data, and your local city/county usually has an open-data portal. When evaluating a new source, always check what is published, when it was last updated, and what machine-readable formats are available.