从 matlab 箱线图中删除某些异常值
Remove certain outliers from matlab 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'];
我使用默认的 matlab 函数从中生成箱线图:
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])
结果如下:
如您所见,在我对胡须进行更改后,我的一些异常值与胡须重叠。
我的问题是如何确保我的胡须内的异常值在我的更改后被删除(并显示我的胡须外)。我意识到我需要以某种方式使用 'Outliers' 句柄,但解决方案并没有向我展示...因为这只是一个示例数据集,所以解决方案必须适用于大型数据集。
因此,如果一个点小于您的最高胡须,但大于最低胡须,您将删除它们。
您不能只从 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)
放置一个循环
[/edit]
根据@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)
这导致下面的情节可以与我在问题中的原始情节进行比较。欢迎任何关于如何改进我的解决方案的提示!
在 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'];
我使用默认的 matlab 函数从中生成箱线图:
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])
结果如下:
如您所见,在我对胡须进行更改后,我的一些异常值与胡须重叠。
我的问题是如何确保我的胡须内的异常值在我的更改后被删除(并显示我的胡须外)。我意识到我需要以某种方式使用 'Outliers' 句柄,但解决方案并没有向我展示...因为这只是一个示例数据集,所以解决方案必须适用于大型数据集。
因此,如果一个点小于您的最高胡须,但大于最低胡须,您将删除它们。
您不能只从 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)
[/edit]
根据@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)
这导致下面的情节可以与我在问题中的原始情节进行比较。欢迎任何关于如何改进我的解决方案的提示!