The diagram package makes it easy to create flowcharts in R. In this post I'll show an example of creating a simple flowchart. The most important part is to understand how the coordinate systems works; once you understand that, it's just a matter of placing your arrows and boxes accordingly to create your flowchart. To get started, install the package if you haven't already.
install.packages('diagram')
The flowchart I want to create has 13 steps and I want the boxes arranged in the formation 1, 3, 3, 3, and 3. Imagine a football/soccer formation with 1 person at the top, followed by 3, and another 3 and so on. The coordinates() function helps me create this.
library(diagram)
# creates an empty plot
openplotmat()
# create the coordinates
pos <- coordinates(c(1,3,3,3,3))
pos
[,1] [,2]
[1,] 0.5000000 0.9
[2,] 0.1666667 0.7
[3,] 0.5000000 0.7
[4,] 0.8333333 0.7
[5,] 0.1666667 0.5
[6,] 0.5000000 0.5
[7,] 0.8333333 0.5
[8,] 0.1666667 0.3
[9,] 0.5000000 0.3
[10,] 0.8333333 0.3
[11,] 0.1666667 0.1
[12,] 0.5000000 0.1
[13,] 0.8333333 0.1
class(pos)
[1] "matrix"
plot(pos, type = 'n')
text(pos)
The coordinate system ranges from 0 to 1 on both the x and y axes. The coordinates stored in the matrix pos are used to specify connections for arrows and to place boxes. The order in which you draw the objects matters; if you place the boxes first, the arrows will be placed on top of the boxes.
I will use two types of arrows: straightarrow() and segmentarrow(). They are straightforward to use; you just need to specify the start and end points. The segmentarrow() requires a little bit of tinkering for aesthetic purposes.
par(mar = rep(1, 4)) openplotmat() pos <- coordinates(c(1,3,3,3,3)) # the dd parameter was used to move the segment arm segmentarrow (from = pos[1, ], to = pos[2, ], dd = 0.45) straightarrow(from = pos[2, ], to = pos[3, ]) straightarrow(from = pos[3, ], to = pos[4, ]) straightarrow(from = pos[7, ], to = pos[6, ]) straightarrow(from = pos[6, ], to = pos[5, ]) straightarrow(from = pos[10, ], to = pos[9, ]) straightarrow(from = pos[9, ], to = pos[8, ]) straightarrow(from = pos[13, ], to = pos[12, ]) straightarrow(from = pos[12, ], to = pos[11, ]) # the path parameter was used to change the direction # arr.pos was used to position the arrow # arr.side was used to specific where the arrow should be drawn segmentarrow (from = pos[4, ], to = pos[7, ], dd = 0.15, path = 'RVL', arr.pos = 0.24, arr.side = 3) segmentarrow (from = pos[4, ], to = pos[10, ], dd = 0.15, path = 'RVL', arr.pos = 0.24, arr.side = 3) segmentarrow (from = pos[4, ], to = pos[13, ], dd = 0.15, path = 'RVL', arr.pos = 0.24, arr.side = 3)
Now we can draw the boxes on top of the arrows. I've added some conditionals just to change the colour of the boxes.
my_label <- c(1, 2, 3, 4, 7, 6, 5, 10, 9, 8, 13, 12, 11)
my_text_size <- 1.3
my_edge_length <- 0.08
for(i in 1:length(my_label)){
if (i %in% 5:7){
textrect(mid = pos[i,], radx = my_edge_length, rady = my_edge_length, lab = my_label[i], cex = my_text_size, box.col = "#0072B2")
} else if (i %in% 8:10){
textrect(mid = pos[i,], radx = my_edge_length, rady = my_edge_length, lab = my_label[i], cex = my_text_size, box.col = "#009E73")
} else if (i %in% 11:13){
textrect(mid = pos[i,], radx = my_edge_length, rady = my_edge_length, lab = my_label[i], cex = my_text_size, box.col = "#D55E00")
} else {
textrect(mid = pos[i,], radx = my_edge_length, rady = my_edge_length, lab = my_label[i], cex = my_text_size, box.col = "#999999")
}
}
Functions for flowcharts
In the example above I only used two types of arrows and one type of textbox. Below is a full list of the arrows and textboxes that can be used for creating flowcharts.
| Function | Description |
|---|---|
| openplotmat | creates an empty plot |
| coordinates | calculates coordinates of elements, neatly arranged in rows/columns |
| bentarrow | adds 2-segmented arrow between two points |
| curvedarrow | adds curved arrow between two points |
| segmentarrow | adds 3-segmented arrow between two points |
| selfarrow | adds a circular self-pointing arrow |
| splitarrow | adds a branched arrow between several points |
| straightarrow | adds straight arrow between two points |
| treearrow | adds dendrogram-like branched arrow between several points |
| shadowbox | adds a box with a shadow to a plot |
| textdiamond | adds lines of text in a diamond-shaped box to a plot |
| textellipse | adds lines of text in a ellipse-shaped box to a plot |
| textempty | adds lines of text on a colored background to a plot |
| texthexa | adds lines of text in a hexagonal box to a plot |
| textmulti | adds lines of text in a multigonal box to a plot |
| textparallel | adds lines of text in a parallelogram to a plot |
| textplain | adds lines of text to a plot |
| textrect | adds lines of text in a rectangular-shaped box to a plot |
| textround | adds lines of text in a rounded box to a plot |
The vignette contains code to visualise all the different types of textboxes.
openplotmat(main = "textbox shapes")
rx <- 0.1
ry <- 0.05
pos <- coordinates(c(1, 1, 1, 1, 1, 1, 1,1 ), mx = -0.2)
pos
textdiamond(mid = pos[1,], radx = rx, rady = ry, lab = LETTERS[1], cex = 2, shadow.col = "lightblue")
textellipse(mid = pos[2,], radx = rx, rady = ry, lab = LETTERS[2], cex = 2, shadow.col = "blue")
texthexa(mid = pos[3,], radx = rx, rady = ry, lab = LETTERS[3], cex = 2, shadow.col = "darkblue")
textmulti(mid = pos[4,], nr = 7, radx = rx, rady = ry, lab = LETTERS[4], cex = 2, shadow.col = "red")
textrect(mid = pos[5,], radx = rx, rady = ry, lab = LETTERS[5], cex = 2, shadow.col = "darkred")
textround(mid = pos[6,], radx = rx, rady = ry, lab = LETTERS[6], cex = 2, shadow.col = "black")
textparallel(mid = pos[7,], radx = rx, rady = ry, lab = LETTERS[7], cex = 2, theta = 40, shadow.col = "black")
textempty(mid = pos[8,], lab = LETTERS[8], cex = 2, box.col = "yellow")
pos[ ,1] <- pos[ ,1] + 0.5
pos
text(pos[ ,1],pos[ ,2], c("textdiamond", "textellipse", "texthexa",
"textmulti", "textrect", "textround",
"textparallel", "textempty"))
And all the different arrows.
par(mar = c(1, 1, 1, 1))
openplotmat(main = "Arrowtypes")
elpos <- coordinates (c(1, 2, 1), mx = 0.1, my = -0.1)
curvedarrow(from = elpos[1, ], to = elpos[2, ], curve = -0.5, lty = 2, lcol = 2)
straightarrow(from = elpos[1, ], to = elpos[2, ], lty = 3, lcol = 3)
segmentarrow (from = elpos[1, ], to = elpos[2, ], lty = 1, lcol = 1)
treearrow (from = elpos[2:3, ], to = elpos[4, ], lty = 4, lcol = 4)
bentarrow (from = elpos[3, ], to = elpos[3, ]-c(0.1, 0.1),arr.pos=1,lty=5,lcol=5)
bentarrow(from = elpos[1, ], to = elpos[3, ], lty = 5, lcol = 5)
selfarrow(pos = elpos[3, ], path = "R",lty = 6, curve = 0.075, lcol = 6)
splitarrow(from = elpos[1, ], to = elpos[2:3, ], lty = 1, lwd = 1, dd = 0.7, arr.side = 1:2, lcol = 7)
for ( i in 1:4){
textrect (elpos[i, ], 0.05, 0.05, lab = i, cex = 1.5)
}
legend("topright", lty = 1:7, legend = c("segmentarrow","curvedarrow", "straightarrow", "treearrow", "bentarrow",
"selfarrow", "splitarrow"), lwd = c(rep(2, 6), 1), col = 1:7)
Summary
I thought the diagram package was quite easy to use for creating a flowchart in R. I needed to tinker a bit with the placement of lines and arrows but all in all it didn't take long to create the flowchart.

This work is licensed under a Creative Commons
Attribution 4.0 International License.





Does this package allow for pdf export or only HTML?
Thanks in advance