当前位置: 首页 > article >正文

R语言绘制有向无环图(DAG)

有向无环图(Directed Acyclic Graph,简称DAG)是一种特殊的有向图,它由一系列顶点和有方向的边组成,其中不存在任何环路。这意味着从任一顶点出发,沿着箭头方向移动,你永远无法回到起始点。

在这里插入图片描述
从流行病学来说,有向无环图主要用来进行因果推断。研究者们会通过已知的理论框架来构建自己的DAG、确定研究假设、确定统计分析的思路。DAG更多时候是作为一个更加直观的方式来梳理和呈现一个研究者的研究框架。这种梳理和呈现是非常有意义的,因为它会指导你如何设计你的研究以及如何分析你的数据。

下面咱们来介绍一下怎么使用R语言来绘制有向无环图,先导入R包

library(ggdag)
library(ggplot2)
theme_set(theme_dag())

先来个最基础的,比如x导致y

dagify(y ~ x) %>%
  ggdag()

在这里插入图片描述
上图可以看到x到y有个箭头,表明x导致y
下面做一个双向的

dagify(y ~ ~x) %>%
  ggdag()

在这里插入图片描述
上图有点奇怪,因为少了一个潜在变量,咱们重新画一下

###规范化DAG:将潜在变量添加到图中
dagify(y ~ ~x) %>%
  ggdag_canonical()

在这里插入图片描述
可以看出,是L1导致x和y
上面两个只是比较初级的,用得不是很顺手,下面咱们来个自定义的:x导致y,a导致x, y导致a

###自己编写方向
dagify(
  y ~ x,
  x ~ a,
  a ~ y
) %>%
  ggdag()

在这里插入图片描述
咱们也可以不走通道写成下面这种形式

dag <- dagify(
  y ~ x,
  x ~ a,
  a ~ y,
  labels = c(
    "y" = "outcome",
    "x" = "observed",
    "a" = "mediator"
  )
) 

ggdag(dag)

在这里插入图片描述
上面这些只是一些比较简单的情况,ggdag包还能绘制一些比较复杂的因果关系

假设我们正在研究吸烟与 心搏骤停。我们可以假设吸烟(smoking)会导致胆固醇(cholesterol),导致心脏骤停(cardiacarrest)

从吸烟到心脏骤停的路径是:吸烟 导致胆固醇升高,从而增加患心脏病的风险 逮捕。胆固醇是介于吸烟和 心搏骤停。有向路径也是链,因为每个链都是因果关系 在下一个。假设我们还假设体重会导致胆固醇 升高,从而增加心脏骤停的风险。现在还有另一个 DAG 中的链条:从体重到心脏骤停。然而,这条链条是间接的,至少就吸烟之间的关系而言 心脏骤停。

我们还假设吸烟的人更有可能是 从事其他不健康行为的人,例如暴饮暴食。在 DAG 的 DAG 节点,这被描述为一个潜在(未测量的)节点,称为 unhealthy 生活方式。偏爱不健康的行为会导致 吸烟和体重增加。在这里,两者之间的关系 吸烟和体重是通过一条分叉路径(体重 < - 不健康 生活方式 - >吸烟)而不是连锁店;因为他们有一个共同的 父母、吸烟和体重有关(在现实生活中,有 可能是两者之间更直接的关系,但我们会忽略 为简单起见)。

smoking_ca_dag <- dagify(cardiacarrest ~ cholesterol,
                         cholesterol ~ smoking + weight,
                         smoking ~ unhealthy,
                         weight ~ unhealthy,
                         labels = c(
                           "cardiacarrest" = "Cardiac\n Arrest",
                           "smoking" = "Smoking",
                           "cholesterol" = "Cholesterol",
                           "unhealthy" = "Unhealthy\n Lifestyle",
                           "weight" = "Weight"
                         ),
                         latent = "unhealthy",
                         exposure = "smoking",
                         outcome = "cardiacarrest"
)

ggdag(smoking_ca_dag, text = FALSE, use_labels = "label")

