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