3

What I want to do is to create a basic flowchart with R, add it to my R Markdown file and make it referencable (if possible like I did with my ggplot2 figures -> fig.cap = " " in the code chunk header).

The Flowchart:

library(grid)
library(Gmisc)

grid.newpage()

# set some parameters to use repeatedly
leftx <- .25
midx <- .5
rightx <- .75
width <- .4
gp <- gpar(fill = "lightgrey")

# create boxes
(Pharmazie <- boxGrob("Verbrauchsdaten von der\n Spitalpharmazie (Excel-Tabelle)", 
                  x=leftx, y=0.876, box_gp = gp, width = width))

(Finanzen <- boxGrob("Belegzahlen vom Ressort\n Finanzen (Excel-Tabelle)", 
                 x=rightx, y=.876, box_gp = gp, width = width))

(A <- boxGrob("Import der Daten aus Excel ins\n Microsoft Access (Datenbanksoftware)", 
          x=midx, y=0.76, box_gp = gp, width = width))

(B <- boxGrob("Zusammenführen der Informationen\n und erstellen neuer, berechneter Tabellen", 
          x=midx, y=.64, box_gp = gp, width = width))

(C <- boxGrob("Export der neu erstellten Tabellen\n in Form von Excel-Tabellen", 
          x=midx, y=.52, box_gp = gp, width = width))

(D <- boxGrob("Import der neuen Tabellen in R", 
          x=midx, y=.414, box_gp = gp, width = width))

(E <- boxGrob("Berechnung und grafische Darstellung\n der Grafiken und Tabellen", 
          x=midx, y=.308, box_gp = gp, width = width))


connectGrob(Pharmazie, A, "L")
connectGrob(Finanzen, A, "L")
connectGrob(A, B, "N")
connectGrob(B, C, "N")
connectGrob(C, D, "N")
connectGrob(D, E, "N")

The problem that I'm having is that I cannot find a way to save the flowchart to a variable / png file (to import it into my R Markdown file later) or, even better, to include it directly within a code chunk (it looks different when I execute the code within a code chunk vs. when executing it in a script, also when trying to give it a fig.cap it fails to knit).

Example of how differently it looks: enter image description here.

Any help would be greatly appreciated!

