NDC to ATC in Python — Actually Clean Data Guide: https://actuallycleandata.com/guides/ndc-to-atc-python.html Checked October 14, 2026. Python 3.10+, standard library only; no API calls. Save input.csv, crosswalk.csv, lookup-status.csv and join.py in one folder. Run from that folder (one line also works; use python on Windows if needed): python3 join.py --input input.csv --crosswalk crosswalk.csv \ --lookup-status lookup-status.csv --output result.csv Optional: save check.py in the same folder and run python3 check.py. Compare result.csv to expected.csv and result-summary.json to example-summary.json. Expected: 8 input rows, 8 output rows, 45 units, 3 matched input rows. The line IDs and quantities are synthetic. The two crosswalk rows and four lookup rows are exact selections from the published customer download. not_in_lookup_table describes only the supplied lookup file, not every drug. For your own input, preserve NDCs as text. --ndc-column names your code column. Use the full crosswalk CSV and ndc_lookup_status.csv from the SAME purchased ZIP. This helper performs an exact join on hyphenated package NDCs. It does not normalize 11-digit billing codes, infer missing segments, or resolve history. Every original input row is retained; multiple classifications would expand rows. Check acd_match_count and the summary before summing quantities after a join. The helper checks keys and classified-code agreement, not source authenticity; verify the full CSV against metadata.json and keep files from one release together. The reference has ATC levels 1–4, not level 5 or DDD. Not for clinical decisions. See provenance.json for the pinned source versions, publication and file checksums. ATC classification: WHO Collaborating Centre for Drug Statistics Methodology. Mappings supplied through NLM ATCPROD. Independent preparation; no endorsement.