ggdag:DAG和因果图

近几年来,因果推断同时受到多个学科的重视,是最火热的研究方向之一。因果图(或称路径图)是研究因果关系的一个有效的辅助性工具。借助因果图可以分析因果关系,将复杂问题图形化。本文介绍一个用来绘制因果图的R包ggdag。

1、DAG

有向无环图(DAG,Direct Acyclic Graph)是一种图模型。图由节点和边组成,节点代表变量,边代表变量之间的某种联系。如果两个节点之间的边是有明确指向的,就是有向图。如果一个有向图从某个节点出发后,无法通过若干条边回到原节点,就是一个有向无环图。贝叶斯网是有向无环图的一个著名的例子。

2、因果图

DAG可以用作因果图。在DAG中,因果关系由变量之间的有向边表示(方向箭头由因指向果)。在因果推断的背景下,DAG表明(1)两个变量之间的因果关系必须是单向的,变量之间不能相互影响。(2)要完成DAG,必须包含DAG中任何两个变量的共同原因。

三种路径

路径是指连接两个节点的一系列有向边,这些边的方向不一定相同,但是只能通过一个变量一次。

路径可分为三类:因果路径(或链状路径,A—>B—>C)、混淆路径(或叉状路径,A<—C—>B)和对撞路径(或反叉状路径,A—>B<—C)。

(1)因果路径

因果路径(也叫有向路径)是解释变量(也称为处置、暴露)X指向被解释变量(也称为结果)Y的单向路径。

图1-a 直接因果关系路径,X和Y之间没有中介变量(mediator)

图1-b 间接因果关系路径,X和Y之间有中介变量A

图1-c 两种情况的混合。

如果两个 变量之间存在着因果关系路径,它们就存在相关性,所以因果路径为开放路径。

(2)混淆路径

如果在X和Y的路径上存在一个变量C同时影响X和Y,这个变量C叫做混淆变量(confounder),这条路径称为混淆路径(也叫后门路径)。

图2-a C是X和Y共同的解释变量,C是一个混淆变量。

图2-b C是观测不到的混淆变量

(3)对撞变量

如果变量D被变量X和Y共同影响,D叫做对撞变量(collider)。包含对撞变量的路径是对撞路径(也叫阻塞路径)。

图3 对撞变量

对撞路径不会造成X和Y之间的相关性,是一条死路径。

3、ggdag

dagitty(有个对应的R包,也叫dagitty)是一个功能强大的基于浏览器的因果模型图分析工具。ggdag对dagitty包做了一些扩展,可以创建整洁(tidy)的因果有向无环图。ggdag的图形建立在ggplot2和ggraph(见网络数据可视化(3修订版)ggraph:ggplot2的网络可视化)的基础上,可以在R环境下更轻松的绘制DAG。

(1)创建DAG

ggdag可以直接将dagitty包创建的DAG转化为整洁的数据结构。

library(dagitty)library(ggdag)

dag <- dagitty('dag{y <- z -> x}')tidy_dagitty(dag)#> # A DAG with 3 nodes and 2 edges#> ##> # A tibble: 4 x 8#> name x y direction to xend yend circular#>#> 1 z 28.5 23.3 -> x 28.5 24.4 FALSE #> 2 z 28.5 23.3 -> y 28.5 22.1 FALSE #> 3 x 28.5 24.4NA NA FALSE #> 4 y 28.5 22.1NA NA FALSE

(注:dagitty支持很多图模型。ggdag目前只支持DAG。)

ggdag提供了使用R的公式语法创建dagitty对象的功能,通过dagify()函数实现。dagify()接受任意数量的公式来创建DAG。它还可以选择声明变量,以及每个节点的坐标和标签。

dagified <- dagify(x ~ z,                   y ~ z,                   exposure = 'x',                   outcome = 'y')tidy_dagitty(dagified)#> # A DAG with 3 nodes and 2 edges#> ##> # Exposure: x#> # Outcome: y#> ##> # A tibble: 4 x 8#>   name      x     y direction to     xend  yend circular#>                 #> 1 z      23.6  20.4 ->        x      23.6  21.5 FALSE   #> 2 z      23.6  20.4 ->        y      23.6  19.2 FALSE   #> 3 x      23.6  21.5          NA    NA   FALSE   #> 4 y      23.6  19.2          NA    NA   FALSE

