mcpField
G
geo-database

geo-database

github.com/jaechang-hits数据与数据库38437 次安装1 周前更新
代码仓库

关于 geo-database

geo-database 是用于查找、下载和解析 NCBI GEO 公共功能基因组学记录的技能。研究人员可通过 GEOparse 和 NCBI E-utilities 获取 GEO 系列、表达数据及样本元数据。

主要功能

  1. 01通过 E-utilities 搜索 GEO 记录
  2. 02下载并解析 GSE、GPL 和 GSM 记录
  3. 03提取表达矩阵与样本元数据
  4. 04将平台探针关联到基因注释
  5. 05通过 FTP 下载大型系列矩阵文件

适用场景

  1. 01按物种、组织或条件查找研究
  2. 02为差异分析准备 GEO 表达数据
  3. 03收集用于荟萃分析的样本注释

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jaechang-hits/sciagent-skills --skill geo-database

安装后在 Claude Code 中输入/geo-database确认已加载。

详细介绍

GEO 基因表达综合数据库

概述

GEO(Gene Expression Omnibus)是 NCBI 的公共高通量功能基因组学数据存储库,包含来自微阵列、RNA-seq、ChIP-seq、甲基化和蛋白质组学实验的 200,000 多个数据集(系列)。GEOparse 提供了用于下载和解析 GEO 记录(GSE 系列、GPL 平台、GSM 样本)的 Python 接口,而 NCBI E-utilities 则支持以编程方式搜索 GEO 元数据。

适用场景

  • 按生物体、组织、疾病或实验条件搜索公开的基因表达数据集
  • 下载和解析特定的 GEO 系列(GSE)及其表达矩阵和样本元数据
  • 提取样本注释表(例如治疗组、临床协变量)用于荟萃分析
  • 将微阵列表达数据(带 GPL 平台注释的探针)加载到整洁的 DataFrame 中
  • 检索与感兴趣的基因或通路相关的所有 GEO 实验
  • 构建自动化工作流,下载并处理 GEO 数据集以供下游分析
  • 对于大规模单细胞 RNA-seq 数据,请使用 cellxgene-census;对于已比对的读段,请改为从 ENA/SRA 下载 FASTQ

前置条件

  • Python 包:GEOparse、requests、pandas
  • 数据要求:GSE/GPL/GSM 登录号或搜索词
  • 环境:需要互联网连接;下载时需要对本地目录具有写入权限
  • 速率限制:E-utilities:未认证时为 3 req/s,使用 API key 时为 10 req/s;GEO FTP 不限速
pip install GEOparse requests pandas

快速入门

import GEOparse

# Download a GEO series (caches in current directory)
gse = GEOparse.get_GEO("GSE2553", destdir="./geo_data/")
print(f"Title: {gse.metadata['title'][0]}")
print(f"Samples: {len(gse.gsms)}")
print(f"Platform: {list(gse.gpls.keys())}")

# Sample metadata
meta = gse.phenotype_data
print(meta.head())

核心 API

查询 1:通过 E-utilities 搜索 GEO 数据集

按关键词、生物体或数据集类型查找 GEO 系列(GSE)。

import requests

EMAIL = "[email protected]"
BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils"

def geo_search(query, retmax=20):
    r = requests.get(f"{BASE}/esearch.fcgi",
                     params={"db": "gds", "term": query,
                             "retmax": retmax, "retmode": "json", "email": EMAIL})
    r.raise_for_status()
    return r.json()["esearchresult"]

# Search for human breast cancer RNA-seq datasets
result = geo_search(
    "breast cancer[title] AND Homo sapiens[organism] AND gse[entry type]",
    retmax=10
)
print(f"Found {result['count']} matching GEO datasets")
print(f"First accessions (UIDs): {result['idlist']}")
# Search for specific platform (e.g., Illumina HumanHT-12)
result = geo_search(
    "Illumina HumanHT-12[platform] AND Homo sapiens[organism] AND gse[entry type]",
    retmax=5
)
print(f"Illumina HumanHT-12 human datasets: {result['count']}")
查询 2:获取数据集摘要元数据

检索搜索结果的标题、登录号和生物体信息。

import requests

EMAIL = "[email protected]"
BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils"

def geo_summary(uids):
    r = requests.post(f"{BASE}/esummary.fcgi",
                      data={"db": "gds", "id": ",".join(uids),
                            "retmode": "json", "email": EMAIL})
    r.raise_for_status()
    return r.json()["result"]

# Get metadata for search results
result = geo_search_func = lambda q: requests.get(
    f"{BASE}/esearch.fcgi",
    params={"db": "gds", "term": q, "retmax": 3, "retmode": "json", "email": EMAIL}
).json()["esearchresult"]["idlist"]

