如何在matlab中将分布拟合到数据集?

时间:2018-01-01 19:27:47

标签: matlab

我正在尝试使用matlab找到适合我的数据但是我遇到了很多麻烦,这是我到目前为止所做的:

A = load('homicide_crime.txt')  % A is a two column array the first column is the year and the second column is crime in that year
norm_crime = (A(:,2)-mean(A(:,2)))/std(A(:,2)); 
[f,x]=hist(norm_crime,20);
plot(x,f/trapz(x,f))
y=normpdf(x,0,1);
hold on
plot(x,y)

这是结果图

所以我后来尝试使用分配钳工给了我这个。   这些事情看起来都不正确,因为峰值没有对齐且拟合太小。

这是任何有兴趣的人的数据集 https://pastebin.com/CyddrN1R

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

实际上,我认为您将数据转换与分布拟合混淆。

数据转换

在这种方法中,数据通过非线性变换进行操作,以实现完美契合。这意味着它会强制您的数据遵循所选的分配规则。要通过正态分发实现此目的,您只需应用以下代码:

A = load('homicide_crime.txt');
years = A(:,1);
crimes = A(:,2);
figure(),histfit(crimes);

rank = tiedrank(crimes);
p = rank ./ (numel(rank) + 1);
crimes_normal = norminv(p,0,1);
figure(),histfit(crimes_normal);

使用以下操作:

crimes_normal = (crimes - mean(crimes)) ./ std(crimes);

也可以写成:

crimes_normal = zscore(crimes);

您修改了观察结果,使其具有mu=0sigma=1,但这远远不能使它们完全符合正态分布。

分销适合

在这种方法中,在给定数据集上计算所选分布的参数,然后绘制随机观察值。一方面,您有经验观察,另一方面,您有适合的数据。拟合优度检验最终可以告诉您经验观察与给定分布的拟合程度与理论观察结果的比较。

由于您正在使用正态分布,因此您知道它由两个参数完整描述:musigma。因此:

A = load('homicide_crime.txt');
years = A(:,1);
crimes_emp = A(:,2);

[mu,sigma] = normfit(crimes_emp);

% you can also use
% mu = mean(crimes);
% sigma = std(crimes);
% to achieve the same result

[f,x] = hist(crimes_emp);
crimes_the = normpdf(x,mu,sigma) .* max(f);

figure();
bar(x, (f ./ sum(f)));
hold on;
plot(x,crimes_the,'-r','LineWidth',2);
hold off;

这会返回与您最初注意到的问题非常接近的内容。你可以清楚地看到,甚至没有运行Kolmogorov-Smirnov或Anderson-Darling ......你的数据也不适合正常分布。

答案 1 :(得分:0)

您可以尝试非参数密度估算方法。我使用内核密度估计(KDE)和默认的正态分布作为内核,以获得如下所示的结果。相同的Matlab命令是ksdensity(),可以找到文档here

A = load('homicide_crime.txt')                     % load data
years = A(:,1);
values = A(:,2);
[f0,x0] = hist(values,100);                        % plot the actual histogram
[f1,x1,b1] = ksdensity(values);                    % KDE with automatically assigned bandwidth
[f2,x2,b2] = ksdensity(values,'Bandwidth',b1*0.6); % 60% of initial bandwidth (b1)
[f3,x3,b3] = ksdensity(values,'Bandwidth',b2*0.6); % 60% of previous bandwidth (b2) = 36% of initial bandwidth (b1)
[f4,x4,b4] = ksdensity(values,'Bandwidth',b3*0.6); % 60% of previous bandwidth (b3) = 21.6% of initial bandwidth (b1)

figure; hold on;
bar(years, f0/(sum(f0)*10) );                      % scaled for visualization 
plot(years, f1, 'y')
plot(years, f2, 'c')
plot(years, f3, 'g')
plot(years, f4, 'r','linewidth',3)                 % Final fit

enter image description here

在上面的代码中,我首先绘制直方图,然后在没有任何用户指定带宽的情况下计算kde。这导致过于平滑的拟合(黄色曲线)。通过几次试验将带宽减少到前一次迭代的60%,我终于能够得到最接近的拟合(红色曲线)。您可以围绕带宽来获得更好的合适效果。