如何在Matlab中基于频数表格正确绘制与估计ECDF
问题描述
我之前看到过类似问题,但我的情况有点不一样。我有一组包含x值和对应频数的表格:
| x | 150 | 250 | 350 | 450 | 550 | 650 | 750 |
|---|---|---|---|---|---|---|---|
| y(频数) | 1 | 2 | 8 | 30 | 18 | 16 | 5 |
我搞不懂Matlab内置函数[f,x] = ecdf(y)的逻辑,用它估计并绘制的经验累积分布函数(ECDF)明显不对——从直方图来看,得到的ECDF和正确分布完全不匹配。我想知道:怎么基于这个表格正确构建针对x的ECDF,并且直接估计和绘制累积分布函数?
以下是我绘制直方图和ECDF的代码:
%% data y = [1; 2; 8; 30; 18; 16; 5]; x = [150; 250; 350; 450; 550; 650; 750]; %% hist and polygon figure(1) bar(x,y,'LineWidth',1,... 'FaceColor',[0.0745098039215686 0.623529411764706 1],... 'EdgeColor',[0.149019607843137 0.149019607843137 0.149019607843137],... 'BarWidth',1,... 'BarLayout','stacked'); hold on plot(x,y,'-o','Color','red','LineWidth',1) hold off %% ecdf [ff,x] = ecdf(y); x_e = [0;x]; figure(2) stairs(x_e,ff,'Marker','o','LineWidth',1,'Color',[0.0745098039215686 0.623529411764706 1]); set(gca,'GridAlpha',0.25,'GridLineStyle','--','MinorGridLineStyle','--',... 'XGrid','on','XMinorGrid','on','YGrid','on'); xlim([0 780]);
解决方案
你的问题出在直接把频数数组y传给了ecdf函数——ecdf的输入应该是原始样本数据,而不是频数统计结果。它会把输入的每个元素当作一个独立样本,所以你传y进去,相当于在对[1,2,8,30,18,16,5]这7个值做ECDF,完全和你的x变量无关,结果自然不对。
要基于分组频数数据构建x的ECDF,有两种简单方法:
方法1:展开成原始样本数组
把每个x值按照对应的频数重复,生成完整的样本数组,再传给ecdf:
%% 生成原始样本数组 sample = []; for i = 1:length(x) sample = [sample; repmat(x(i), y(i), 1)]; end %% 计算并绘制ECDF figure(3) [f, ecdf_x] = ecdf(sample); stairs(ecdf_x, f, 'Marker','o','LineWidth',1,'Color',[0.0745098039215686 0.623529411764706 1]); set(gca,'GridAlpha',0.25,'GridLineStyle','--','MinorGridLineStyle','--',... 'XGrid','on','XMinorGrid','on','YGrid','on'); xlim([100 800]);
方法2:手动计算累积频率
如果数据量很大,展开数组太占内存,可以手动计算累积频率,直接绘制ECDF:
%% 计算总样本数 total = sum(y); %% 计算累积频数和累积频率 cum_y = cumsum(y); cum_freq = cum_y / total; %% 构建ECDF的x轴(补充左端点,让曲线从0开始) ecdf_x = [x(1)-100; x]; % 这里x(1)-100是为了让曲线在x=150前保持0,可根据需求调整 ecdf_f = [0; cum_freq]; %% 绘制ECDF figure(4) stairs(ecdf_x, ecdf_f, 'Marker','o','LineWidth',1,'Color',[0.0745098039215686 0.623529411764706 1]); set(gca,'GridAlpha',0.25,'GridLineStyle','--','MinorGridLineStyle','--',... 'XGrid','on','XMinorGrid','on','YGrid','on'); xlim([100 800]);
两种方法得到的结果是一致的,都能正确反映x变量的累积分布。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