uids = requests.get(
    f"{BASE}/esearch.fcgi",
    params={"db": "gds", "term": "lung cancer[title] AND gse[entry type]",
            "retmax": 3, "retmode": "json", "email": EMAIL}
).json()["esearchresult"]["idlist"]

summaries = geo_summary(uids)
for uid in summaries.get("uids", []):
    s = summaries[uid]
    print(f"\nAccession: {s.get('accession')} | {s.get('title')}")
    print(f"  Organism: {s.get('taxon')}")
    print(f"  Samples: {s.get('n_samples')}")
    print(f"  Type: {s.get('gdstype')}")
查询 3:下载并解析 GEO 系列

使用 GEOparse 下载完整的 GSE 记录,包括表达矩阵和样本元数据。

import GEOparse

# Download GSE (auto-caches; skip download if already present)
gse = GEOparse.get_GEO("GSE2553", destdir="./geo_data/", silent=True)

# Series metadata
print(f"Title   : {gse.metadata['title'][0]}")
print(f"Summary : {gse.metadata['summary'][0][:200]}...")
print(f"Samples : {len(gse.gsms)} GSMs")
print(f"Platforms: {list(gse.gpls.keys())}")
# Sample metadata table (phenotype data)
meta = gse.phenotype_data
print(f"Metadata columns: {list(meta.columns)}")
print(meta.head())
查询 4:提取表达矩阵

解析探针级表达数据,并可选择与平台基因注释合并。

import GEOparse, pandas as pd

gse = GEOparse.get_GEO("GSE2553", destdir="./geo_data/", silent=True)

# Pivot to gene expression matrix (probes × samples)
gpl_id = list(gse.gpls.keys())[0]
pivot = gse.pivot_samples("VALUE", gpl_id)
print(f"Expression matrix shape: {pivot.shape}")  # (probes, samples)
print(pivot.iloc[:5, :3])
# Annotate probes with gene symbols from the GPL platform
gpl = gse.gpls[gpl_id]
annot = gpl.table[["ID", "Gene Symbol", "Gene Title"]].copy()
annot.columns = ["ID", "gene_symbol", "gene_title"]
annot = annot.dropna(subset=["gene_symbol"])
annot = annot[annot["gene_symbol"] != ""]

expr_annotated = pivot.join(annot.set_index("ID"), how="inner")
print(f"Annotated expression matrix: {expr_annotated.shape}")
print(expr_annotated[["gene_symbol", "gene_title"]].head())
查询 5:下载单个样本(GSM)

获取单个样本的表达值和元数据。

import GEOparse

gsm = GEOparse.get_GEO("GSM45553", destdir="./geo_data/", silent=True)

print(f"Title   : {gsm.metadata['title'][0]}")
print(f"Source  : {gsm.metadata.get('source_name_ch1', ['n/a'])[0]}")
print(f"Organism: {gsm.metadata.get('organism_ch1', ['n/a'])[0]}")
print(f"Data rows: {len(gsm.table)}")
print(gsm.table.head())
查询 6:通过 FTP 直接下载大型系列

对于大型数据集,可直接从 GEO FTP 下载系列矩阵文件。

import urllib.request, gzip, io, pandas as pd

# GEO series matrix file URL pattern
accession = "GSE2553"
series_num = accession[3:]  # strip "GSE"
folder = f"GSE{series_num[:-3]}nnn" if len(series_num) > 3 else f"GSE{series_num[:-2]}nn"

url = f"https://ftp.ncbi.nlm.nih.gov/geo/series/{folder}/{accession}/matrix/{accession}_series_matrix.txt.gz"

with urllib.request.urlopen(url) as resp:
    with gzip.open(resp, "rt", encoding="utf-8") as f:
        lines = f.readlines()

# Find metadata lines (start with !) and data table
meta_lines = [l for l in lines if l.startswith("!")]
data_start = next(i for i, l in enumerate(lines) if l.startswith('"ID_REF"'))
df = pd.read_csv(
    io.StringIO("".join(lines[data_start:])),
    sep="\t", index_col=0
)
print(f"Matrix shape: {df.shape}")
print(df.iloc[:3, :3])

关键概念

GEO 记录类型
  • GSE(系列):包含所有样本和元数据的完整实验
  • GPL(平台):微阵列或测序平台定义(探针/基因映射)
  • GSM(样本):单次杂交或测序运行
  • GDS(数据集):从系列中整理和标准化的子集(数量少于 GSE 记录)
超级系列和子系列

