临床研究中常需要绘制两组或多组患者(如非AKI组和AKI组)的基线特征表。
下图就是临床中常见的基线特征表,从下图我们可以看出,第1列为两组患者需要比较的变量;第2列为所有患者的基线特征,这一列在论文中可有可不有;第3列和第4列分别为非AKI组和AKI组的基线特征;第5列比较两组基线特征有没有统计学差异。

在上图中,分类变量表示为计数(百分比),连续变量若呈正态分布表示为均值±标准差,呈非正态分布表示为中位数和四分位数。
那么在R中怎么快速绘制绘制临床论文中的基线特征表1?
可以使用tableone包来绘制。
1. 绘制基线表前的准备
安装需要用到的R包
install.packages("tableone")
install.packages("survival")
加载数据集和包
library(tableone)
library(survival)
data(colon)
View(colon)
本次用来演示的数据集为survival包的colon数据。
2. 单组汇总数据
CreateTableOne(data = colon)

从上面可以看出,colon数据集中共有1858例患者,但由于没有将分类变量转化为因子,所以分类变量显示的也是均值+标准差。
3. 分类变量处理
在数据处理中,大多数分类变量是采用数字编码,二分类变量常表示为0和1,多分类变量表示为0、1和2等。
有两种方法可以将分类变量转化为因子:一是先在数据集中将分类变量转化为因子,然后再使用tableone包进行汇总,二是在tableone包中直接指定哪些变量属于因子(使用factorVars参数进行转换),然后在进行汇总。
dput(names(colon))
输出变量名称:
c("id", "study", "rx", "sex", "age",
"obstruct", "perfor", "adhere",
"nodes", "status", "differ", "extent",
"surg", "node4", "time", "etype")
从数据集介绍中,我们知道 "rx"、"sex"、"obstruct"、"perfor"、"adhere"、"status"、"differ"、"extent"、"surg"、"node4"、"etype"都是分类变量。
指定基线表中需要比较的变量
排除一些不需要比较的变量,如id、study之类的变量
myVars <- c("rx", "sex", "age", "obstruct", "perfor",
"adhere", "nodes", "status", "differ",
"extent", "surg", "node4", "time", "etype")
指定基线表中哪些变量是分类变量
catVars <- c("rx", "sex","obstruct", "perfor", "adhere", "status",
"differ","extent", "surg", "node4","etype")
4. 优化单组汇总
tab2 <- CreateTableOne(vars = myVars,
data = colon,
factorVars = catVars);tab2

从上图可以看出,在指定基线表的汇总变量、分类变量,排除掉无关变量后,基线表的结果显示比前面好很多。
二分类变量显示为第2水平的计数(百分比),比如分类变量为0和1,则显示1的结果;如果为多分类变量,则显示出所有水平数据。
如果在表中要显示所有水平的数据,则输入:
print(tab2, showAllLevels = TRUE)
注意:分类变量的百分比数据是在排除缺失值后计算的。
5. 显示基线表所有数据信息
如果需要显示所有数据信息,包括分类变量和连续变量的缺失值信息,对结果对象使用summary()函数,先输出连续变量数据信息,在输出分类变量数据信息。
summary(tab2)


6. 指定非正态分布变量
从前面的表中可以看到,连续变量都表示为均数+标准差,这是认为连续变量都呈正态分布。但是实际上有些数据呈非正态分布,需要用中位数(四分位数)表示。
假设数据集中"time"和"nodes"两个连续变量呈非正态分布。
nonvar <- c("time","nodes")
print(tab2, nonnormal = nonvar)

可以看出"time"和"nodes"这两个连续变量都用中位数(四分位数)表示了。
如果在print()函数中输入的是nonnormal = TRUE,则所有连续变量都按非正态分布进行分析。
7. 多组汇总数据
在前面,我们对数据集信息进行了单组汇总。但是通常,我们需要比较两组患者之间的基线特征,如比较AKI组和非AKI组。
在本数据集中,我们需要对"status"生存状态(1为死亡,0为删失)进行分组汇总。
tab3 <- CreateTableOne(vars = myVars,
strata = "status",
data = colon,
factorVars = catVars); tab3

