临床、生信发文都需要的Table 1

基线表显示了研究中包含的研究对象的特征。根据研究设计,它们可能有特定目的,但通常它们显示所包含的人群是否符合研究的资格标准。它们还表明结果可以推广到哪些人群。在病例对照研究中,基线表可以确认成功匹配或表明组之间的差异。在随机对照试验 (RCT) 中,随机化过程旨在分配可能影响结果的组参与者特征;基线表将表明随机化是否导致成功平衡。在可行性研究中,基线表也可能表明哪些人群愿意参与研究设计。在对单个研究进行荟萃分析时,可能需要多个基线表,其中应为组合数据集以及每个单个研究提供特征,以便评估人群中的同质性

image

前言说了这么多,其实就是如上图所示(表来源于The Lancet Regional Health – Europe,https://doi.org/10.1016/j.lanepe.2021.100096),其中数据主要分为两大类,分类变量(例如性别)和连续变量(例如临床指标胆红素、血红蛋白......)

1. 问题

问题1: 这么多统计量,P值计算需要注意什么?
答: 一句话总结:
连续变量需要区分方差是否齐,是否为正态分布两组比较还是多组比较;
分类变量需要区分二分类变量(性别(男/女)****)还是多分类变量(血型(A、B、O、AB))。
根据不同的统计结果,就可以选择不同的统计方法了(t检验,方差分析,秩和检验,kruskal检验,卡方检验,fisher检验等等

问题2: 怎么选?你能帮帮我吗?
答: 一图搞定

image

问题3: 太复杂了,不仅得一个一个计算,还得考虑不同的算法,你还能帮帮我吗?
答: 这也就引出了今天的主角,自动生成Table 1的神器

2. 正文

tableone包是一个 R 包,它简化了“表1”的构建,即在生物医学研究论文中常见的患者基线特征表。这些包可以汇总一个表中混合的连续变量和分类变量。分类变量可以概括为计数和/或百分比。连续变量可以用“正态”方式(平均值和标准差)或“非正态”方式(中位数和四分位距)来概括

2.1 包的安装与加载

install.packages("tableone") #安装包
library("tableone") #载入包

2.2 数据介绍

数据主要来源于survival包中的pbc数据集,里边包含了患者的生存时间生存状态以及其他临床指标的一些数据,可以通过以下代码在R中加载,也可以后台回复Tableone获取这个数据

library(survival) # 需要安装
data(pbc)

2.3 最简单的用法

CreateTableOne(data = pbc)
#此处为结果,无需运行                      
Overall          
n                        418          
id (mean (SD))        209.50 (120.81) 
time (mean (SD))     1917.78 (1104.67)
status (mean (SD))      0.83 (0.96)   
trt (mean (SD))         1.49 (0.50)   
age (mean (SD))        50.74 (10.45)  
sex = f (%)              374 (89.5)   
ascites (mean (SD))     0.08 (0.27)   
hepato (mean (SD))      0.51 (0.50)   
spiders (mean (SD))     0.29 (0.45)   
edema (mean (SD))       0.10 (0.25)   
bili (mean (SD))        3.22 (4.41)   
chol (mean (SD))      369.51 (231.94) 
albumin (mean (SD))     3.50 (0.42)   
copper (mean (SD))     97.65 (85.61)  
alk.phos (mean (SD)) 1982.66 (2140.39)
ast (mean (SD))       122.56 (56.70)  
trig (mean (SD))      124.70 (65.15)  
platelet (mean (SD))  257.02 (98.33)  
protime (mean (SD))    10.73 (1.02)

但是,这还是和我们之前看见的表还是有差距的:

  1. 没有分组与P值
  2. 类似于status这种分类变量,它还是用均值(标准差)来表示的,这肯定不符合要求

因此需要找出分类变量和连续变量

2.4 分类变量的操作

大多数分类变量都是用数字编码的,所以我们要么必须将它们转换为数据集中的因子,要么使用 factorVars 参数即时转换它们。此外,最好通过 vars 参数指定要汇总的变量,并排除 ID 变量。什么是因子,其实就是分组,二分类就是2个因子,三分类就是3个因子

## 查看变量类型
dput(names(pbc))
## 此处为结果,无需运行
c("id", "time", "status", "trt", "age", "sex", "ascites", "hepato", 
  "spiders", "edema", "bili", "chol", "albumin", "copper", "alk.phos", 
  "ast", "trig", "platelet", "protime", "stage")

然后把分类变量挑出来

## 所有变量
myVars <- c("time", "status", "trt", "age", "sex", "ascites", "hepato",
            "spiders", "edema", "bili", "chol", "albumin", "copper", "alk.phos",
            "ast", "trig", "platelet", "protime", "stage")
## 分类变量
catVars <- c("status", "trt", "ascites", "hepato",
             "spiders", "edema", "stage")
## 创建Table one
tab2 <- CreateTableOne(vars = myVars, data = pbc, factorVars = catVars)
tab2
#此处为结果,无需运行                
Overall          
n                        418          
time (mean (SD))     1917.78 (1104.67)
status (%)                            
0                     232 (55.5)   
1                      25 ( 6.0)   
2                     161 (38.5)   
trt = 2 (%)              154 (49.4)   
age (mean (SD))        50.74 (10.45)  
sex = f (%)              374 (89.5)   
ascites = 1 (%)           24 ( 7.7)   
hepato = 1 (%)           160 (51.3)   
spiders = 1 (%)           90 (28.8)   
edema (%)                             
0                     354 (84.7)   
0.5                    44 (10.5)   
1                      20 ( 4.8)   
bili (mean (SD))        3.22 (4.41)   
chol (mean (SD))      369.51 (231.94) 
albumin (mean (SD))     3.50 (0.42)   
copper (mean (SD))     97.65 (85.61)  
alk.phos (mean (SD)) 1982.66 (2140.39)
ast (mean (SD))       122.56 (56.70)  
trig (mean (SD))      124.70 (65.15)  
platelet (mean (SD))  257.02 (98.33)  
protime (mean (SD))    10.73 (1.02)   
stage (%)                             
1                      21 ( 5.1)   
2                      92 (22.3)   
3                     155 (37.6)   
4                     144 (35.0)

这分组是正常了,但是还没有分组和P值,而且在文章中不同分类一般是单独一列的。

如果要显示所有级别,可以使用 print() 方法的 showAllLevels 参数

print(tab2, showAllLevels = TRUE, formatOptions = list(big.mark = ","))
# 此处为结果,无需运行             
level Overall            
n                               418           
time (mean (SD))           1,917.78 (1,104.67)
status (%)           0          232 (55.5)    
1           25 ( 6.0)    
2          161 (38.5)    
trt (%)              1          158 (50.6)    
2          154 (49.4)    
age (mean (SD))               50.74 (10.45)   
sex (%)              m           44 (10.5)    
f          374 (89.5)    
ascites (%)          0          288 (92.3)    
1           24 ( 7.7)    
hepato (%)           0          152 (48.7)    
1          160 (51.3)    
spiders (%)          0          222 (71.2)    
1           90 (28.8)    
edema (%)            0          354 (84.7)    
0.5         44 (10.5)    
1           20 ( 4.8)    
bili (mean (SD))               3.22 (4.41)    
chol (mean (SD))             369.51 (231.94)  
albumin (mean (SD))            3.50 (0.42)    
copper (mean (SD))            97.65 (85.61)   
alk.phos (mean (SD))       1,982.66 (2,140.39)
ast (mean (SD))              122.56 (56.70)   
trig (mean (SD))             124.70 (65.15)   
platelet (mean (SD))         257.02 (98.33)   
protime (mean (SD))           10.73 (1.02)    
stage (%)            1           21 ( 5.1)    
2           92 (22.3)    
3          155 (37.6)    
4          144 (35.0)

2.5 连续变量正态与非正态分布描述是不一样的

除了时间、年龄、白蛋白和血小板外,大多数连续变量看起来都高度偏斜(生物标志物通常以强正偏态分布)。一般来说,正态分布数据使用均值(标准差),偏态分布采用中位数(上四分位数,下四分位数)进行描述会获得同行评审的认可。因此,在 print() 方法中定义非正态分布的变量,即可完成。如果设置 nonnormal = TRUE,那么所有变量都以“非正态”的方式汇总

biomarkers <- c("bili","chol","copper","alk.phos","ast","trig","protime")

2.6 两组之间进行统计检验

就像例子所示,我们一般根据实验目的,将患者分组并逐组统计检验。这也很简单。按暴露类别(数据中为trt列)分组可能是最常见的方式。因此,代码如下,主要设定strata参数为"trt",分类参数为factorVars:

tab3 <- CreateTableOne(vars = myVars, strata = "trt" , data = pbc, factorVars = catVars)
# 此处为结果,无需运行
Stratified by trt
level 1                           2                           p      test   
n                                  158                         154                                  
time (mean (SD))              2,015.62 (1,094.12)         1,996.86 (1,155.93)          0.883        
status (%)              0           83 ( 52.5)                  85 ( 55.2)             0.894        
1           10 (  6.3)                   9 (  5.8)                          
2           65 ( 41.1)                  60 ( 39.0)                          
trt (%)                 1          158 (100.0)                   0 (  0.0)            <0.001        
2            0 (  0.0)                 154 (100.0)                          
age (mean (SD))                  51.42 (11.01)               48.58 (9.96)              0.018        
sex (%)                 m           21 ( 13.3)                  15 (  9.7)             0.421        
f          137 ( 86.7)                 139 ( 90.3)                          
ascites (%)             0          144 ( 91.1)                 144 ( 93.5)             0.567        
1           14 (  8.9)                  10 (  6.5)                          
hepato (%)              0           85 ( 53.8)                  67 ( 43.5)             0.088        
1           73 ( 46.2)                  87 ( 56.5)                          
spiders (%)             0          113 ( 71.5)                 109 ( 70.8)             0.985        
1           45 ( 28.5)                  45 ( 29.2)                          
edema (%)               0          132 ( 83.5)                 131 ( 85.1)             0.877        
0.5         16 ( 10.1)                  13 (  8.4)                          
1           10 (  6.3)                  10 (  6.5)                          
bili (median [IQR])               1.40 [0.80, 3.20]           1.30 [0.72, 3.60]        0.842 nonnorm
chol (median [IQR])             315.50 [247.75, 417.00]     303.50 [254.25, 377.00]    0.544 nonnorm
albumin (mean (SD))               3.52 (0.44)                 3.52 (0.40)              0.874        
copper (median [IQR])            73.00 [40.00, 121.00]       73.00 [43.00, 139.00]     0.717 nonnorm
alk.phos (median [IQR])       1,214.50 [840.75, 2,028.00] 1,283.00 [922.50, 1,949.75]  0.812 nonnorm
ast (median [IQR])              111.60 [76.73, 151.51]      117.40 [83.78, 151.90]     0.459 nonnorm
trig (median [IQR])             106.00 [84.50, 146.00]      113.00 [84.50, 155.00]     0.370 nonnorm
platelet (mean (SD))            258.75 (100.32)             265.20 (90.73)             0.555        
protime (median [IQR])           10.60 [10.03, 11.00]        10.60 [10.00, 11.40]      0.588 nonnorm
stage (%)               1           12 (  7.6)                   4 (  2.6)             0.201        
2           35 ( 22.2)                  32 ( 20.8)                          
3           56 ( 35.4)                  64 ( 41.6)                          
4           55 ( 34.8)                  54 ( 35.1)

如果需要显示标准均值差(SMD),仅需设置参数即可

print(tab3, nonnormal = biomarkers, exact = "stage", smd = TRUE)
# 结果略

但是,这些结果都是在R中,复制粘贴的话,操作不方便,而且还需要后期对齐,因此推荐输出为csv,代码如下:

tab3Mat <- print(tab3, nonnormal = biomarkers, exact = "stage", quote = FALSE, noSpaces = TRUE, printToggle = FALSE)
## 保存为csv格式文件
write.csv(tab3Mat, file = "myTable.csv")

2.7 简洁版

上面看着还挺复杂,其实实际使用的话仅需要这么几步

library(tableone)
library(survival)
data(pbc)
#设置所有变量
myVars <- c("time", "status", "trt", "age", "sex", "ascites", "hepato",
            "spiders", "edema", "bili", "chol", "albumin", "copper", "alk.phos",
            "ast", "trig", "platelet", "protime", "stage")
## 设置分类变量
catVars <- c("status", "trt", "ascites", "hepato",
             "spiders", "edema", "stage")
for (i in catVars) {
    pbc[,i]<-as.factor(pbc[,i])
}
## 设置偏态分布变量
biomarkers <- c("bili","chol","copper","alk.phos","ast","trig","protime")
tab3 <- CreateTableOne(vars = myVars, strata = "trt" , data = pbc, factorVars = catVars)
tab3Mat <- print(tab3, nonnormal = biomarkers, exact = "stage", quote = FALSE, noSpaces = TRUE, printToggle = FALSE)
## 保存为csv格式文件
write.csv(tab3Mat, file = "myTable.csv")

在Excel或者WPS中就可以优雅地打开了

image

最后一个常见问题,就是这个技能、代码是否有必要学习?

我认为其实就像过河一样,有的河一辈子就过一次,那么游过去就行了;而有的时候每隔几天就需要过一次河,那么为什么不花点时间造个桥,平平坦坦走过去呢

感谢观看,如果有用还请点赞,收藏,转发

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

推荐阅读更多精彩内容