快速完成TCGA数据集临床基线表的整理
大家好,我是阿琛。在生信分析的文章中,往往第一张表格是基于TCGA数据库患者临床信息的基线资料表,以展示分析的整体水平。在前面的内容中,我们学习了使用tableone包中相关的函数来快速的制作临床基线资料表(“R语言一键生成好看的Table 1?小白也能十分钟之内搞定!”)。
接下来,我们来看下如何基于下载得到TCGA临床数据,逐步完成整个表格的整理内容,同时来看一下数据清洗和字符串匹配相关内容的应用。
下面,我们来看下如何基于TCGA数据的临床信息绘制临床基线资料表。
1.TCGA临床数据下载
首先,使用TCGAbiolinks包下载TCGA-LIHC患者的相关临床信息。
library(TCGAbiolinks)clinical <- GDCquery(project = "TCGA-LIHC", data.category = "Clinical", file.type = "xml")GDCdownload(clinical)cliquery <- GDCprepare_clinic(clinical, clinical.info = "patient")save(cliquery, file = "TCGA-LIHC.clinical.rda")
将下载结果保存为rda文件。可以看到,在当前目录下多了一个.rda文件,后续在使用时直接使用load()函数进行读取即可。在结果中,其中包含415个患者的82个不同的临床信息。
#load("TCGA-LIHC.clinical.rda")colnames(cliquery)[1] <- "Tumor_Sample_Barcode"cliquery[1:3,1:3]write.csv(cliquery, "TCGA-LIHC.Clinical.csv")
将临床信息的第一列列名修改为“TumorSampleBarcode”,便于后续分析处理;同时将其保存为csv文件。
2.病人分组筛选
rm(list = ls())library(tidyverse)rt <- read.csv("TCGA-LIHC.Clinical.csv")
接下来,读取保存好的临床信息,用于后续的临床数据整理和分组筛选。在这里,为了演示方便,我们通过存活和死亡的方法来对所有患者进行分组作为演示。
p1 = rt %>% filter(vital_status == "Alive") p2 = rt %>% filter(vital_status == "Dead") cli = rt %>% filter(vital_status != "")
简单解释一下:分别根据临床信息数据框中“vital_status”的信息,筛选“Alive”的患者作为存活组别,筛选“Dead”的患者作为死亡组别,同时去除其中缺失的患者后,作为纳入的所有患者。当然,在实际应用过程中,也可以根据自己的数据需求,对患者进行重新分组。
可以看到,最终纳入分析对患者中,存活的患者为315例,死亡的患者为100例,总计415例。
3. 选取性别分组
接着,对临床数据进行整理,首先对当前分组下性别数据内容进行整理。
s1 = p1 %>% group_by(gender) %>% summarise(alive=n())s1
这里,使用group_by()函数结合summarise()函数,分别统计存活Alive的患者中男性和女性数量。结果显示,其中女性96个,男性219个。
s2 = p2 %>% group_by(gender) %>% summarise(dead=n())s2
同样,对死亡患者进行整理。结果显示,在死亡dead的患者中女性40个,男性60个:
接着,使用merge()函数对两个统计分析结果进行合并。
sex <- merge(s1, s2, by='gender', all = TRUE) %>% as.data.framesexrownames(sex) <- sex[,1]sex <- sex[,-1]
结果显示:
随后,使用chisq.test()函数进行卡方检验,对统计结果进行分析,计算对应的P值。
sex.p = chisq.test(sex)$p.valueprint(sex.p)
结果显示,经过卡方检验,P值为0.099,说明性别在死亡和存活患者之间无显著性差异。
sex$total <- rowSums(sex)sum <- colSums(sex)##计算百分比并写到括号里#用sprintf格式化为小数点后保留1位,加上百分号sex <- rbind(c(NA, NA, NA), paste0(sex[1,], " (", sprintf("%1.1f%%", sex[1,]/sum*100), ")"),            paste0(sex[2,], " ("sprintf("%1.1f%%", sex[2,]/sum*100), ")"))#加上行名、列名rownames(sex) <- c("Sex", "Female", "Male")colnames(sex) = paste0(c("Alive", "Dead", "Total"), "\n(n=", sum, ")")print(sex)
最后,对细节信息进行整理,统计添加所有患者数量,分别对行名和列名进行设置,同时添加百分比。
结果显示:
4. 选取年龄分组
随后,选取一个数值型变量,来看看如何对数值型变量进行整理分析。在此,我们来对患者的年龄情况进行统计分析。
age1 <- p1 %>% summarise(age = round(mean(age_at_initial_pathologic_diagnosis,na.rm = T), 1), sd = round(sd(age_at_initial_pathologic_diagnosis,na.rm = T), 1), median=round(median(age_at_initial_pathologic_diagnosis,na.rm = T), 1),min=round(min(age_at_initial_pathologic_diagnosis,na.rm = T), 1),max=round(max(age_at_initial_pathologic_diagnosis,na.rm = T), 1))age1 <- c("Age(Mean (SD))" = with(age1, paste0(age, " (", sd, ")")),"Age(Median [MIN, MAX])" = with(age1, paste0(median, " [", min, ",", max, "]")))
计算分组1存活的患者中相应年龄的平均数(SD值),中位数(最小值,最大值)。使用summarise()函数来进行统计,包括mean,sd值,中位值,min和max,同时使用round()函数来设置保留小数点后一位。将计算得到的结果使用paste0()函数进行整合成标准形式。
age2 <- p2 %>% summarise(age = round(mean(age_at_initial_pathologic_diagnosis,na.rm = T), 1), sd=round(sd(age_at_initial_pathologic_diagnosis,na.rm = T), 1), median=round(median(age_at_initial_pathologic_diagnosis,na.rm = T), 1),min=round(min(age_at_initial_pathologic_diagnosis,na.rm = T), 1),max=round(max(age_at_initial_pathologic_diagnosis,na.rm = T), 1) )age2 <- c("Age(Mean (SD))" = with(age2, paste0(age, " (", sd, ")")),"Age(Median [MIN, MAX])" = with(age2, paste0(median, " [", min, ",", max, "]")))
同样的,对死亡的患者年龄进行统计分析。
age <- cli %>% summarise(age = round(mean(age_at_initial_pathologic_diagnosis,na.rm = T), 1), sd=round(sd(age_at_initial_pathologic_diagnosis,na.rm = T), 1), median=round(median(age_at_initial_pathologic_diagnosis,na.rm = T), 1),min=round(min(age_at_initial_pathologic_diagnosis,na.rm = T), 1),max=round(max(age_at_initial_pathologic_diagnosis,na.rm = T), 1) )age <- c("Age(Mean (SD))" = with(age, paste0(age, " (", sd, ")")),"Age(Median [MIN, MAX])" = with(age, paste0(median, " [", min, ",", max, "]")))
最后,对所有患者的年龄进行统计分析。这样,在环境变量中多了三个年龄的计算结果。
结果显示
age <- cbind(age1, age2) %>% cbind(age)colnames(age) <- colnames(sex)print(age)
使用cbind()函数将三个的统计结果进行合并,并将性别sex中整理好的列名赋值给年龄age。
结果显示:
在此,呈现了两种连续变量的展示形式;在实际使用过程中,任选其中一种方法进行展示即可。
5.选取分期分组
在肿瘤分析过程中,肿瘤分期是个重要信息。接下来,对肿瘤分期进行分组整理。
stage_a <- p1 %>% filter(stage_event_pathologic_stage != "") %>% group_by(stage_event_pathologic_stage) %>% summarise(stage = n())stage_d <- p2 %>% filter(stage_event_pathologic_stage != "") %>% group_by(stage_event_pathologic_stage) %>% summarise(stage = n())stage_t <- cli %>% filter(stage_event_pathologic_stage != "") %>% group_by(stage_event_pathologic_stage) %>% summarise(stage = n())
筛选-分组-统计。去除分期Stage中缺失的患者,并按pathologic_stage分组情况进行分组,然后使用summarise()函数进行统计汇总。
接着,对三组临床分期进行合并。这里使用merge()函数进行数据的合并;注意一点的是,记得加上参数all = TRUE,表示即使另一组为缺失值,这个变量分组依然会保存。
stage <- merge(stage_a, stage_d, by="stage_event_pathologic_stage", all = TRUE) %>% merge(stage_t, by="stage_event_pathologic_stage", all = TRUE) %>% as.data.frame
结果显示:
随后,对行名和列名进行设置。
rownames(stage) <-stage[,1]stage <-stage[,-1]colnames(stage) <-colnames(sex)print(stage)
结果显示:
随后,计算两组之间的统计显著性差异。既然是计算存活和死亡之间组别的差异,那么自然需要将第三组total去掉,并将其赋值给一个新变量。
sgx <- stage[, -3]sgx <- sgx[!apply(sgx, 1, anyNA),]sg.p = chisq.test(sgx)$p.value
去除包含NA的分组,随后使用chisq.test()函数进行卡方检验。
结果显示:
最后,将最后的结果汇总输出。首先,将缺失值以NA代替,同时与性别一样,计算其各个值所占的百分比,并保留一位小数。随后,对行名和列名进行相应的设置。
sgv2 <- lapply(1:nrow(stage), function(i) ifelse(is.na(stage[i,]), NA, paste0(stage[i,]," (", sprintf("%1.1f%%", stage[i,]/sum * 100), ")"))) sgv2 <- do.call(rbind, sgv2)rownames(sgv2) <- rownames(stage)colnames(sgv2) <- colnames(stage)sgv <- rbind(c(NA, NA, NA), sgv2)rownames(sgv)[1] <- "Stage"print(sgv)
结果显示:
6.临床信息合并
res = rbind(sex, age) %>% rbind(sgv) %>% as.data.frameprint(res)
最后,使用rbind()函数将性别,年龄,和分期信息进行合并,并使用as.data.frame()函数将结果转换为数据框格式。
结果显示:
7.输出结果
所有内容都整理好了,最后将结果以csv形式输出,并命名为TABLE1.csv。
tab <- print(res, quote = FALSE, #不显示引号 noSpaces = TRUE,            printToggle = FALSE)write.csv(tab, file = "TABLE1.csv")
注意,使用参数quote = FALSE将引号去除,其余默认。可以看到,在当前工作目录下多了一个名为TABLE1.csv的结果文件。
结果显示:
这样,一份基于生存情况都基线资料表就整理好了~当然,如果你对其他信息感兴趣的话,也可以进行相应的整理。
回复“阿琛54”即可获得相应的代码和数据~
系列传送门
R语言小白入门课|一刻钟带你学会R数据转化
END

撰文丨阿   琛
排版丨四金兄
值班 | 火   火

主编丨小雪球
继续阅读
阅读原文