P.S. I tried to make the flowchart with the package "DiagrammeR", but I gave up after I did not manage to find a way to have the text on more than one line per box (so it wouldn't be so broad).

Hurlikus
  • 399
  • 3
  • 13

2 Answers2

2

For reference png() is how you would easily save your flowchart to a png file. Other formats are possible, like pdf(). Below is how you would save the vignette example to a png file, though you won't see it in the viewport as you run the code. Note dev.off() at the end.

#r flowchart with gmisc
#https://cran.r-project.org/web/packages/Gmisc/vignettes/Grid-based_flowcharts.html

#install.packages("Gmisc")
library(Gmisc)
library(grid)
#example x

#get file ready to receive image
png("vignette flowchart.png", width=500, height = 500, units = "px")

grid.newpage()

# Initiate the boxes that we want to connect
side <- boxPropGrob("Side", "Left", "Right", 
                    prop=.3, 
                    x=0, y=.9,
                    bjust = c(0,1))

start <- boxGrob("Top", 
                 x=.6, y=coords(side)$y, 
                 box_gp = gpar(fill = "yellow"))

bottom <- boxGrob("Bottom", x=.6, y=0, 
                  bjust="bottom")


sub_side_left <- boxGrob("Left", 
                         x = coords(side)$left_x, 
                         y = 0,
                         bjust = "bottom")
sub_side_right <- boxGrob("Right", 
                          x = coords(side)$right_x, 
                          y = 0,
                          bjust = "bottom")

odd <- boxGrob("Odd\nbox", 
               x=coords(side)$right, 
               y=.5)

odd2 <- boxGrob("Also odd", 
                x=coords(odd)$right + 
                  distance(bottom, odd, type="h", half=TRUE) -
                  unit(2, "mm"), 
                y=0,
                bjust = c(1,0))

exclude <- boxGrob("Exclude:\n - Too sick\n - Prev. surgery", 
                   x=1, y=coords(bottom)$top + 
                     distance(start, bottom, 
                              type="v", half=TRUE), 
                   just="left", bjust = "right")

# Connect the boxes and print/plot them



connectGrob(start, bottom, "vertical")
connectGrob(start, side, "horizontal")
connectGrob(bottom, odd, "Z", "l")
connectGrob(odd, odd2, "N", "l")
connectGrob(side, sub_side_left, "v", "l")
connectGrob(side, sub_side_right, "v", "r")
connectGrob(start, exclude, "-", 
            lty_gp = gpar(lwd=2, col="darkred", fill="darkred"))

# Print the grobs
start
bottom
side
exclude
sub_side_left
sub_side_right
odd
odd2

#save and close file
dev.off()
Mark Neal
  • 996
  • 16
  • 52
1

It looks different, because the viewport you are drawing on is not the same. You just need to fiddle a bit with the positioning options to make it fit. Below I used fig.width and fig.height and created a wrapper function in which I also vertically justified the boxes (top end). This makes it easier to build the chart top to bottom using the y coordinate.

---
output: pdf_document
---


```{r echo = F, message = F, fig.width=7, fig.height = 6}
library(grid)
library(Gmisc)

# grid.newpage()
# set some parameters to use repeatedly
leftx <- .2
midx <- .5
rightx <- .8

myBoxGrob <- function(text, ...) {
  boxGrob(label = text, bjust = "top", box_gp = gpar(fill = "lightgrey"), ...)
}

# create boxes
(Pharmazie <- myBoxGrob("Verbrauchsdaten von der\n Spitalpharmazie (Excel-Tabelle)", x=leftx, y=1, width = 0.38))
(Finanzen <- myBoxGrob("Belegzahlen vom Ressort\n Finanzen (Excel-Tabelle)", x=rightx, y=1, width = 0.38))
(A <- myBoxGrob("Import der Daten aus Excel ins\n Microsoft Access (Datenbanksoftware)", x=midx, y=0.87, width = 0.5))
(B <- myBoxGrob("Zusammenführen der Informationen\n und erstellen neuer, berechneter Tabellen", x=midx, y=.70, width = 0.5))
(C <- myBoxGrob("Export der neu erstellten Tabellen\n in Form von Excel-Tabellen", x=midx, y=.53, width = 0.5))
(D <- myBoxGrob("Import der neuen Tabellen in R", x=midx, y=.36,  width = 0.5))
(E <- myBoxGrob("Berechnung und grafische Darstellung\n der Grafiken und Tabellen", x=midx, y=.21, width = 0.5))


connectGrob(Pharmazie, A, "L")
connectGrob(Finanzen, A, "L")
connectGrob(A, B, "N")
connectGrob(B, C, "N")
connectGrob(C, D, "N")
connectGrob(D, E, "N")
```

enter image description here

If the flowchart is acceptable, you can scale the plot using the chunk option out.width (here =".5\\textwidth"):

enter image description here

Martin Schmelzer
  • 23,283
  • 6
  • 73
  • 98
  • Thank you, that looks already very good! Also fig.cap seems to work again! Is there a way to crop it without distorting it again (which happened when I tried to alter the fig.width and height)? I would like to have the flowchart on the right side of the page with some text left of it if possible. – Hurlikus Jan 08 '19 at 13:51
  • 1
    If you mean scale and not crop, try `out.width` (see update). – Martin Schmelzer Jan 08 '19 at 16:23
  • Perfect, thanks! I have another question that goes a bit further: The figure is now the size I want it (it's at 70%) and right aligned (`fig.align="right"`). The fig.cap is still in the middle of the page beneath the figure (instead of centered relative to the figure) and the text does not use the space on the left of the figure. Would you have any idea how to solve that? I've tried a couple of things like [link](https://stackoverflow.com/questions/43551312/wrap-text-around-plots-in-markdown), but I can't get it to work. – Hurlikus Jan 08 '19 at 17:17
  • I do have a solution. But I would kindly ask you to open another question since it is not good practice to elaborate on further problems in a question. – Martin Schmelzer Jan 08 '19 at 18:49