目前,ggdag支持有向(x~y)和双向(x~~y)关系

tidy_dagitty()使用R包ggraph和igraph中提供的布局函数创建坐标,可以使用layout参数指定坐标。使用ggdag()可以快速绘制tidy_dagitty或dagitty类的对象。如果DAG还没有整理成整洁的形式,ggdag()和ggdag中的大多数其他快速绘图函数都会在内部进行整理:

ggdag(dag, layout = 'circle')

tidy_dagitty对象是一个列表,包括一个叫做data的tbl_df数据框对象和一个叫做dag的dagitty对象:

tidy_dag <- tidy_dagitty(dagified)str(tidy_dag)#> List of 2#>  $ data: tibble [4 × 8] (S3: tbl_df/tbl/data.frame)#>   ..$ name     : chr [1:4] 'z' 'z' 'x' 'y'#>   ..$ x        : num [1:4] 23.3 23.3 22.9 23.7#>   ..$ y        : num [1:4] 25.5 25.5 26.6 24.4#>   ..$ direction: Factor w/ 3 levels '<-','->','<->': 2 2 NA NA#>   ..$ to       : chr [1:4] 'x' 'y' NA NA#>   ..$ xend     : num [1:4] 22.9 23.7 NA NA#>   ..$ yend     : num [1:4] 26.6 24.4 NA NA#>   ..$ circular : logi [1:4] FALSE FALSE FALSE FALSE#>  $ dag : 'dagitty' Named chr 'dag {\nx [exposure]\ny [outcome]\nz\nz -> x\nz -> y\n}\n'#>  - attr(*, 'class')= chr 'tidy_dagitty'

(2)操作DAG

dagitty中的大部分分析函数在ggdag中都有对应的扩展,处理特定节点的命名为dag_*( ),处理整个DAG的命名为node_*( )。比如node_parents( ),它在tidy_dagitty对象中添加了一列关于给定变量的父对象:

node_parents(tidy_dag, 'x')#> # A DAG with 3 nodes and 2 edges#> ##> # Exposure: x#> # Outcome: y#> ##> # A tibble: 4 x 9#> name x y direction to xend yend circular parent#>#> 1 z 23.3 25.5 -> x 22.9 26.6 FALSE parent#> 2 z 23.3 25.5 -> y 23.7 24.4 FALSE parent#> 3 x 22.9 26.6NA NA FALSE child #> 4 y 23.7 24.4NA NA FALSE

或者和整个DAG一起,生成一个具有两个变量之间所有路径的tidy_dagitty对象:

bigger_dag <- dagify(y ~ x + a + b,                     x ~ a + b,                     exposure = 'x',                     outcome = 'y')#  automatically searches the paths between the variables labelled exposure and #  outcomedag_paths(bigger_dag)  #> # A DAG with 4 nodes and 17 edges#> ##> # Exposure: x#> # Outcome: y#> ##> # A tibble: 20 x 10#>    set   name      x     y direction to     xend  yend circular path     #>                        #>  1 1     a      17.3  19.2 ->        x      16.8  18.2 FALSE         #>  2 1     a      17.3  19.2 ->        y      17.7  18.2 FALSE         #>  3 1     b      17.3  17.2 ->        x      16.8  18.2 FALSE         #>  4 1     b      17.3  17.2 ->        y      17.7  18.2 FALSE         #>  5 1     x      16.8  18.2 ->        y      17.7  18.2 FALSE    open path#>  6 1     y      17.7  18.2          NA    NA   FALSE    open path#>  7 2     a      17.3  19.2 ->        x      16.8  18.2 FALSE    open path#>  8 2     a      17.3  19.2 ->        y      17.7  18.2 FALSE    open path#>  9 2     b      17.3  17.2 ->        x      16.8  18.2 FALSE         #> 10 2     b      17.3  17.2 ->        y      17.7  18.2 FALSE         #> 11 2     x      16.8  18.2 ->        y      17.7  18.2 FALSE         #> 12 2     y      17.7  18.2          NA    NA   FALSE    open path#> 13 2     x      16.8  18.2 ->        y      17.7  18.2 FALSE    open path#> 14 3     a      17.3  19.2 ->        x      16.8  18.2 FALSE         #> 15 3     a      17.3  19.2 ->        y      17.7  18.2 FALSE         #> 16 3     b      17.3  17.2 ->        x      16.8  18.2 FALSE    open path#> 17 3     b      17.3  17.2 ->        y      17.7  18.2 FALSE    open path#> 18 3     x      16.8  18.2 ->        y      17.7  18.2 FALSE         #> 19 3     y      17.7  18.2          NA    NA   FALSE    open path#> 20 3     x      16.8  18.2 ->        y      17.7  18.2 FALSE    open path

