R生成三线表

时间:2022-11-18 17:51:36


主要基于table1 或tableone 包

table1包

测试数据生成

data=data.frame(
  性别=sample(c("男","女"), 1000,replace=T),
  年龄=round(rnorm(1000,50, 15)),
  民族= sample(c("汉族","壮族","其他"),1000,replace=T),
  身高= round(rnorm(1000,170, 5)),
  体重= round(rnorm(1000,75, 5)),
  收缩压= round(rnorm(1000,130, 15)),
  舒张压= round(rnorm(1000,90, 5)),
  身体状况= sample(c("优","中","差"), 1000,replace=T),
  高血压= sample(c("是","否"), 1000,replace=T),
  吸烟= sample(c("是","否"), 1000,replace=T),
  喝酒= sample(c("是","否"), 1000,replace=T)
)
head(data)

#运行内容
  性别 年龄 民族 身高 体重 收缩压 舒张压 身体状况 高血压 吸烟 喝酒
165 壮族  176   67    149     82       差     否   否   否
284 其他  177   73    137     92       差     是   是   是
375 其他  168   82    111     90       优     是   是   否
467 其他  171   76    152     93       差     是   是   否
567 壮族  172   73    118     83       优     否   否   是
644 壮族  168   82    141     83       优     是   否   是

制作三线表

基本三线表, 分类变量默认以 例数(占比%),连续变量以均数(标准差)或者中位数[最小、最大]表示

pacman::p_load(table1) #加载table1包

# ~ 后面接需要统计描述的列,| 表示分组
# 按是否患有高血压分组统计 性别、年龄、民族、身高情况
table1(~性别+年龄+民族+身高|高血压,data = data)

R生成三线表

考虑统计检验(卡方检验、t检验)

#———————————————————————————————————————————— 定义检验函数
# 这两个主要是实现卡方检验和t检验,若是需要用到非参数检验、方差分析需要自己定义
pvalue <- function(x, ...) {
  y <- unlist(x)
  g <- factor(rep(1:length(x), times=sapply(x, length)))

  if (is.numeric(y)) {
    # 数值型数据用t-test(两组比较)
    p <- t.test(y ~ g)$p.value                          
     } else {
    # 因子型数据用卡方
    p <- chisq.test(xtabs(~y+ g))$p.value                
     }
  c("", sub("<", "&lt;", format.pval(p, digits=3, eps=0.001)))
  
}

statistic <- function(x, ...) {
  y <- unlist(x)
  g <- factor(rep(1:length(x), times=sapply(x, length)))

  if (is.numeric(y)) {
   
   statistic <- t.test(y ~ g)$statistic
  } else {
   
  statistic <- chisq.test(xtabs(~y+ g))$statistic
      }
  c("",round(statistic,3))
}

#———————————————————————————————————————————— 三线表
# 输出带有统计检验的三线表
# 分别比较是否患有高血压两组之间所有特征的差异~
table1(~.|高血压,data = data, extra.col=list( 'statistic'=statistic,'P-value'=pvalue), overall=F)

R生成三线表
table1输出的结果格式是html格式的,可用浏览器打开,然后复制到word或者excel中。也直接导出保存为csv格式,导出时格式可能略微有点不同。

out=table1(~.|高血压,data = data, extra.col=list( 'statistic'=statistic,'P-value'=pvalue), overall=F)
write.csv(out, "d:/out.csv",row.names = F)

Tableone包

加载包 探索数据类型

pacman::p_load(tableone)#1.加载R包
rm(list = ls()) #2.清理运行环境
str(data)   #3.查看数据数据性质
names(data) #4.提取变量的名字

#运行内容
'data.frame':	1000 obs. of  11 variables:
 $ 性别    : chr  "女" "女" "男" "男" ...
 $ 年龄    : num  65 84 75 67 67 44 50 64 44 47 ...
 $ 民族    : chr  "壮族" "其他" "其他" "其他" ...
 $ 身高    : num  176 177 168 171 172 168 169 165 164 163 ...
 $ 体重    : num  67 73 82 76 73 82 82 79 69 83 ...
 $ 收缩压  : num  149 137 111 152 118 141 131 118 123 135 ...
 $ 舒张压  : num  82 92 90 93 83 83 90 91 91 91 ...
 $ 身体状况: chr  "差" "差" "优" "差" ...
 $ 高血压  : chr  "否" "是" "是" "是" ...
 $ 吸烟    : chr  "否" "是" "是" "是" ...
 $ 喝酒    : chr  "否" "是" "否" "否" ...
 > names(data) #4.提取变量的名字
 [1] "性别"     "年龄"     "民族"     "身高"     "体重"     "收缩压"   "舒张压"   "身体状况" "高血压"   "吸烟"     "喝酒" 

数据整理分类

myVars的()中输入想要在Table 1出现的变量

myVars <- c("性别","年龄","民族","身高", 
            "体重","收缩压", "舒张压","身体状况","高血压", 
            "吸烟","喝酒") 

