Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Parkinson's Commercial Analytics (Medicare Part D)

Prescriber segmentation and sales-force allocation for a branded Parkinson's levodopa franchise, built on the public CMS Medicare Part D prescriber data.

The question: given a branded product in a market dominated by cheap generics, where should a limited field force spend its calls to grow share? The analysis sizes the market by molecule, segments prescribers by volume and loyalty, isolates the high-volume-low-share targets, and allocates a fixed call budget to where the untapped volume actually sits.

Data

Primary source: CMS "Medicare Part D Prescribers - by Provider and Drug" (data.cms.gov, public). src/fetch_cms.py resolves the current release UUID from the data.cms.gov catalog (data.json) and pulls the Parkinson's molecules via the data-api filter syntax. The current outputs are built from the real calendar year 2024 file (2026 release): 279,965 prescriber-drug rows, 144,884 prescribers, 10.6M claims, $738M drug cost.

One thing the real data forced: most of these molecules are multi-indication. Ropinirole and pramipexole are mostly restless-legs scripts, benztropine and trihexyphenidyl mostly manage antipsychotic side effects, rivastigmine is mostly dementia. The opportunity segment therefore requires at least some levodopa-class prescribing; without that screen the "target list" fills up with psychiatrists who have never written a levodopa script.

If no real pull is present, the analysis falls back to src/simulate_rx.py, a generator calibrated to published Part D magnitudes with the same schema, and every chart and slide carries a clear "synthetic, illustrative" label. Synthetic runs write to outputs/synthetic/ so they cannot overwrite the committed real results, and deck/make_deck.js refuses to build from a synthetic summary.

Limitation worth stating up front: Part D is Medicare only (~2/3 of beneficiaries, skews 65+). It is the older-patient slice, not the entire PD market.

Run

Run everything from the repository root.

pip install pandas numpy matplotlib pytest

python -m pytest                   # 22 tests, no data or network needed

# option A: synthetic (works anywhere, immediately) -> outputs/synthetic/
python src/simulate_rx.py
python src/analyze.py

# option B: real CMS data (needs open network) -> outputs/
python src/fetch_cms.py            # writes data/rx_raw.csv + rx_raw.meta.json
python src/analyze.py              # auto-detects the real file

node deck/make_deck.js             # 8-slide deck, needs pptxgenjs, real data only

data/rx_raw.csv is 41 MB and gitignored, so a fresh clone runs the synthetic path. The numbers quoted above and in outputs/ come from the real pull.

Outputs

outputs/market_share.csv          molecule volume/cost/share table
outputs/prescriber_segments.csv   per-prescriber volume, loyalty, tier, opportunity flag
outputs/rep_allocation.csv        call budget by state
outputs/levodopa_brands.csv       brand split inside the levodopa line (real pull only)
outputs/headroom_sensitivity.csv  how much the target list depends on the scoring rule
outputs/charts/*.png              5 charts
outputs/summary.json              headline numbers, plus pull provenance
deck/parkinsons_commercial_analytics.pptx

Does the scoring rule actually matter?

Targets are ranked by headroom, volume x (1 - loyalty), rather than by raw volume, so the field force is pointed at convertible demand instead of at prescribers who are already loyal. That choice is worth checking rather than asserting, so headroom_sensitivity() sweeps the exponent in volume x (1 - loyalty)**w and compares each variant's top 50 against the shipped rule at w=1:

w overlap with w=1 shared targets
0.0 (pure volume) 0.34 17 of 50
0.5 0.66 33
1.0 (shipped) 1.00 50
1.5 0.92 46
2.0 0.80 40

Ranking by raw volume shares only 17 of 50 targets with the headroom rule, so the weighting decides two thirds of the call list and is not cosmetic. The list is also stable to the exact exponent: anything from w=1 to w=2 keeps at least 80% of the same prescribers, so the result does not hinge on w being exactly 1.

Context

Two years of Parkinson's biomarker research (EEG, DAT-SPECT, gait) on the clinical side; this is the commercial side of the same disease.

About

Sizes a $738M Parkinson's drug market from real CMS Medicare Part D data and ranks 144K prescribers by untapped headroom.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages