如何在DiagrammeR中把文本显示在箭头上方?
我正在用这段代码,根据结构方程模型的结果来绘制图表:
create_sem_diagram_ex <- function(node_edges) {
sig_level <- 0.05
marginal_level <- 0.1
var_names <- c(
"CN_ratio" = "C/N ratio",
"tot_basal_area_m2perha"= "Forest basal area",
"pimu_cover" = "Mountain pine cover",
"elevation" = "Elevation",
"bac_tax_shannon_bc" = "Bacterial tax. div.",
"fun_tax_shannon_bc" = "Fungal tax. div."
)
rename_var <- function(var) {
ifelse(var %in% names(var_names), var_names[var], var)
}
left_column_default <- c("pimu_cover", "tot_basal_area_m2perha", "elevation")
all_nodes <- unique(c(node_edges$Predictor, node_edges$Response))
left_column <- left_column_default[left_column_default %in% all_nodes]
node_edges <- node_edges %>%
mutate(
edge_colour = case_when(
P.Value > marginal_level ~ "grey80",
P.Value <= sig_level & Std.Estimate > 0 ~ "forestgreen",
P.Value <= sig_level & Std.Estimate < 0 ~ "darkorange3",
P.Value <= marginal_level & Std.Estimate > 0 ~ "#99c58f",
P.Value <= marginal_level & Std.Estimate < 0 ~ "tan1"
),
penwidth = case_when(
P.Value <= sig_level ~ 2.5,
P.Value <= marginal_level ~ 1.5,
TRUE ~ 0.8
),
path_label = ifelse(P.Value <= marginal_level, sprintf("%.3f", Std.Estimate), "")
)
node_defs <- sapply(all_nodes, function(node) {
sprintf(' "%s" [label="%s", shape=box, style="rounded,filled", fillcolor="white", fontname=Helvetica];',
node, rename_var(node))
})
edges <- apply(node_edges, 1, function(row) {
label_attr <- if (nchar(row["path_label"]) > 0)
sprintf(', label="%s"', row["path_label"]) else ""
sprintf(
' "%s" -> "%s" [color="%s", penwidth=%s%s];',
row["Predictor"], row["Response"],
row["edge_colour"], row["penwidth"],
label_attr
)
})
# invisible edges keep mid-ranked nodes tidier
invisible_edges <- c()
if (length(left_column) > 1) {
for (i in 1:(length(left_column) - 1)) {
invisible_edges <- c(invisible_edges,
sprintf(' "%s" -> "%s" [style=invis];', left_column[i], left_column[i + 1]))
}
}
mid_column_default <- c("pH", "CN_ratio")
mid_column <- mid_column_default[mid_column_default %in% all_nodes]
mid_rank_block <- if (length(mid_column) > 0) {
paste0(" { rank=same;\n",
paste(sprintf(' "%s";', mid_column), collapse = "\n"),
"\n }\n\n")
} else ""
dot_spec <- paste0(
"digraph SEM {\n",
" graph [rankdir=LR, nodesep=0.2, ranksep=0.5];\n",
" edge [fontname=Helvetica, fontsize=10];\n\n",
paste(node_defs, collapse = "\n"),
"\n\n { rank=source;\n",
paste(sprintf(' "%s";', left_column), collapse = "\n"),
"\n }\n\n",
paste(invisible_edges, collapse = "\n"),
"\n\n",
paste(edges, collapse = "\n"),
"\n}"
)
grViz(dot_spec)
}
但边上的文本会被绘制在各自箭头的下方,这有时会导致信号被遮挡。在下面的示例中,-0.535的负号被完全遮挡。

