Kaplan-Meier生存曲线

生存分析有个难点是删失(cersored)数据处理,删失数据是指整个数据收集过程都没发生事件的数据。说的有点拗口,举例说我们做某癌症生存分析,那么事件就是因此癌症导致病人死亡。如果有个病人随访期间不幸被车撞死了,那么这个病人记录到此为止,但是我们的事件并没有发生;或者病人突然搬到国外去了,无法继续随访记录,那这个人数据收集结束了,但事件也没有发生。这例子是右删失数据,还有左删失等感兴趣朋友可自行了解,我们一般都是碰到右删失数据。

Kaplan-Meier生存曲线的生存率公式如下,n是存活总人数,d是事件发生数目。
S(t_{i}) = S(t_{i-1})\dot(1 - \frac{d_{i}}{n_{i}})


R语言用 survivalsurvminer 包可以很容易实现生存曲线分析与可视化,下面展示一个TCGA数据分析例子。要提醒一下有些教程让人把数据处理成0,1,其实应该把数据处理成1和2,用1表示删失,2表示事件发生(死亡)

首先准备生存数据,TCGA数据可以直接下载tsv格式临床数据,但是不建议使用,下载的这个数据有不少地方列错位。我曾经下载json版数据用python自己提取,这是个方法。更好方法是去cBioPortal(cBioPortal for Cancer Genomics)下载其整理好的,下载后用excel打开检查一下,还是可能部分条目有问题的。刚刚说把数据转换为1和2,下面就先这样处理一下。

> library(survival, quietly = TRUE)
> library(survminer, quietly = TRUE)
> library(tidyverse, quietly = TRUE)
 
# 定义转换函数,LIVING(删失)是1,死亡是2. 符号 > 和 + 是因为交互模式,写代码记得去掉。
> statusNum <- function(x){
+ if(x == "LIVING"){
+   return(1)}
+ else{
+   return(2)}
+ }

# 临床数据列非常多,选择我们需要的几列,同时改改列名方便R操作
> clinicaL <- read_tsv("20190211Survival/cBioPortal-blca_tcga_pub_2017_clinical_data.tsv") %>% dplyr::select(`Patient ID`, `Overall Survival (Months)`, `Overall Survival Status`) %>% filter(!is.na(`Overall Survival (Months)`) & !is.na(`Overall Survival Status`)) %>% rename(time=`Overall Survival (Months)`, patient_id=`Patient ID`) %>% mutate(status=map_dbl(`Overall Survival Status`, statusNum)) %>% dplyr::select(patient_id, time, status)

# 数据如下
> head(clinicaL)
# A tibble: 6 x 3
  patient_id     time status
  <chr>         <dbl>  <dbl>
1 TCGA-2F-A9KP  12.0       2
2 TCGA-2F-A9KQ  94.8       1
3 TCGA-2F-A9KR 105.        2
4 TCGA-2F-A9KT 109.        1
5 TCGA-2F-A9KW   8.34      2
6 TCGA-4Z-AA7M  16.3       1

然后读取基因表达数据,选取有生存数据的病人,根据自己需要基因表达量分组。

> geneExpr <- read_tsv("20190211Survival/ALL_FPKM_UQ_ENTREZID.tsv")
> colnames(geneExpr) %>% head()
[1] "ENSEMBL"       "entrezgene_id" "hgnc_symbol"   "TCGA-FD-A5BX"  "TCGA-K4-A3WS"  "TCGA-E7-A8O7" 

# 筛选同时有生存数据和表达数据的病人
> patientList <- intersect(clinicaL$patient_id, colnames(geneExpr))
> head(patientList)
[1] "TCGA-2F-A9KP" "TCGA-2F-A9KQ" "TCGA-2F-A9KR" "TCGA-2F-A9KT" "TCGA-2F-A9KW" "TCGA-4Z-AA7M"
> length(patientList)
[1] 399

# 为了后面方便,直接把表达数据样本按照临床数据样本顺序排列
> clinicaL2 <- dplyr::filter(clinicaL, patient_id %in% patientList) %>% dplyr::distinct(patient_id, .keep_all = TRUE)
> geneExpr2 <- dplyr::select(geneExpr, hgnc_symbol, clinicaL2$patient_id)
> dim(clinicaL2)
[1] 399   3
> dim(geneExpr2)
[1] 20084   400

# 我这里就随便选个基因
> head(genE)
       hgnc_symbol       TCGA-2F-A9KP       TCGA-2F-A9KQ       TCGA-2F-A9KR       TCGA-2F-A9KT       TCGA-2F-A9KW 
           "SCFD2" "17.6915874147098" "17.1654098740173" "17.7186146961568" "16.8297194432778" "16.3051962379739" 

# 因为之前表达数据样本排列根据临床样本顺序来的,我就直接把表达数据添加到临床数据表格了
> clinicaL3 <- mutate(clinicaL2, SCFD2=genE[-1]) %>% dplyr::arrange(desc(SCFD2)) %>% mutate(SCFD2_Expr=c(rep("High", 200), rep("Low", 199)))
> head(clinicaL3, n=3)
# A tibble: 3 x 5
  patient_id    time status SCFD2            SCFD2_Expr
  <chr>        <dbl>  <dbl> <chr>            <chr>     
1 TCGA-BT-A20X  8.25      2 18.5989977626721 High      
2 TCGA-E7-A85H 12.9       1 18.4226732766918 High      
3 TCGA-FD-A3SJ 24.3       2 18.4119859441587 High      
> tail(clinicaL3, n=3)
# A tibble: 3 x 5
  patient_id    time status SCFD2            SCFD2_Expr
  <chr>        <dbl>  <dbl> <chr>            <chr>     
1 TCGA-LT-A5Z6  15.6      1 15.6753402657604 Low       
2 TCGA-FJ-A3ZF  17.2      1 15.5461411355296 Low       
3 TCGA-ZF-A9R7  21.8      1 14.6207572703697 Low 

现在把样品分组信息添加到了临床信息表,下面用 survivalsurvminer 分析按SCFD2表达分组生存是否差异。

fit <- survfit(Surv(time, status) ~ SCFD2_Expr, data = clinicaL3)
# 画图
ggsurvplot(fit, pval = TRUE)
2.png

从这结果看按照SCFD2基因表达分2组生存率无显著差异。对于图片美化, ggsurvplot 产生图片是ggplot2对象,可以直接用ggplot2进行任意修改。

> p <- ggsurvplot(fit, pval = TRUE)

# 换个主题把坐标翻转
> p$plot <- p$plot + theme_dark() + coord_flip()
> p$plot
3.png

参考资料
Survival Analysis in R
survminer R package: Survival Data Analysis and Visualization - Easy Guides - Wiki - STHDA

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 生存分析指根据试验或调查得到的数据对生物或人的生存时间进行分析和推断,研究生存时间和结局与众多影响因素间关系及其程...
    生信宝典阅读 3,133评论 0 5
  • 相识 由于老城改造,原来租住的房子要拆迁,所以只好搬家。这次搬到了学校的后门。租住的房子小,租金却不少,一年九千。...
    诗意人生_36da阅读 177评论 2 3
  • 寝室里吵吵闹闹过后,就这么平静下来了,觉得自己特别空,什么都没有,自己这点可怜的精神食粮想想都好笑。专业课还没有学...
    洋相相相阅读 161评论 0 0
  • 我们学校对面有很多的杨树。他们是先在上小树苗,然后一点一点的慢慢的长大,春姑娘来了,给大树们披上绿色的新衣,妈妈...
    冷格玉荻阅读 55评论 0 2