ggdag支持dplyr,还支持函数的管道,并在内部包含管道:

library(dplyr)# find how many variables are in between x and y in each pathbigger_dag %>% dag_paths() %>%group_by(set) %>%filter(!is.na(path) & !is.na(name)) %>% summarize(n_vars_between = n() - 1L)#> # A tibble: 3 x 2#> set n_vars_between#>#> 1 1 1#> 2 2 3#> 3 3 3

(3)绘制DAG

大多数dag_*( )和node_*( )都有对应的ggdag_*()用于快速绘制图形。这些函数在内部调用dag_*( )或node_*( ),以ggplot2的形式绘制结果。如ggdag_paths( )绘制暴露和结果变量之间的所有路径,ggdag_parents()强调了父节点,ggdag_adjustment_set( )绘制协变量调整集:

###图4ggdag_paths(bigger_dag)###图5ggdag_parents(bigger_dag, 'x',node_size=8)+theme_void()###图6ggdag_adjustment_set(bigger_dag,node_size=8)+theme_void()

图-4

图-5

图-6

从这些图中可见,默认的ggdag_*()看起来就是ggplot2的形式,可以调整参数或者使用ggplot2的绘图函数对图形进行修改。

(4)使用ggplot2绘制DAG

大致上,ggdag( )和ggdag包里类似的函数dou都是ggplot2几何对象的打包,用于绘制节点、文本和边。例如,上文的ggdag_parents( )可以使用ggplot2和ggdag提供的几何对象实现:

###图7bigger_dag %>% node_parents('x') %>%ggplot(aes(x = x, y = y, xend = xend, yend = yend, color = parent)) +geom_dag_point(size=8) +geom_dag_edges() +geom_dag_text(col = 'white') +theme_dag() +scale_color_hue(breaks = c('parent', 'child'))

图-7

ggdag自己提供的一些几何对象:geom_dag_node()/geom_dag_point(),

geom_dag_edges(),geom_dag_text(),theme_dag()和scale_adjusted()。

geom_dag_node()略带风格(有一个内部的白圈),geom_dag_point()看起来更像是大号的geom_point()。theme_dag()移除了所有的轴和刻度,因为这些在因果模型中没有意义。expand_plot()绘图比例进行修改,使其更适合具有更大的点和文本的节点。scale_ adjusted()提供DAG分析中常见的默认值的调整,例如将调整变量的形状设置为正方形。

geom_dag_edges()用于绘制具有不同几何对象和箭头的定向边和双向边。有向边是带有一个箭头的直线,而双向线是两个双向变量(如a<-L->b)之间潜在父变量的简写,绘制为带有箭头的弧。也可以直接调用边函数,特别是只有有向边时。ggdag的很多边函数都来自ggraph,默认值(如箭头、截断线)是根据DAG进行设置的。目前,ggdag有四种类型的边几何对象:绘制直线的geom_dag_edges_link()、绘制圆弧的geom_dag_edges_arc()和geom_dag_edges_diagonal()、绘制扇形的geom_dag_edges_fan():

###图8dagify(y ~ x,       m ~ x + y) %>%   ggplot(aes(x = x, y = y, xend = xend, yend = yend)) +    geom_dag_point() +    geom_dag_edges_arc() +    geom_dag_text() +    theme_dag()

图8

如果有双向边,但希望按方向绘制,node_canonical()将自动插入潜变量:

