Fitting a density (distribution) to a histogram in Matlab - matlab

I have a matrix M(mx2). The first column is my bins and the second one is the frequency associated with each bin. I want to fit a smooth curve to this histogram in matlab, but most of what I have tried (like kdensity) needs the real distribution of data, which I don't have them.
Is there any functions that can take the bins and their frequency and give me a smooth curve of bin-freq. ?

Here's a hack that should work for you: generate a sample from your histogram, then run ksdensity on the sample.
rng(42) % seed RNG to make reproducible
% make example histogram
N = 1e3;
bins = -5:5;
counts = round(rand(size(bins))*N);
M = [bins' counts'];
figure
hold on
bar(M(:,1), M(:,2));
% draw a sample from it
sampleCell = arrayfun( #(i) repmat(M(i,1), M(i,2), 1), 1:size(M,1), 'uniformoutput', false )';
sample = cat(1, sampleCell{:});
[f, x] = ksdensity(sample);
plot(x, f*sum(M(:,2)));

Related

Vectors must be the same length error in Curve Fitting in Matlab

I'm having problems in curve fitting my randomized data for the function
Here is my code
N = 100;
mu = 5; stdev = 2;
x = mu+stdev*randn(N,1);
bin=mu-6*stdev:0.5:mu+6*stdev;
f=hist(x,bin);
plot(bin,f,'bo'); hold on;
x_ = x(1):0.1:x(end);
y_ = (1./sqrt(8.*pi)).*exp(-((x_-mu).^2)./8);
plot(x_,y_,'b-'); hold on;
It seems like I'm having vector size problems since it is giving me the error
Error using plot
Vectors must be the same length.
Note that I simplified y_ since mu and the standard deviation is known.
Plot:
Well first of all some adjustments to your question:
You are not trying to do curve fitting. What you are trying to do (in my opinion) is to overlay a probability density function on an histogram obtained by taking random points from the same distribution (A normal distribution with parameters (mu,sigma)). These two curve should indeed overlay, as they represent the same thing, only one is analytical and the other one is obtained numerically.
As seen in the hist documentation, hist is not recommended and you should use histogram instead
First step: Generating your random data
Knowing the distribution is the Normal distribution, we can use MATLAB's random function to do that :
N = 150;
rng('default') % For reproducibility
mu = 5;
sigma = 2;
r = random('Normal',mu,sigma,N,1);
Second step: Plot the histogram
Because we don't just want a count of the elements in each bin, but a feel of the probability density function, we can use the 'Normalization' 'pdf' arguments
Nbins = 25;
f=histogram(r,Nbins,'Normalization','pdf');
hold on
Here I'd rather specify a number of bins than specifying the bins themselves, because you never know in advance how far from the mean your data is going to be.
Last step: overlay the probability density function over the histogram
The histogram being already consistent with a probability density function, it is sufficient to just overlay the density function:
x_ = linspace(min(r),max(r),100);
y_ = (1./sqrt(2*sigma^2*pi)).*exp(-((x_-mu).^2)./(2*sigma^2));
plot(x_,y_,'b-');
With N = 150
With N = 1500
With N = 150.000 and Nbins = 50
If for some obscure reason you want to use old hist() function
The old hist() function can't handle normalization, so you'll have to do it by hand, by normalizing your density function to fit your histogram:
N = 1500;
% rng('default') % For reproducibility
mu = 5;
sigma = 2;
r = random('Normal',mu,sigma,1,N);
Nbins = 50;
[~,centers]=hist(r,Nbins);
hist(r,Nbins); hold on
% Width of bins
Widths = diff(centers);
x_ = linspace(min(r),max(r),100);
y_ = N*mean(Widths)*(1./sqrt(2*sigma^2*pi)).*exp(-((x_-mu).^2)./(2*sigma^2));
plot(x_,y_,'r-');

How to plot a covariance matrix on a 2D plot in MATLAB?

In MATLAB there is a function called cov. If I insert a matrix X into cov like this cov(X), then cov will return a square matrix of covariance.
My question is very simple:
How can I, with MATLAB, plot that matrix cov(X) onto a 2D plot like this.
I can see a lot of covariance matrix plots at Google. But how do they create them?
My best guess is that you're trying to add the principal components to the plot. To do that, you could do something like this.
%% generate data points
S_tru = [2 1; 1 1];
N = 1000;
%% compute mean, covariance, principal components
X = mvnrnd([0,0],S_tru,N);
mu = mean(X);
S = cov(X);
[U,D] = eig(S);
%% specify base points/directions for arrows
base = [mu;mu];
vecs = sqrt(D)*U';
vecs = 2 * vecs;
%% plot
plot(X(:,1),X(:,2), 'r.')
axis equal
hold on
quiver(base(:,1),base(:,2),vecs(:,1),vecs(:,2),'blue','LineWidth',2)
Resulting graph:

Potting sampling result frequency in histogram

I am just starting to learn Matlab.
Case:
From 3 elements, let's say 1,2, and 3. I want to sample 2 elements randomly. I want to simulate it 100 times to see the probability of the outcomes pair.
How can I plot the result on histogram that I can visualize the frequency of each pair. So far, I can do the sampling :
for i=1:100
datasample(1:3,2,'Replace',true)
end
So possible outcome is (1,1),(1,2),(2,1),(2,3), etc.
How can I plot the frequency of the outcome using histogram?
Thanks in advance
n = 100;
% generate data random
arr = zeros(n, 2);
for i = 1:n
arr(i, :) = randi([1,3],1,2);
end
% frequency
[ii, jj, kk] = unique(arr, 'rows', 'stable');
f = histc(kk, 1:numel(jj));
result = [ii f];
% plot
cuts = strcat(num2str(result(:,1)), '-',num2str(result(:,2)));
bar(result(:,3))
grid on
xlabel('combination')
ylabel('frequency')
set(gca,'xticklabel',{cuts});
set(gca,'XTickLabelRotation',45);

Solving convolutions in Matlab using `conv` or `fft`

This is follow-up question to my other SO post about performing multiple convolutions like
where the functions are defined in my code below.
I need to rescale the result of the convolution with respect to the number of time steps in the calculation, N.
N = 1000;
t = linspace(-10,10,N);
x = t.*exp(-t.^2);
y = exp(-4*t.^2).*cos(t);
z = (t-2)/((t-2).^2+3^2);
w = exp(-3*t.^2).*exp(2i*t);
% convolution
u = conv(conv(conv(x,y)/N,z)/N,w)/N;
% Fourier transform
L_x=fft(x)/N;
L_y=fft(y)/N;
L_z=fft(z)/N;
L_w=fft(w)/N;
L_u=L_x.*L_y.*L_z.*L_w; %convolution on frequency domain
v=ifft(L_u)*N;
figure(1)
ax1 = subplot(2,1,1);
ax2 = subplot(2,1,2);
plot(ax1,1:length(u),real(u))
title(ax1,'conv')
hold off
plot(ax2,t,real(v))
title(ax2,'fft')
xlabel(ax2,'t')
How do I scale the convolution correctly? (N.B. If I change to N=1e5 timesteps, the y-values decrease).
How do I ensure that the conv output spans the same time region as the fft output? Graph of real part of convolution below:

how to normalize histogram

I ma creating the exponential distribution using inverse method. I want to normalize histogram. How can I do it?
This is my code
N=100;
Lambda=2;
r=rand(N,1);
X=-log(1-r)/Lambda;
hist(X), colormap(bone);
t = 0:0.01:5;
pdf=Lambda*exp(-Lambda*t);
hold on, plot(t,pdf,'LineWidth',2)
The histogram should be normalized to unit area so that it can be compared with the theoretical pdf. To normalize to unit area you need to divide by the number of samples and by the bin width:
N = 100;
Lambda=2;
r = rand(N,1);
X = -log(1-r)/Lambda;
[hy, hx] = hist(X); %/ get histogram values
hy = hy/numel(X)/(hx(2)-hx(1)); %//normalize histogram
bar(hx, hy) %// plot histogram
t = 0:0.01:5;
pdf = Lambda*exp(-Lambda*t);
hold on, plot(t,pdf,'LineWidth',2) %// plot pdf
Or use the new histogram function (introduced in R2014b), which automatically normalizes according to the specified normalization option:
N = 100;
Lambda=2;
r = rand(N,1);
X = -log(1-r)/Lambda;
histogram(X, 'Normalization', 'pdf') %// plot normalized histogram
t = 0:0.01:5;
pdf = Lambda*exp(-Lambda*t);
hold on, plot(t,pdf,'LineWidth',2) %// plot pdf