顏值夠格的風險森林圖

0.輸入數據和R包

在生信星球公眾號聊天框回復“forest779”即可獲得輸入數據。也可以自己根據表達矩陣與臨床信息生成,如下:

rm(list = ls())
load("cox_dat.Rdata")
str(dat)
## 'data.frame':    516 obs. of  10 variables:
##  $ time  : num  47.867 0.533 39.7 24.5 49.767 ...
##  $ event : num  0 0 1 1 0 0 0 0 0 0 ...
##  $ gender: Factor w/ 2 levels "female","male": 2 1 2 2 2 2 2 1 2 2 ...
##  $ stage : Factor w/ 4 levels "i","ii","iii",..: 3 3 1 1 2 2 1 1 1 1 ...
##  $ age   : num  66 77 57 59 57 67 70 52 51 53 ...
##  $ miR21 : num  16.7 18 18 17.8 18.4 ...
##  $ miR143: num  17 18 17.1 16.5 16.8 ...
##  $ miR10b: num  17.7 17.9 17.5 17.1 17.1 ...
##  $ miR192: num  15.3 11.6 14.4 14.2 14.6 ...
##  $ miR183: num  8.44 11.24 10.53 10.03 8.43 ...
library(survival)
library(survminer)
library(forestplot)
library(stringr)

1.多因素cox回歸

建模就一句代碼,出森林圖也是一句代碼。

model <- coxph(Surv(time, event) ~., data = dat )
ggforest(model)

這個雖然是ggplot2對象,但是灰色背景去不掉,也沒辦法用常規的ggplot2語法去修改顏色,只能是導出去再慢慢調咯。

2.美化版森林圖-forestplot

用到一個新的R包,forestplot。

它就沒有ggforest那么智能了,森林圖展示的內容是需要自己組織的。

2.1學學幫助文檔

看看函數的幫助文檔,最簡單的用法:

row_names <- list(list("test = 1", expression(test >= 2)))
test_data <- data.frame(
  coef = c(1.59, 1.24),
  low = c(1.4, 0.78),
  high = c(1.8, 1.55)
)
forestplot(row_names,
  test_data$coef,
  test_data$low,
  test_data$high,
  zero = 1,
  cex  = 2,
  lineheight = "auto",
  xlab = "Lab axis txt"
)

最核心的信息就是HR值和它的置信區間范圍,我們可以從cox模型中提取到圖上的這些信息。

2.2組織輸入數據

照葫蘆畫瓢開始,準備添加在圖上的label列。

m = summary(model)
colnames(m$coefficients)
## [1] "coef"      "exp(coef)" "se(coef)"  "z"         "Pr(>|z|)"
colnames(m$conf.int)
## [1] "exp(coef)"  "exp(-coef)" "lower .95"  "upper .95"
#p值改一下格式,加上顯著性
p = ifelse(
  m$coefficients[, 5] < 0.001,
  "<0.001 ***",
  ifelse(
    m$coefficients[, 5] < 0.01,
    "<0.01  **",
    ifelse(
      m$coefficients[, 5] < 0.05,
      paste(round(m$coefficients[, 5], 3), " *"),
      round(m$coefficients[, 5], 3)
    )
  )
)
#HR和它的置信區間
dat2 = as.data.frame(round(m$conf.int[, c(1, 3, 4)], 2))
dat2 = tibble::rownames_to_column(dat2, var = "Trait")
colnames(dat2)[2:4] = c("HR", "lower", "upper")
#需要在圖上顯示的HR文字和p值
dat2$HR2 = paste0(dat2[, 2], "(", dat2[, 3], "-", dat2[, 4], ")")
dat2$p = p

str(dat2)
## 'data.frame':    10 obs. of  6 variables:
##  $ Trait: chr  "gendermale" "stageii" "stageiii" "stageiv" ...
##  $ HR   : num  1.08 1.22 2.5 6.39 1.03 1.41 0.86 0.89 0.82 0.95
##  $ lower: num  0.76 0.61 1.6 4.12 1.01 1.14 0.74 0.75 0.76 0.85
##  $ upper: num  1.53 2.46 3.89 9.9 1.05 1.75 0.99 1.05 0.9 1.06
##  $ HR2  : chr  "1.08(0.76-1.53)" "1.22(0.61-2.46)" "2.5(1.6-3.89)" "6.39(4.12-9.9)" ...
##  $ p    : chr  "0.668" "0.574" "<0.001 ***" "<0.001 ***" ...

2.3基礎畫圖

forestplot(
  dat2[, c(1, 4, 6)],
  mean = dat2[, 2],
  lower = dat2[, 3],
  upper = dat2[, 4],
  zero = 1,
  boxsize = 0.4,
  col = fpColors(box = '#1075BB', lines = 'black', zero = 'grey'),
  lty.ci = "solid",
  graph.pos = 2
)

2.4加點細節

主要是分類向量,如這里的性別和分期,需要畫出reference,那就需要在輸入數據dat2里添加幾行。

dat2$Trait = str_remove(dat2$Trait, "gender|stage")

ins = function(x) {
  c(x, rep(NA, ncol(dat2) - 1))
}

dat2 = rbind(
  c("Trait", NA, NA, NA, "HR", "p"),
  ins("gender"),
  ins("female"),
  dat2[1, ],
  ins("stage"),
  ins("i"),
  dat2[2:nrow(dat2), ]
)
for(i in 2:4) {
  dat2[, i] = as.numeric(dat2[, i])
}
str(dat2)
## 'data.frame':    15 obs. of  6 variables:
##  $ Trait: chr  "Trait" "gender" "female" "male" ...
##  $ HR   : num  NA NA NA 1.08 NA NA 1.22 2.5 6.39 1.03 ...
##  $ lower: num  NA NA NA 0.76 NA NA 0.61 1.6 4.12 1.01 ...
##  $ upper: num  NA NA NA 1.53 NA NA 2.46 3.89 9.9 1.05 ...
##  $ HR2  : chr  "HR" NA NA "1.08(0.76-1.53)" ...
##  $ p    : chr  "p" NA NA "0.668" ...

重新畫圖

forestplot(
  dat2[, c(1, 5, 6)],
  mean = dat2[, 2],
  lower = dat2[, 3],
  upper = dat2[, 4],
  zero = 1,
  boxsize = 0.4,
  col = fpColors(box = '#1075BB', lines = 'black', zero = 'grey'),
  lty.ci = "solid",
  graph.pos = 2,
  #xticks = F,
  is.summary = c(T, T, F, F, T, rep(F, 10)),
  align = "l",
  hrzl_lines = list(
    "1" = gpar(lty=1),
    "2" = gpar(lty=1),
    "16"= gpar(lty=1)),
  colgap = unit(5, 'mm')
)

差不多啦!可以。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容