La tabla 1 es una tabla que presenta estadística descriptiva de las variables principales en un estudio en artículos científicos, sobre todo de revistas biomédicas y usualmente es la primera tabla del artículo puesto que presenta información en la línea base del estudio. Algunos paquetes para R están dedicados o tienen comandos para construir esta tabla 1. En esta sesión usaremos el paquete tableone para crear una tabla como esta.


Librerías

library(tableone)
library(tidyverse)

Consulte la viñeta del paquete tableone aquí.


Datos

Datos simulados

Descargue un archivo con datos simulados aquí, e importe los datos con el siguiente código:

dat <- read.csv(file = "dats_6var.csv", na.strings = "")
str(dat)
'data.frame':   200 obs. of  6 variables:
 $ V1: int  35 40 17 53 43 41 25 36 34 45 ...
 $ V2: int  8 NA 20 NA 36 33 18 21 27 36 ...
 $ V3: int  0 1 0 0 1 1 0 0 0 1 ...
 $ V4: chr  "B" "B" "A" "B" ...
 $ V5: chr  "Z2" "Z4" "Z4" "Z2" ...
 $ V6: int  118 71 110 116 85 112 100 89 107 104 ...


Peso al nacimiento

Usaremos los datos del peso al nacimiento que tiene el paquete MASS. Cargue estos datos de la siguiente forma:

bw <- MASS::birthwt  # se crea una copia de los datos
str(bw)
'data.frame':   189 obs. of  10 variables:
 $ low  : int  0 0 0 0 0 0 0 0 0 0 ...
 $ age  : int  19 33 20 21 18 21 22 17 29 26 ...
 $ lwt  : int  182 155 105 108 107 124 118 103 123 113 ...
 $ race : int  2 3 1 1 1 3 1 3 1 1 ...
 $ smoke: int  0 0 1 1 1 0 0 0 1 1 ...
 $ ptl  : int  0 0 0 0 0 0 0 0 0 0 ...
 $ ht   : int  0 0 0 0 0 0 0 0 0 0 ...
 $ ui   : int  1 0 0 1 1 0 0 0 0 0 ...
 $ ftv  : int  0 3 1 2 0 0 1 1 1 0 ...
 $ bwt  : int  2523 2551 2557 2594 2600 2622 2637 2637 2663 2665 ...

Consulte la ayuda de la tabla escribiendo en consola: ?MASS::birthwt


Uso básico de tableone

El comando CreateTableOne es el caballo de batalla del paquete tableone. Este comando crea la clásica tabla 1 con estadísticos de resumen para cada tipo de variable.

El uso más simple es cuando utilizamos el argumento data para poner el data.frame con los datos. Aquí un ejemplo:

# Usando CreateTableOne:
CreateTableOne(data = dat)
                
                 Overall       
  n                 200        
  V1 (mean (SD))  39.33 (10.55)
  V2 (mean (SD))  28.20 (10.76)
  V3 (mean (SD))   0.36 (0.48) 
  V4 (%)                       
     A               38 (20.4) 
     B              110 (59.1) 
     C               38 (20.4) 
  V5 (%)                       
     Z1              18 ( 9.0) 
     Z2              80 (40.0) 
     Z3              53 (26.5) 
     Z4              49 (24.5) 
  V6 (mean (SD)) 100.03 (20.99)

Observe que el comando reconoce entre variables de texto (categóricas) y variables numéricas, y hace un resumen adecuado para cada tipo. Encuentre más sobre el tipo de variables en las siguientes secciones.


Seleccionando variables

También podemos controlar cuales variables (y en que orden) serán analizadas:

# Seleccionando las variables que seran analizadas 
CreateTableOne(data = dat, vars = c("V4", "V2", "V1"))
                
                 Overall      
  n                200        
  V4 (%)                      
     A              38 (20.4) 
     B             110 (59.1) 
     C              38 (20.4) 
  V2 (mean (SD)) 28.20 (10.76)
  V1 (mean (SD)) 39.33 (10.55)


Tipos de variables

Es frecuente que las variables categóricas sean codificadas con números enteros. Para el caso la tabla dat, la variables V3 es un ejemplo de esto. Para declarar estas variables como categóricas al comando CreateTableOne hacemos lo siguiente:

# Declarando variables tipo "factor" o "categoricas"
CreateTableOne(data = dat, factorVars = c("V3"))
                
                 Overall       
  n                 200        
  V1 (mean (SD))  39.33 (10.55)
  V2 (mean (SD))  28.20 (10.76)
  V3 = 1 (%)         73 (36.5) 
  V4 (%)                       
     A               38 (20.4) 
     B              110 (59.1) 
     C               38 (20.4) 
  V5 (%)                       
     Z1              18 ( 9.0) 
     Z2              80 (40.0) 
     Z3              53 (26.5) 
     Z4              49 (24.5) 
  V6 (mean (SD)) 100.03 (20.99)

