WORKING RESEARCH NOTE · NOT PEER REVIEWED

Publication growth by condition, 2010–2025

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.

What this does and does not show

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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-trends
python3 - <<'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"]))
PY
python3 - <<'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))
PY

Publication status

Draft. Auto-generated from public API responses; requires editorial review before publication.