从matlab boxplot中删除某些异常值

时间:2017-06-29 15:02:44

标签: matlab plot boxplot

在MATLAB中,boxplot命令可用于生成箱图。此函数的默认行为是晶须长度为1.5 * IQR(第75百分位数 - 第25百分位数),如果需要,此晶须长度可以更改为IQR的另一倍数。但是,不可能使用特定的百分位数作为胡须的限制,这是我需要的(在我的例子中是第10和第90百分位数)。正如您将在下面的示例中看到的那样,我到目前为止已遇到问题。

考虑以下数据:

    Box_Data_PFCA = [-3;1;2;3;4;5;5;5;6;40;45;77;7;9;1;2;3;7;7;7;10;11;11;40;30;101;110;150];
    label = ['PFOS';'PFOS';'PFOS';'PFOS';'PFOS';'PFOS';'PFOS';'PFOS';'PFOS';'PFOS';'PFOS';'PFOS';'PFOS';'PFOS';...
             'PFDA';'PFDA';'PFDA';'PFDA';'PFDA';'PFDA';'PFDA';'PFDA';'PFDA';'PFDA';'PFDA';'PFDA';'PFDA';'PFDA'];

我使用defualt matlab函数生成一个boxplot:

h = boxplot(Box_Data_PFCA,label)

然后我计算生成箱线图所需的百分位数:

PFOS_10=prctile([-3;1;2;3;4;5;5;5;6;40;45;77;7;9],10)
PFOS_25=prctile([-3;1;2;3;4;5;5;5;6;40;45;77;7;9],25)
PFOS_75=prctile([-3;1;2;3;4;5;5;5;6;40;45;77;7;9],75)
PFOS_90=prctile([-3;1;2;3;4;5;5;5;6;40;45;77;7;9],90)
PFDA_10=prctile([1;2;3;7;7;7;10;11;11;40;30;101;110;150],10)
PFDA_25=prctile([1;2;3;7;7;7;10;11;11;40;30;101;110;150],25)
PFDA_75=prctile([1;2;3;7;7;7;10;11;11;40;30;101;110;150],75)
PFDA_90=prctile([1;2;3;7;7;7;10;11;11;40;30;101;110;150],90)

然后我继续使用图形句柄编辑方框图(在我的情况下编辑框是不确定的,因为25%到75%的默认设置适合我,但我显示完整性):

set(h(5,1), 'YData', [PFOS_25 PFOS_75 PFOS_75 PFOS_25 PFOS_25])
set(h(1,1), 'YData', [PFOS_75 PFOS_90])
set(h(2,1), 'YData', [PFOS_10 PFOS_25])
set(h(3,1), 'YData', [PFOS_90 PFOS_90])
set(h(4,1), 'YData', [PFOS_10 PFOS_10])
set(h(5,2), 'YData', [PFDA_25 PFDA_75 PFDA_75 PFDA_25 PFDA_25])
set(h(1,2), 'YData', [PFDA_75 PFDA_90])
set(h(2,2), 'YData', [PFDA_10 PFDA_25])
set(h(3,2), 'YData', [PFDA_90 PFDA_90])
set(h(4,2), 'YData', [PFDA_10 PFDA_10])

导致以下结果:

enter image description here

正如你所看到的,我对胡须的改变后,我的一些异常值与胡须重叠。

我的问题是如何确保在我的更改后,我的胡须内的异常值被移除(并且在我的胡须之外)。我意识到我需要以某种方式使用'Outliers'句柄,但解决方案并没有呈现给我...因为这只是一个示例数据集,解决方案必须处理大型数据集。

2 个答案:

答案 0 :(得分:1)

因此,如果一个点小于最高胡须,并且大于最低胡须,则会删除它们。

您只能通过h变量检查自己的位置。 像这样的东西:

idx = find(h(6:end,1).YData<PFOS_90&h(6:end,1).YData>PFOS_10);
h(5+idx,1)=[];

[编辑]

很高兴上面的想法指出了一个有效的解决方案!你的代码有点长,但非常易读。这也很重要。但也许这四条线做同样的工作?

idx = find(h(7,1).YData<PFOS_90&h(7,1).YData>PFOS_10);
h(7,1).YData(idx)=[];h(7,1).XData(idx)=[];
idx = find(h(7,2).YData<PFOS_90&h(7,2).YData>PFOS_10);
h(7,2).YData(idx)=[];h(7,2).XData(idx)=[];

如果你有很多要删除的点,你需要检查的不仅仅是(7,1)和(7,2)吗?在这种情况下,请使用for i = 1:size(h,2)

放置一个循环

[/编辑]

答案 1 :(得分:0)

关注@Gelliants提示我已经设法找到了解决方案。它不漂亮,毫无疑问会更精致,但它的工作原理。我将以下代码行添加到我的问题中发布的代码:

a = get(h(7,1), 'YData')
b = get(h(7,1), 'XData')
idx = find(a<PFOS_90&a>PFOS_10)
a(idx)=[]
b(idx)=[]
set(h(7,1), 'YData', a, 'XData', b)
e = get(h(7,2), 'YData')
f = get(h(7,2), 'XData')
idx = find(e<PFDA_90&e>PFDA_10)
e(idx)=[]
f(idx)=[]
set(h(7,2), 'YData', e, 'XData', f)

这导致下面的图表可以与问题中的原始图表进行比较。欢迎提供有关如何优化我的解决方案的任何提示!

enter image description here