多重检测或多批次提交(例如 RNA-seq + ATAC-seq)会组织为一个引用一个或多个 子系列 GSE 的 超级系列 GSE。每个子系列都有自己的样本、平台和矩阵;超级系列本身不包含样本。两者都通过 gse.metadata 标记:

  • 超级系列:gse.metadata["relation"] 包含类似 "SuperSeries of: GSExxxx" 的条目
  • 子系列:gse.metadata["relation"] 包含 "SubSeries of: GSEyyyy"

提取表达矩阵前,务必先解析子系列——单独下载超级系列只能获得元数据,不包含数据。

import GEOparse

gse = GEOparse.get_GEO("GSE47966", destdir="./geo_data/", silent=True)  # a SuperSeries
relations = gse.metadata.get("relation", [])
subseries = [r.split(": ")[1] for r in relations if r.startswith("SuperSeries of")]
print(f"SubSeries to download: {subseries}")

for acc in subseries:
    sub = GEOparse.get_GEO(acc, destdir="./geo_data/", silent=True)
    print(f"  {acc}: {len(sub.gsms)} samples, platforms={list(sub.gpls.keys())}")
SOFT 与 MiniML 格式

GEOparse 下载 SOFT 格式文件(纯文本)。如需基于 XML 的访问,请通过 E-utilities 使用 MiniML 格式。系列矩阵文件(制表符分隔)是表达数据最紧凑的格式。

常见工作流

工作流 1:下载并准备差异表达分析所需的表达数据

目标:下载 GEO 数据集,提取表达矩阵和分组标签,并保存以供下游差异表达分析使用。

import GEOparse, pandas as pd

# Download series
gse = GEOparse.get_GEO("GSE2553", destdir="./geo_data/", silent=True)

# 1. Extract expression matrix
gpl_id = list(gse.gpls.keys())[0]
expr = gse.pivot_samples("VALUE", gpl_id)

# 2. Extract sample groups from characteristics
meta = gse.phenotype_data
print("Available metadata columns:", list(meta.columns))

# 3. Annotate probes with gene symbols
gpl = gse.gpls[gpl_id]
gene_col = "Gene Symbol" if "Gene Symbol" in gpl.table.columns else gpl.table.columns[1]
annot = gpl.table[["ID", gene_col]].dropna()
annot.columns = ["probe_id", "gene_symbol"]
annot = annot[annot["gene_symbol"].str.strip() != ""]

expr_genes = expr.join(annot.set_index("probe_id")[["gene_symbol"]], how="inner")
expr_genes = expr_genes.groupby("gene_symbol").mean()  # average duplicate probes

print(f"Genes × Samples: {expr_genes.shape}")
expr_genes.to_csv("expression_matrix.csv")
meta.to_csv("sample_metadata.csv")
print("Saved: expression_matrix.csv, sample_metadata.csv")
工作流 2:搜索并构建数据集清单

目标:在 GEO 中搜索符合主题的数据集,并构建经过整理的数据集清单 CSV。

import requests, time, pandas as pd

EMAIL = "[email protected]"
BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils"

topic = "Alzheimer disease"
r = requests.get(f"{BASE}/esearch.fcgi",
                 params={"db": "gds", "email": EMAIL, "retmode": "json", "retmax": 50,
                         "term": f"{topic}[title] AND Homo sapiens[organism] AND gse[entry type]"})
uids = r.json()["esearchresult"]["idlist"]
print(f"Found {len(uids)} GSE datasets for '{topic}'")

rows = []
for i in range(0, len(uids), 20):
    batch = uids[i:i+20]
    r2 = requests.post(f"{BASE}/esummary.fcgi",
                       data={"db": "gds", "id": ",".join(batch),
                             "retmode": "json", "email": EMAIL})
    result = r2.json()["result"]
    for uid in result.get("uids", []):
        s = result[uid]
        rows.append({
            "accession": s.get("accession"),
            "title": s.get("title"),
            "n_samples": s.get("n_samples"),
            "organism": s.get("taxon"),
            "gds_type": s.get("gdstype"),
            "pub_date": s.get("pdat"),
        })
    time.sleep(0.4)

df = pd.DataFrame(rows).sort_values("n_samples", ascending=False)
df.to_csv(f"{topic.replace(' ', '_')}_geo_datasets.csv", index=False)
print(df[["accession", "title", "n_samples"]].head(10).to_string(index=False))

关键参数

