# How can I fit a function onto a histogram?

SampleData = RandomVariate[RayleighDistribution[3], 5000];
Histogram[SampleData]


This creates a histogram that (in my case) looks something like this:

I want to fit this histogram with a curve. The documentation of RandomVariate shows something similar to what I had in mind:

(However the blue line isn't actually a fitted curve; the documentation is simply plotting the [known] analytical formula.)

How can I fit the histogram? The obvious way is to use Interpolation, but the naive attempt to Interpolation[Histogram[SampleData]] doesn't work; Mathematica complains that the histogram is not a list of data and coordinates.

Edit: My raw data contains about 6000 points and looks like this:

This isn't what I'm trying to fit however; I want to fit the histogram, which looks like this:

Ideally the defined "NewFunction" would be able to take input such as NewFunction[3] and return about 70. A normalized NewFunction would be even better.

• how SmoothKernelDistribution, e.g., Show[Histogram[SampleData, Automatic, PDF], Plot[Evaluate@PDF[SmoothKernelDistribution[SampleData]][x], {x, 0, 15}, PlotStyle -> Directive[Red, Thick]]]? – kglr Jun 18 '19 at 5:17
• @kglr that works, thanks! – Allure Jun 18 '19 at 5:24
• Allure, posted the comment as an answer. – kglr Jun 18 '19 at 5:31
• Allure, you want to use bar width and height information from histogram to construct an estimated PDF? – kglr Jun 18 '19 at 5:39
• Allure: You have the raw data. Constructing a histogram and fitting it loses information. You certainly don't want to use a regression function (NonlinearModelFit, for example). With the large amount of data you have, using SmoothKernelDistribution as @kglr shows you is what you want. If you have a particular probability distribution in mind, then you should consider EstimatedDistribution. – JimB Jun 18 '19 at 15:32

Update 2: Extracting bin center and height information from Histogram output and using Interpolation:

histogram = Histogram[SampleSampleData];
datafromrectangles =  Cases[histogram,
Rectangle[a_, b_, ___] :> {Mean[{a[[1]], b[[1]]}], b[[2]]}, All];
intF = Interpolation[datafromrectangles];

Show[histogram,
Quiet@ Plot[intF[x], {x, 0, 15}, PlotStyle -> Directive[Blue, Thick], Filling -> Axis]]


Update: An alternative using WeightedData on histogram bin limits and heights combined with Interpolation:

{binlims, heights} = HistogramList[SampleData];
wd = WeightedData[MovingAverage[binlims, 2], heights];
bw = binlims[[2]] - binlims[[1]];
iF = (1/bw) Interpolation[Transpose[wd["EmpiricalPDF"]]][#] &;
Show[Histogram[SampleData, Automatic, PDF],
Quiet@ Plot[iF[x], {x, 0,
15}, PlotStyle -> Directive[Blue, Thick], Filling -> Axis]]


Note: This approach works only for fixed bin width and PDF as the height function.

You can use SmoothKernelDistribution with SampleData as input to get a distribution object use its PDF:

SeedRandom[1]
SampleData = RandomVariate[RayleighDistribution[3], 5000];
dist =SmoothKernelDistribution[SampleData];

Show[Histogram[SampleData, Automatic, PDF],
Plot[Evaluate@PDF[dist][x], {x, 0, 15},
PlotStyle -> Directive[Blue, Thick], Filling -> Axis]]


• Thanks for the answer. The second update worked for the sample data, but not the actual data; still I understand what you're doing and will adapt the code. Two questions: what does the "Empirical PDF" do? Also, for the third update, did you define a histogram somewhere previously? As it is, it doesn't run for me. – Allure Jun 18 '19 at 7:30
• @Allure, forgot to copy/paste the line for histogram. For a WeightedData object w, the property "EmpiricalPDF" of w (accessed using w["EmpiricalPDF"]) gives two lists, the first containing data values and the second estimated weights. – kglr Jun 18 '19 at 7:52

How about just using EstimatedDistribution?

SampleData = RandomVariate[RayleighDistribution[3], 5000];
fitDist = EstimatedDistribution[SampleData, RayleighDistribution[s]]
Show[
Histogram[SampleData, Automatic, "PDF"],
Plot[PDF[fitDist, x], {x, 0, 12}]
]


If you have an arbitrary PDF, you can fit to a ProbabilityDistribution:

fitDist = EstimatedDistribution[
SampleData,
ProbabilityDistribution[(E^(-(x^2/(2 s^2))) x)/s^2, {x, 0, \[Infinity]}],
{{s, 1}}
]