###图9dagify(y ~ x + z,x ~~ z) %>% node_canonical() %>% ggplot(aes(x = x, y = y, xend = xend, yend = yend)) +geom_dag_point() +geom_dag_edges_diagonal() +geom_dag_text() +theme_dag()

图9

(0)

相关推荐

  • tidyr总结篇-续

    欢迎来到医科研,这里是白介素2的读书笔记,跟我一起聊临床与科研的故事, 生物医学数据挖掘,R语言,TCGA.GEO数据挖掘. tidyr总结篇  gather(data,key="" ...

  • R语言动态图可视化:如何、创建具有精美动画的图

    原文链接:http://tecdat.cn/?p=8003 演示数据集 library(gapminder) head(gapminder)## # A tibble: 6 x 6 ## countr ...

  • dplyr总结篇

    欢迎来到医科研,这里是白介素2的读书笔记,跟我一起聊临床与科研的故事, 生物医学数据挖掘,R语言,TCGA.GEO数据挖掘. dplyr-总结  有必要对dplyr进行一个总结 对行处理 数据处理对于 ...

  • 互助问答第394期 关于工具变量的问题

    关于工具变量的问题 如果发现所选择的工具变量并不好,可能通过出内生变量之外的其他路径影响Y,那么是否可以通过将这些路径控制起来,解决这个问题? 技术上是可以实现的.但是你要确认,你控制的这些变量本身是 ...

  • 设置了环境变量还是不行 soundstretch.exe

    表白:黑白圣堂血天使,天剑鬼刀阿修罗.  讲解对象:/设置了环境变量还是不行 作者:融水公子 rsgz 因为设置环境变量几乎没有出错过,今天却出错了 很奇怪,路径直接复制过来的啊.怎么可能会出错! 哎 ...

  • R语言如何让全世界说爱你

    ggplot版本词云也要是爱你的形状 写在前面 词云作为一种比较时髦的可视化方式,为我们文字方向的工作提供了易于表达的可视化方案,一目了然有大方美观.本次我为大家带来gplot版本的词云,并且用爱你的 ...

  • 西门子TIA S7-1200 配方快速入门实例

    关于启程 启程自动化培训成立于2012年,培训项目主打西门子PLC编程系统集成.工业机器人编程.EPLAN电气设计.视觉等培训与技术服务的机构.推荐高薪就业,越努力越幸运 配方数据文件按照标准 CSV ...

  • 丁乙:唯一不让艺术失败的方法是专注

    丁乙近照 受访者:丁乙 采访及编辑:田露思 提到丁乙,总让人联想到被反复言说的"十示",从1988年至今,无论是创作技巧还是所指向的精神图景,丁乙的画面其实一直在变."十 ...

  • 基于R语言股票市场收益的统计可视化分析

    原文链接:http://tecdat.cn/?p=16453 金融市场上最重要的任务之一就是分析各种投资的历史收益.要执行此分析,我们需要资产的历史数据.数据提供者很多,有些是免费的,大多数是付费的. ...

  • R语言自适应LASSO 多项式回归、二元逻辑回归和岭回归应用分析

    原文链接:http://tecdat.cn/?p=21602 正则化(regularization) 正则化路径是在正则化参数lambda的值网格上计算套索LASSO或弹性网路惩罚的正则化路径.该算法 ...

  • 让我们定义一个ggplot版本的华夫饼图吧

    写在前面 不知何时起,我总是喜欢在推文前面写上写在前面,可能是表达我的一种心境吧.在家里的日子在不断的测试和完善流程,每当我累了的时候,总想去gogle找一些新鲜东西,然后修改,适最后合自己的模子,变 ...

  • R语言ggplot2绘制箱线图

    欢迎来到医科研,这里是白介素2的读书笔记,跟我一起聊临床与科研的故事, 生物医学数据挖掘,R语言,TCGA.GEO数据挖掘. R语言ggplot2绘制箱线图  差异基因与基因交集 if(T){ req ...

  • 《R数据科学》--千变万化的数据只需一个readr便可

    [toc] 写在前面 数据导入是使用R语言分析数据的第一步,但是这部分的细节确实非常多,尤其是对于咱们微生物组数据来说,经常会遇到制表符和逗号作为分隔符的文件,其次,物种注释文件的七级注释往往使用分号 ...