参数模块默认值范围 / 选项作用
destdirGEOparse.get_GEO"./"任意目录路径下载文件的保存位置
silentGEOparse.get_GEOFalseTrue/False隐藏下载进度输出
retmaxESearch201–10000返回的数据集记录数上限
entry type 查询ESearch—"gse"、"gds"、"gpl"、"gsm"按 GEO 记录类型筛选
VALUE 列pivot_samples—GSM 表中的列名要透视的表达值列
emailE-utilities必填有效的电子邮件地址用于 NCBI 速率限制归属

最佳实践

  1. 在 GEOparse 中使用 silent=True:隐藏冗长的下载进度;添加自己的 print 语句以确认下载完成。

  2. 缓存下载内容:如果 .soft.gz 文件已存在于 destdir 中,GEOparse 会跳过重新下载。跨会话设置共用的 destdir,避免重复下载。

  3. 大型数据集优先使用 Series Matrix:对于样本数超过 100 个的系列,直接从 FTP 下载 _series_matrix.txt.gz,而不要解析单个 GSM soft 文件——速度会快几个数量级。

  4. 谨慎处理探针到基因的映射:许多探针会映射到多个基因或没有对应基因。分析前,先决定如何处理映射到多个基因的探针(删除、拆分或保留)。对于 Affymetrix 芯片,使用 gene_symbol.str.split(" /// ")。

  5. 检查平台列名:GPL 注释表的列名因平台而异(例如,"Gene Symbol"、"GENE_SYMBOL" 或 "gene_id")。假定字段名称前,务必检查 gpl.table.columns。

  6. 分析前始终解析 SubSeries:加载任何 GSE 后,检查 gse.metadata.get("relation", []) 中是否有 "SuperSeries of: ..." 条目。如果存在,则遍历所有引用的 SubSeries accession 并逐一下载——SuperSeries 记录本身不包含样本或表达矩阵。跳过此步骤会导致实际数据被悄然遗漏。

常用示例

示例:快速查看 GSE 元数据

适用场景:获取任意 GSE accession 的系列标题、样本数量和平台。

import GEOparse

gse = GEOparse.get_GEO("GSE2553", destdir="./geo_data/", silent=True)
print(f"Title : {gse.metadata['title'][0]}")
print(f"Samples: {len(gse.gsms)}")
print(f"Platform: {list(gse.gpls.keys())}")
print(f"Summary: {gse.metadata['summary'][0][:300]}")
示例:提取样本特征

适用场景:将 GEO 样本特征解析为整洁的 DataFrame,以便分组。

import GEOparse, pandas as pd, re

gse = GEOparse.get_GEO("GSE2553", destdir="./geo_data/", silent=True)
meta = gse.phenotype_data

# Parse "characteristics_ch1" columns
ch_cols = [c for c in meta.columns if "characteristics" in c.lower()]
print(f"Characteristic columns: {ch_cols}")
print(meta[ch_cols].head())
示例:列出系列中的所有 GSM

适用场景:枚举样本 accession,以便下载或收集元数据。

import GEOparse

gse = GEOparse.get_GEO("GSE2553", destdir="./geo_data/", silent=True)
gsm_ids = list(gse.gsms.keys())
print(f"Total samples: {len(gsm_ids)}")
print("First 5:", gsm_ids[:5])

故障排除

问题原因解决方案
下载期间出现 FileNotFoundErrordestdir 不正确先创建目录:os.makedirs("geo_data/", exist_ok=True)
pivot_samples 返回空 DataFrameGPL 注释表缺少 ID检查 gpl.table.columns;使用正确的探针 ID 列名
"Gene Symbol" 出现 KeyError平台使用了不同的列名检查 gpl.table.columns 并使用正确的注释列
大型系列下载卡住SOFT 文件较大(GB 级)大型系列改用 FTP Series Matrix 下载,而不要使用 GEOparse
ESearch 返回 0 个结果entry type 或字段标签错误将 gse[entry type] 改为 gds[entry type];检查查询语法
数值样本列包含 null表达值缺失或不存在使用 df.fillna(0) 填充,或删除缺失值较多的列
GSE 没有样本 / gse.gsms 为空accession 是 SuperSeries解析 gse.metadata["relation"] 中的 SuperSeries of: 条目,并逐一下载每个 SubSeries

相关技能

  • cellxgene-census — 大规模单细胞 RNA-seq 数据(超过 6,100 万个细胞),可作为 GEO 的 scRNA-seq 替代来源
  • gene-database — NCBI Gene 记录,包含 GEO 研究中基因的精选注释
  • pubmed-database — 通过 NCBI ELink 检索与 GEO 数据集关联的出版物
  • pydeseq2-differential-expression — 加载 GEO 计数数据后的下游差异表达分析

参考资料

评论

支持 Markdown