visNetwork: Rotate Graph arranged by Sugiyama Layout Algorithm - visnetwork

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

Related

Random forest variable importance

Does anyone know how to do variable importance for multiple factors (TILLAGEm, CROPSTAGEm ) in R? Show multiple factor effects on..
1.factor
TILLAGEm <- randomForest(TILLAGE~SWC+DHA+GLU+PHOS+LC, data=datarandom,importance=TRUE,proximity=TRUE,mtry=3,ntree=1000, maxnodes=21 )
2.factor
CROPSTAGEm <- randomForest(CROPSTAGE~SWC+DHA+GLU+PHOS+LC, data=datarandom, importance=TRUE,proximity=TRUE,mtry=2,ntree=1000, maxnodes=21 )
RandomForest::varImpPlot(TILLAGEm, type=1, sort = T, scale = T, bg = "blue", pch=22, main = 'TILLAGE') #PLOT
RandomForest::varImpPlot(TILLAGEm, type=1, sort = T, scale = T, bg = "blue", pch=22, main = 'TILLAGE') #PLOT
type here
enter image description here

How to assign one conditional label per stacked bar (not per stack) on time series ggplot in facet grid

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

Why does Tesseract fail to recognize 6 out of 26 of my alphabetic keyboard keys even with several parameter tunings?

TL;DR I'm using:
adaptive thresholding
segmenting by keys (width/height ratio) - see green boxes in image result
psm 10 to treat each key as a character
but it fails to recognize some keys, falsely identifies others or identifies 2 for 1 char (see the L character in the image result, it's an L and P), etc.
Note: I cropped the image and re-ran the results to get it to fit on this site, but before cropping it did slightly better (recognized more keys, fewer false positives, etc).
I just want it to recognize the alphabet keys. Ultimately I will want it to work for realtime video.
config:
'-l eng --oem 1 --psm 10 -c tessedit_char_whitelist="ABCDEFGHIJKLMNOPQRSTUVWXYZ"'
I've tried scaling the image differently, scaling the individual key segments, using opening/closing/etc but it doesn't recognize all the keys.
original image
image result
Update: new results if I make the image straighter (bird's eye) and remove the whitelisting, it manages to detect all for the most part (although it thinks the O is a 0 and the I is a |, which is understandable). Why is this and how could I make this adaptive enough for a dynamic video when it is so sensitive to these conditions?
Code:
import pytesseract
import numpy as np
try:
from PIL import Image
except ImportError:
import Image
import cv2
from tqdm import tqdm
from collections import defaultdict
def get_missing_chars(dict):
capital_alphabet = [chr(ascii) for ascii in range(65, 91)]
return [let for let in capital_alphabet if let not in dict]
def draw_box_and_char(img, contour_dims, c, box_col, text_col):
x, y, w, h = contour_dims
top_left = (x, y)
bot_right = (x + w, y+h)
font_offset = 3
text_pos = (x+h//2+12, y+h-font_offset)
img_copy = img.copy()
cv2.rectangle(img_copy, top_left, bot_right, box_col, 2)
cv2.putText(img_copy, c, text_pos, cv2.FONT_HERSHEY_SIMPLEX, fontScale=.5, color=text_col, thickness=1, lineType=cv2.LINE_AA)
return img_copy
def detect_keys(img):
scaling = .25
img = cv2.resize(img, None, fx=scaling, fy=scaling, interpolation=cv2.INTER_AREA)
print("img shape", img.shape)
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ratio_min = 0.7
area_min = 1000
nbrhood_size = 1001
bias = 2
# adapt to different lighting
bin_img = cv2.adaptiveThreshold(gray_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
cv2.THRESH_BINARY_INV, nbrhood_size, bias)
items = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = items[0] if len(items) == 2 else items[1]
key_contours = []
for c in contours:
x, y, w, h = cv2.boundingRect(c)
ratio = h/w
area = cv2.contourArea(c)
# square-like ratio, try to get character
if ratio > ratio_min and area > area_min:
key_contours.append(c)
detected = defaultdict(int)
n_kept = 0
img_copy = cv2.cvtColor(bin_img, cv2.COLOR_GRAY2RGB)
let_to_contour = {}
n_contours = len(key_contours)
# offset to get smaller square within the key segment for easier char recognition
offset = 10
show_each_char = False
for _, c in tqdm(enumerate(key_contours), total=n_contours):
x, y, w, h = cv2.boundingRect(c)
ratio = h/w
area = cv2.contourArea(c)
base = np.zeros(bin_img.shape, dtype=np.uint8)
base.fill(255)
n_kept += 1
new_y = y+offset
new_x = x+offset
new_h = h-2*offset
new_w = w-2*offset
base[new_y:new_y+new_h, new_x:new_x+new_w] = bin_img[new_y:new_y+new_h, new_x:new_x+new_w]
segment = cv2.bitwise_not(base)
# try scaling up individual keys
# scaling = 2
# segment = cv2.resize(segment, None, fx=scaling, fy=scaling, interpolation=cv2.INTER_CUBIC)
# psm 10: treats the segment as a single character
custom_config = r'-l eng --oem 1 --psm 10 -c tessedit_char_whitelist="ABCDEFGHIJKLMNOPQRSTUVWXYZ"'
d = pytesseract.image_to_data(segment, config=custom_config, output_type='dict')
conf = d['conf']
c = d['text'][-1]
if c:
# sometimes recognizes multiple keys even though there is only 1
for sub_c in c:
# save character and contour to draw on image and show bounds/detection
if sub_c not in let_to_contour or (sub_c in let_to_contour and conf > let_to_contour[sub_c]['conf']):
let_to_contour[sub_c] = {'conf': conf, 'cont': (new_x, new_y, new_w, new_h)}
else:
c = "?"
text_col = (0, 0, 255)
if show_each_char:
contour_dims = (new_x, new_y, new_w, new_h)
box_col = (0, 255, 0)
text_col = (0, 0, 0)
segment_with_boxes = draw_box_and_char(segment, contour_dims, c, box_col, text_col)
cv2.imshow('segment', segment_with_boxes)
cv2.waitKey(0)
cv2.destroyAllWindows()
# draw boxes around recognized keys
for c, data in let_to_contour.items():
box_col = (0, 255, 0)
text_col = (0, 0, 0)
img_copy = draw_box_and_char(img_copy, data['cont'], c, box_col, text_col)
detected = {k: 1 for k in let_to_contour}
for det in let_to_contour:
print(det, let_to_contour[det])
print("total detected: ", let_to_contour.keys())
missing = get_missing_chars(detected)
print(f"n_missing: {len(missing)}")
print(f"chars missing: {missing}")
return img_copy
if __name__ == "__main__":
img_file = "keyboard.jpg"
img = cv2.imread(img_file)
img_with_detected_keys = detect_keys(img)
cv2.imshow("detected", img_with_detected_keys)
cv2.waitKey(0)
cv2.destroyAllWindows()

Creating flowchart with DiagrammeR nodes and edges instead of graphviz

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

Mixing solidguage and column in a graph with highcharter

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

Resources