我需要怎么修改,才能让文本出现在箭头之上?或者至少避开箭头?
解决方案
你可以通过将所有svg text 元素在视觉上放到最前面来实现,将它们追加到主图 graph0。
create_sem_diagram_ex(node_edges) |>
htmlwidgets::onRender('function(el, x) {
var svg = el.querySelector("svg");
var graph = svg.querySelector("g#graph0");
var texts = graph.querySelectorAll("g.edge text");
texts.forEach(function(t) {
graph.appendChild(t);
});
}')
数据、函数、库调用
library(DiagrammeR)
library(dplyr)
create_sem_diagram_ex <- function(node_edges) {
sig_level <- 0.05
marginal_level <- 0.1
var_names <- c(
"CN_ratio" = "C/N ratio",
"tot_basal_area_m2perha"= "Forest basal area",
"pimu_cover" = "Mountain pine cover",
"elevation" = "Elevation",
"bac_tax_shannon_bc" = "Bacterial tax. div.",
"fun_tax_shannon_bc" = "Fungal tax. div."
)
rename_var <- function(var) {
ifelse(var %in% names(var_names), var_names[var], var)
}
left_column_default <- c("pimu_cover", "tot_basal_area_m2perha", "elevation")
all_nodes <- unique(c(node_edges$Predictor, node_edges$Response))
left_column <- left_column_default[left_column_default %in% all_nodes]
node_edges <- node_edges %>%
mutate(
edge_colour = case_when(
P.Value > marginal_level ~ "grey80",
P.Value <= sig_level & Std.Estimate > 0 ~ "forestgreen",
P.Value <= sig_level & Std.Estimate < 0 ~ "darkorange3",
P.Value <= marginal_level & Std.Estimate > 0 ~ "#99c58f",
P.Value <= marginal_level & Std.Estimate < 0 ~ "tan1"
),
penwidth = case_when(
P.Value <= sig_level ~ 2.5,
P.Value <= marginal_level ~ 1.5,
TRUE ~ 0.8
),
path_label = ifelse(P.Value <= marginal_level, sprintf("%.3f", Std.Estimate), "")
)
node_defs <- sapply(all_nodes, function(node) {
sprintf(' "%s" [label="%s", shape=box, style="rounded,filled", fillcolor="white", fontname=Helvetica];',
node, rename_var(node))
})
edges <- apply(node_edges, 1, function(row) {
label_attr <- if (nchar(row["path_label"]) > 0)
sprintf(', label="%s"', row["path_label"]) else ""
sprintf(
' "%s" -> "%s" [color="%s", penwidth=%s%s];',
row["Predictor"], row["Response"],
row["edge_colour"], row["penwidth"],
label_attr
)
})
# invisible edges keep mid-ranked nodes tidier
invisible_edges <- c()
if (length(left_column) > 1) {
for (i in 1:(length(left_column) - 1)) {
invisible_edges <- c(invisible_edges,
sprintf(' "%s" -> "%s" [style=invis];', left_column[i], left_column[i + 1]))
}
}
mid_column_default <- c("pH", "CN_ratio")
mid_column <- mid_column_default[mid_column_default %in% all_nodes]
mid_rank_block <- if (length(mid_column) > 0) {
paste0(" { rank=same;\n",
paste(sprintf(' "%s";', mid_column), collapse = "\n"),
"\n }\n\n")
} else ""
dot_spec <- paste0(
"digraph SEM {\n",
" graph [rankdir=LR, nodesep=0.2, ranksep=0.5];\n",
" edge [fontname=Helvetica, fontsize=10];\n\n",
paste(node_defs, collapse = "\n"),
"\n\n { rank=source;\n",
paste(sprintf(' "%s";', left_column), collapse = "\n"),
"\n }\n\n",
paste(invisible_edges, collapse = "\n"),
"\n\n",
paste(edges, collapse = "\n"),
"\n}"
)
grViz(dot_spec)
}
set.seed(1)
node_edges <- data.frame(
Predictor = sample(c("elevation", "pimu_cover", "tot_basal_area_m2perha", "CN_ratio", "pH", "pimu_cover"), 10, replace = T),
Response = sample(c("elevation", "pimu_cover", "tot_basal_area_m2perha", "CN_ratio", "pH", "pimu_cover"), 10, replace = T),
Std.Estimate = rnorm(10),
P.Value = rnorm(10),
stringsAsFactors = FALSE
)
其他选项:
这些也是我尝试过的选项,但效果并不理想,因为它们会移动标签、改变颜色,却不能解决主要问题。它们也许对你有用。
你也可以尝试调整 taillabel labeldistance,但我发现这也相当手动。
edges <- apply(node_edges, 1, function(row) {
label_attr <- if (nchar(row["path_label"]) > 0)
sprintf(', taillabel="%s" labeldistance=1', row["path_label"]) else ""
...
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。