También puede convertir a factor las variables deseadas usted mismo y en ese caso no tendrá que usar el argumento factorVars.


Método print

Los objetos creados con el comando createTableOne pueden ser pasados por el comando print para controlar varios aspectos en la impresión de la tabla. Se recomienda revisar la ayuda para consultar todas las opciones (?tableone::print.TableOne).

Por ejemplo, para las variables dicotómicas, por defecto sólo se muestra la frecuencia del 2do. nivel o categoría, sin embargo, se pueden habilitar los dos niveles pasando la impresión de la tabla por el comando print:

# Declarando variables tipo "factor" o "categoricas"
CreateTableOne(data = dat, factorVars = c("V3")) %>%
  print(showAllLevels = T, contDigits = 3, catDigits = 2, missing = T,
        formatOptions = list(decimal.mark = ","))
                
                 level Overall          Missing
  n                        200                 
  V1 (mean (SD))        39,330 (10,548)  0,0   
  V2 (mean (SD))        28,198 (10,762) 11,5   
  V3 (%)         0         127 (63,50)   0,0   
                 1          73 (36,50)         
  V4 (%)         A          38 (20,43)   7,0   
                 B         110 (59,14)         
                 C          38 (20,43)         
  V5 (%)         Z1         18 ( 9,00)   0,0   
                 Z2         80 (40,00)         
                 Z3         53 (26,50)         
                 Z4         49 (24,50)         
  V6 (mean (SD))       100,030 (20,985)  0,0   


En el último ejemplo también controlamos con el método print la cantidad de decimales, el separador decimal y si se presentan porcentajes de valores perdidos por variable. Por ejemplo, la variable V4 tiene un 7% de valores perdidos:

sum(is.na(dat$V4))        # cantidad de valores perdidos en V4
[1] 14
mean(is.na(dat$V4))*100   # pct de valores perdidos en V4
[1] 7


Ejercicio: Utilice los datos del peso al nacimiento (bw) y los comandos CreateTableOne y print para reproducir la siguiente tabla:

                 
                  level Overall          
  n                          189         
  age (mean (SD))          23.24 (5.30)  
  ftv (mean (SD))           0.79 (1.06)  
  bwt (mean (SD))       2,944.59 (729.21)
  race (%)        1           96 (50.8)  
                  2           26 (13.8)  
                  3           67 (35.4)  
  smoke (%)       0          115 (60.8)  
                  1           74 (39.2)  
  low (%)         0          130 (68.8)  
                  1           59 (31.2)  


Código solución

CreateTableOne(
  data = bw, 
  vars = c("age", "ftv", "bwt", "race", "smoke", "low"),
  factorVars = c("race", "smoke", "low")) %>%
  print(showAllLevels = TRUE, formatOptions = list(big.mark = ","))



Modo summary

El comando summary recibe el objeto de CreateTableOne e imprime un resultado con más estadísticos:

CreateTableOne(data = dat) %>%
  summary()

     ### Summary of continuous variables ###

strata: Overall
     n miss p.miss  mean   sd median p25 p75 min max skew kurt
V1 200    0      0  39.3 10.5     40  33  46   9  62 -0.3 -0.2
V2 200   23     12  28.2 10.8     29  20  36   1  50 -0.2 -0.6
V3 200    0      0   0.4  0.5      0   0   1   0   1  0.6 -1.7
V6 200    0      0 100.0 21.0    101  86 116  43 156 -0.2 -0.2

=======================================================================================

     ### Summary of categorical variables ### 

strata: Overall
 var   n miss p.miss level freq percent cum.percent
  V4 200   14    7.0     A   38    20.4        20.4
                         B  110    59.1        79.6
                         C   38    20.4       100.0
                                                   
  V5 200    0    0.0    Z1   18     9.0         9.0
                        Z2   80    40.0        49.0
                        Z3   53    26.5        75.5
                        Z4   49    24.5       100.0
                                                   


Variables no normales

El argumento nonnormal del comando print permite identificar aquellas variables para las cuales se quiere resumir usando los tres cuartiles. Observe el siguiente código:

CreateTableOne(
  data = dat, vars = c("V1", "V2", "V6", "V3"), factorVars = "V3") %>%
  print(showAllLevels = TRUE, nonnormal = c("V2", "V6" ), missing = T )
                   
                    level Overall                Missing
  n                          200                        
  V1 (mean (SD))           39.33 (10.55)          0.0   
  V2 (median [IQR])        29.00 [20.00, 36.00]  11.5   
  V6 (median [IQR])       101.00 [86.00, 116.00]  0.0   
  V3 (%)            0        127 (63.5)           0.0   
                    1         73 (36.5)                 


