I would like to create a flowchart using the DiagrammeR nodes and edges functionality with R instead of using the graphviz wrapper function.
However, I can't figure out how to make the edges straight to make it nice.
This is the graphviz solution that looks like what I want:
# Packages needed for the test
library(DiagrammeR)
# grViz solution
grViz("digraph flowchart {
# node definitions with substituted label text
node [fontname = Helvetica, shape = rectangle]
tab1 [label = '##1', group=gr1]
tab2 [label = '##2', group=gr2]
tab3 [label = '##3', group=gr3]
invis1 [style = invis, shape=point, width = 0, group=gr1]
invis1a [style = invis, shape=point, width = 0, group=gr2]
invis1b [style = invis, shape=point, width = 0, group=gr3]
# edge definitions with the node IDs
edge [arrowhead='none']
tab1 -> invis1;
invis1a -> invis1 -> invis1b; {rank=same invis1a invis1 invis1b}
edge [arrowhead='normal']
invis1a -> tab2;
invis1b -> tab3; {rank=same tab2 tab3}}
[1]: 'A'
[2]: 'B'
[3]: 'C'
")
This is my attempt to recreate the same graph with the nodes and edges solution:
# Packages needed for the test
library(DiagrammeR)
library(magrittr)
# Node and edge df solution
create_graph() %>%
add_node( # id 1
label = "A",
type = "group_1",
node_aes = node_aes(
style = "filled",
shape = "rectangle",
fixedsize = FALSE)
) %>%
add_node( # id 2
type = "group_1",
node_aes = node_aes(
style = "invisible",
height = 0,
width = 0)
) %>%
add_edge(
from = 1,
to = 2,
edge_aes = edge_aes(
arrowhead = "none")
) %>%
add_node( # id 3
type = "group_2",
node_aes = node_aes(
style = "invisible",
height = 0,
width = 0)
) %>%
add_edge(
from = 2,
to = 3,
edge_aes = edge_aes(
arrowhead = "none")
) %>%
add_node( # id 4
type = "group_3",
node_aes = node_aes(
style = "invisible",
height = 0,
width = 0)
) %>%
add_edge(
from = 2,
to = 4,
edge_aes = edge_aes(
arrowhead = "none")
) %>%
add_node( # id 5
label = "B",
type = "group_2",
node_aes = node_aes(
style = "filled",
shape = "rectangle",
fixedsize = FALSE)
) %>%
add_edge(
from = 3,
to = 5,
edge_aes = edge_aes(
arrowhead = "normal")
) %>%
add_node( # id 6
label = "C",
type = "group_3",
node_aes = node_aes(
style = "filled",
shape = "rectangle",
fixedsize = FALSE)
) %>%
add_edge(
from = 4,
to = 6,
edge_aes = edge_aes(
arrowhead = "normal")
) %>%
render_graph()
Related
I would love to have your input how to solve this issues.
I have a time series (x=date) ggplot with bars (y=cmass1), and my bars are on position="stack" using a factor (polymer) to display polymer types for each sample.
Each bar represents another sampling station (factor sample), and I would like to identify which bar is which station (factor "sample" in my data frame) and add the label above each bar.
I've come so far that I can show the "sample" labels, but then there appear multiple replicated labels (one for each data point in the stacked parts of the bar). But I need only one per bar!
Can someone help, how I can create one label per bar (above each bar) that identifies which sample it is (without manual annotation)?
Additional date display problem:
Also, on one date (11 November) I have two samples, and in this plot they are cumulated, but I would need them next to each - so two as stacked bars on one date (like with besides=TRUE, but that doesn't seem to work with stacked bars). Any help here?
I hope it is clear, and thanks so much for any help!
Cleo
The plot, where S1, S2 etc should be above each bar as a label
Dataframe view_partial
ggplot(Merg1[!(is.na(Merg1$campaign)),] ,
aes(date,y=cmass1,group_by(sample1), fill=polymer))+
geom_col(show.legend = T, alpha = 0.8, position="stack",
stat="identity")+
xlab("July 2021 November 2021 February 2022 July 2022") +
facet_grid(.~campaign, scales = "free_x",space = "free_x" )+
geom_point(aes(y=montsouris_mm*20 ),color="#A3009F",size=2.5, position="dodge")+
geom_point(aes(y=melun_mm*20 ),color="#558C8C",size=2.5, position="dodge")+
geom_point(aes(y=fauville_mm*20 ),color="#E8DB7D",size=2.5, position="dodge")+
scale_y_continuous(expand = c(0,0),limits=c(0, 1000), breaks = seq(0, 1000, by = 100),
sec.axis = sec_axis(~./20, name = "Precipitation (mm)",
breaks = seq(0, 50, by = 10))) +
scale_x_date(date_breaks = "1 day", labels = date_format("%d"))+
ylab(expression(bold(paste(~C[mass]~ (µg ~L^{-1}))))) +
theme(axis.text.x=element_text(color="black", size=12, angle=0, vjust=0.5),
axis.text.y=element_text(color="black", size=12, angle=0, vjust=0.5),
axis.ticks.x=element_blank(),
axis.title.x = element_text(size = 12,
color = "black",
face = "bold"),
strip.background = element_rect(color="white", fill="white", size=0.5,
linetype="solid"),
legend.text = element_text(color = "black",size = 12),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_rect(size = 0.5,colour="#D4CDCB",
fill="white" ,linetype = 'solid'),
legend.key.height= unit(0.2, 'cm'),
legend.key.width= unit(0.4, 'cm'))+
scale_fill_manual(name = "", values = MPcol, breaks = c("abs","acrylic", "acrylic paints", "alkyd","epoxy", "pa", "pan_acrylic fibre", "pe", "polyester", "pp", "ps", "pu", "pvac", "pvc", "sbr", "vinyl copolymer"),
labels=c("Acrylonitrile butadiene styrene (ABS)","Acrylic", "Acrylic paint", "Alkyd", "Epoxy", "Polyamide (PA)", "Pan acrylic fibre", "Polyethylene (PE)", "Polyester (PET)", "Polypropylene (PP)", "Polystyrene (PS)", "Polyurethane (PU)", "Polyvinyl acetate (PVAC)", "Poly vinyl chloride (PVC)", "Styrene butadiene rubber (SBR)", "Vinyl copolymere"))+
theme(legend.position = "bottom",
legend.background = element_rect(fill = "#FFFCFB", # Background
colour = 1),
legend.title = element_text(family = "sans",
color = "black",
size = 10,
face = 2)) +
theme(panel.grid.minor = element_line(color = "#D4CDCB",
size = 0.15,
linetype = 2))+
theme(strip.text.x = element_text(size=14, face="bold",
vjust = 2, color="black")) +
#geom_text( label = label1, vjust = -1, position = position_dodge(0.90), size = 3, hjust=-0.5)+
labs(title = "Microplastics",
subtitle = "Mass Concentrations by Polymer Types",
caption = "Still missing S4 repeated samples and M1 in Campaign D. S4 in Campaign C cumulated repetaed samples. MPs >300µm are excluded, also natural particles are excluded.",
tag = "Fig. 5-1") +
theme(plot.title = element_text(family = "serif", # Font family
face = "bold", # Font face
color = 1, # Font color
size = 16, # Font size
hjust = 1, # Horizontal adjustment
vjust = 1, # Vertical adjustment
angle = 0, # Font angle
lineheight = 1, # Line spacing
margin = margin(5, 0, 0, 0)), # Margins (t, r, b, l)
plot.subtitle = element_text(family = "serif",
hjust = 1, size=14), # Subtitle customization
plot.caption = element_text(hjust = 0.25, size =11,
family = "serif",face = "italic"), # Caption customization
plot.tag = element_text(face = "italic"), # Tag customization
plot.title.position = "plot", # Title and subtitle position ("plot" or "panel")
plot.caption.position = "panel", # Caption position ("plot" or "panel")
plot.tag.position = "top") # Tag position
i have this table
animals = {
{sname = "bunny", name = "bunny hase", size = 4, size2 = 8, size3 = 9},
{sname = "mouse", name = "Micky Mouse", size = 1, size2 = 12, size3 = 22},
{sname = "cow", name = "Die Kuh", size = 30, size2 = 33, size3 = 324
}
there i can search by a listed entry
for _,v in pairs(animals) do
if v.sname == "bunny" then
print(v.sname, v.name, v.size, v.size2, v.size3)
break
end
end
and get the result:
bunny bunny hase 4 8 9
Now i want to search in my table by starting with a single Letter, for example "b", that show me all the entries starting with the letter "b" to get the same result?
I found no Solution. May you can help me?
First: The table animals needs a trailing } ;-)
Put it in a Lua -i console and play around with...
>animals = {
{sname = "bunny", name = "bunny hase", size = 4, size2 = 8, size3 = 9},
{sname = "mouse", name = "Micky Mouse", size = 1, size2 = 12, size3 = 22},
{sname = "cow", name = "Die Kuh", size = 30, size2 = 33, size3 = 324}
}
-- Now set a __call metamethod on same table
>setmetatable(animals,{__call=function(tab,...)
local args={...}
for key, value in pairs(tab) do
if value.sname:find(args[1],1) then print(key,'=',value.sname) end
end
end})
table: 0x565c4a00
-- Lets try it once
>animals('b')
1 = bunny
-- Next one
>animals('c')
3 = cow
-- Last one
>animals('m')
2 = mouse
Using metatables holds your stuff together.
Another fine place is the __index metamethod that can hold all functions you need for that table and can be used like the string functions on a string.
( Like: value.sname:find(args[1],1) )
This leads to the heart of what find should do.
In first example it looks in whole sname for a matching pattern.
Check the Lua patterns what also can be useful.
Maybe a ^ only for the begining sounds smart?
So construct the find pattern: '^'..args[1]
...and use more than one letter if you have a cow, crow, frog and fish in your animals.
Example with function name find in __index
>animals = {
{sname = "bunny", name = "bunny hase", size = 4, size2 = 8, size3 = 9},
{sname = "mouse", name = "Micky Mouse", size = 1, size2 = 12, size3 = 22},
{sname = "cow", name = "Die Kuh", size = 30, size2 = 33, size3 = 324}
}
-- Place a find function into __index
>setmetatable(animals,{__index={find=function(tab,...)
local args={...}
for key, value in pairs(tab) do
if value.sname:find('^'..args[1]) then print(key,'=',value.sname) end
end
end}})
table: 0x565c3db0
-- first
>animals:find('c')
3 = cow
-- next
>animals:find('m')
2 = mouse
-- last
>animals:find('b')
1 = bunny
If you like to print all key values then extend the print() in find().
Stop, i found an issue....
Look here - i prefer the first solution:
animals = {
{sname = "bunny", name = "bunny hase", size = 4, size2 = 8, size3 = 9},
{sname = "mouse", name = "Micky Mouse", size = 1, size2 = 12, size3 = 22},
{sname = "cow", name = "Die Kuh", size = 30, size2 = 33, size3 = 324}
}
-- Now set a __call metamethod on same table
setmetatable(animals,{__call=function(tab,...)
local args={...}
for v,k in pairs(tab) do
if k.sname:find(args[1],1) then print(v,'=',k.sname) end
end
end})
-- Search Entries with Start U.....
-- there should be no result, but....
animals('u')
i get the Result:
1 = bunny
2 = mouse
that should not be the result!
The following directed example graph is initially arranged with the visIgraphLayout("layout_with_sugiyama") algorithm:
library(dplyr)
library(visNetwork)
### create nodes
nodes <- tibble(id = c (1:13), group = c("D","D","D","A","C","C","C","C","A","A","C","A","A"),
label = c("only outgoing a","only outgoing b","only outgoing c","only incoming d","e","f","g","h","only incoming i","only incoming j","k","only incoming l","only incoming m")
### create edges
edges <- tibble(id = 1:12, from = c(1,1,2,3,3,7,6,8,8,5,11,11), to = c(5,6,5,4,7,8,8,9,11,10,12,13), arrows = "to")
### visualize graph
visNetwork(nodes, edges, main = "Test") %>%
visGroups(groupname = "A", size = 25, color = list(
background = "#005A83",
border = "#005A83")) %>%
visGroups(groupname = "C",size = 20, color = list(
background = "#994350",
border = "#000000")) %>%
visGroups(groupname = "D", size = 20, color = list(
background = "#44706F",
border = "#44706F")) %>%
visEdges(smooth = F, font = list("size"=5), color = "black") %>%
visLegend(width = 0.2) %>%
visIgraphLayout("layout_with_sugiyama") %>%
visInteraction(navigationButtons = TRUE) %>%
visPhysics(enabled = F)
The algorithm arranged the directed graph from the top to the bottom. I would like to visualize it from the left to the right. Hence, i only would like to rotate the graph by 90 degree to the left so that the green start-nodes are at the left and the blue end-nodes at the right. The legend etc. should not be affected.
Anybody an idea?
Found a solution due to bthieurmel on github:
graph <- visNetwork(nodes, edges, main = "Test") %>%
visGroups(groupname = "A", size = 25, color = list(
background = "#005A83",
border = "#005A83")) %>%
visGroups(groupname = "C",size = 20, color = list(
background = "#994350",
border = "#000000")) %>%
visGroups(groupname = "D", size = 20, color = list(
background = "#44706F",
border = "#44706F")) %>%
visEdges(smooth = F, font = list("size"=5), color = "black") %>%
visLegend(width = 0.2) %>%
visIgraphLayout("layout_with_sugiyama") %>%
visInteraction(navigationButtons = TRUE) %>%
visPhysics(enabled = F)
# access to the coordinates of the graph object with graph$nodes$x
# change the x and y coordinates
coord_y <- graph$x$nodes$y
graph$x$nodes$y <- graph$x$nodes$x
graph$x$nodes$x <- coord_y
graph
I have this two dataframes
1) t1 (Var1(numeric), Var2(string), Freq (numeric))
2) pref.media (pref.media (numeric)
I have this separated graphs, but I want to print like two series in the same graph
1) Column chart, ok
column1 <- highchart() %>%
hc_add_series(t1$Freq, type = "column") %>%
hc_xAxis(categories = t1$Var1) %>%
hc_plotOptions(series = list(showInLegend = FALSE,dataLabels = list(enabled = TRUE, color = t1$Var1)))
2) Solid gauge chart (ok)
gauge1 <- highchart(width = 800, height = 600) %>%
hc_chart(type = "solidgauge",backgroundColor = "#F0F0F0",marginTop = 50) %>%
hc_title(text = "Preferencia",style = list(fontSize = "24px")) %>%
hc_tooltip(borderWidth = 0, backgroundColor = 'none',shadow = FALSE,style = list(fontSize = '16px')) %>%
hc_pane(startAngle = -90,endAngle = 90) %>%
hc_yAxis(min = 0,max = 11,lineWidth = 0,tickPositions = list(0,1,2,3,4,5,6,7,8,9,10,11)) %>%
hc_plotOptions(solidgauge = list(borderWidth = '34px',dataLabels = list(enabled = TRUE, style = list(borderWidth = 3,backgroundColor = 'none',shadow = FALSE, fontSize = '16px',color="#888800")),linecap = 'round',stickyTracking = FALSE)) %>%
hc_add_series(name = "Preferencia",borderColor = "#000000",data = list(list(color = "#888800"),radius = "100%",innerRadius = "100%",y = round(pref.media[[1,1]],2)))
3) Mixing the charts (not ok, with errors)
highchart() %>%
hc_add_series(t1, "column", hcaes(x = Var1, y = Freq), name = "Preferencia") %>%
hc_add_series(pref.media, "solidgauge", hcaes(name = "Gauge", y = round(pref.media[[1,1]],2)), name = "Indicador") %>%
hc_plotOptions(
series = list(showInLegend = FALSE,pointFormat = "{point.y}%"),
column = list(colorByPoint = TRUE),
solidgauge = list(borderWidth = '34px',dataLabels = list(enabled = TRUE),linecap = 'round',stickyTracking = FALSE)) %>%
hc_pane(startAngle = -90,endAngle = 90) %>%
hc_yAxis(title = list(text = "Porcentaje de preferencia"),labels = list(format = "{value}%"), max = 100) %>%
hc_xAxis(categories = t1$Var1) %>%
hc_title(text = "Título") %>%
hc_subtitle(text = "Subtítulo")
I don't understand the sequence for mixing two series. I tried it with a J.Kunst's example in http://jkunst.com/highcharter/highcharts.html
Thanks
> polyline = {color = "blue", thickness = 2, npoints = 4, {x=0,y=0}, {x=-10,y=0}, {x=-10,y=1}, {x=0,y=1}}
> print(polyline[2])
table: 0x55ad5c0f3f90
> print(polyline[2].x)
-10
Why does print(polyline[2]) give out -10 ?
If you do not provide a key explicitly, table elements are assigned to numeric keys within the table constructor.
polyline = {color = "blue", thickness = 2, npoints = 4, {x=0,y=0}, {x=-10,y=0}, {x=-10,y=1}, {x=0,y=1}}
is equivalent to
do
polyline = {}
polyline.color = "blue"
polyline.thickness = 2
polyline.npoints = 4
do
polyline[1] = {}
polyline[1].x = 0
polyline[1].y = 0
end
do
polyline[2] = {}
polyline[2].x = -10
polyline[2].y = 0
end
do
polyline[3] = {}
polyline[3].x = -10
polyline[3].y = 1
end
do
polyline[4] = {}
polyline[4].x = 0
polyline[4].y = 1
end
end
Refer to
https://www.lua.org/manual/5.3/manual.html#3.4.9