在R中绘制简单的中介图
Drawing simple mediation diagram in R
有没有一种(最好是简单直接的)方法来在 R 中绘制带有中介系数的简单路径图?
我一直在寻找 DiagrammeR
包,但这看起来有点矫枉过正(老实说,我没弄清楚如何制作情节)。
我知道的其他选项是Dia or Inkscape,但那些需要手动定位、连接路径等
mediation
包有一个 plot
选项,但它绘制了自举的 CI,我想要实现的是一个简单的路径,其系数如下所示:
我对 ggraph 一无所知,但这可能是一条可能的路线。这是 5 分钟的谷歌搜索让我得到的结果:
library(ggraph)
require(igraph)
test <- data.frame(from = c(1,2,3), to=c(2,3,1), coef = letters[1:3])
simple <- graph_from_data_frame(test)
V(simple)$name <- LETTERS[1:3]
ggraph(simple, layout = 'auto') +
geom_edge_link(aes(label = coef),
angle_calc = 'along',
label_dodge = unit(2.5, 'mm'),
arrow = arrow(length = unit(4, 'mm')),
end_cap = circle(3, 'mm')) +
geom_node_label(aes(label = name),size = 5) +
theme_graph()
我不知道如何强制执行几何(如果可能的话),但好消息是布局可以自动概括。
虽然 解决方案也可能有效,但我一直在寻找可发布的格式。
library(diagram)
中的函数 plotmat
是最接近我的示例的函数:
对于可重现的示例,请使用:
library(diagram)
data <- c(0, "'.47*'", 0,
0, 0, 0,
"'.36*'", "'.33* (.16)'", 0)
M<- matrix (nrow=3, ncol=3, byrow = TRUE, data=data)
plot<- plotmat (M, pos=c(1,2),
name= c( "Math self-efficacy","Math ability", "Interest in the math major"),
box.type = "rect", box.size = 0.12, box.prop=0.5, curve=0)
您可以使用 'psych' 包来测试您的 moderation/mediation 它也会给您一个情节。
mediate(Output ~ Independent1 + (Mediator), data =mydata)
这里有两个版本的中介图是用 DiagrammeR
构建的,第三个是用 TikZ 构建的。每个人都有优点和缺点:
DiagrammeR + Graphviz:
- 优点:使用提供的功能可以轻松创建图表,有很多选项可以调整节点的设计。
- 缺点:调整边缘文本的选项很少,输出是一个 htmlwidget 对象,可以打印为 pdf,但在特定情况下(例如在 for 循环中)可能需要转换。
TikZ
- 优点:高度可定制,包括边缘文字;使用提供的功能轻松生成图表
- 缺点:如果您需要 HTML 输出,它是为 LaTeX 设计的;语法可能令人困惑
DiagrammeR 原生语法(提供只是为了完整性)
- 优点:代码非常易于阅读,为
R
用户编辑
- 缺点:调整边缘文本的明显方法更少
我用函数 med_diagram
对第一个和第二个示例进行了编码,该函数使用 glue
包 assemble 相关的 graphviz 或 TikZ 代码。该函数需要一个 data.frame,它需要一行包含相关标签和系数的列。对于 DiagrammeR 特定的功能,也有参数来调整设计的各种元素。
Diagrammer + Graphviz
med_data <-
data.frame(
lab_x = "Math\nAbility",
lab_m = "Math\nself-efficacy",
lab_y = "Interest in the\nmath major",
coef_xm = ".47*",
coef_my = ".36*",
coef_xy = "0.33* (.16)"
)
med_diagram <- function(data, height = .75, width = 2, graph_label = NA, node_text_size = 12, edge_text_size = 12, color = "black", ranksep = .2, minlen = 3){
require(glue)
require(DiagrammeR)
data$height <- height # node height
data$width <- width # node width
data$color <- color # node + edge border color
data$ranksep <- ranksep # separation btwn mediator row and x->y row
data$minlen <- minlen # minimum edge length
data$node_text_size <- node_text_size
data$edge_text_size <- edge_text_size
data$graph_label <- ifelse(is.na(graph_label), "", paste0("label = '", graph_label, "'"))
diagram_out <- glue::glue_data(data,
"digraph flowchart {
fontname = Helvetica
<<graph_label>>
graph [ranksep = <<ranksep>>]
# node definitions with substituted label text
node [fontname = Helvetica, shape = rectangle, fixedsize = TRUE, width = <<width>>, height = <<height>>, fontsize = <<node_text_size>>, color = <<color>>]
mm [label = '<<lab_m>>']
xx [label = '<<lab_x>>']
yy [label = '<<lab_y>>']
# edge definitions with the node IDs
edge [minlen = <<minlen>>, fontname = Helvetica, fontsize = <<edge_text_size>>, color = <<color>>]
mm -> yy [label = '<<coef_my>>'];
xx -> mm [label = '<<coef_xm>>'];
xx -> yy [label = '<<coef_xy>>'];
{ rank = same; mm }
{ rank = same; xx; yy }
}
", .open = "<<", .close = ">>")
DiagrammeR::grViz(diagram_out)
}
med_diagram(med_data)
抖音
TikZ 和 PGF 需要作为序言中的 LaTeX 包加载。下面的示例代码包括这些包和一些额外的命令,例如,为图表中使用的 'mynode' 设置全局规范。我收到了在我的序言中包含 \pgfplotsset{compat=1.17}
的警告,但对其他人来说可能没有必要。请注意,此代码基于此处提供的示例:https://tex.stackexchange.com/a/225940/34597
---
title: "Sample Rmd"
author: "Your name here"
output: pdf_document
header-includes:
- \usepackage{tikz}
- \usepackage{pgfplots}
- \pgfplotsset{compat=1.17}
- \tikzset{mynode/.style={draw,text width=1in,align=center} }
- \usetikzlibrary{positioning}
---
```{r, load_packages, include = FALSE}
library(glue)
```
```{r, load_function}
med_diagram_tikz <- function(data) {
glue::glue_data(med_data,
"
\begin{figure}
\begin{center}
\begin{tikzpicture}[font=\sffamily]
\node[mynode] (m){<<lab_m>>};
\node[mynode,below left=of m](x) {<<lab_x>>};
\node[mynode,below right=of m](y) {<<lab_y>>};
\draw[-latex] (x.north) -- node[auto] {<<coef_xm>>} (m.west);
\draw[-latex] (m.east) -- node[auto] {<<coef_my>>} (y.north);
\draw[-latex] (x.east) --
node[below=2mm, align=center] {<<coef_xy>>} (y.west);
\end{tikzpicture}
\end{center}
\end{figure}
",
.open = "<<", .close = ">>"
)
}
```
```{r create_diagram, echo = FALSE, results = 'asis'}
med_data <-
data.frame(
lab_x = "Math\\Ability",
lab_m = "Math\\self-efficacy",
lab_y = "Interest in the\\math major",
coef_xm = ".47*",
coef_my = ".36*",
coef_xy = "0.33* (.16)"
)
tikz_diagram_out <- med_diagram_tikz(med_data)
# requires chunk header to be set to results = 'asis'
cat("\n", tikz_diagram_out, "\n")
```
Diagrammer 原生语法
中介图的第三个版本使用的语法更容易被 R
用户理解,但我不喜欢边缘标签文本的奇怪放置方式(因此有上面的两个替代版本)。
library(DiagrammeR)
# Create a node data frame (ndf)
ndf <- create_node_df(
n = 3,
label = c( "Math\nself-efficacy","Math\nability", "Interest in\nthe math major"),
shape = rep("rectangle", 3),
style = "empty",
fontsize = 6,
fixedsize = TRUE,
height = .5,
width = .75,
color = "gray80",
x = c(1, 2, 3),
y = c(1, 2, 1)
)
# Create an edge data frame (edf)
edf <- create_edge_df(
from = c(1, 1, 2),
to = c(2, 3, 3),
label = c(".47*", ".33* (.16)", ".36*"),
fontsize = 6,
minlen = 1,
color = "gray80",
)
# Create a graph with the ndf and edf
graph <- create_graph(
nodes_df = ndf,
edges_df = edf
)
graph %>%
render_graph()
有没有一种(最好是简单直接的)方法来在 R 中绘制带有中介系数的简单路径图?
我一直在寻找 DiagrammeR
包,但这看起来有点矫枉过正(老实说,我没弄清楚如何制作情节)。
我知道的其他选项是Dia or Inkscape,但那些需要手动定位、连接路径等
mediation
包有一个 plot
选项,但它绘制了自举的 CI,我想要实现的是一个简单的路径,其系数如下所示:
我对 ggraph 一无所知,但这可能是一条可能的路线。这是 5 分钟的谷歌搜索让我得到的结果:
library(ggraph)
require(igraph)
test <- data.frame(from = c(1,2,3), to=c(2,3,1), coef = letters[1:3])
simple <- graph_from_data_frame(test)
V(simple)$name <- LETTERS[1:3]
ggraph(simple, layout = 'auto') +
geom_edge_link(aes(label = coef),
angle_calc = 'along',
label_dodge = unit(2.5, 'mm'),
arrow = arrow(length = unit(4, 'mm')),
end_cap = circle(3, 'mm')) +
geom_node_label(aes(label = name),size = 5) +
theme_graph()
我不知道如何强制执行几何(如果可能的话),但好消息是布局可以自动概括。
虽然
library(diagram)
中的函数 plotmat
是最接近我的示例的函数:
对于可重现的示例,请使用:
library(diagram)
data <- c(0, "'.47*'", 0,
0, 0, 0,
"'.36*'", "'.33* (.16)'", 0)
M<- matrix (nrow=3, ncol=3, byrow = TRUE, data=data)
plot<- plotmat (M, pos=c(1,2),
name= c( "Math self-efficacy","Math ability", "Interest in the math major"),
box.type = "rect", box.size = 0.12, box.prop=0.5, curve=0)
您可以使用 'psych' 包来测试您的 moderation/mediation 它也会给您一个情节。
mediate(Output ~ Independent1 + (Mediator), data =mydata)
这里有两个版本的中介图是用 DiagrammeR
构建的,第三个是用 TikZ 构建的。每个人都有优点和缺点:
DiagrammeR + Graphviz:
- 优点:使用提供的功能可以轻松创建图表,有很多选项可以调整节点的设计。
- 缺点:调整边缘文本的选项很少,输出是一个 htmlwidget 对象,可以打印为 pdf,但在特定情况下(例如在 for 循环中)可能需要转换。
TikZ
- 优点:高度可定制,包括边缘文字;使用提供的功能轻松生成图表
- 缺点:如果您需要 HTML 输出,它是为 LaTeX 设计的;语法可能令人困惑
DiagrammeR 原生语法(提供只是为了完整性)
- 优点:代码非常易于阅读,为
R
用户编辑 - 缺点:调整边缘文本的明显方法更少
- 优点:代码非常易于阅读,为
我用函数 med_diagram
对第一个和第二个示例进行了编码,该函数使用 glue
包 assemble 相关的 graphviz 或 TikZ 代码。该函数需要一个 data.frame,它需要一行包含相关标签和系数的列。对于 DiagrammeR 特定的功能,也有参数来调整设计的各种元素。
Diagrammer + Graphviz
med_data <-
data.frame(
lab_x = "Math\nAbility",
lab_m = "Math\nself-efficacy",
lab_y = "Interest in the\nmath major",
coef_xm = ".47*",
coef_my = ".36*",
coef_xy = "0.33* (.16)"
)
med_diagram <- function(data, height = .75, width = 2, graph_label = NA, node_text_size = 12, edge_text_size = 12, color = "black", ranksep = .2, minlen = 3){
require(glue)
require(DiagrammeR)
data$height <- height # node height
data$width <- width # node width
data$color <- color # node + edge border color
data$ranksep <- ranksep # separation btwn mediator row and x->y row
data$minlen <- minlen # minimum edge length
data$node_text_size <- node_text_size
data$edge_text_size <- edge_text_size
data$graph_label <- ifelse(is.na(graph_label), "", paste0("label = '", graph_label, "'"))
diagram_out <- glue::glue_data(data,
"digraph flowchart {
fontname = Helvetica
<<graph_label>>
graph [ranksep = <<ranksep>>]
# node definitions with substituted label text
node [fontname = Helvetica, shape = rectangle, fixedsize = TRUE, width = <<width>>, height = <<height>>, fontsize = <<node_text_size>>, color = <<color>>]
mm [label = '<<lab_m>>']
xx [label = '<<lab_x>>']
yy [label = '<<lab_y>>']
# edge definitions with the node IDs
edge [minlen = <<minlen>>, fontname = Helvetica, fontsize = <<edge_text_size>>, color = <<color>>]
mm -> yy [label = '<<coef_my>>'];
xx -> mm [label = '<<coef_xm>>'];
xx -> yy [label = '<<coef_xy>>'];
{ rank = same; mm }
{ rank = same; xx; yy }
}
", .open = "<<", .close = ">>")
DiagrammeR::grViz(diagram_out)
}
med_diagram(med_data)
抖音
TikZ 和 PGF 需要作为序言中的 LaTeX 包加载。下面的示例代码包括这些包和一些额外的命令,例如,为图表中使用的 'mynode' 设置全局规范。我收到了在我的序言中包含 \pgfplotsset{compat=1.17}
的警告,但对其他人来说可能没有必要。请注意,此代码基于此处提供的示例:https://tex.stackexchange.com/a/225940/34597
---
title: "Sample Rmd"
author: "Your name here"
output: pdf_document
header-includes:
- \usepackage{tikz}
- \usepackage{pgfplots}
- \pgfplotsset{compat=1.17}
- \tikzset{mynode/.style={draw,text width=1in,align=center} }
- \usetikzlibrary{positioning}
---
```{r, load_packages, include = FALSE}
library(glue)
```
```{r, load_function}
med_diagram_tikz <- function(data) {
glue::glue_data(med_data,
"
\begin{figure}
\begin{center}
\begin{tikzpicture}[font=\sffamily]
\node[mynode] (m){<<lab_m>>};
\node[mynode,below left=of m](x) {<<lab_x>>};
\node[mynode,below right=of m](y) {<<lab_y>>};
\draw[-latex] (x.north) -- node[auto] {<<coef_xm>>} (m.west);
\draw[-latex] (m.east) -- node[auto] {<<coef_my>>} (y.north);
\draw[-latex] (x.east) --
node[below=2mm, align=center] {<<coef_xy>>} (y.west);
\end{tikzpicture}
\end{center}
\end{figure}
",
.open = "<<", .close = ">>"
)
}
```
```{r create_diagram, echo = FALSE, results = 'asis'}
med_data <-
data.frame(
lab_x = "Math\\Ability",
lab_m = "Math\\self-efficacy",
lab_y = "Interest in the\\math major",
coef_xm = ".47*",
coef_my = ".36*",
coef_xy = "0.33* (.16)"
)
tikz_diagram_out <- med_diagram_tikz(med_data)
# requires chunk header to be set to results = 'asis'
cat("\n", tikz_diagram_out, "\n")
```
Diagrammer 原生语法
中介图的第三个版本使用的语法更容易被 R
用户理解,但我不喜欢边缘标签文本的奇怪放置方式(因此有上面的两个替代版本)。
library(DiagrammeR)
# Create a node data frame (ndf)
ndf <- create_node_df(
n = 3,
label = c( "Math\nself-efficacy","Math\nability", "Interest in\nthe math major"),
shape = rep("rectangle", 3),
style = "empty",
fontsize = 6,
fixedsize = TRUE,
height = .5,
width = .75,
color = "gray80",
x = c(1, 2, 3),
y = c(1, 2, 1)
)
# Create an edge data frame (edf)
edf <- create_edge_df(
from = c(1, 1, 2),
to = c(2, 3, 3),
label = c(".47*", ".33* (.16)", ".36*"),
fontsize = 6,
minlen = 1,
color = "gray80",
)
# Create a graph with the ndf and edf
graph <- create_graph(
nodes_df = ndf,
edges_df = edf
)
graph %>%
render_graph()