# How to write a custom distribution using pdf from a Kernel Density Estimator?

**URL:** <https://discourse.julialang.org/t/how-to-write-a-custom-distribution-using-pdf-from-a-kernel-density-estimator/68175>\
**Category:** Performance\
**Tags:** statistics, turing, distributions\
**Created:** [September 14, 2021, 9:01pm UTC](https://discourse.julialang.org/t/how-to-write-a-custom-distribution-using-pdf-from-a-kernel-density-estimator/68175 "2021-09-14T21:01:45Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![vkv](https://avatars.discourse-cdn.com/v4/letter/v/d9b06d/32.png) [@vkv](https://discourse.julialang.org/u/vkv)\
**Post date:** [September 14, 2021, 9:01pm UTC](https://discourse.julialang.org/t/how-to-write-a-custom-distribution-using-pdf-from-a-kernel-density-estimator/68175/1 "2021-09-14T21:01:45Z")

</div>

Let

`x = rand(100); #some data`

PDF of `x` can be estimated using KDE:

```julia
using KernelDensity
KDE_x = kde(x)
ik = InterpKDE(KDE_x)
KDE_pdf(x) = pdf(ik, x)

```

How can the `KDE_pdf` function be used in to construct a custom distribution?

Here’s my partial first try, still have to implement `rand` for this distribution:

I want to use the `KDEDist` in a Turing.jl model

```julia
using Distributions, KernelDensity

struct KDEDist <: ContinuousUnivariateDistribution
    data::Vector{Float64}
end

function Distributions.pdf(d::KDEDist, x::Real)
    KDE_fit = kde(d.data)
    ik = InterpKDE(KDE_fit)
    return pdf(ik, x)
end

```

As we can see that when the `pdf` function is called the KDE is fitted every time which is wasteful. Is there a way to just the pdf(ik, x) function into the `Distributions.pdf` function to avoid wasteful computation?

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [September 14, 2021, 9:21pm UTC](https://discourse.julialang.org/t/how-to-write-a-custom-distribution-using-pdf-from-a-kernel-density-estimator/68175/2 "2021-09-14T21:21:07Z")

</div>

Do the KDE fit when constructing the struct.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [September 14, 2021, 9:22pm UTC](https://discourse.julialang.org/t/how-to-write-a-custom-distribution-using-pdf-from-a-kernel-density-estimator/68175/3 "2021-09-14T21:22:30Z")

</div>

Also consider doing the same for multivariate distributions using [https://github.com/noilreed/MultiKDE.jl](https://github.com/noilreed/MultiKDE.jl). Also, this would be a valuable package 🙂

---

<div class="post-metadata">

**Author:** ![vkv](https://avatars.discourse-cdn.com/v4/letter/v/d9b06d/32.png) [@vkv](https://discourse.julialang.org/u/vkv)\
**Post date:** [September 14, 2021, 9:47pm UTC](https://discourse.julialang.org/t/how-to-write-a-custom-distribution-using-pdf-from-a-kernel-density-estimator/68175/4 "2021-09-14T21:47:39Z")

</div>

I don’t know how to KDE fit inside struct.

Instead passed the KDE\_pdf into struct like this:

```julia
struct KDEDist <: ContinuousUnivariateDistribution
    KDE_pdf::Function
    h::Float64 #used for rand
end

function Distributions.pdf(d::KDEDist, x::Real)
    return KDE_pdf(x) 
end

dist = KDEDist(KDE_pdf, 1.0)
pdf(dist, 10)

```

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [September 14, 2021, 9:50pm UTC](https://discourse.julialang.org/t/how-to-write-a-custom-distribution-using-pdf-from-a-kernel-density-estimator/68175/5 "2021-09-14T21:50:12Z")

</div>

Something like this

```julia
using Distributions, KernelDensity

struct KDEDist{D, K} <: ContinuousUnivariateDistribution
    data::D
    kde::K
end
function KDEDist(data)
    KDE_fit = kde(d.data)
    ik = InterpKDE(KDE_fit)
    return KDEDist(data, ik)
end

function Distributions.pdf(d::KDEDist, x::Real)
    return pdf(d.kde, x)
end

```
