Data Science

The analytics behind
LottoPickle

LottoPickle is a data science platform built on top of a publicly available lottery dataset. Each view in the app applies a distinct analytical technique — from descriptive statistics and time series analysis to combinatorics and probabilistic modeling. This page documents the methodology, implementation decisions, and underlying concepts.

The Dataset

New York State Lottery — Open Data

All analysis is performed on historical Powerball and Mega Millions draw data sourced from the New York State government open data portal (data.ny.gov). The dataset is publicly available, machine-readable, and updated after each draw.

Data is fetched via the SODA (Socrata Open Data API) REST interface, requesting up to 5,000 records ordered chronologically. Each record contains a draw date and space-delimited winning numbers. Parsing, filtering, and normalization happen client-side in the browser.

~2,800Powerball draws
~2,900Mega Millions draws
0Cost to access

Data Pipeline

01
FetchSODA REST API → JSON response
02
ParseMap rows → {date, main[], bonus}
03
FilterApply date range (1y / 3y / 5y / all)
04
Computefreq[], lastSeen[], pairs via useMemo
05
RenderChart.js + CSS visualizations
Analytical Methods

Eight analytical views,
eight different techniques

Each tab in the app applies a distinct data science concept to the same underlying dataset, demonstrating how a single data source can be interrogated from multiple analytical angles.

📊Descriptive Statistics

Frequency Distribution Analysis

Every lottery number is assigned a draw count across the full historical dataset. By plotting these counts as a bar chart ordered by number, we reveal the raw empirical distribution — a foundational step in any statistical exploration. Color encoding (hot/warm/neutral/cold) maps percentile rank to visual temperature, making outliers immediately apparent without needing to read axis values.

Empirical frequencyPercentile rankingData encodingExploratory Data Analysis (EDA)
🗺Data Visualization

Heatmap Visualization

The heatmap maps the same frequency data onto a spatial grid, using color intensity as the data channel. The color scale interpolates through indigo → purple → green, creating perceptually uniform transitions. This technique — common in genomics, financial analysis, and web analytics — lets viewers scan a two-dimensional structure and identify clusters of high or low activity instantly.

Sequential color scalesPerceptual uniformityGrid-based visualizationSpatial encoding
📈Time Series Analysis

Time Series & Trend Analysis

Cumulative frequency curves are computed for individual numbers across 2,800+ chronologically ordered draws. A single-pass O(n·k) algorithm builds the running totals efficiently. The resulting multi-line chart reveals convergence behavior — numbers tend toward the mean frequency over time, a classic demonstration of the Law of Large Numbers. Users can inject arbitrary numbers to compare trajectories.

Cumulative time seriesLaw of Large NumbersAlgorithmic complexityMulti-variate line charts
🔔Inferential Statistics

Statistical Distribution Analysis

The distribution tab answers a meta-question: how are the frequencies themselves distributed? A histogram of frequencies exposes whether the draw process produces a normal distribution (expected under true randomness) or a skewed one. Four statistics are computed: mean, median, standard deviation, and Fisher-Pearson skewness coefficient. Deviation from symmetry (|skewness| > 0.5) is flagged as noteworthy.

HistogramsNormal distributionStandard deviationSkewness coefficientSummary statistics
🔗Combinatorial Analysis

Co-occurrence & Pair Analysis

Each 5-number draw contains C(5,2) = 10 unique pairs. Across 2,800+ draws, this yields ~28,000 pair observations. A hash map accumulates co-occurrence counts in O(n) time. The result is a frequency table of number pairs — a form of association analysis. Users can query any number to retrieve its top co-occurring partners, a technique directly analogous to market basket analysis in retail data science.

CombinatoricsAssociation analysisHash map aggregationMarket basket analogy
Temporal Analysis

Gap Analysis (Recency Weighting)

Gap analysis tracks the number of draws since each ball last appeared — its "gap" or recency score. Numbers are sorted by gap descending to surface the most overdue. This is a form of recency weighting, a technique used in recommendation systems (RFM analysis), inventory management, and time-decay models. The visual gap bar provides an immediate proportional comparison.

Recency scoringRFM analysisTime-decay weightingSorted ranking
🎯Probabilistic Modeling

Probabilistic Number Generation

The number picker implements three sampling strategies: (1) weighted sampling where each number appears in the pool proportionally to its historical frequency — a basic Monte Carlo approach; (2) overdue-biased sampling from the top 40% most-gapped numbers; (3) uniform random sampling as a baseline. These represent the spectrum from data-informed to purely stochastic selection.

Monte Carlo samplingWeighted random selectionUniform distributionSampling strategies
📋Data Provenance

Temporal Context — Draw History

Raw draw data is presented in reverse-chronological order with frequency-aware ball coloring, grounding all analysis in the actual source records. Each ball is colored by its overall temperature — a cross-reference between historical context and aggregate statistics. This data provenance view is essential in any analytical workflow: always trace aggregate conclusions back to the raw data.

Data provenanceTemporal orderingCross-referencingContextual encoding
Implementation

Under the hood

Built entirely client-side — no backend required. All computation runs in the browser using standard React patterns.

React 19
UI framework — component architecture, hooks, memoization
Chart.js 4
Canvas-based charting — bar, line, histogram renders
NY.gov Open Data API
Live data source — 5,000 draws per game via SODA REST API
useMemo / useCallback
Derived state memoization — prevents redundant O(n) recomputation
Stripe
Subscription billing — checkout and entitlement gating for pro features
React Router v6
Client-side routing — SPA navigation without page reloads
Engineering Notes

Key design decisions

Client-side computation

All statistical computation happens in the browser via React useMemo hooks. For a dataset of ~5,000 rows and up to 70 numbers, this is well within browser capabilities and eliminates the need for a backend API — reducing infrastructure cost and latency to zero.

Memoization strategy

Derived data (freq, lastSeen, pairs, distribution) is computed once per data+filter change using useMemo with precise dependency arrays. This prevents O(n) recomputation on every render. The pairs computation — O(10n) — runs in a single pass rather than nested lookups.

Freemium gating

Free views (Frequency, Hot/Cold, Heatmap, History) are chosen to showcase the depth of data without requiring payment. Pro views (Trends, Distribution, Pairs, Gap Analysis, Picker) represent deeper analytical capability and personalized features, aligning paywall placement with perceived value.

Date range filtering

Filtering by 1, 3, or 5 years is implemented as a useMemo over the raw draws array — all downstream computations automatically recompute from the filtered slice. This architecture means adding new filter dimensions requires zero changes to the visualization components.

See the analysis in action

All eight analytical views are live in the app — free to explore.

Open LottoPickle