Ejercicio: Utilice los datos del peso al nacimiento (bw) y los comandos CreateTableOne y print para reproducir la siguiente tabla:

                    
                     level Overall                
  n                             189               
  age (median [IQR])          23.00 [19.00, 26.00]
  ftv (median [IQR])           0.00 [0.00, 1.00]  
  bwt (mean (SD))          2,944.59 (729.21)      
  race (%)           1           96 (50.8)        
                     2           26 (13.8)        
                     3           67 (35.4)        


Código solución

CreateTableOne(
  data = bw, 
  vars = c("age", "ftv", "bwt", "race"),
  factorVars = "race") %>%
  print(showAllLevels = TRUE, nonnormal = c("age","ftv"),
        formatOptions = list(big.mark = ","))



Resumen por grupo (strata)

El argumento strata dentro de CreateTableOne permite específicar variables que formarían grupos. De usarse, todos los cálculos se realizan por grupo.

CreateTableOne(
  data = dat,
  vars = c("V1", "V2", "V3"),
  strata = "V4",
  factorVars = "V3"
) %>%
  print(showAllLevels = T)
                Stratified by V4
                 level A             B             C             p      test
  n                       38           110            38                    
  V1 (mean (SD))       39.92 (9.10)  38.74 (10.55) 38.95 (12.33)  0.839     
  V2 (mean (SD))       28.00 (10.04) 27.79 (10.92) 28.97 (11.23)  0.855     
  V3 (%)         0        23 (60.5)     74 (67.3)     22 (57.9)   0.516     
                 1        15 (39.5)     36 (32.7)     16 (42.1)             


Ejercicio: Utilice los datos del peso al nacimiento (bw) y los comandos CreateTableOne y print para reproducir la siguiente tabla:

                 Stratified by smoke
                  level 0                 1                 p      test
  n                          115                74                     
  age (mean (SD))          23.43 (5.47)      22.95 (5.05)    0.545     
  bwt (mean (SD))       3,055.70 (752.66) 2,771.92 (659.63)  0.009     
  low (%)         0           86 (74.8)         44 (59.5)    0.040     
                  1           29 (25.2)         30 (40.5)              


Código solución

CreateTableOne(
  data = bw, 
  vars = c("age", "bwt",  "low"),
  factorVars = c("smoke", "low"),
  strata = "smoke") %>%
  print(showAllLevels = TRUE,
        formatOptions = list(big.mark = ","))



Exportando la tabla

El autor del paquete tableone propone exportar la tabla a un archivo plano, p.e. un csv, para que sea cargada a Excel, poder editarse en ese programa para luego llevarla a Word. La exportación de la tabla a un archivo csv se puede facilitar con el comando print.

# Se crea y se guarda la tabla
tab <- CreateTableOne(
  data = bw, 
  vars = c("age", "bwt",  "low"),
  factorVars = c("smoke", "low"),
  strata = "smoke")

# Se imprime y se guarda
tab_imp <- print(tab, showAllLevels = TRUE, quote = TRUE, noSpaces = TRUE )
                   "Stratified by smoke"
 ""                 "level" "0"                "1"                "p"    
  "n"               ""      "115"              "74"               ""     
  "age (mean (SD))" ""      "23.43 (5.47)"     "22.95 (5.05)"     "0.545"
  "bwt (mean (SD))" ""      "3055.70 (752.66)" "2771.92 (659.63)" "0.009"
  "low (%)"         "0"     "86 (74.8)"        "44 (59.5)"        "0.040"
  ""                "1"     "29 (25.2)"        "30 (40.5)"        ""     
                   "Stratified by smoke"
 ""                 "test"
  "n"               ""    
  "age (mean (SD))" ""    
  "bwt (mean (SD))" ""    
  "low (%)"         ""    
  ""                ""    
# Se exporta como un archivo csv:
write.csv(tab_imp, file = "tab_imp.csv", quote = F)


El archivo tab_imp.csv se puede pegar en Excel y utilizar la opción de Texto a columnas de Excel para separar las columnas de acuerdo a una “coma” y continuar su edición en Excel.


Otros paquetes y comandos similares

Además de tableone, otros paquetes tienen comandos enfocados a producir resultados de estadística descriptiva de forma masiva para todas las columnas de una tabla con más o menos opciones de personalización. Aquí una lista de ellos.

Paquete Comandos Viñeta
skimr skimr Aquí
summarytools freq; ctable; descr; etc. Aquí
table1 table1 Aquí
furniture table1 Aquí
Hmisc describe
psych describe; describeBy Aquí
arsenal tableby Aquí
compareGroups compareGroups Aquí


Finalmente, algunos blogs en internet realizan comparaciones de este tipo de paquetes: