dir=none on exclusion edges makes them side branches (no arrows).
shape = note and fillcolor = mistyrose give a “note” look for exclusions.
Section labels are positioned using invisible edges.
library(DiagrammeR)
gr<-grViz("
digraph flowchart {
graph [layout = dot, rankdir = TB]
# Node defaults
node [shape = box, style = filled, fillcolor = lightgray, fontname = Helvetica]
# Main flow nodes
study1 [label = 'Study 1 (n=160)']
study2 [label = 'Study 2 (n=140)']
population [label = 'Population (n=300)']
exclusion_pop [label = 'Excluded (n=15)\\n• MRI not collected (n=3)\\n• Tissues not collected (n=4)\\n• Other (n=8)', shape = note, fillcolor = mistyrose]
randomized [label = 'Randomized (n=200)']
armA [label = 'Arm A (n=100)']
armB [label = 'Arm B (n=100)']
exclusion_A [label = 'Excluded (n=15)\\n• MRI not collected (n=3)\\n• Tissues not collected (n=4)\\n• Other (n=8)', shape = note, fillcolor = mistyrose]
exclusion_B [label = 'Excluded (n=7)\\n• MRI not collected (n=3)\\n• Tissues not collected (n=4)', shape = note, fillcolor = mistyrose]
final_A [label = 'Final analysis (n=85)']
final_B [label = 'Final analysis (n=93)']
# Section labels (plaintext nodes)
label_screening [label = 'Screening', shape = plaintext, fontsize = 12]
label_randomized [label = 'Randomized', shape = plaintext, fontsize = 12]
label_final [label = 'Final analysis', shape = plaintext, fontsize = 12]
# Rank groups
{ rank = same; study1; study2 }
{ rank = same; armA; armB }
{ rank = same; final_A; final_B }
# Edges
study1 -> population
study2 -> population
population -> exclusion_pop [dir=none]
population -> randomized
randomized -> armA
randomized -> armB
armA -> exclusion_A [dir=none]
armB -> exclusion_B [dir=none]
armA -> final_A
armB -> final_B
# Invisible edges to help label positioning
label_screening -> population [style = invis]
label_randomized -> randomized [style = invis]
label_final -> final_A [style = invis]
}
")
Note: This diagram’s data is from CONSORT package’s Tutorial cite https://cran.r-project.org/web/packages/consort/vignettes/consort_diagram.html
gr
# Export to SVG
svg_code <- export_svg(gr)
# Save as high-res PNG
rsvg_png(charToRaw(svg_code), file = "flowchart.png", width = 2000, height = 1200)
# Convert PNG to TIFF using magick
img <- image_read("flowchart.png")
image_write(img, path = "flowchart.tiff", format = "tiff", density = "300x300")
library(grid)
library(consort)
# Might want to change some settings
options(txt_gp = gpar(cex = 0.8))
txt0 <- c("Study 1 (n=160)", "Study 2 (n=140)")
txt1 <- "Population (n=300)"
txt1_side <- "Excluded (n=15):\n\u2022 MRI not collected (n=3)\n\u2022 Tissues not collected (n=4)\n\u2022 Other (n=8)"
# supports pipeline operator
g <- add_box(txt = txt0) |>
add_box(txt = txt1) |>
add_side_box(txt = txt1_side) |>
add_box(txt = "Randomized (n=200)") |>
add_split(txt = c("Arm A (n=100)", "Arm B (n=100)")) |>
add_side_box(txt = c("Excluded (n=15):\n\u2022 MRI not collected (n=3)\n\u2022 Tissues not collected (n=4)\n\u2022 Other (n=8)",
"Excluded (n=7):\n\u2022 MRI not collected (n=3)\n\u2022 Tissues not collected (n=4)")) |>
add_box(txt = c("Final analysis (n=85)", "Final analysis (n=93)")) |>
add_label_box(txt = c("1" = "Screening",
"3" = "Randomized",
"4" = "Final analysis"))
library(gridSVG)
##
## Attaching package: 'gridSVG'
## The following objects are masked from 'package:grid':
##
## linearGradient, pattern, radialGradient
## The following object is masked from 'package:grDevices':
##
## dev.off
# You must plot it first for gridSVG to capture it
plot(g)
# Now export to SVG
grid.export("flowchart.svg")
library(rsvg)
# Convert to high-res PNG (e.g., 2000x1200 pixels)
rsvg_png("flowchart.svg", file = "flowchart.png", width = 2000, height = 1200)
library(magick)
# Read the PNG
img <- image_read("flowchart.png")
# Write as TIFF at 300 DPI
image_write(img, path = "flowchart.tiff", format = "tiff", density = "300x300")