除了使用GEO2R,我们也可以通过分析数据库提供的矩阵文件来获取差异基因。与GEO2R相比,分析矩阵文件有其自身的优势。比如分析没有时间限制,还可以使用特定程序包生成一些GEO2R不支持的图表(如:热图)。此外,对于某些不支持GEO2R的数据集,分析矩阵文件也是一种很实用的方法。但是直接分析矩阵文件操作较为复杂,此外还需要安装特定的软件。
一、软件准备
分析矩阵文件主要需要使用以下软件
- SQLite
- R
SQLite
SQLite是一个轻量级的数据库引擎,主要用来为数据添加注释信息,还可以用来给数据分组排序。
为什么不用Excel?
理论上Excel可以完成同样的任务,但是使用数据库管理信息具有一些优势。
- 数据库在处理大量数据时更方便,速度也很快。
- Excel会对某些数据进行自动转换(比如SEPT9基因会被转换成9月9日),尽管可以关闭这一功能,但数据库基本不存在这一问题。
安装SQLite
建议使用db browser for SQLite来管理数据库。在这里下载db browser for SQLitehttp://www.sqlitebrowser.org/dl/
也可以使用SQLite命令行工具对数据库进行管理。在这里下载https://www.sqlite.org/download.html
在Linux系统下也可使用包管理器安装,以Ubuntu为例:
sudo apt-get install sqlite3
R
我们主要使用R语言对数据进行统计分析以及图像绘制。在这里任意选择一个镜像即可下载Rhttps://cran.r-project.org/mirrors.html
在Linux系统下可使用包管理器安装R(以Ubuntu为例)
sudo apt-get install r-base
二、下载数据
- 找到合适的数据集后在下拉到Download family表格,点击Series Matrix File(s)即可下载文件
- 上拉,找到Platforms,点击后面的链接下载平台文件。
三、注释数据
矩阵文件中记录的是探针和样本的对应关系,然而,探针名不直观也不通用,这就要求我们使用探针对应的基因名称来代替探针名称(对应关系记录在平台文件中)
将矩阵文件和平台文件导入数据库
- 首先将文件复制一份以作备份,然后删除文件首尾以
!
或#
开头的行 - 在db browser for SQLite中可以点击
文件
-导入
-表来自CSV文件...
来导入文件,字段分隔符选择Tab
,引号选择其他,然后在后面的输入框中输入双引号,表名称设置为probe和platform
或者使用命令
.open data.db --打开/创建一个数据库
.separator "\t" --矩阵文件以制表符分隔列
--导入矩阵文件
--将matrixFileName.txt改为自己的矩阵文件的名字
.import matrixFileName.txt probe
--导入平台文件
--将platformFileName.txt改为自己的平台文件的名字
.import platformFileName.txt platform
.quit --退出
对数据进行注释
在执行SQL选项卡或命令行中使用命令
CREATE TABLE gene AS
SELECT p.GeneSymbol, m.*
FROM probe AS m INNER JOIN platform AS p
WHERE p.ID = m.ID_REF;
DELETE FROM gene WHERE GeneSymbol = '';
就完成了对基因的注释。切换到浏览数据选项卡或使用命令
SELECT * FROM gene;
就可以看到在每一个探针的前面已经加入了对应的基因的信息。
四、数据分组
有的数据集中实验组和对照组是杂乱排列的,这就需要我们对数据表中的样本重新编排顺序,以便于我们统计、作图。
在GEO数据库的Sample中可以看到数据的分组情况
如果这里的信息看不懂,也可以查看矩阵文件里面一开始被删掉的那些以
!
开头的信息,这里面会有每个样本的来源等信息。不管这些信息来自网页还是文件,它们都是以Tab分隔的,这就意味着我们都可以将其直接复制到Excel中进行处理。处理的方式可以是多样的,但我们最终的目的就是得到属于实验组和属于对照组的样品名称。
将这些信息全部复制到Excel中,可以看到数据被分为两列
将对照组的样本名称复制下来,新建control.txt,粘贴并保存;同样,将实验组的样本名称保存为case.txt。
使用SQL命令
CREATE TABLE groupedGenes AS
SELECT GeneSymbol,
--这一行是对照组的样本,样本与样本之间用英文半角逗号分隔
GSM3351235, GSM3351236, GSM3351237, GSM3351238, GSM3351239, GSM3351240, GSM3351241, GSM3351242, GSM3351243, GSM3351244, GSM3351245, GSM3351246, GSM3351247, GSM3351248, GSM3351249,
--这一行是实验组的样本,样本与样本之间用英文半角逗号分隔
GSM3351220, GSM3351221, GSM3351222, GSM3351223, GSM3351224, GSM3351225, GSM3351226, GSM3351227, GSM3351228, GSM3351229, GSM3351230, GSM3351231, GSM3351232, GSM3351233, GSM3351234
FROM gene;
就完成了分组
如果不想手写SQL命令或是担心写错,也可以使用这段Python脚本生成SQL脚本。将control.txt和case.txt放在脚本同一目录下,双击运行即可。
control = open("./control.txt", mode='r')
case = open("./case.txt", mode='r')
controlSamples = control.readlines()
caseSamples = case.readlines()
control.close()
case.close()
keyName = "GeneSymbol"
tableInput = "gene"
tableOutput = "groupedGene"
resBuf = ("CREATE TABLE " + tableOutput + " AS\nSELECT " + keyName + "\n")
for sample in controlSamples:
sample = sample.strip()
resBuf += (", " + sample)
resBuf += "\n"
for sample in caseSamples:
sample = sample.strip()
resBuf += (", " + sample)
resBuf += ("\nFROM " + tableInput + ";")
dest = open("./group.sql", mode = 'w')
dest.write(resBuf)
dest.close()
五、差异分析
导出数据
我们使用R语言进行差异分析,为此首先要将数据库中的数据导出。在在db browser for SQLite中可以点击文件
-导出
-Table(s) as CSV file...
来导出文件,字段分隔符选择Tab
,勾选列名在首行,选择groupedGene,按OK导出。
或者使用命令
.header on
.output groupedGene.txt
SELECT * FROM groupedGene;
.output stdout
然后使用R语言进行差异分析,就可以得到差异基因了。
#########################################################
# logFC的筛选标准
threshold.logFC = 1
# P的筛选标准
threshold.P = 0.05
# 是否对P进行校正
method.UseAdjP = TRUE
# 是否进行对数变换
method.UseLog2 = FALSE
# 校正P的方法
method.AdjP = "fdr"
# 输出基因的最大数量
method.maxGenes = 100000
# 是否输出差异基因
output.table.differential = TRUE
# 是否输出全部基因
output.table.all = TRUE
# 是否输出上调基因
output.table.up = TRUE
# 是否输出下调基因
output.table.down = TRUE
# 对照组数量
group.control = 10
# 实验组数量
group.case = 10
# 输入文件的目录,同时也将作为输出文件保存的位置
# 注意将\\替换为\,如C:\\Users\\Lenovo\\Desktop
config.workdir = ""
#输入文件的名称
config.inputFile = ""
#########################################################
library("limma")
setwd(config.workdir)
rawData = read.table(config.inputFile, sep = "\t", header = TRUE)
rawData = avereps(rawData[,-1], ID = rawData$ID)
exprSet = as.matrix(rawData)
if(method.UseLog2){
exprSet = log2(exprSet + 1)
}
design = model.matrix(~ 0 + factor(c(rep("control", group.control), rep("case", group.case))))
colnames(design) = c("control", "case")
rownames(design) = colnames(exprSet)
contrast = makeContrasts(case-control, levels = design)
fit = lmFit(exprSet, design)
fit2 = contrasts.fit(fit, contrast)
fit2 = eBayes(fit2)
result = topTable(fit2, adjust = method.AdjP, number = method.maxGenes)
result = na.omit(result)
if(output.table.all){
res = result
id = rownames(res)
res = cbind(id, res)
write.table(
res,
file = "allGenes.txt",
sep = "\t",
row.names = FALSE,
col.names = TRUE,
quote = FALSE
)
}
if(output.table.differential){
if(method.UseAdjP){
res = subset(result, (abs(result$logFC) > threshold.logFC) & (result$adj.P.Val < threshold.P))
}
else{
res = subset(result, (abs(result$logFC) > threshold.logFC) & (result$P.Val < threshold.P))
}
id = rownames(res)
res = cbind(id, res)
write.table(
res,
file = "differentialGenes.txt",
sep = "\t",
row.names = FALSE,
col.names = TRUE,
quote = FALSE
)
}
if(output.table.up){
if(method.UseAdjP){
res = subset(result, (result$logFC > threshold.logFC) & (result$adj.P.Val < threshold.P))
}
else{
res = subset(result, (result$logFC > threshold.logFC) & (result$P.Val < threshold.P))
}
id = rownames(res)
res = cbind(id, res)
write.table(
res,
file = "upregulatedGenes.txt",
sep = "\t",
row.names = FALSE,
col.names = TRUE,
quote = FALSE
)
}
if(output.table.up){
if(method.UseAdjP){
res = subset(result, (result$logFC < -threshold.logFC) & (result$adj.P.Val < threshold.P))
}
else{
res = subset(result, (result$logFC < -threshold.logFC) & (result$P.Val < threshold.P))
}
id = rownames(res)
res = cbind(id, res)
write.table(
res,
file = "downregulatedGenes.txt",
sep = "\t",
row.names = FALSE,
col.names = TRUE,
quote = FALSE
)
}