在这里插入图片描述
上图可以理清各种关系,最后导致心脏停博得原因,调理非常清晰。
还可以显示变量间得开放路径

ggdag_paths(smoking_ca_dag, text = FALSE, use_labels = "label", shadow = TRUE)

在这里插入图片描述
Ggdag包还能绘制很多得复杂因果结构图,我这里不打算一一介绍,有兴趣得可以去看R包说明。我打算介绍ggdag包得一个辅助包dagitty包,用它来辅助绘制更加简单。
先导入R包,

library(dagitty)

还是刚才得例子,这个例子没有实际意义,只是演示用

dag1 <- dagitty:: dagitty("dag{
                         x-> y;
                         y-> a;
                         a-> x
                  }")

这里可以看到,dagitty包写法稍有不同,方向用箭头替代,也是很清洗明了的。接下来咱们要把dag1转成tidy格式,有利于后面操作,这里seed = 1234是设定一个种子,避免每次图形不一样

dag_tidy <- ggdag::tidy_dagitty(dag1, seed = 1234) %>%
  dag_label(labels = c("x" = "observed",  
                       "y" = "outcome",  
                       "a" = "mediator")
            )

最后绘图,

# dag_tidy是你的dag数据,node_size可以修改点的大小,text_size可以修改字母大小
# label_size修改标签大小,edge_type是边的类型,可以是直的,也可以是弯的
# geom_dag_label_repel里面是添加标签的函数,最好不要变动
# geom_dag_edges可以改变边的属性,我这里改变了宽度
# theme_dag_blank可以删掉背景
ggdag(dag_tidy, node_size = 15, text_size = 5, label_size = 5,
      edge_type = "link_arc") +
  geom_dag_label_repel(aes(label = label)) +
  geom_dag_edges(edge_width = 1) +
  theme_dag_blank() +
  expand_plot(expand_x = expansion(c(0.1, 0.1)),
              expand_y = expansion(c(0.1, 0.1)))

在这里插入图片描述
转换格式后能轻松的对图形修改和设定。

参考文献:

  1. ggdag包说明
  2. https://zhuanlan.zhihu.com/p/350952313

http://www.kler.cn/a/529926.html

相关文章:

  • tiktok 国际版抖抖♬♬ X-Bogus参数算法逆向分析
  • C语言:链表排序与插入的实现
  • 9 点结构模块(point.rs)
  • MySQL5.5升级到MySQL5.7
  • Vue 3 30天精进之旅:Day 12 - 异步操作
  • 【LLM-agent】(task4)搜索引擎Agent
  • 普通用户(非root) 安装libreoffice
  • Python的那些事第九篇:从单继承到多继承的奇妙之旅
  • 【leetcode详解】T598 区间加法
  • 手机Python爬虫教程:利用手机学习Python爬虫的终极指南_python可以在手机上写爬虫吗
  • 人机交互系统实验三 多通道用户界面
  • C++模板编程——可变参函数模板之折叠表达式
  • 使用 DeepSeek-R1 与 AnythingLLM 搭建本地知识库
  • IM 即时通讯系统-46-OpenIM 提供了专为开发者设计的开源即时通讯解决方案
  • bat脚本实现自动化漏洞挖掘
  • 【零基础学JAVA】数据类型
  • 20250202在Ubuntu22.04下使用Guvcview录像的时候降噪
  • Java/Kotlin HashMap 等集合引发 ConcurrentModificationException
  • [HOT 100] 0167. 两数之和 ||
  • Elasticsearch 指南 [8.17] | Search APIs
  • python算法和数据结构刷题[6]:二叉树、堆、BFS\DFS
  • 机器学习算法在网络安全中的实践
  • 系统学习算法: 专题八 二叉树中的深搜
  • Node.js——异步编程(异步:阻塞与非阻塞、JavaScript执行机制、callBack hell 回调地狱,Promise、Async await)
  • Stable Diffusion创始人:DeepSeek没有抄袭!
  • 深入浅出并查集(不相交集合实现思路)