graphviz - SEM residual covariance - graph

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.

Related

DiagrammeR grViz Flow Chart Top Alignment

I am using DiagrammeR/grViz in R Studio to make a flow chart from left to right. I have included the R code below. This works fine but I would like to align Block 1 to Block 6 with the top so that they are flush at the top.
Any ideas or links to help would be appreciated.
library(DiagrammeR)
grViz("
digraph boxes_and_circles {
graph[rankdir = LR]
graph [overlap = false, fontsize = 10]
node[shape = rectangle, style = filled, style = rounded]
subgraph cluster_0 {
label = 'BLOCK 1'
node [shape = box,
fixedsize = true,
height = 0.7,
width = 1.2,
]
CS1[label = '1A'];
CS2[label = '1B'];
CS3[label = '1C'];
}
subgraph cluster_1 {
label = 'BLOCK 2'
node [shape = circle,
fixedsize = true,
width = 1.2,
] // sets as circles
CR1[label = '2A'];
CR2[label = '2B'];
}
subgraph cluster_3 {
label = 'BLOCK 4'
node [shape = box,
fixedsize = true,
height = 0.7,
width = 1.2,
]
RM1; RM2;
RM1[label = '4A'];
RM2[label = '4B'];
}
subgraph cluster_5 {
label = 'BLOCK 6'
node [shape = box,
fixedsize = true,
height = 0.7,
width = 1.2,
]
R1[label = '6A'];
R2[label = '6B'];
R3[label = '6C'];
}
CS1->CR1->RM1->R1
CS1-> R1
CS2->CR2->RM2->R1
CS1->CR2
CS3-> R3
}
")

diagrammeR - adaptation from "how can I add arms to my flowchart?"

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
}")

networkD3 package: show node names of all connected nodes when hovering over

Using the forceNetwork function of the networkD3 package, it is possible to create an interactive network graph that can show the node names when hovering over them.
I am trying to create a graph that not only shows the node where the mouse is hovering over, but also all neighboring nodes, i.e. all nodes that are directly connected to the selected node. However, it should not show any nodes that are not directly connected to the node.
Although I found the argument opacityNoHover, it will affect all the nodes that the mouse is not covering and not just the nodes with a direct connection.
library(networkD3)
# example data
data(MisLinks)
data(MisNodes)
# creating the plot
forceNetwork(Links = MisLinks, Nodes = MisNodes,
Source = "source", Target = "target",
Value = "value", NodeID = "name",
Group = "group", opacity = 1, fontSize = 15,
opacityNoHover = 0)
You could re-write the mouseover and mouseout functions and override them with htmlwidgets::onRender...
library(networkD3)
library(htmlwidgets)
data(MisLinks)
data(MisNodes)
fn <- forceNetwork(Links = MisLinks, Nodes = MisNodes, Source = "source",
Target = "target", Value = "value", NodeID = "name",
Group = "group", opacity = 1, fontSize = 15,
opacityNoHover = 0)
customJS <- '
function(el,x) {
var link = d3.selectAll(".link")
var node = d3.selectAll(".node")
var options = { opacity: 1,
clickTextSize: 10,
opacityNoHover: 0.1,
radiusCalculation: "Math.sqrt(d.nodesize)+6"
}
var unfocusDivisor = 4;
var links = HTMLWidgets.dataframeToD3(x.links);
var linkedByIndex = {};
links.forEach(function(d) {
linkedByIndex[d.source + "," + d.target] = 1;
linkedByIndex[d.target + "," + d.source] = 1;
});
function neighboring(a, b) {
return linkedByIndex[a.index + "," + b.index];
}
function nodeSize(d) {
if(options.nodesize){
return eval(options.radiusCalculation);
}else{
return 6}
}
function mouseover(d) {
var unfocusDivisor = 4;
link.transition().duration(200)
.style("opacity", function(l) { return d != l.source && d != l.target ? +options.opacity / unfocusDivisor : +options.opacity });
node.transition().duration(200)
.style("opacity", function(o) { return d.index == o.index || neighboring(d, o) ? +options.opacity : +options.opacity / unfocusDivisor; });
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", function(d){return nodeSize(d)+5;});
node.select("text").transition()
.duration(750)
.attr("x", 13)
.style("stroke-width", ".5px")
.style("font", 24 + "px ")
.style("opacity", function(o) { return d.index == o.index || neighboring(d, o) ? 1 : 0; });
}
function mouseout() {
node.style("opacity", +options.opacity);
link.style("opacity", +options.opacity);
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", function(d){return nodeSize(d);});
node.select("text").transition()
.duration(1250)
.attr("x", 0)
.style("font", options.fontSize + "px ")
.style("opacity", 0);
}
d3.selectAll(".node").on("mouseover", mouseover).on("mouseout", mouseout);
}
'
onRender(fn, customJS)

Meta-analysis flowchart

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
")

Position node to the left and right of an edge in DOT in graphviz

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;
}

Resources