Index

1. Introduction

2. The {flowchart} package

3. Hands-on examples

4. Conclusions

Introduction

Flowcharts

  • In any study, a participant flowchart serves as a visual representation of the steps and decisions in the study workflow.

  • Usually different decisions are made from the initial cohort of eligible or screened subjects until a final number of these subjects are considered to be included in the analyses.

  • It is essential that the steps and numbers are clearly defined and that the process is transparent in order to ensure the reproducibility of the study and the quality of the reporting.

  • In clinical research, the CONSORT, STROBE and ICH guidelines strongly recommend the use of flowcharts.

Flowchart creation

  • The creation of flowcharts are time-consuming and labor-intensive, as every screened or recruited subject must be included, without exception.

  • Usually this process must be repeated many times until the database is closed for analysis.

  • There are several R packages dedicated to building flowcharts: {Gmisc}, {DiagrammeR}, {consort}, {ggflowchart}.

  • Some involve complex programming and manual parameterization and others are designed for building other kind of diagrams.

The {flowchart} package

{flowchart}


  • It produces flowcharts that automatically adapt to the study database, ensuring reproducibility.

  • It follows the tidyverse philosophy: from the study database we have to define a set of simple operations combined with the pipe operator (|> or %>%).

  • These functions are highly customizable allowing manual parameters to be entered if necessary.


Published in CRAN since February 2024:

        

{flowchart}

Alexander Calder (1898-1976)

Overview of the package


  • Create a flowchart:

    • as_fc()

    • fc_draw()

    • fc_split()

    • fc_filter()

  • Combine flowcharts:

    • fc_merge()

    • fc_stack()

  • Customize flowcharts:

    • fc_modify()
    • fc_theme()
  • Export flowcharts:

    • fc_export()

safo dataset

  • It’s the built-in dataset of the package.

  • Randomly generated dataset from the SAFO clinical trial1.

ID did not meet inclusion criteria met exclusion criteria declined to participate treatment received intention to treat (ITT) per protocol (PP)
1 Yes No NA NA NA NA
2 No No Yes NA NA NA
3 No No No cloxacillin plus fosfomycin Yes Yes
4 No Yes NA NA NA NA
5 No No No cloxacillin plus fosfomycin Yes Yes
6 No Yes NA NA NA NA

How to create a flowchart

as_fc()

  • Allows to initialize a dataset in the class fc created for this package.

  • Creates a flowchart with an initial box showing the total number of rows of the dataset.

library(flowchart)

safo_fc <- safo |> 
  as_fc()

as_fc()

  • Allows to initialize a dataset in the class fc created for this package.

  • Creates a flowchart with an initial box showing the total number of rows of the dataset.

library(flowchart)

safo_fc <- safo |> 
  as_fc()

str(safo_fc, max.level = 1)
List of 2
 $ data: tibble [925 × 21] (S3: tbl_df/tbl/data.frame)
 $ fc  : tibble [1 × 22] (S3: tbl_df/tbl/data.frame)
 - attr(*, "class")= chr "fc"

as_fc()

safo_fc$fc

id x y n N perc label text_pattern text type group just text_color text_fs text_fface text_ffamily text_padding bg_fill border_color width height end
1 0.5 0.5 925 925 100 Initial dataframe {label} {N} Initial dataframe 925 init NA center black 8 1 NA 1 white black NA NA TRUE

fc_draw()

  • Allows to draw a previously created fc object:
safo |> 
  as_fc()

fc_draw()

  • Allows to draw a previously created fc object:
safo |> 
  as_fc() |> 
  fc_draw()

fc_draw()

  • Allows to draw a previously created fc object:
safo |> 
  as_fc(label = "Patients assessed for eligibility") |> 
  fc_draw()
  • We can use the label argument to modify the box label.

fc_filter()

  • We can filter an existing flowchart specifying the logic in which the filter is to be applied:
safo |> 
  as_fc(label = "Patients assessed for eligibility") |> 
  fc_draw()

fc_filter()

  • We can filter an existing flowchart specifying the logic in which the filter is to be applied:
safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_filter(!is.na(group)) |> 
  fc_draw()

fc_filter()

  • We can filter an existing flowchart specifying the logic in which the filter is to be applied:
safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_filter(!is.na(group), label = "Randomized") |> 
  fc_draw()

  • We can change again the label.

fc_filter()

  • We can filter an existing flowchart specifying the logic in which the filter is to be applied:
safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_filter(!is.na(group), label = "Randomized", show_exc = TRUE) |> 
  fc_draw()

  • We can change again the label.

  • We can use show_exc=TRUE to show the excluded rows.

fc_split()

  • We can split an existing flowchart according to the different values of a column:
safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_filter(!is.na(group), label = "Randomized", show_exc = TRUE) |> 
  fc_draw()

fc_split()

  • We can split an existing flowchart according to the different values of a column:
safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_filter(!is.na(group), label = "Randomized", show_exc = TRUE) |> 
  fc_split(group) |> 
  fc_draw()

Customize a flowchart

Modify function arguments

  • We can customize the flowchart either with the arguments provided by each function: as_fc(), fc_filter() and fc_split().
label= modify the label.
text_pattern= modify the pattern of the text (e.g. {label}\n {n} ({perc}%).
round_digits= number of digits to round percentages (default is 2)
text_color= modify the color of the text.
text_fs= modify the font size of the text.
bg_fill= modify the background color of the box.
  • We can use the fc_theme() function to modify at once all arguments for all boxes.

Export flowcharts

fc_export()

  • We can export the drawn flowchart to some of the most popular graphic devices.

  • These include both bitmap (png, jpeg, tiff, bmp) and vector (svg, pdf) formats.

safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_filter(!is.na(group), label = "Randomized", show_exc = TRUE) |> 
  fc_draw() 

fc_export()

  • We can export the drawn flowchart to some of the most popular graphic devices.

  • These include both bitmap (png, jpeg, tiff, bmp) and vector (svg, pdf) formats.

safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_filter(!is.na(group), label = "Randomized", show_exc = TRUE) |> 
  fc_draw() |> 
  fc_export("flowchart.png")

fc_export()

  • We can export the drawn flowchart to some of the most popular graphic devices.

  • These include both bitmap (png, jpeg, tiff, bmp) and vector (svg, pdf) formats.

safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_filter(!is.na(group), label = "Randomized", show_exc = TRUE) |> 
  fc_draw() |> 
  fc_export("flowchart.png", width = 3000, height = 4000, res = 700)
  • We can customize the size and resolution of the image to save.

Hands-on examples

Example 1

  • We will try to build a flowchart for the complete participant flow of the SAFO study trial:

Example 1

safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_draw()

Example 1

safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_filter(!is.na(group), label = "Randomized", show_exc = TRUE) |> 
  fc_draw()

Example 1

safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_filter(!is.na(group), label = "Randomized", show_exc = TRUE) |> 
  fc_split(group) |> 
  fc_draw()

Example 1

safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_filter(!is.na(group), label = "Randomized", show_exc = TRUE) |> 
  fc_split(group) |> 
  fc_filter(itt == "Yes", label = "Included in ITT") |> 
  fc_draw()

Example 1

safo |> 
  as_fc(label = "Patients assessed for eligibility") |>
  fc_filter(!is.na(group), label = "Randomized", show_exc = TRUE) |> 
  fc_split(group) |> 
  fc_filter(itt == "Yes", label = "Included in ITT") |> 
  fc_filter(pp == "Yes", label = "Included in PP") |> 
  fc_draw()

Example 1

Grillo, S., Pujol, M., Miró, J.M. et al. Cloxacillin plus fosfomycin versus cloxacillin alone for methicillin-susceptible Staphylococcus aureus bacteremia: a randomized trial. Nat Med 29, 2518–2525 (2023). https://doi.org/10.1038/s41591-023-02569-0

Example 2

  • Now, we will create a flowchart without any dataset using the N= argument:

Example 2

as_fc(N = 300, label = "Available patients") |> 
  fc_draw()

Example 2

as_fc(N = 300, label = "Available patients") |>
  fc_filter(N = 240, label = "Randomized patients", show_exc = TRUE) |> 
  fc_draw()

Example 2

as_fc(N = 300, label = "Available patients") |>
  fc_filter(N = 240, label = "Randomized patients", show_exc = TRUE) |> 
  fc_split(N = c(100, 80, 60), label = c("Group A", "Group B", "Group C")) |>
  fc_draw()

Example 2

as_fc(N = 300, label = "Available patients") |>
  fc_filter(N = 240, label = "Randomized patients", show_exc = TRUE) |> 
  fc_split(N = c(100, 80, 60), label = c("Group A", "Group B", "Group C")) |>
  fc_filter(N = c(80, 75, 50), label = "Finished the study") |> 
  fc_draw()

Conclusions

Conclusions

  • A clear and detailed reporting of the flow of participants in health research studies is required and recommended.

  • With this package, flowchart programming in R is made easier and accessible within the tidyverse workflow.

  • Flowchart reproducibility is assured.

  • As a limitation, we have not considered all possible scenarios and study designs, although is highly customizable.

Code repository



github.com/bruigtp


Thank you!


Website:

bruigtp.github.io/flowchart