# 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:** 1\
**Showing post:** 5

<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?

---

_[View the full topic](https://discourse.julialang.org/t/ann-causalinference-jl-causal-inference-in-julia/6154)._
