3
$\begingroup$

I have 20060 dates and I used the SmoothkernelDistribution function to get a distribution of them:

enter image description here

However, I also need a functional form of the distribution to use it in another program without use the input data. How can I get this functional form of this distribution?

$\endgroup$
3
  • $\begingroup$ If you look at PDF[\[ScriptCapitalD], x], you'll see that the functional form is a Hermite interpolation function, which would be rather tedious to port over. You might have more luck with KernelMixtureDistribution, which returns a sum of Gaussians. $\endgroup$ Commented Jul 14, 2020 at 14:03
  • $\begingroup$ You could always get a few thousand values of the PDF at regular intervals and store it in a big lookup table. You'd rescale your input x into an index into the table, and you could also smooth this value with the next and previous values. $\endgroup$
    – flinty
    Commented Jul 14, 2020 at 14:10
  • $\begingroup$ If your dates are just days of the year (and no times), it appears that you have a discrete distribution with integer values ranging from 0 to 14. If so, then a table of 15 relative frequencies will describe the sample distribution. (If there are no zeros, then you'll only have 14 relative frequencies). If there is some theoretical basis for a particular distribution, then sharing that would also be helpful to get a good answer. And, finally, noting the other application that needs the distribution (cumulative distribution?) would also be helpful. $\endgroup$
    – JimB
    Commented Jul 14, 2020 at 17:22

1 Answer 1

5
$\begingroup$

The definition of the distribution is actually give in the documentation, and it should be rather straight forward to port it. The definition is $$ f(x) = \frac{1}{n h}\sum^n_{i=1}k\left(\frac{x-x_i}{h}\right). $$

The only unknown here is h, the bandwidth, which can be extracted from the DataDistribution object.

Sample distribution and data:

dist = MixtureDistribution[
   {1, 2},
   {NormalDistribution[], NormalDistribution[2, 1/2]}
   ];

data = RandomVariate[dist, 10^4];
dataDist = SmoothKernelDistribution[data];

Now we can extract values as follows:

sampleY = dataDist[[2, 1]];
sampleX = dataDist[[2, 2]];
bandwidth = dataDist[[2, 3]];

Using the bandwidth, we can now compute the probability density for an arbitrary x, in a way that's easy to port to other languages because it only requires basic math functions. I'm going to use a Gaussian kernel, which is the default (look in the documentation for the definition of other kernels):

k[u_] := (1./Sqrt[2. Pi]) Exp[-u^2./2.]
f[x_, h_] := (1/(Length[data] h)) Sum[k[(x - xi)/h], {xi, data}]

To see that f[x_, h_] works, we can compute it for the sample points given in the DataDistribution object:

samplePts = {#, f[#, bandwidth]} & /@ sampleX;
Plot[
 PDF[dataDist, x], {x, -4, 4},
 Epilog -> {
   Red,
   PointSize[Small],
   Point@samplePts
   }]

Output

This picture shows that the formula works, and returns the same values as PDF[dataDist, x] does. As pointed out in the comments, Mathematica applies some interpolation. I don't think you need to bother to port the exact interpolation method to your other language, it doesn't look like it would make any difference. And in any case, you have the formula so you can compute the PDF with arbitrary precision.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.