I found the following example of diagrammeR here (diagrammer - how can I add arms to my flowchart?):
library(DiagrammeR)
grViz("digraph flowchart {
# node definitions with substituted label text
node [fontname = Helvetica, shape = rectangle, fixedsize = false, width = 1]
1 [label = 'data (100%)']
2 [label = 'data (74.4%)']
3 [label = 'data (69.6%)']
4 [label = 'data (55.4%)']
m1 [label = 'missing (25.6%)']
m2 [label = 'missing (4.8%)']
node [shape=none, width=0, height=0, label='']
p1 -> 2; p2 -> 3 -> 4;
{rank=same; p1 -> m1}
{rank=same; p2 -> m2}
edge [dir=none]
1 -> p1; 2 -> p2;
}")
Output is:
In my case I have multiple exclusions (m2, m3, m4, m5, m6, m7, m8) between box 2 and 3:
grViz("digraph flowchart {
# node definitions with substituted label text
node [fontname = Helvetica, shape = rectangle, fixedsize = false, width = 1]
1 [label = 'Box 1']
2 [label = 'Box 2']
3 [label = 'Box 3']
m1 [label = 'm1']
m2 [label = 'm2']
m3 [label = 'm3']
m4 [label = 'm4']
m5 [label = 'm5']
m6 [label = 'm6']
m7 [label = 'm7']
m8 [label = 'm8']
node [shape=none, width=0, height=0, label='']
p1 -> 2; p2 -> 3;
{rank=same; p1 -> m1}
{rank=same; p2 -> m2}
{rank=same; p2 -> m3}
{rank=same; p2 -> m4}
{rank=same; p2 -> m5}
{rank=same; p2 -> m6}
{rank=same; p2 -> m7}
{rank=same; p2 -> m8}
edge [dir=none]
1 -> p1; 2 -> p2;
}")
Currently this gives me:
But I would like to have a longer arrow between box 2 and 3 so that all m boxes are one below the other, and not to the right, is this possible? Like:
Box 2
|--- m2
|--- m3
|--- m4
|--- m5
|--- m6
|--- m7
|--- m8
Box 3
This should get you up and running. Just add more (p3 -> p4... in edge section etc.).
library(DiagrammeR)
grViz("digraph flowchart {
# node definitions with substituted label text
node [fontname = Helvetica, shape = rectangle, fixedsize = false, width = 1]
1 [label = 'Box 1']
2 [label = 'Box 2']
3 [label = 'Box 3']
m1 [label = 'm1']
m2 [label = 'm2']
m3 [label = 'm3']
node [shape=none, width=0, height=0, label='']
p1 -> 2; p3 -> 3
{rank=same; p1 -> m1}
{rank=same; p2 -> m2}
{rank=same; p3 -> m3}
edge [dir=none, arrowhead=none]
1 -> p1; 2 -> p2; p2 -> p3
}")
Is it possible to reproduce a meta-analysis type of flowchart as the one in the picture below using any R tool?
My attempt was using mermaid:
diagram = "
graph LR
subgraph Screening
b1-->b2
end
subgraph Eligibility
c1-->c2
end
subgraph Included
d1-->d2
end
subgraph Identification
a1-->a2
end
"
mermaid(diagram)
Which generated:
But I cannot find a way of connect the nodes accross the subgraphs.
Is there another tool better fitting to this kind of job? I am thinking on any package that I could use from within my Rmarkdown document.
I have found the DiagrammeR package easiest to do this. The general idea would be something like:
library(glue)
library(DiagrammeR)
excluded <- glue('Full text articles excluded
n = 1000
Reasons for exclusion
Reason 1
Reason 2')
grViz("
digraph cohort_flow_chart
{
node [fontname = Helvetica, fontsize = 12, shape = box, width = 4]
a[label = 'Records identified in original search']
b[label = 'Records identified with update']
c[label = 'Records after duplicates removed']
d[label = 'Records screened']
e[label = 'Records excluded']
f[label = 'Full text articles assessed']
g[label = 'Studies included']
h[label = '##1']
{ rank = same; a b}
{ rank = same; d, e}
{ rank = same; f, h}
a -> c;
b -> c;
c -> d;
d -> e [ minlen = 3 ];
d -> f;
f -> h [ minlen = 3 ];
f -> g;
}
[1]: excluded
")
Will look like:
Image with labels and empty nodes
grViz("
digraph cohort_flow_chart
{
node [fontname = Helvetica, fontsize = 12, shape = box, width = 4]
i[label = 'Identification', fillcolor = LightBlue,
style = filled, width = 2]
j[label = 'Screening',fillcolor = LightBlue, style = filled, width = 2]
k[label = 'Eligibility', fillcolor = LightBlue, style = filled,
width = 2]
l[label = 'Included', fillcolor = LightBlue, style = filled, width = 2]
a[label = 'Records identified in original search']
b[label = 'Records identified with update']
c[label = 'Records after duplicates removed']
d[label = 'Records screened']
e[label = 'Records excluded']
f[label = 'Full text articles assessed']
g[label = 'Studies included']
h[label = '##1']
blank_1[label = '', width = 0.01, height = 0.01]
blank_2[label = '', width = 0.01, height = 0.01]
blank_4[label = '', width = 4, color = White]
{ rank = same; a b i}
{ rank = same; blank_4 c j}
{ rank = same; f k}
{ rank = same; g l}
{ rank = same; blank_1 e}
{ rank = same; blank_2 h}
a -> c;
b -> c;
b -> blank_4 [ dir = none, color = White];
c -> d;
d -> blank_1 [ dir = none ];
blank_1 -> e [ minlen = 3 ];
blank_1 -> f;
f -> blank_2 [ dir = none ];
blank_2 -> h [ minlen = 3 ];
blank_2 -> g;
}
[1]: excluded
")
I wrote the below DOT to generate a diagram. In addition to the nodes that are defined and laid out, I want to place one node to the left and another node to the right of the edge marked L, they should be close to L and in between NODE3 and NODE6.
I tried with some invisible nodes. The new nodes either go to the first row or the second row, but I want them to be in the new row between the first and second.
digraph g {
ranksep=0.5
graph [rankdir = "TB"];
graph [splines=ortho];
node [fontsize = "8"];
edge [];
node0 [label = "{NODE0}" shape = "record" ];
node1 [label = "{NODE1}" shape = "record" ];
node2 [label = "{NODE2}" shape = "record" ];
node3 [label = "{NODE3}" shape = "record" ];
node4 [label = "{NODE4}" shape = "record" ];
node5 [label = "{NODE5}" shape = "record" ];
node6 [label = "{NODE6}" shape = "record" ];
node7 [label = "{NODE7}" shape = "record" ];
node8 [label = "{NODE8}" shape = "record" ];
node9 [label = "{NODE9}" shape = "record" ];
node10 [label = "{NODE10}" shape = "record" ];
node11 [label = "{NODE11}" shape = "record" ];
node12 [label = "{NODE12}" shape = "record" ];
{rank=same; node0 -> node1 -> node2 -> node3 -> node4};
{rank=same; node5 -> node6 -> node7 -> node8 -> node9};
{rank=same; node10 -> node11 -> node12};
node1 -> node5;
node5 -> node3;
node3 -> node6[label="L"];
node7 -> node10;
node11 -> node8;
node9 -> node12;
}
How about something like this? I created a "point" node for the new ones to connect to within their rank. Also fiddled with the arrowheads to give you an idea of the possibilities there.
digraph g {
ranksep=0.5
graph [rankdir = "TB"];
graph [splines=ortho];
node [fontsize = "8"];
edge [];
node0 [label = "{NODE0}" shape = "record" ];
node1 [label = "{NODE1}" shape = "record" ];
node2 [label = "{NODE2}" shape = "record" ];
node3 [label = "{NODE3}" shape = "record" ];
node4 [label = "{NODE4}" shape = "record" ];
node5 [label = "{NODE5}" shape = "record" ];
node6 [label = "{NODE6}" shape = "record" ];
node7 [label = "{NODE7}" shape = "record" ];
node8 [label = "{NODE8}" shape = "record" ];
node9 [label = "{NODE9}" shape = "record" ];
node10 [label = "{NODE10}" shape = "record" ];
node11 [label = "{NODE11}" shape = "record" ];
node12 [label = "{NODE12}" shape = "record" ];
nodenew1 [label="new1" shape=record];
nodenew2 [label="new2" shape=record];
{rank=same; node0 -> node1 -> node2 -> node3 -> node4};
{rank=same; node5 -> node6 -> node7 -> node8 -> node9};
{rank=same; node10 -> node11 -> node12};
node1 -> node5;
node5 -> node3;
{
rank = same;
nodenew1 -> nodepoint -> nodenew2 [ arrowhead=none]
}
nodepoint [shape=point]
node3 -> nodepoint [label="L" arrowhead=none];
nodepoint -> node6[label="L"];
node7 -> node10;
node11 -> node8;
node9 -> node12;
}
I can't find out how to draw a curved line between two rectangle using graphviz such as
digraph G {
SatisfactionF [style=filled, shape = rectangle]
SatisfactionM [style=filled, shape = rectangle]
Marital[shape = circle]
SatisfactionF -> Marital
SatisfactionM -> Marital
}
Here you go:
digraph G {
{
rank = same;
SatisfactionF [style=filled, shape = rectangle]
SatisfactionM [style=filled, shape = rectangle]
}
Marital[shape = circle]
SatisfactionF -> Marital
SatisfactionM -> Marital
SatisfactionF -> SatisfactionM [label = "0.4" tailport=n headport=n dir=both arrowhead=none]
}
It gives a warning but it works.
I'm using TwoAxisPlot to combine two plots for functions from an NDSolve, but the result has one of the curves truncated and is hence incomplete. I don't understand all the jargon when defining the TwoAxisPlot function so I don't know the origin of the problem. Code is as follows:
a = 0.99*10^-9;
b = 0.24*10^-3;
d = 1.21*10^-3;
T0 = 1*10^6;
n0 = 0.9*10^9;
ti = -20;
tf = 500;
kB = 1.38*10^-16;
Qb = 0.33*10^-3;
sig = 1;
var = sig^2;
Ag = 16.5;
Qg = Ag* Exp[-(t - 10)^2/(2*var)];
Qgt = Qg + Qb;
sss = NDSolve[{T'[t] == -(n[t]^-1) T[t]^(7/2) (a) -
n[t] T[t]^(-1/2) (b) + Qgt/(2*kB*n[t]),
n'[t] == T[t]^(5/2) (a) - (n[t]^2) (T[t]^(-3/2)) (d), T[ti] == T0,
n[ti] == n0}, {T, n}, {t, ti, tf}];
This gives me two interpolating functions which I can plot fully individually:
TP = Plot[T[t] /. sss, {t, ti, 300}, PlotRange -> All];
TPPa = Show[TP, Frame -> True,
FrameLabel -> {{"Temperature, K", ""}, {"Time, s", ""}}]
NP = Plot[n[t] /. sss, {t, ti, 300}, PlotRange -> All];
NPPa = Show[NP, Frame -> True,
FrameLabel -> {{"Density, \!\(\*SuperscriptBox[\(cm\), \(-3\)]\)",
""}, {"Time, s", ""}}]
I then define the TwoAxisPlot function, unchanged, copied from this website: Wolfram Documentation Center
TwoAxisPlot[{f_, g_}, {x_, x1_, x2_}] :=
Module[{fgraph, ggraph, frange, grange, fticks,
gticks}, {fgraph, ggraph} =
MapIndexed[
Plot[#, {x, x1, x2}, Axes -> True,
PlotStyle -> ColorData[1][#2[[1]]]] &, {f, g}]; {frange,
grange} = (PlotRange /. AbsoluteOptions[#, PlotRange])[[
2]] & /# {fgraph, ggraph}; fticks = N#FindDivisions[frange, 5];
gticks =
Quiet#Transpose#{fticks,
ToString[NumberForm[#, 2], StandardForm] & /#
Rescale[fticks, frange, grange]};
Show[fgraph,
ggraph /.
Graphics[graph_, s___] :>
Graphics[
GeometricTransformation[graph,
RescalingTransform[{{0, 1}, grange}, {{0, 1}, frange}]], s],
Axes -> False, Frame -> True,
FrameStyle -> {ColorData[1] /# {1, 2}, {Automatic, Automatic}},
FrameTicks -> {{fticks, gticks}, {Automatic, Automatic}}]]
and use it
TwoAxisPlot[{T[t] /. sss, n[t] /. sss}, {t, -20, 300}]
but the plot is now truncated and doesn't show the full curve. How can I fix this?
Add PlotRange -> Full as included below.
TwoAxisPlot[{f_, g_}, {x_, x1_, x2_}] := Module[
{fgraph, ggraph, frange, grange, fticks, gticks},
{fgraph, ggraph} = MapIndexed[Plot[#, {x, x1, x2}, Axes -> True,
PlotStyle -> ColorData[1][#2[[1]]], PlotRange -> Full] &, {f, g}];
{frange, grange} = (PlotRange /. AbsoluteOptions[#, PlotRange])[[2]] & /#
{fgraph, ggraph};
fticks = N#FindDivisions[frange, 5];
gticks = Quiet#Transpose#{fticks, ToString[NumberForm[#, 2],
StandardForm] & /# Rescale[fticks, frange, grange]};
Show[fgraph, ggraph /. Graphics[graph_, s___] :> Graphics[
GeometricTransformation[graph, RescalingTransform[{{0, 1}, grange},
{{0, 1}, frange}]], s], Axes -> False, Frame -> True,
FrameStyle -> {ColorData[1] /# {1, 2}, {Automatic, Automatic}},
FrameTicks -> {{fticks, gticks}, {Automatic, Automatic}}]]
Labeled[
TwoAxisPlot[{T[t] /. sss, n[t] /. sss}, {t, -20, 300}],
{Rotate["Temperature, K", Pi/2], "Time, s",
Rotate["Density, \!\(\*SuperscriptBox[\(cm\), \(-3\)]\)", Pi/2]},
{Left, Bottom, Right}]