packageVersion("vtree")
## [1] '4.0.0'
library(vtree)

vtree is a great way to make CONSORT-style diagrams. Not only does vtree produce a CONSORT-style figure, it calculates the numbers in the figure. This ensures accuracy and reproducibility.

Note that vtree cannot match the exact format of the CONSORT diagram, so the final version may need to transferred to the CONSORT format.

Data frame

Let’s define the following variables

rand Logical: Was this patient randomized?
exc1 Logical: Reason not randomized (#1).
exc2 Logical: Reason not randomized (#2).
oth1 Logical: Other reason not randomized.
group Character: “A” or “B”
recv Logical: Received allocated intervention?
not1 Logical: Reason allocated intervention not received (#1)
not2 Logical: Reason allocated intervention not received (#2)
fu Logical: Was this patient followed up?
lost Logical: If not followed up, was it because lost to follow up?
disc Logical: If not followed up, was it because discontinued intervention?
exca Logical: Excluded from analysis?
e1 Logical: Reason excluded from analysis (#1).
e2 Logical: Reason excluded from analysis (#2).

Now let’s build a data frame with these variables:

df <- build.data.frame(
  c(  "rand","exc1","exc2","oth1", "group","recv","not1","not2","fu",  "lost","disc","exca","e1","e2"),
  list(T,    F,     F,     F,      "A",     T,    F,     F,     T,     F,     F,     F,     NA,  NA,  100),
  list(T,    F,     F,     F,      "B",     T,    F,     F,     T,     F,     F,     F,     NA,  NA,  100),
  list(T,    F,     F,     F,      "A",     T,    F,     F,     T,     F,     F,     T,     T,   F,   14),
  list(T,    F,     F,     F,      "B",     T,    F,     F,     T,     F,     F,     T,     F,   T,   27),
  list(T,    F,     F,     F,      "A",     T,    F,     F,     T,     F,     F,     T,     F,   T,   3),
  list(T,    F,     F,     F,      "B",     T,    F,     F,     T,     F,     F,     T,     T,   F,   8),
  list(T,    F,     F,     F,      "A",     T,    F,     F,     T,     T,     F,     F,     NA,  NA,  10),
  list(T,    F,     F,     F,      "B",     T,    F,     F,     T,     T,     F,     F,     NA,  NA,  20),
  list(T,    F,     F,     F,      "A",     T,    F,     F,     F,     T,     F,     F,     NA,  NA,  10),
  list(T,    F,     F,     F,      "B",     T,    F,     F,     F,     T,     F,     F,     NA,  NA,  20),
  list(T,    F,     F,     F,      "A",     T,    F,     F,     F,     F,     T,     F,     NA,  NA,  3),
  list(T,    F,     F,     F,      "B",     T,    F,     F,     F,     F,     T,     F,     NA,  NA,  2),
  list(T,    F,     F,     F,      "A",     F,    T,     F,     NA,    NA,    NA,    NA,    NA,  NA,  80),
  list(T,    F,     F,     F,      "B",     F,    T,     F,     NA,    NA,    NA,    NA,    NA,  NA,  70),
  list(T,    F,     F,     F,      "A",     F,    F,     T,     NA,    NA,    NA,    NA,    NA,  NA,  80),
  list(T,    F,     F,     F,      "B",     F,    F,     T,     NA,    NA,    NA,    NA,    NA,  NA,  70),
  list(F,    T,     F,     F,      NA,      NA,   NA,    NA,    NA,    NA,    NA,    NA,    NA,  NA,  188),
  list(F,    F,     T,     F,      NA,      NA,   NA,    NA,    NA,    NA,    NA,    NA,    NA,  NA,  213))

CONSORT-style diagram

vtree(df,"rand group recv fu exca",horiz=FALSE,
  title="Assessed for eligibility",
  labelnode=list(
    rand=c("Randomized"=TRUE,"Excluded"=FALSE),
    recv=c("Received\nallocated intervention"=TRUE,"Did not receive\nallocated intervention"=FALSE),
    fu=c("Followed up"=TRUE,"Not followed up"=FALSE),
    exca=c("Excluded from analysis"=TRUE,"Analyzed"=FALSE)),
  follow=list(rand=TRUE,recv=TRUE,fu=TRUE,exca=FALSE),
  summary=c(
    "exc1 \nExclusion reason 1: %sum%%var=rand%%node=FALSE%",
    "exc2 \nExclusion reason 2: %sum%%var=rand%%node=FALSE%",
    "not1 \nReason 1: %sum%%var=recv%%node=FALSE%",
    "not2 \nReason 2: %sum%%var=recv%%node=FALSE%",
    "lost \nLost to follow-up: %sum%%var=fu%%node=FALSE%",
    "disc \nDiscontinued intervention: %sum%%var=fu%%node=FALSE%",
    "e1 \nReason 1: %sum%%var=exca%%node=TRUE%",
    "e2 \nReason 2: %sum%%var=exca%%node=TRUE%"),
  fillcolor="white",splitwidth=Inf,showvarnames=FALSE,showpct=FALSE,imagewidth="10in")

Notes

Study flow variables

The CONSORT diagram is a vertical tree, so we specify horiz=FALSE. The diagram starts with a node showing all patients assessed for eligibility. Specifying title="Assessed for eligibility" labels this node accordingly. The variables that define the tree are, in sequence, rand (was the patient randomized?), group (what group was the patient randomized to?), fu (was the patient followed up?), and exca (was the patient excluded from analysis?).

Labeling nodes

Node labels are specified using the labelnode parameter.

labelnode=list(
  rand=c("Randomized"=TRUE,"Excluded"=FALSE),
  recv=c("Received\nallocated intervention"=TRUE,"Did not receive\nallocated intervention"=FALSE),
  fu=c("Followed up"=TRUE,"Not followed up"=FALSE),
  exca=c("Excluded from analysis"=TRUE,"Analyzed"=FALSE))

Pruning

The CONSORT diagram tracks patients from their assessment for eligibility, all the way through to their inclusion in the analysis. Other paths are pruned. For example, patients who are not randomized are not followed further. The pruning is specified using the follow parameter:

follow=list(rand=TRUE,recv=TRUE,fu=TRUE,exca=FALSE)

Reasons for exclusion

The summary parameter is used to show reasons for exclusion, etc.:

summary=c(
    "exc1 \nExclusion reason 1: %sum%%var=rand%%node=FALSE%",
    "exc2 \nExclusion reason 2: %sum%%var=rand%%node=FALSE%",
    "not1 \nReason 1: %sum%%var=recv%%node=FALSE%",
    "not2 \nReason 2: %sum%%var=recv%%node=FALSE%",
    "lost \nLost to follow-up: %sum%%var=fu%%node=FALSE%",
    "disc \nDiscontinued intervention: %sum%%var=fu%%node=FALSE%",
    "e1 \nReason 1: %sum%%var=exca%%node=TRUE%",
    "e2 \nReason 2: %sum%%var=exca%%node=TRUE%")

The %sum% code indicates that the total number of TRUE values should be tallied. The %var% and %node% codes are used to indicate which nodes the summaries should appear in.

Additional settings

A few other settings are used to fine-tune the display:

fillcolor="white",splitwidth=Inf,showvarnames=FALSE,showpct=FALSE,imagewidth="10in")

Specifying fillcolor="white" is used to remove the default vtree colors; splitwidth=Inf turns off line-splitting; showvarnames=FALSE suppresses variable names; showpct=FALSE suppresses percentages (which are not part of the standard CONSORT diagram); and imagewidth=10in specifies the size of the image.