介绍
一般来说,我们做生存分析,会有(P<0.05)和(P>0.05)两种结果。KM plot在生物医学中很常见,主要用来做预后分析,比如可以根据表达量把病人分成两组,然后比较哪组病人预后好,进而可以得出基因表达量高低与病人预后好坏相关性的结论。 画KM plot时,有时候会比较纠结怎样对病人进行分组,如何来设置分组的cutoff。一般来说常见的几种设置cutoff值得思路如下: 1:大多数情况下,根据表达量从低到高对样本进行排序,取前50%为低表达,后50%为高表达,然后画KM plot。 2:还有一些文章也会将样本表达量均分为三组或者四组。 3:一些文章也会选一些其它的cutoff,比如前1/3和后2/3,前25%和后25%(中间50%的数据去掉)。
例子
例如下面例子所示:(通过NFE2L2基因的表达量中位值,我们将所有的样本分为高表达和低表达两组,然后通过绘制KM生存分析曲线的形式来探讨两组生存概率是否存在差别)
代码语言:javascript复制> # =======================================================
> ####
> # =======================================================
>
> library(dplyr)
>
> library(tidyr)
>
> library(tidyverse)
>
> library(survival)
>
> library(survminer)
>
> setwd('D:\train\sur')
>
> rm(list=ls())
>
> data <- read.csv('data.csv', header = T)
>
> head(data)
sample NFE2L2 OS OS.Time
1 sam590 660 0 1.413699
2 sam1034 749 0 2.326027
3 sam164 859 0 1.227397
4 sam1079 1034 0 5.569863
5 sam266 1068 0 1.221918
6 sam935 1098 0 1.986301
>
> str(data)
'data.frame': 1086 obs. of 4 variables:
$ sample : Factor w/ 1086 levels "sam1","sam10",..: 633 41 160 90 273 1016 32 37 271 400 ...
$ NFE2L2 : int 660 749 859 1034 1068 1098 1126 1197 1201 1208 ...
$ OS : int 0 0 0 0 0 0 0 0 0 0 ...
$ OS.Time: num 1.41 2.33 1.23 5.57 1.22 ...
>
> data['NFE2L2'] <- ifelse(data['NFE2L2'] > median(data[,'NFE2L2']), 'high', 'low' )
>
> fit <- survfit(Surv(OS.Time, OS) ~NFE2L2, data =data)
>
> ggpar( ggsurvplot(
fit, data = data,
pval = TRUE,
# conf.int = TRUE,
# legend.title = "CUL3",
xlim = c(0,5),
xlab = "Time in years",
break.time.by = 1,
pval.size = 8,
risk.table = "absolute",
risk.table.y.text.col = T,
risk.table.y.text = FALSE,
risk.table.fontsize = 5,
# legend.labs = c("high", "Low"),
palette = c("#E41A1C","#377EB8")),
font.y = c(16, "bold"),
font.x = c(16, "bold"),
legend = "top",
font.legend = c(16, "bold"))
但是很尴尬的发现,通过该基因的中位值分成的高低两组并不存在生存差异。这个时候,我们首先可以通过三分法或者四分法,将患者均分为三个组别或者四个组别。
代码语言:javascript复制# =======================================================
####
# =======================================================
library(dplyr)
library(tidyr)
library(tidyverse)
library(survival)
library(survminer)
setwd('D:\train\sur')
rm(list=ls())
data <- read.csv('data.csv', header = T)
head(data)
str(data)
rt <- data %>%
mutate_at(vars(NFE2L2:NFE2L2),
funs(Hmisc::cut2(as.numeric(.), g = 3)))
table(rt$NFE2L2)
fit <- survfit(Surv(OS.Time, OS) ~NFE2L2, data =rt)
ggpar( ggsurvplot(
fit, data = rt,
pval = TRUE,
# conf.int = TRUE,
# legend.title = "CUL3",
xlim = c(0,5),
xlab = "Time in years",
break.time.by = 1,
pval.size = 8,
risk.table = "absolute",
risk.table.y.text.col = T,
risk.table.y.text = FALSE,
risk.table.fontsize = 5
# legend.labs = c("high", "Low"),
# palette = c("#E41A1C","#377EB8")
),
font.y = c(16, "bold"),
font.x = c(16, "bold"),
legend = "top",
font.legend = c(16, "bold"))
我们通过Hmisc::cut2(as.numeric(.), g = 3)),将患者均分为三组,但是虽然P值下降了,仍然没有达到想要的(P<0.05)的效果。所以,我们需要其他方法。
代码语言:javascript复制# =======================================================
####
# =======================================================
library(dplyr)
library(tidyr)
library(tidyverse)
library(survival)
library(survminer)
setwd('D:\train\sur')
rm(list=ls())
data <- read.csv('data.csv', header = T)
sur.cut <- surv_cutpoint(data, time= 'OS.Time',
event = 'OS' ,
variables = 'NFE2L2' )
sur.cut
sur.cat <- surv_categorize(sur.cut)
table(sur.cat$NFE2L2)
fit <- survfit(Surv(OS.Time, OS) ~NFE2L2, data =sur.cat)
ggpar( ggsurvplot(
fit, data = sur.cat,
pval = TRUE,
conf.int = TRUE,
# legend.title = "CUL3",
xlim = c(0,5),
xlab = "Time in years",
break.time.by = 1,
pval.size = 8,
risk.table = "absolute",
risk.table.y.text.col = T,
risk.table.y.text = FALSE,
risk.table.fontsize = 5,
# legend.labs = c("high", "Low"),
palette = c("#E41A1C","#377EB8")),
font.y = c(16, "bold"),
font.x = c(16, "bold"),
legend = "top",
font.legend = c(16, "bold"))
通过sur.cut我们达到了P小于0.05的目标,这一步的主要原理是,放弃以前所用的中位值来定义高低组的方法,采用不同的阈值来重新定义高低分组以达到最低的P值。我们看到经过这样的步骤,高组别的患者明显多于低组别。
代码语言:javascript复制> sur.cut
cutpoint statistic
NFE2L2 3705 3.039985
sur.cut即是我们找到的最佳cutoff值,当我们通过这个cutoff值来定义高低分组时,P值达到最低。但是我们可以逐渐尝试该cutoff值附近的值,来找到一个合适的阈值。