用ggplot2画肿瘤领域常见的泳道图

2022-11-15 11:32:53 浏览数 (2)

泳道图可以展示不同患者在一定时间内接受不同治疗(或者处于不同时期)的情况,在肿瘤治疗领域的文献中很常见,但是竟然百度不到它的具体含义。。。

泳道图

上面这张图横坐标表示月数,纵坐标表示病人ID,一个条形就是一个病人,条形的颜色表示疾病的不同阶段,不同的形状表示肿瘤治疗中的起止,这张图是用SAS画出来的~

复习下肿瘤领域的几个术语:

  • 完全缓解(CR, complete response):所有靶病灶消失,无新病灶出现,且肿瘤标志物正常,至少维持4周。
  • 部分缓解(PR, partial response):靶病灶最大径之和减少≥30%,至少维持4周。
  • 疾病进展(PD, progressive disease):靶病灶最大径之和至少增加≥20%,或出现新病灶。
  • 疾病稳定(SD, stable disease):靶病灶最大径之和缩小未达PR,或增大未达PD。

“数就是图,图就是数

这个图形其实不复杂,主体部分就是我们常见的条形图,再加上几个形状,无非就是不同的坐标进行映射即可。

一般我们在收集病人信息的时候都是宽数据,一行表示一个病人,每一列表示不同的信息,数据结构大概像下面这样:

代码语言:javascript复制
suppressMessages(library(tidyverse))

set.seed(200)
df <- data.frame(Patient = 1:12, 
                 Months = sample(6:30, 12, replace=TRUE),
                 Stage = sample(1:4, 12, replace=TRUE),
                 Continued = sample(0:1, 12, replace=TRUE))

df <- df |> 
  mutate(Patient = fct_reorder(factor(Patient), Months)) |> # 画图时保证顺序
  group_by(Patient) |> 
  mutate('Complete Response Start'=sample(c(6:(max(Months)-1),NA), 1, 
                         prob=c(rep(1, length(6:(max(Months)-1))),5), replace=TRUE),
         'Partial Response Start'=sample(c(6:(max(Months)-1),NA), 1, 
                        prob=c(rep(1, length(6:(max(Months)-1))),5), replace=TRUE),
         'Durable'=sample(c(-0.5,NA), 1, replace=TRUE),
         'Response End'=sample(c(6:(max(Months)-1),NA), 1, 
                        prob=c(rep(1, length(6:(max(Months)-1))),5), replace=TRUE)
         )

# 数据大概这样
head(df)
## # A tibble: 6 × 8
## # Groups:   Patient [6]
##   Patient Months Stage Continued Complete Response Sta…¹ Parti…² Durable Respo…³
##   <fct>    <int> <int>     <int>                   <int>   <int>   <dbl>   <int>
## 1 1           11     1         1                      10       8    -0.5      NA
## 2 2           23     4         1                      NA      15    NA        17
## 3 3           20     2         0                      16      NA    NA        17
## 4 4           13     3         0                      11       9    -0.5      10
## 5 5           28     4         0                      NA      23    NA        15
## 6 6           17     4         0                      NA      NA    -0.5      NA
## # … with abbreviated variable names ¹`Complete Response Start`,
## #   ²`Partial Response Start`, ³`Response End`

由于手里没有此类研究的信息,只能自己构建一个,可能有错误,但是不影响画图。

有了这个数据,我们其实就可以开始画图了。先画一个简单的条形图:

代码语言:javascript复制
p <- ggplot(df, aes(Months, Patient)) 
  geom_bar(stat = "identity", aes(fill=factor(Stage)),width = 0.7)

p

plot of chunk unnamed-chunk-2

这个图出来之后,我们只要再把不同的形状加上去就好了。形状代表不同的信息,因此这些信息需要在一列里才行,所以我们需要一个长数据

下面就把不同的信息变成一个长数据,长宽数据转换真的是太重要了,尤其是临床收集的数据大部分都是宽数据,长宽转换非常频繁,如果你还不会,赶紧翻看之前的推文:

宽数据变为长数据的5种情况! 长数据变为宽数据的7种情况! 长宽数据转换的特殊情况

宽数据转为长数据:

代码语言:javascript复制
df_long <- df |> 
  pivot_longer(5:8,names_to = "type",values_to = "value") |> 
  mutate(type=factor(type, # 顺便给type排个序,画图保证顺序
                     levels = c("Complete Response Start","Partial Response Start","Response End","Durable")))

head(df_long)
## # A tibble: 6 × 6
## # Groups:   Patient [2]
##   Patient Months Stage Continued type                    value
##   <fct>    <int> <int>     <int> <fct>                   <dbl>
## 1 1           11     1         1 Complete Response Start  10  
## 2 1           11     1         1 Partial Response Start    8  
## 3 1           11     1         1 Durable                  -0.5
## 4 1           11     1         1 Response End             NA  
## 5 2           23     4         1 Complete Response Start  NA  
## 6 2           23     4         1 Partial Response Start   15

你看这样用来映射形状的不同信息就都在type这一列了!

然后就可以添加形状了。

代码语言:javascript复制
p1 <- p   
  geom_point(data = df_long, aes(value, Patient, shape=type, color=type), size=5)

p1

这是这个图已经具有雏形了,但是还少一个箭头,由于R默认的形状(pch)中并没有箭头,所以一开始并没有把箭头表示的信息也加入到type这一列中。。

我们可以通过geom_segment()函数添加箭头信息。

代码语言:javascript复制
p2 <- p1   
  geom_segment(data = df |> dplyr::filter(Continued == 1), 
                        aes(x=Months 0.1, xend=Months 1.5, y=Patient, yend=Patient),
                        size = 2, 
                        arrow = arrow(length = unit(0.3,"cm"))
                        )

p2

plot of chunk unnamed-chunk-5

非常棒!其实到这里就已经基本成功了,该有的东西都有了,剩下的就是各种scale_xxxx/theme(xxx)进行修改颜色、形状、大小等细节问题。在ggplot2中一旦你掌握了规律,修改这些东西真的非常简单!

ggplot2修改坐标轴详细介绍 超详细教程:修改ggplot2图例

下面就是修改细节。

  • 调整大小
  • 修改图例形状
  • 修改图例标题
  • 修改横纵坐标
  • 修改整体背景
  • ......
代码语言:javascript复制
p3 <- p2   
  scale_shape_manual(values = c(16:18,15))  
  scale_color_manual(values = c("red","blue","grey","black")) 
  scale_x_continuous(limits = c(-1,32), breaks = -1:30,expand = c(0,0.6)) 
  labs(fill = "Disease Stage", shape = NULL, color = NULL) 
  theme_bw() 
  theme(panel.grid.minor=element_blank(),
        panel.grid.major=element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        legend.position = c(0.9,0.3)
        )

p3

plot of chunk unnamed-chunk-6

这样一幅泳道图就画好了!是不是很简单呢?

画图1分钟,准备数据10分钟!

难的还是准备符合要求的数据,这其中长款数据转换就是必备的技能!以后还会分享一些中药数据挖掘方面的内容,长款数据转换将会是其中的核心技能~

最后给大家看看怎么用Excel画泳道图:https://peltiertech.com/swimmer-plots-excel/

0 人点赞