# User-defined distribution function example

**URL:** <https://discourse.julialang.org/t/user-defined-distribution-function-example/22035>\
**Category:** Statistics\
**Tags:** question\
**Created:** [March 19, 2019, 12:01pm UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035 "2019-03-19T12:01:19Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [March 19, 2019, 12:01pm UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/1 "2019-03-19T12:01:19Z")

</div>

I am new to Julia, and I want to define my own distribution function. I found [this post](https://discourse.julialang.org/t/help-with-creating-a-custom-distribution/13229) and followed the [documentation](https://juliastats.github.io/Distributions.jl/latest/extends.html#Create-a-Distribution-1), but I did not understand where do I put in the actual function (namely f(x)) of the distribution. Can someone help me with an example of say defining a gaussian distribution?

---

<div class="post-metadata">

**Author:** ![alejandromerchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alejandromerchan/32/10500_2.png) [@alejandromerchan](https://discourse.julialang.org/u/alejandromerchan)\
**Post date:** [March 19, 2019, 3:20pm UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/2 "2019-03-19T15:20:38Z")

</div>

You probably just need to learn how to create functions in general, as explained [here](https://docs.julialang.org/en/v1/manual/functions/). And then use that function for whatever you need, without worrying about the Distributions package. The idea of creating a sampler and all that is a little more involved than just a regular function. Do you know the equation you want to implement?

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [March 19, 2019, 3:53pm UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/3 "2019-03-19T15:53:00Z")

</div>

@alejandromerchan my distribution is x\exp(-x) for x\in (0, \infty)  
If I look at the example code from the [post](https://discourse.julialang.org/t/help-with-creating-a-custom-distribution/13229)

```julia
type MyDist <: ContinuousUnivariateDistribution
    mu::Float64
    sigma::Float64
    MyDist(mu, sigma) = new(Float64(mu), Float64(sigma))
end

pdf(d::MyDist, x::Float64) = pdf(Normal(d.mu, 2*d.sigma), x)

```

I do not understand where should I introduce my function.  
In this code the `Normal` distribution is used, but how to insert a custom function like `f(x)=x*exp(-x)` ?

---

<div class="post-metadata">

**Author:** ![jbrea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbrea/32/3879_2.png) [@jbrea](https://discourse.julialang.org/u/jbrea)\
**Post date:** [March 19, 2019, 4:42pm UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/4 "2019-03-19T16:42:33Z")

</div>

I’m not sure I understand the question, but maybe you just want

```julia
pdf(d::MyDist, x::Float64) = x * exp(-x)

```

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [March 19, 2019, 4:59pm UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/5 "2019-03-19T16:59:58Z")

</div>

@jbrea I cannot even make the first part work, where the `MyDist` definition is.  
Could you give an example of how to define a distribution with the function f(x)=xe^{-x}?

---

<div class="post-metadata">

**Author:** ![jbrea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbrea/32/3879_2.png) [@jbrea](https://discourse.julialang.org/u/jbrea)\
**Post date:** [March 19, 2019, 5:22pm UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/6 "2019-03-19T17:22:31Z")

</div>

Here is a full example

```julia
julia> using Distributions

julia> struct MyDist <: ContinuousUnivariateDistribution end

julia> Distributions.pdf(::MyDist, x) = x * exp(-x)
pdf (generic function with 73 methods)

julia> pdf(MyDist(), 3)
0.14936120510359183

```

The example you posted is quite old julia code; `type` was renamed to `stuct` at some point.

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [March 21, 2019, 7:40am UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/7 "2019-03-21T07:40:00Z")

</div>

@jbrea thanks!  
But how do I sample from it?  
I tried

```julia
struct MyDist <: ContinuousUnivariateDistribution end
Distributions.pdf(::MyDist, x) = x * exp(-x)
d = MyDist()
rand(d)

```

But this doesn’t work.  
I thought I need to create a sampler according to [the documentation](https://juliastats.github.io/Distributions.jl/latest/extends.html#Create-a-Sampler-1), but I couldn’t figure out how to do it.  
Could you add this to the example?

---

<div class="post-metadata">

**Author:** ![jbrea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbrea/32/3879_2.png) [@jbrea](https://discourse.julialang.org/u/jbrea)\
**Post date:** [March 21, 2019, 8:11am UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/8 "2019-03-21T08:11:11Z")

</div>

As specified in the documentation you referred to, you need also to define

```julia
function Distributions.rand(::MyDist)
...
end

```

I guess [inverse transform sampling](https://en.wikipedia.org/wiki/Inverse_transform_sampling) could be useful.

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [March 21, 2019, 8:31am UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/9 "2019-03-21T08:31:36Z")

</div>

You can also import the desired functions if you don’t want to qualify with `Distributions.` For example,

```julia
import Distributions: rand,pdf,cdf

struct mydist <: ContinuousUnivariateDistribution
    ...
end 

function rand(dist::mydist)
    ...
end

...

```

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [March 21, 2019, 8:35am UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/10 "2019-03-21T08:35:21Z")

</div>

@Christopher_Fisher, @jbrea, my problem is that I’m not sure what should go into the `...`. I need an example of some implementation of such a `rand` function.

---

<div class="post-metadata">

**Author:** ![jbrea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbrea/32/3879_2.png) [@jbrea](https://discourse.julialang.org/u/jbrea)\
**Post date:** [March 21, 2019, 9:46am UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/11 "2019-03-21T09:46:07Z")

</div>

The package [Distributions.jl](https://github.com/JuliaStats/Distributions.jl) contains examples for all implemented distributions. You may use, e.g. `@edit rand(Exponential(1.))` to see the implemention for the `Exponential` distribution or just browse the source code of the package.

---

<div class="post-metadata">

**Author:** ![jbrea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbrea/32/3879_2.png) [@jbrea](https://discourse.julialang.org/u/jbrea)\
**Post date:** [March 21, 2019, 9:59am UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/12 "2019-03-21T09:59:37Z")

</div>

Btw. the distribution with `pdf(x) = x * exp(-x)` is known as the gamma distribution with shape `α = 2` and rate `β = 1` and it is already implemented as `Gamma(2, 1)`.

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [March 21, 2019, 12:04pm UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/13 "2019-03-21T12:04:07Z")

</div>

@jbrea, in the code I see

```julia
#### Sampling
rand(d::Exponential) = rand(GLOBAL_RNG, d)
rand(rng::AbstractRNG, d::Exponential) = xval(d, randexp(rng))

```

I did not understand how can I use this.  
BTW, what does the `d` before the `::` stands for?

I probably need something like

```julia
function rand(d::MyDist)
    uni = Uniform()
    x = rand(uni)
    # do something with x, to get my distribution. e.g. x^2
end

```

I tried implementing the [inverse transform sampling](https://en.wikipedia.org/wiki/Inverse_transform_sampling) but here the CDF is 1- e^{-x}(x+1) which cannot be inverted.

Using the Gamma function is a nice solution, but I eventually want to add parameters to the function, which do not conform to the Gamma function.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [March 21, 2019, 12:20pm UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/14 "2019-03-21T12:20:42Z")

</div>

> [@roi.holtzman](#):
>
> what does the `d` before the `::` stands for?

The argument. You should probably start with giving the [manual](https://docs.julialang.org/en/v1/) thorough reading.

> [@roi.holtzman](#):
>
> here the CDF is 1−e−x(x+1)1- e^{-x}(x+1) which cannot be inverted.

You can always find the root iteratively, using Newton’s method (usually works, and you can prove convergence) or bisection (worst case).

Providing all the methods is an investment that may not be needed for custom, one-off distributions, but this depends on the context.

---

<div class="post-metadata">

**Author:** ![jbrea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbrea/32/3879_2.png) [@jbrea](https://discourse.julialang.org/u/jbrea)\
**Post date:** [March 21, 2019, 12:28pm UTC](https://discourse.julialang.org/t/user-defined-distribution-function-example/22035/15 "2019-03-21T12:28:30Z")

</div>

You may also want to have a look at [wikipedia](https://en.wikipedia.org/wiki/Gamma_distribution#Generating_gamma-distributed_random_variables) or [this link](https://wiki.math.uwaterloo.ca/statwiki/index.php?title=techniques_for_Normal_and_Gamma_Sampling), brought up by a simple web search.