catVars的()内指明上述中哪些是分类变量

catVars <- c("性别","民族","身体状况","高血压", 
              "吸烟","喝酒") 

指定非正态分布连续变量变量

 nonvar <- c("收缩压","舒张压")  #此为举例

假如有T<5变量应使用Fisher精确检验,本文数量大,无需Fisher精确检验

 exactvars <- c("a", "b")  #此为举例

catDigits = 2, contDigits = 3, pDigits = 4,修改连续变量小数位数为2位,分类变量百分比位数为3位,调整小数位数为4位;

构建Table函数

 table <- CreateTableOne(vars = myVars, #条件1
                       factorVars = catVars,#条件2
                       strata = "高血压", #条件4 用于分为两个类别
                        data = data, #原始数据
                     addOverall = TRUE  );table#条件6加入overall
  
 table1<- print(table, #构建的table函数(带条件1.2.3)
                 nonnormal = nonvar,#条件4
                 #exact = exactvars,#条件5
                 catDigits = 2,contDigits = 3,pDigits = 4, #附加条件

                 showAllLevels=TRUE, #显示所有变量
                 quote = FALSE, # 不显示引号
                 noSpaces = TRUE, # #删除用于对齐的空格
                 printToggle = TRUE) #展示输出结果  
                 
 write.csv(table1, "E:/Rworkplace//table1.csv",row.names = F)                   

Tableone函数细节

table <- CreateTableOne(
  vars, #指定哪些变量是Table 1需要汇总的变量
  strata,#指定进行分类的变量,不写则只出Overall列
  data,# 变量的数据集名称
  factorVars,#指定哪些变量为分类变量,指定的变量应是vars参数中的变量
  includeNA = FALSE,#为TRUE则将缺失值作为因子处理,仅对分类变量有效
  test = TRUE,#默认为TRUE,当有2个或多个组时,自动进行组间比较
  testApprox = chisq.test,#默认卡方检验
  argsApprox = list(correct = TRUE),# 进行连续校正的chisq.test
  testExact = fisher.test,#进行fisher精确检验
  argsExact = list(workspace = 2 * 10^5),# 指定fisher.test分配的内存空间
  testNormal = oneway.test, # 连续变量为正态分布进行的检验,默认为oneway.test,两组时相当于t检验
  argsNormal = list(var.equal = TRUE), # 假设为等方差分析
  testNonNormal = kruskal.test,# 默认为Kruskal-Wallis秩和检验
  argsNonNormal = list(NULL),#传递给testNonNormal中指定的函数的参数的命名列表
  smd = TRUE,#如果为TRUE(如默认值)并且有两个以上的组,则将计算所有成对比较的标准化均值差。
  addOverall = FALSE#仅在分组时使用)将整个列添加到表中。Smd和p值计算仅使用分层的列阵进行。
);table

table1<- print(
  x, #CreateTableOne()的 <- 前的名字(x=table)
  catDigits = 1, #连续变量小数位1位
  contDigits = 2,#分类变量保留2位
  pDigits = 3,#p值保留3位
  quote = FALSE,#默认值为FALSE。如果为TRUE
                #,则包括行名和列名在内的所有内容都用引号引起来,以便您可以轻松地将其复制到Excel。
  missing = FALSE,#是否显示丢失的数据信息
  explain = TRUE,#显示百分比时是否在变量名称中添加解释,即(%)添加到变量名称中。
  printToggle = TRUE,#如果为FALSE,则不输出
  test = TRUE,#是否显示p值。默认为TRUE。
  smd = FALSE,#是否显示标准化均值差异。默认为FALSE。如果存在多个对比,则显示所有可能的标准化均值差的平均值。
  noSpaces = FALSE,#是否删除为对齐而添加的空格。
  padColnames = FALSE,#是否用空格填充列名以居中对齐。默认值为FALSE。如果noSpaces = TRUE,则不进行
  varLabels = FALSE,#是否用从labelled :: var_label()函数获得的变量标签替换变量名。
  format = c("fp", "f", "p", "pf")[1],#默认值为“ fp”频率(百分比)。您也可以选择仅“ f”频率,“仅p”百分比和“ pf”百分比(频率)。
  showAllLevels = FALSE,#是否显示所有级别。
  cramVars = NULL,#字符向量,用于指定两个级别的分类变量,对于这两个级别的变量,应在一行中显示两个级别。
  dropEqual = FALSE,#是否删除“ =第二级名称”描述,指示为两级分类变量显示哪个级别。
  exact = NULL,#字符向量,用于指定p值应为精确测试值的变量。
  nonnormal = NULL,#字符向量,用于指定p值应为非参数检验的变量的变量。
  minMax = FALSE#对于非正态变量,是否使用[min,max]而不是[p25,p75]。默认值为FALSE。
)

相比之下 table1包输出的html格式的表格更为简洁 好看

参考两篇公众号文章:
1.你的时间应该用在更重要的事情上–table1
2.R语言|4. 轻松绘制临床基线表Table 1