GEOquery 下载 GEO 数据

前言

NCBI Gene Expression Omnibus(基因表达综合数据库,GEO)公开了很多高通量基因组学数据集。尽管名字很好听,但这个数据库并不是专门针对基因表达数据的。

NCBI GEO

NCBI GEO 是以样本的形式组织起来的,这些样本被归入 series。对于较大的实验,有 SubSeriesSuperSeries 两种

一个 SuperSeries 就是一篇论文的所有实验,一个 SuperSeries 可以分解为不同技术的 SubSeries

举个例子,看看 SuperSeries GSE19486。在这篇论文中,他们使用了 2 个不同的平台(这是个奇怪的名字,平台是一种技术和物种的组合)

他们对两种不同的因子(NFkB-IIPol II)进行 RNA-seqChIP-seq。这导致 4 个子系列(2 个用于 RNA-seq2 个用于 ChIP-seq

一个更简单的例子,如 GSE994,使用 Affymetrix 微阵列比较来自当前和以前吸烟者的样本

提交给 NCBI GEO 的数据既可以是 "raw",也可以是 "proceseed"。我们暂且把重点放在基因表达数据上。"proceseed" 的数据是经过标准化和量化的,通常是在基因水平上,以基因对应样本的矩阵形式提供。

"raw" 数据可以是任何东西,从测序读数到微阵列图像文件。甚至可以有不同状态的 "raw" 数据,例如对于一个 RNA-seq 数据集,可能包含:

  • FASTQ 文件(原始 read
  • BAM 文件(比对 read
  • 基因样本表达矩阵(非标准化)
  • 基因样本表达矩阵(标准化)

所以,什么是 "raw",什么是 "proceseed",可能非常依赖于背景信息。

在某些情况下,该领域有一个共识。对于 Affymetrix 基因表达芯片来说,"raw" 文件是所谓的 CEL 文件(Affymetrix 发明的一种文件格式),"proceseed" 数据是经过归一化和量化的数据,在探针集层面进行了汇总。

最后,GEOSeries 标识符(如 GSE19486)和样本标识符(GSM486297)。用户几乎总是对一个给定 Series 中的所有样品感兴趣,所以系列标识符,也叫 accession number

Platforms(平台)

平台记录了阵列上的元素列表(如 cDNA、寡核苷酸探针组、ORF、抗体)或该实验中可能被检测和量化的元素列表(如 SAGE 标签、肽)。

每个平台记录都有一个唯一的 GEO accession numberGPLxxx)。一个平台可以包含多个提交者提交的样品。

Samples(样本)

一份样品记录描述了处理单个样品的条件、所涉及的操作以及从中获得的每种元素的丰度测量。

每个样品记录都有一个唯一的 GEO accession number(GSMxxx)。一个样品只能属于一个平台,但是可以被加入多个系列

Series(系列)

系列记录定义了一组相关的样品,这些样品是如何相关的,以及它们是否排序或如何排序的。

系列记录提供了整体实验的关注点和描述信息。还可以包含所提取的数据的描述、简要结论或分析。

每个系列记录都有一个唯一的 GEO accession numberGSExxx)。系列记录有几种不同的格式,均由 GEOquery 独立处理。

小而新的 GSEMatrix 文件的解析速度相当快;GEOquery 使用一个参数来选择是否使用 GSEMatrix 文件

Datasets(数据集)

GEO 数据集(GDSxxx)是 GEO 样本数据的精选集。一个 GDS 记录代表了一个在生物学和统计学上可比较的 GEO 样本的集合,并构成了 GEO 数据可视化和分析工具的基础。

GDS 内的样本来自同一个平台,它们共享一组共同的探针集。

假设 GDS 内每个样品的测量值是以同样方式计算的,即考虑背景处理和归一化等因素。

GEOquery

今天我们的重点并不是要介绍上面的内容,而是要和大家聊聊该怎么用 R 来下载 GEO 的数据。

我们使用的是 GEOquery 包,下来就来详细介绍一下

安装

Bioconductor 安装

if (!requireNamespace("BiocManager", quietly=TRUE))
    install.packages("BiocManager")
BiocManager::install("GEOquery")

GitHub 安装

library(devtools)
install_github('GEOquery','seandavi')

使用

1 GEOquery 入门

GEO 中获取数据真的很容易。只需要一个命令: getGEO。这一个函数对其输入进行解释,以确定如何从 GEO 中获取数据,然后将数据解析成有用的 R 数据结构。

用法很简单。首先加载 GEOquery

library(GEOquery)

现在,我们可以自由访问任何 GEO accession number。请注意,在下文中,我使用了一个与 GEOquery 包一起打包的文件。

一般来说,你只要传入正确的 GEO accession 就行,正如代码注释中所指出的那样

# 更常用的方式是传入 GEO accession,从 GEO 数据库中下载数据:
# gds <- getGEO("GDS507")
gds <- getGEO(filename=system.file("extdata/GDS507.soft.gz",package="GEOquery"))

现在,gds 包含了 R 数据结构(GDS 类),表示 GEOGDS507 条目。

您会注意到用于存储下载的文件名被输出到屏幕上(但没有保存到任何地方),以便以后调用 getGEO(filename=...) 时使用。

# 更常用的方式是直接传入 GSM 号,从数据库中下载:
# gds <- getGEO("GSM11805")
gsm <- getGEO(filename=system.file("extdata/GSM11805.txt.gz",package="GEOquery"))
1.1 getGEO
  1. 描述

该函数是 GEOquery 包中主要的用户级函数。它引导下载(如果没有指定文件名)并将 GEO SOFT 格式文件解析为 R 数据结构,该结构是专门设计的,便于访问 GEO SOFT 格式的每个重要部分。

  1. 使用
getGEO(GEO = NULL, filename = NULL, destdir = tempdir(),
       GSElimits = NULL, GSEMatrix = TRUE, 
       AnnotGPL = FALSE, getGPL = TRUE,
       parseCharacteristics = TRUE)
  1. 参数
image.png

2 GEOquery 数据结构

GEOquery 的数据结构其实有两种形式。第一种,由 GDSGPLGSM 组成,它们的行为都是相似的,访问器对每一种都有相似的作用。

第四种 GEOquery 数据结构 GSE,是由 GSMGPL 对象组合而成的复合数据类型。我先把前三个一起解释一下。

2.1 GDS、GSM 和 GPL 类

这些类中的每一个类都由一个元数据头(与 SOFT 格式头部信息几乎一致)和一个 GEODataTable 组成。

GEODataTable 有两个简单的部分: ColumnsTableColumns 部分是对 Table 部分的列的描述。此外,每个类还有一个 show 方法。

例如,对于上面的 gsm,查看元数据

> head(Meta(gsm))
$channel_count
[1] "1"

$comment
[1] "Raw data provided as supplementary file"

$contact_address
[1] "715 Albany Street, E613B"

$contact_city
[1] "Boston"

$contact_country
[1] "USA"

$contact_department
[1] "Genetics and Genomics"

查看与 GSM 相关的数据

> Table(gsm)[1:5,]
          ID_REF  VALUE ABS_CALL
1 AFFX-BioB-5_at  953.9        P
2 AFFX-BioB-M_at 2982.8        P
3 AFFX-BioB-3_at 1657.9        P
4 AFFX-BioC-5_at 2652.7        P
5 AFFX-BioC-3_at 2019.5        P

查看列描述

> Columns(gsm)
    Column                                                                Description
1   ID_REF                                                                           
2    VALUE                         MAS 5.0 Statistical Algorithm (mean scaled to 500)
3 ABS_CALL MAS 5.0 Absent, Marginal, Present call  with Alpha1 = 0.05, Alpha2 = 0.065

GPL 类的行为与 GSM 类完全相同。然而,GDS 类的 Columns 方法保存了更多的信息。

> Columns(gds)[,1:3]
     sample disease.state individual
1  GSM11815           RCC        035
2  GSM11832           RCC        023
3  GSM12069           RCC        001
4  GSM12083           RCC        005
5  GSM12101           RCC        011
6  GSM12106           RCC        032
7  GSM12274           RCC          2
8  GSM12299           RCC          3
9  GSM12412           RCC          4
10 GSM11810        normal        035
11 GSM11827        normal        023
12 GSM12078        normal        001
13 GSM12099        normal        005
14 GSM12269        normal          1
15 GSM12287        normal          2
16 GSM12301        normal          3
17 GSM12448        normal          4
2.2 GSE 类

GSEGEO 中最容易混淆的。一个 GSE 条目可以代表在任意数量的平台上运行的任意数量的样本。

GSE 类和其他类一样,有一个元数据部分,但是它没有 GEODataTable

相反,它包含了两个列表,可以使用 GPLListGSMList 方法进行访问,这两个列表分别是 GPLGSM 对象的列表。

举个例子,我们从本地读取 soft 文件

gse <- getGEO(filename=system.file("extdata/GSE781_family.soft.gz",package="GEOquery"))

查看元数据

> head(Meta(gse))
$contact_address
[1] "715 Albany Street, E613B"

$contact_city
[1] "Boston"

$contact_country
[1] "USA"

$contact_department
[1] "Genetics and Genomics"

$contact_email
[1] "[email protected]"

$contact_fax
[1] "617-414-1646"

获取 GSE 中包含的所有 GSM 对象的名称

> names(GSMList(gse))
 [1] "GSM11805" "GSM11810" "GSM11814" "GSM11815" "GSM11823" "GSM11827" "GSM11830" "GSM11832" "GSM12067"
[10] "GSM12069" "GSM12075" "GSM12078" "GSM12079" "GSM12083" "GSM12098" "GSM12099" "GSM12100" "GSM12101"
[19] "GSM12105" "GSM12106" "GSM12268" "GSM12269" "GSM12270" "GSM12274" "GSM12283" "GSM12287" "GSM12298"
[28] "GSM12299" "GSM12300" "GSM12301" "GSM12399" "GSM12412" "GSM12444" "GSM12448"

获得列表中的第一个 GSM 对象

> GSMList(gse)[[1]]
An object of class "GSM"
channel_count 
[1] "1"
comment 
[1] "Raw data provided as supplementary file"
contact_address 
[1] "715 Albany Street, E613B"
contact_city 
[1] "Boston"
contact_country 
[1] "USA"
contact_department 
[1] "Genetics and Genomics"
contact_email 
[1] "[email protected]"
...
****** Column Descriptions ******
    Column                                                                Description
1   ID_REF                                                                           
2    VALUE                         MAS 5.0 Statistical Algorithm (mean scaled to 500)
3 ABS_CALL MAS 5.0 Absent, Marginal, Present call  with Alpha1 = 0.05, Alpha2 = 0.065
****** Data Table ******
          ID_REF  VALUE ABS_CALL
1 AFFX-BioB-5_at  953.9        P
2 AFFX-BioB-M_at 2982.8        P
3 AFFX-BioB-3_at 1657.9        P
4 AFFX-BioC-5_at 2652.7        P
5 AFFX-BioC-3_at 2019.5        P
22278 more rows ...

获取所有 GPL 名称

> names(GPLList(gse))
[1] "GPL96" "GPL97"

3 转换为表达谱

GEO 数据集与 limmaMAList 数据结构和 BiobaseExpressionSet 数据结构非常相似

存在两个函数 GDS2MAGDS2eSet,能够将 GEOquery 数据结构分别转换为 MAListExpressionSet

3.1 获取 GSE Series Matrix

除了解析较大的 soft 文件,我们也可以直接获取处理后的 Series matrix 文件。

getGEO 能够快速解析该类型的文件,解析返回的数据结构是 ExpressionSet 的列表

gset <- getGEO("GSE11675",destdir = './')

显示文件结构信息

> show(gset)
$GSE11675_series_matrix.txt.gz
ExpressionSet (storageMode: lockedEnvironment)
assayData: 12625 features, 6 samples 
  element names: exprs 
protocolData: none
phenoData
  sampleNames: GSM296630 GSM296635 ... GSM296639 (6 total)
  varLabels: title geo_accession ... data_row_count (34 total)
  varMetadata: labelDescription
featureData
  featureNames: 1000_at 1001_at ... AFFX-YEL024w/RIP1_at (12625 total)
  fvarLabels: ID GB_ACC ... Gene Ontology Molecular Function (16 total)
  fvarMetadata: Column Description labelDescription
experimentData: use 'experimentData(object)'
  pubMedIds: 19855080 
Annotation: GPL8300 

使用 Biobase 包的函数,获取样本的表型数据

> show(pData(phenoData(gset[[1]]))[, 1:5])
                  title geo_accession                status submission_date last_update_date
GSM296630     Lin-CD34-     GSM296630 Public on Jan 05 2010     Jun 04 2008      Jan 05 2010
GSM296635 CML Lin-CD34-     GSM296635 Public on Jan 05 2010     Jun 04 2008      Jan 05 2010
GSM296636 CML Lin-CD34+     GSM296636 Public on Jan 05 2010     Jun 04 2008      Jan 05 2010
GSM296637     Lin-CD34+     GSM296637 Public on Jan 05 2010     Jun 04 2008      Jan 05 2010
GSM296638     Lin+CD34+     GSM296638 Public on Jan 05 2010     Jun 04 2008      Jan 05 2010
GSM296639 CML Lin+CD34+     GSM296639 Public on Jan 05 2010     Jun 04 2008      Jan 05 2010

使用 exprs 获取处理后的表达谱数据

> head(exprs(gset[[1]]))
          GSM296630 GSM296635 GSM296636 GSM296637  GSM296638 GSM296639
1000_at   103.88700  138.0500 133.32200 242.86600  175.73400 165.28400
1001_at     3.39447   31.1682  98.97760  69.78960   56.16700 101.31200
1002_f_at  10.56290    3.4511   1.63724   5.92232    3.26876   3.33937
1003_s_at   8.42204   20.7501  18.65330  12.75090    5.53738   6.18855
1004_at     5.55025   14.6198  17.52940  14.25250   16.76820  16.43160
1005_at   802.71900  846.3760 761.27500 911.98200 2650.83000 801.71700
3.2 将 GDS 转换为 ExpressionSet

对于上面的 gds 对象,我们可以简单地进行转换

eset <- GDS2eSet(gds,do.log2=TRUE)

现在,eset 是一个 ExpressionSet 类型,它包含了 GEO 数据集信息,以及样本信息

> eset
ExpressionSet (storageMode: lockedEnvironment)
assayData: 22645 features, 17 samples 
  element names: exprs 
protocolData: none
phenoData
  sampleNames: GSM11815 GSM11832 ... GSM12448 (17 total)
  varLabels: sample disease.state individual description
  varMetadata: labelDescription
featureData
  featureNames: 200000_s_at 200001_at ... AFFX-TrpnX-M_at (22645 total)
  fvarLabels: ID Gene title ... GO:Component ID (21 total)
  fvarMetadata: Column labelDescription
experimentData: use 'experimentData(object)'
  pubMedIds: 14641932 
Annotation:  

获取样本信息

> pData(eset)[,1:3]
           sample disease.state individual
GSM11815 GSM11815           RCC        035
GSM11832 GSM11832           RCC        023
GSM12069 GSM12069           RCC        001
GSM12083 GSM12083           RCC        005
GSM12101 GSM12101           RCC        011
GSM12106 GSM12106           RCC        032
GSM12274 GSM12274           RCC          2
GSM12299 GSM12299           RCC          3
GSM12412 GSM12412           RCC          4
GSM11810 GSM11810        normal        035
GSM11827 GSM11827        normal        023
GSM12078 GSM12078        normal        001
GSM12099 GSM12099        normal        005
GSM12269 GSM12269        normal          1
GSM12287 GSM12287        normal          2
GSM12301 GSM12301        normal          3
GSM12448 GSM12448        normal          4
3.3 将 GDS 转换为 MAList

由于 ExpressionSet 没有包含基因信息,所以没有检索到任何注释信息(也称为平台信息)

不过,要获得这些信息也很容易。首先,我们需要知道这个 GDS 使用的是什么平台。然后,再调用 getGEO 就可以得到我们需要的信息。

先获取 GDS 的平台

> Meta(gds)$platform
[1] "GPL97"

再使用 getGEO 获取该平台的信息

gpl <- getGEO(filename=system.file("extdata/GPL97.annot.gz",package="GEOquery"))

gpl 变量现在包含了来自 GEOGPL97 的信息。

ExpressionSet 不同的是,limma MAList 是存储了基因的注释信息,我们可以在调用 GDS2MA 时将我们新创建的 GPL 结构对象 gpl 传入进去

MA <- GDS2MA(gds,GPL=gpl)

查看 MA 类型信息

> class(MA)
[1] "MAList"
attr(,"package")
[1] "limma"

MAMAList 类型,不仅包含数据,还包含与 GDS507 相关的样本信息和基因信息

3.4 将 GSE 转换为 ExpressionSet

首先,请确保使用 3.1 的方法是无法满足分析需求的。因为该方法快速且简便。

如果确实无法满足分析需求,那么可以使用下面的方法

GSE 对象转换为 ExpressionSet 对象需要一点点 R 基础数据操作,因为 GSE 的底层 GSMGPL 对象中可以存储各种数据。

首先,我们需要确保所有的 GSM 都来自同一个平台。

> gsmplatforms <- lapply(GSMList(gse),function(x) {Meta(x)$platform_id})
> head(gsmplatforms)
$GSM11805
[1] "GPL96"

$GSM11810
[1] "GPL97"

$GSM11814
[1] "GPL96"

$GSM11815
[1] "GPL97"

$GSM11823
[1] "GPL96"

$GSM11827
[1] "GPL97"

这个例子包含两个平台 GPL96GPL97。我们可以对 GSMlist 的结果进行过滤,提取出 GPL96 的样本

> gsmlist <- Filter(function(gsm) {Meta(gsm)$platform_id=='GPL96'},GSMList(gse))
> length(gsmlist)
[1] 17

现在我们想知道哪一列数据是我们想要的,我们可以先查看某一个 GSMTable 的前几行信息

> head(Table(gsmlist[[1]]))
           ID_REF  VALUE ABS_CALL
1  AFFX-BioB-5_at  953.9        P
2  AFFX-BioB-M_at 2982.8        P
3  AFFX-BioB-3_at 1657.9        P
4  AFFX-BioC-5_at 2652.7        P
5  AFFX-BioC-3_at 2019.5        P
6 AFFX-BioDn-5_at 3531.5        P

然后获取对应的列描述信息

> head(Columns(gsmlist[[1]]))
    Column                                                                Description
1   ID_REF                                                                           
2    VALUE                         MAS 5.0 Statistical Algorithm (mean scaled to 500)
3 ABS_CALL MAS 5.0 Absent, Marginal, Present call  with Alpha1 = 0.05, Alpha2 = 0.065

现在,我们知道了 VALUE 列是我们想要的,然后使用下面的代码来将这些数据转换为矩阵形式

# 先获取探针集
probesets <- Table(GPLList(gse)[[1]])$ID
# 将每个样本的 VALUE 列按列拼接起来
data.matrix <- do.call('cbind',
                        lapply(gsmlist,function(x) {
                        tab <- Table(x)
                        # 我们使用 match 保证每列的探针顺序一致
                        mymatch <- match(probesets,tab$ID_REF)
                        return(tab$VALUE[mymatch])
                        })
                      )
data.matrix <- apply(data.matrix,2,function(x) {as.numeric(as.character(x))})
data.matrix <- log2(data.matrix)

查看结果

> head(data.matrix)
      GSM11805  GSM11814  GSM11823  GSM11830  GSM12067  GSM12075  GSM12079  GSM12098  GSM12100
[1,] 10.926963 11.105254 11.275019 11.438636 11.424376 11.222795 11.469845 10.823367 10.835971
[2,]  5.749534  7.908092  7.093814  7.514122  7.901470  6.407693  5.165912  6.556123  8.207014
[3,]  7.066089  7.750205  7.244126  7.962896  7.337176  6.569856  7.477354  7.708739  7.428779
[4,] 12.660353 12.479755 12.215897 11.458355 11.397568 12.529870 12.240046 12.336534 11.762839
[5,]  6.195741  6.061776  6.565293  6.583459  6.877744  6.652486  3.981853  5.501439  6.247928
[6,]  9.251956  9.480790  8.774458  9.878817  9.321252  9.275892  9.802355  9.046578  9.414474
      GSM12105  GSM12268  GSM12270  GSM12283  GSM12298  GSM12300  GSM12399  GSM12444
[1,] 10.810893 11.062653 10.323055 11.181028 11.566387 11.078151 11.535178 11.105450
[2,]  6.816344  6.563768  7.353147  5.770829  6.912889  4.812498  7.471675  7.488644
[3,]  7.754888  7.126188  8.742815  7.339850  7.602142  7.383704  7.432959  7.381110
[4,] 11.237509 12.412490 11.213408 12.678380 12.232901 12.090939 11.421802 12.172834
[5,]  6.017922  6.525129  6.683696  5.918863  5.837943  6.281698  5.419539  5.469235
[6,]  9.030115  9.252665  9.631359  8.656782  8.920948  8.629357  9.526695  9.494656

最后,我们将其转换为 ExpressionSet 对象

require(Biobase)
# 构建 ExpressionSet 对象
rownames(data.matrix) <- probesets
colnames(data.matrix) <- names(gsmlist)
pdata <- data.frame(samples=names(gsmlist))
rownames(pdata) <- names(gsmlist)
pheno <- as(pdata,"AnnotatedDataFrame")
eset2 <- new('ExpressionSet',exprs=data.matrix,phenoData=pheno)

查看对象

> eset2
ExpressionSet (storageMode: lockedEnvironment)
assayData: 22283 features, 17 samples 
  element names: exprs 
protocolData: none
phenoData
  sampleNames: GSM11805 GSM11814 ... GSM12444 (17 total)
  varLabels: samples
  varMetadata: labelDescription
featureData: none
experimentData: use 'experimentData(object)'
Annotation: 

4 获取原始数据

NCBI GEO 会保存有一些原始数据,如 .CEL.CDF 等文件。有时我们想快速的获取这个文件,可以使用 getGEOSuppFiles 函数

getGEOSuppFiles 函数接受一个 GEO accession number,然后下载与其相关的所有原始数据。

默认情况下,该函数会在当前工作目录下创建一个文件夹来存储这些数据。

getGEOSuppFiles('GSE11675')

获取下载的原始文件的信息

> eList <- getGEOSuppFiles('GSE11675', fetch_files = FALSE)
> eList
             fname                                                                               url
1 GSE11675_RAW.tar https://ftp.ncbi.nlm.nih.gov/geo/series/GSE11nnn/GSE11675/suppl//GSE11675_RAW.tar

下载的原始文件中包含 .CEL.CDF 文件,我们可以使用 affyoligo 包进行分析。有空我们再详细介绍其用法

5 使用示例

GEOquery 对于快速收集大量数据来说是相当强大的,下面展示一个例子

5.1 获取给定平台的所有 Series

有时我们想对某个平台的所有 GSE 数据进行数据挖掘,使用 GEOquery 可以让这一切变得非常简单。

但在使用之前,我们需要对 GPL 记录有一些了解。

gpl97 <- getGEO('GPL97')
info <- Meta(gpl97)

获取 title

> info$title
[1] "[HG-U133B] Affymetrix Human Genome U133B Array"

获取 Series ID

> head(info$series_id)
[1] "GSE362" "GSE473" "GSE620" "GSE674" "GSE781" "GSE907"

> length(info$series_id)
[1] 165

获取样本号

> head(info$sample_id)
[1] "GSM3922" "GSM3924" "GSM3926" "GSM3928" "GSM3930" "GSM3932"

> length(info$sample_id)
[1] 7917

该平台共包含了 165Series,样本总量为 7917。获取到了这些信息,就可以进行批量下载了。

我们以下载前 5 个样本为例,进行说明

> gsmids <- Meta(gpl97)$sample_id
> gsmlist <- sapply(gsmids[1:5], getGEO)
> names(gsmlist)
[1] "GSM3922" "GSM3924" "GSM3926" "GSM3928" "GSM3930"

你可能感兴趣的:(GEOquery 下载 GEO 数据)