从图上我们可以看出,我们已经分组总结好了,并且在表右边已经自动进行了统计检验,输出了检验p值。
但是呈非正态分布的连续变量并没有输出中位数和四分位数,检验方法也需要调整。
别急,后面进行调整。
8. 统计检验
如上表所示,当进行两组或多组分层汇总时,两组或多组间比较的p值会自动随着基线表一起输出,如果p值很小,则显示为<0.001。
tableone默认的检验方法为:分类变量使用卡方检验(chisq.test(),连续性校正);连续变量使用方差分析(oneway.test(),假设等方差),两组间方差分析相当于t检验。
但是在基线表中,有些连续变量是非正态分布变量,有些分类变量中单元格期望值较小,这些变量的统计方法不能使用默认的统计方法。
kruskal.test()函数可以用于呈非正态分布的连续变量,fisher.test()可以指定分类变量进行fisher精确检验。在两组间比较时,kruskal.test()和wilcox.test()等效。
基线表的test列会显示哪些变量是使用非默认检验方法来计算p值。
假设"extent"变量需要使用fisher精确检验。
print(tab3,
nonnormal = nonvar,
exact = "extent")

9. 添加overall列
如最前面的举例所示,基线表中可以添加overall列,表示所有患者的特征。
在CreateTableOne()函数中使用addOverall = TRUE就可以添加overall列了。
tab4 <- CreateTableOne(vars = myVars,
strata = "status",
data = colon,
factorVars = catVars,
addOverall = TRUE)
print(tab4, nonnormal = nonvar, exact = "extent")

可以看到overall列添加成功了。
10. 输出基线特征表
到了这一步,R中基线特征表就基本绘制完成了。接下来就要将表格导出到Excel中进行调整,然后导入到Word中绘制三线表。
简单粗暴的方法:就是复制粘贴,使用quote = TRUE显示引号,使用noSpaces = TRUE删除用于在R控制台中对齐文本的空格,然后直接复制基线表整个内容并将其粘贴到Excel电子表格即可。
print(tab4,
nonnormal = nonvar,
exact = "extent",
quote = TRUE,
noSpaces = TRUE)

另一种方式:
如果您不喜欢复制和粘贴,则可以通过以下方式自动导出。
tab4Mat <- print(tab4, nonnormal = nonvar, exact = "extent",
quote = FALSE,
noSpaces = TRUE,
printToggle = FALSE)
write.csv(tab4Mat, file = "myTable.csv")
注意:quote参数选FALSE,noSpaces参数可选TRUE。

基本和前面的举例差不多了,在自己微调下数据就行。
11. 后续
仅输出分类变量
tab3$CatTable

仅输出连续变量
print(tab3$ContTable, nonnormal = nonvar)

12. CreateTableOne()函数
CreateTableOne()是创建基线特征表的函数,可以汇总所有基线变量信息(包括连续变量和分类变量),并可按一个变量或多个变量进行分层汇总,并进行统计检验。
CreateTableOne(vars, strata, data, factorVars,
includeNA = FALSE,
test = TRUE,
testApprox = chisq.test,
argsApprox = list(correct = TRUE),
testExact = fisher.test,
argsExact = list(workspace = 2 * 10^5),
testNormal = oneway.test,
argsNormal = list(var.equal = TRUE),
testNonNormal = kruskal.test,
argsNonNormal = list(NULL),
smd = TRUE, addOverall = FALSE)
函数参数解释说明
vars
strata
data
factorVars
includeNA = FALSE
test = TRUE
testApprox = chisq.test
argsApprox = list(correct = TRUE)
testExact = fisher.test
argsExact = list(workspace = 2*10^5)
testNormal = oneway.test
argsNormal = list(var.equal = TRUE)
testNonNormal = kruskal.test
argsNonNormal = list(NULL)
smd = TRUE
addOverall = FALSE
参考资料:tableone包帮助文件
End