# ANN:CausalInference.jl - Causal Inference in Julia

**URL:** https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154
**Category:** Community
**Tags:** package, announcement, statistics
**Created:** [September 29, 2017, 9:55am UTC](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154 "2017-09-29T09:55:37Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![mschauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mschauer/32/13946_2.png) [@mschauer](https://discourse.julialang.org/u/mschauer)
#### Post date: [September 29, 2017, 9:55am UTC](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154/1 "2017-09-29T09:55:37Z")

</div>

## CausalInference.jl

→ [https://github.com/mschauer/CausalInference.jl](https://github.com/mschauer/CausalInference.jl)

A very vanilla (at the moment) Julia package for causal inference, graphical models and structure learning with the PC algorithm. The package contains for now the classical PC algorithm and some related functionality.

See the [documentation](https://mschauer.github.io/CausalInference.jl/latest/) for details and perhaps [issue #1 (Roadmap/Contribution)](https://github.com/mschauer/CausalInference.jl/issues/1) if you are interested.

The algorithms use the Julia package [LightGraphs](https://github.com/JuliaGraphs/LightGraphs.jl). Graphs are represented by sorted adjacency lists (vectors in the implemention). CPDAGs are just `DiGraph`s where unoriented edges are represented by both a forward and a backward directed edge.

#### References

- D. M. Chickering: Learning Equivalence Classes of Bayesian-Network Structures. _Journal of Machine Learning Research_ 2 (2002), 445-498.
- D. Colombo, M. H. Maathuis: Order-Independent Constraint-Based Causal Structure Learning. _Journal of Machine Learning Research_ 15 (2014), 3921-3962.

---

<div class="post-metadata">

### Author: ![mschauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mschauer/32/13946_2.png) [@mschauer](https://discourse.julialang.org/u/mschauer)
#### Post date: [January 10, 2023, 10:46am UTC](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154/2 "2023-01-10T10:46:39Z")

</div>

## CausalInference.jl 0.9

Just tagged a new version - in short: the package is alive and kicking. Next plans are perhaps adding the GES algorithm, things for that are in place. [GitHub - mschauer/CausalInference.jl: Causal inference, graphical models and structure learning in Julia](https://github.com/mschauer/CausalInference.jl)

---

<div class="post-metadata">

### Author: ![RobertGregg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robertgregg/32/22105_2.png) [@RobertGregg](https://discourse.julialang.org/u/RobertGregg)
#### Post date: [January 17, 2023, 5:41am UTC](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154/3 "2023-01-17T05:41:36Z")

</div>

This looks awesome! I’ve actually implemented a version of [FGES](https://github.com/RobertGregg/FGES.jl) which may be useful for this package. Maybe it would make sense to combine the two?

---

<div class="post-metadata">

### Author: ![mschauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mschauer/32/13946_2.png) [@mschauer](https://discourse.julialang.org/u/mschauer)
#### Post date: [January 17, 2023, 7:31am UTC](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154/4 "2023-01-17T07:31:26Z")

</div>

I would love to! [Integration with RobertGregg/FGES.jl · Issue #77 · mschauer/CausalInference.jl · GitHub](https://github.com/mschauer/CausalInference.jl/issues/77)

---

<div class="post-metadata">

### Author: ![mschauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mschauer/32/13946_2.png) [@mschauer](https://discourse.julialang.org/u/mschauer)
#### Post date: [July 28, 2023, 9:19am UTC](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154/5 "2023-07-28T09:19:44Z")

</div>

# ANN: Causal Inference 0.11.1

> **[GitHub - mschauer/CausalInference.jl: Causal inference, graphical models and structure...](https://github.com/mschauer/CausalInference.jl)**
>
> Causal inference, graphical models and structure learning in Julia

Just in time for JuliaCon we have added with the help of @RobertGregg the Parallel Greedy Equivalence Search (GES) as score based alternative to the PC algorithm!

Marcel Wienöbst at the same time added an extensive suit of adjustment set search functions I believe only matched by Dagitty in functionality (but perhaps not in performance).

Finally, CausalInference now uses `Threads` now at two crucial steps.

## GES Example

```julia
using CausalInference
using TikzGraphs
using Random
Random.seed!(1)

# Generate some sample data to use with the GES algorithm

N = 2000 # number of data points

# define simple linear model with added noise

x = randn(N)
v = x + randn(N)*0.25
w = x + randn(N)*0.25
z = v + w + randn(N)*0.25
s = z + randn(N)*0.25

df = (x=x, v=v, w=w, z=z, s=s)

```

With this data ready, we can now see to what extent we can back out the underlying causal structure from the data using the GES algorithm. Under the hood, GES uses a score to determine the causal relationships between different variables in a given data set. By default, `ges` uses a Gaussian BIC to score different causal models.

```julia
est_g, score = ges(df; penalty=1.0, parallel=true)
tp = plot_pc_graph_tikz(est_g, [String(k) for k in keys(df)])

```

 ![exampledag](https://global.discourse-cdn.com/julialang/original/3X/9/7/97c22117a7175e36967626f7b0e796f2622fac29.png)

We can conclude from observational data that `v` and `w` are causes of `z` which causes `s`, but aren’t so sure about the relationship between `x`, `v` respective `x` and `w`.

## Adjustment set search

The causal model we are going to study can be represented using the following DAG concerning a set of variables numbered `1` to `8` :

 ![graph3_4](https://global.discourse-cdn.com/julialang/original/3X/2/9/291005ccb42fee7731a97a19fd8cc816645405b3.png)

```julia-auto
using CausalInference

dag = digraph([1 => 3, 3 => 6, 2 => 5, 5 => 8, 6 => 7, 7 => 8, 1 => 4, 2 => 4, 4 => 6, 4 => 8])

```

We are interested in the average causal effect (ACE) of a treatment (variable nr. 6) on an outcome (variable nr. 8). Variables nr. 1 and nr. 2 are unobserved.

Ordinary regression will fail to measure the effect because of the presence of a confounder (variable nr. 4). First intuition is to control for the confounder but it is not so straight forward here because of the presence of variables 1 and 2. But the new function `list_covariate_adjustments` tells what to do:

```julia-auto
Zs = list_covariate_adjustment(dag, 6, 8, Int[], setdiff(Set(1:8), [1, 2]))
# here exclude variables nr. 1 and nr. 2 because they are unobserved.

```

lists possible adjustment sets,

```julia-auto
println.(Zs);

```

```julia-auto
    Set([4, 3])
    Set([5, 4])
    Set([5, 4, 3])

```

tells us to control either for variables 4 and 3, or 5 and 4 etc. With this control variables in the regression we are able to measure the causal effect.

## Parallelisation

I have to say, just adding `Threads.@parallel` in the right place feels like magic. I did this for the PC algorithm and the GES algorithm. GES also uses [GitHub - marius311/Memoization.jl: Easily and efficiently memoize any function, closure, or callable object in Julia.](https://github.com/marius311/Memoization.jl) with a thread save [GitHub - JuliaCollections/LRUCache.jl: An implementation of an LRU Cache in Julia](https://github.com/JuliaCollections/LRUCache.jl).

## Performance

With that, the performance of `CausalInference.jl` is fast and compares with that of the C implementation in the R package `pcalg`. As causal model discovery is not an _NP_ -_hard_ problem if the Causal graph is not sparse.

**PS:** Also, can someone with rights edit the thread title to `ANN:CausalInference.jl - Causal Inference in Julia` so it becomes searchable?

---

<div class="post-metadata">

### Author: ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)
#### Post date: [July 28, 2023, 9:23am UTC](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154/6 "2023-07-28T09:23:40Z")

</div>

Although (as the author of [https://github.com/nilshg/SynthControl.jl](https://github.com/nilshg/SynthControl.jl) and someone who works mostly in Rubin/Imbens causal inference) I gripe about the very general name of the package these are some cool updates!

> [@mschauer](#):
>
> edit the thread

Done.

---

<div class="post-metadata">

### Author: ![mschauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mschauer/32/13946_2.png) [@mschauer](https://discourse.julialang.org/u/mschauer)
#### Post date: [December 2, 2024, 2:03pm UTC](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154/7 "2024-12-02T14:03:17Z")

</div>

Updates: A thread on Bluesky about the package:

> **[Moritz Schauer (@mschauer.bsky.social)](https://bsky.app/profile/mschauer.bsky.social/post/3lb2s3pxdzk2g)**
>
> Once there was a postdoc (me) trying to understand #CausalInference #statistics and I ended up writing the Julia package https://github.com/mschauer/CausalInference.jl (co-dev’d with @schnirz.bsky.social, @mwien.bsky.social, …) You will like:

---

<div class="post-metadata">

### Author: ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)
#### Post date: [December 2, 2024, 4:12pm UTC](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154/8 "2024-12-02T16:12:20Z")

</div>

I only see this post now and I only now see of this package. @mschauer have you seen this: [Associations.jl](https://github.com/JuliaDynamics/Associations.jl) ? It has several implementations for causal inference and causal graph construction on the basis of timeseries. Are the two frameworks on common grounds, and if so, can we collaborate?

---

<div class="post-metadata">

### Author: ![mschauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mschauer/32/13946_2.png) [@mschauer](https://discourse.julialang.org/u/mschauer)
#### Post date: [December 3, 2024, 11:12am UTC](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154/9 "2024-12-03T11:12:15Z")

</div>

@Datseris To be honest, I didn’t understand why you guys (Associations.jl devs, not you personally) decided against reaching out/collaboration on say your reimplementation of the PC algorithm and the skeleton algorithm. You are even using the same representation (partially oriented graphs represented as `Graphs.SimpleDiGraph`) and test your’s against mine showing that they can be exchanged

> <https://github.com/JuliaDynamics/Associations.jl/blob/7bfb8b927d41cecb4fe467837308cf64d54b3174/test/causal_graphs/pc.jl#L25>

---

<div class="post-metadata">

### Author: ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)
#### Post date: [December 3, 2024, 12:25pm UTC](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154/10 "2024-12-03T12:25:25Z")

</div>

> [@mschauer](#):
>
> why you guys ([Associations.jl](https://juliahub.com/ui/Packages/General/Associations) devs, not you personally) decided against reaching out/collaboration on say your reimplementation of the PC algorithm and the skeleton algorithm.

I don’t think such a decision was ever made.I just became aware your project now, and reached out literally within the next 5 minutes 😃 I can’t speak for my collaborator @kahaaga , but given the work we’ve done so far in ComplexityMeasures.jl, I would wager that also he wasn’t aware of your project. Note that Assocations.jl was originally named CausalityTools.jl, a project started August 2018. Looking at CausalInference.jl, it appears to have started _even earlier_, right? I think CausalityTools.jl started as a repo implementing novel PhD work, but over time it increased a lot in size and later added functionality on causal graph inference. In any case, the separation is unfortunate, as we are very big on collaboration, “stop reinventing the wheel” is my middle name 😛

I take it you are interested to collaborate? If yes, send me a DM so that we can arrange a discussion? So that we don’t over-use this thread that is mainly for updates on CausalInference.jl

---

<div class="post-metadata">

### Author: ![mschauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mschauer/32/13946_2.png) [@mschauer](https://discourse.julialang.org/u/mschauer)
#### Post date: [December 3, 2024, 12:27pm UTC](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154/11 "2024-12-03T12:27:46Z")

</div>

Will do!
