Question
How many PubMed records match a fixed condition phrase in the title or abstract in each sampled calendar year between 2010 and 2025, and how do the 2025 counts compare with 2010? This is a count series, not an assessment of research need, quality or funding.
Method
Endpoint: NCBI E-utilities esearch at
https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi,
with db=pubmed, retmode=json,
retmax=0. Only the count field of each
response was used. Requests used Python 3 urllib with a
normal User-Agent, a 0.4 s sleep between requests and a hard cap of 40.
Fetched 2026-10-30.
Exact query form, run once per condition-year pair:
"<CONDITION>"[Title/Abstract] AND <YEAR>[dp]
PubMed expanded [dp] to a full calendar-year
publication-date range, for example
"Alzheimer disease"[Title/Abstract] AND 2010/01/01:2010/12/31[Date - Publication].
All 24 responses returned HTTP 200 with the expected range.
Sampling reduction. The full requested grid was 8 conditions x 16 years (2010-2025) = 128 requests, which exceeds the 40-request cap. Sampling every third year would give 8 x 6 = 48 requests, still over the cap. The grid was therefore cut to 4 conditions x 6 years = 24 requests, using Alzheimer disease, tuberculosis, pancreatic cancer and sickle cell disease, with years 2010, 2013, 2016, 2019, 2022 and 2025. The four conditions dropped (malaria, cystic fibrosis, type 2 diabetes, major depressive disorder) and the ten unobserved years are not represented anywhere in this note.
The 2025 counts are not truncated mid-year: the fetch date was 2026-10-30, so calendar year 2025 had ended.
Requests: 24 made, 24 saved, 0 failures. raw.json
records every attempted query verbatim; its failures array
is empty.
Results
| Condition | 2010 | 2013 | 2016 | 2019 | 2022 | 2025 | 2025/2010 |
|---|---|---|---|---|---|---|---|
| Alzheimer disease | 6,010 | 7,492 | 8,564 | 10,221 | 13,306 | 17,711 | 2.95 |
| tuberculosis | 5,066 | 6,622 | 7,493 | 7,552 | 8,364 | 9,501 | 1.88 |
| pancreatic cancer | 1,583 | 2,291 | 2,977 | 3,710 | 4,805 | 5,199 | 3.28 |
| sickle cell disease | 573 | 672 | 882 | 1,085 | 1,336 | 1,567 | 2.73 |
Counts are records; the ratio column is computed from the 2010 and
2025 cells of data.csv.
- Pancreatic cancer shows the largest 2025/2010 ratio, 3.28 (5,199 against 1,583), and it starts from the second-smallest 2010 base.
- Alzheimer disease holds the largest count in both sampled endpoints, rising from 6,010 to 17,711, a ratio of 2.95 and an increase of 11,701 records.
- Tuberculosis has the smallest ratio, 1.88, rising from 5,066 to 9,501, although it is the second-largest series in both years.
- Sickle cell disease is the smallest series throughout, 573 to 1,567, a ratio of 2.73. The difference between the largest and smallest sampled condition widens from 5,437 in 2010 (6,010 minus 573) to 16,144 in 2025 (17,711 minus 1,567).
What this does and does not show
- Counts are not effort. A count says nothing about study design, sample size, funding or reproducibility. No funding, trial or patient-level data was queried.
- Database growth confounds every series. If the total number of records indexed in PubMed rose over the period, every condition's count would rise for that reason alone. The series are raw counts, not shares of the database, so the two effects are not separated here.
- Coverage is uneven and changes. PubMed does not index every journal, and coverage varies by field, region and date. A steeper series can reflect indexing decisions rather than publication volume.
- Terminology is held fixed. Each query uses one quoted phrase, so spelling variants, synonyms and MeSH-versus-free-text indexing each shift the counts. Preferred terminology itself changes over time.
- Sampling is coarse. Six years and four conditions support a description, not a trend test. No confidence intervals, slopes or significance tests are reported; interpolating between sampled years would be an assumption.
- Single-day snapshot. Counts for a given year can still move as records are indexed late, so another fetch date would give slightly different numbers, most visibly for 2025.
Reproduce
cd /Volumes/Storage/DeepSeek/workspace/pgx-gap-map/research-notes/pubmed-trendspython3 - <<'PY'
import json, time, urllib.parse, urllib.request
BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi"
UA = "pubmed-trends-note/1.0 (research note; contact: tobymikle)"
COND = ["Alzheimer disease", "tuberculosis", "pancreatic cancer", "sickle cell disease"]
YEARS = [2010, 2013, 2016, 2019, 2022, 2025]
raw, made = {"responses": {}, "attempts": [], "failures": []}, 0
for c in COND:
for y in YEARS:
term = f'"{c}"[Title/Abstract] AND {y}[dp]'
if made: time.sleep(0.4)
made += 1
url = BASE + "?" + urllib.parse.urlencode(
{"db": "pubmed", "retmode": "json", "retmax": "0", "term": term})
req = urllib.request.Request(url, headers={"User-Agent": UA})
try:
with urllib.request.urlopen(req, timeout=45) as r:
raw["responses"][f"{c}|{y}"] = {"condition": c, "year": y, "term": term,
"request_url": url, "http_status": r.status,
"body": r.read().decode("utf-8", "replace")}
except Exception as e:
raw["failures"].append({"key": f"{c}|{y}", "error": repr(e)})
raw["_meta"] = {"requests_made": made, "cap": 40, "sleep": 0.4}
json.dump(raw, open("raw.json", "w"), indent=2, ensure_ascii=False)
print(made, len(raw["responses"]), len(raw["failures"]))
PYpython3 - <<'PY'
import csv, json
d = json.load(open("raw.json"))
rows = [(r["condition"], r["year"],
int(json.loads(r["body"])["esearchresult"]["count"]))
for r in d["responses"].values()]
rows.sort()
with open("data.csv", "w", newline="") as f:
w = csv.writer(f)
w.writerow(["condition", "year", "publications"])
w.writerows(rows)
print(len(rows))
PYPublication status
Draft. Auto-generated from public API responses; requires editorial review before publication.