function result=bagplot(x,varargin) %BAGPLOT draws a bagplot, which is a generalisation of the univariate boxplot % to bivariate data. The original bagplot is described in % % Rousseeuw, P.J., Ruts, I. and Tukey, J.W. (1999), % "The bagplot: a bivariate boxplot", The American Statistician, 53, 382-387. % % The construction of this bagplot is based on the halfspacedepth (see also halfspacedepth.m). % As the computation of the halfspacedepth is rather time-consuming, it is recommended at large datasets % to perform the computations on a random subset of the data. The default size of the subset is 200, but this can be % modified by the user. % % The bagplot can also be computed based on the adjusted outlyingness (see also adjustedoutlyingness.m). % This method is described in: % % Hubert, M., and Van der Veeken, S. (2008), % "Outlier detection for skewed data", Journal of Chemometrics, to appear. % % For the up-to-date references, please consult the website: % http://wis.kuleuven.be/stat/robust.html % % The bagplot based on the adjusted outlyingness can be obtained by setting the optional input argument 'type' equal to 'ao'. % % Required input arguments: % x : bivariate data matrix (observations in the rows, variables in the % columns) % % Optional input arguments: % sizesubset : When drawing the bagplot based on the halfspacedepth, the size of the subset used to perform % the main computations. % type : To draw the bagplot based on the halfspacedepth, this parameter should be equal to 'hd' (default). % To draw the bagplot based on the adjusted outlyingness, it should be set to 'ao'. % plots : If equal to 1, a bagplot is drawn (default). If equal to zero, no plot is made. % colorbag : The color of the bag. % colorfence : The color of the fence. % databag : If this parameter is 1, the data within the bag are % plotted. If this parameter is set equal to 0, data points % are not displayed. % datafence : If this parameter is 1, the data within the fence are % plotted. If this parameter is set equal to 0, data points % are not displayed. % % I/O: result=bagplot(x,'sizesubset',200,'type','hd','colorbag',[],'colorfence',[],'databag',1,'datafence',1); % The user should only give the input arguments that have to change their default value. % The name of the input arguments needs to be followed by their value. % The order of the input arguments is of no importance. % % Examples: % result=bagplot(x,'colorfence',[0.2 0.2 0.5],'databag',0) % result=bagplot(x,'datafence',0,colorbag',[1 0 0]) % % % The output of bagplot is a structure containing % % result.center : center of the data. When 'type=hd', this corresponds with the Tukey median. When % 'type=ao', the point with smallest adjusted outlyingness % result.type : same of the input parameter type: 'hd' or 'ao'. % result.flag : is 0 for outliers and equals 1 for regular points % result.datatype : is 2 for observations in the bag, 1 for the observations in the % fence and zero for outliers. % result.depth : when 'type=hd' this is the halfspacedepth of each data point, % when 'type=ao' the adjusted outlyingness. % % Written by Fabienne Verwerft on 25/05/2005 % Update and revision by Stephan Van der Veeken 10/12/2007 % Last revision: 11/02/2008, 25/02/2008 if nargin<1 error('Input argument is undefined') end if size(x,1)<10 error('At least 10 datapoints are needed for the calculation') end if size(x,2)~=2 error('Data should be 2 dimensional') end S=x; counter=1; default=struct('colorbag',[0.6 0.6 1],'colorfence',[0.8 0.8 1],'sizesubset',200,... 'databag',1,'datafence',1,'plots',1,'type','hd'); list=fieldnames(default); result=default; IN=length(list); i=1; %reading the user's input if nargin>1 % %placing inputfields in array of strings % for j=1:nargin-1 if rem(j,2)~=0 chklist{i}=varargin{j}; i=i+1; end end % %Checking which default parameters have to be changed % and keep them in the structure 'result'. % while counter<=IN index=strmatch(list(counter,:),chklist,'exact'); if ~isempty(index) %in case of similarity for j=1:nargin-1 %searching the index of the accompanying field if rem(j,2)~=0 %fieldnames are placed on odd index if strcmp(chklist{index},varargin{j}) I=j; end end end result=setfield(result,chklist{index},varargin{I+1}); index=[]; end counter=counter+1; end end colorbag=result.colorbag; colorfence=result.colorfence; databag=result.databag; datafence=result.datafence; plots=result.plots; type=result.type; sizesubset=result.sizesubset; switch type case 'hd' s1=S(:,1); s2=S(:,2); Q=bagp(s1,s2,sizesubset); bag=Q.interpol; datatyp=Q.datatyp; tukm=Q.tukmed; depth=Q.depth; case 'ao' s1=S(:,1); s2=S(:,2); n=length(s1); Q = adjustedoutlyingness(S); D=[S,Q.outl,Q.flag,(1:n)']; P=sortrows(D,3); L=[P(:,1),P(:,2)]; n=size(P,1); f=floor(n/2); g=sum(Q.flag); h=n-g; bag=L((1:f),:); hulp=[ones(f,1);2*ones(g-f,1);3*ones(h,1)]; d1=[P,hulp]; d2=sortrows(d1,5); datatyp=[d2(:,1),d2(:,2),d2(:,6)]; tukm=L(1,:); depth=Q.outl; end i=find(datatyp(:,3)==1); data1=datatyp(i,1:2); i=find(datatyp(:,3)==2); data2=datatyp(i,1:2); data=[data1;data2]; i=find(datatyp(:,3)>=3); outl=datatyp(i,1:2); plak=[data;bag]; k=convhull(plak(:,1),plak(:,2)); whisk=plak(k,1:2); if plots==1 fill(whisk(:,1),whisk(:,2),colorfence,'LineStyle','none') hold on %This is essential in order to prevent that only the last executed plotting command is executed q=convhull(bag(:,1),bag(:,2)); bagq=bag(q,1:2); fill(bagq(:,1),bagq(:,2),colorbag)%This line should be placed after the command plot(data...) to only %plot %the data outside the bag axis square if databag==1 plot(data1(:,1),data1(:,2),'o','MarkerFaceColor','k','MarkerEdgeColor','k','Markersize',4) end if datafence==1 plot(data2(:,1),data2(:,2),'o','MarkerFaceColor','k','MarkerEdgeColor','k','Markersize',4) end plot(outl(:,1),outl(:,2),'hk','MarkerFaceColor','k','Markersize',8) plot(tukm(1),tukm(2),'o','MarkerFaceColor','w','MarkerEdgeColor','w','MarkerSize',10); plot(tukm(1),tukm(2),'+k','Markersize',8) switch type case 'ao' title('bagplot based on adjusted outlyingness') set(gcf,'Name', 'Bagplot based on adjusted outlyingness', 'NumberTitle', 'off'); case 'hd' title('bagplot based on halfspacedepth') set(gcf,'Name', 'Bagplot based on halfspacedepth', 'NumberTitle', 'off'); end xmin=min(datatyp(:,1)); xmax=max(datatyp(:,1)); small=0.05*(xmax-xmin); xaxis1=xmin-small; xaxis2=xmax+small; ymin=min(datatyp(:,2)); ymax=max(datatyp(:,2)); small=0.05*(ymax-ymin); xaxis3=ymin-small; xaxis4=ymax+small; axis([xaxis1 xaxis2 xaxis3 xaxis4]); box on; hold off end Datatyp=datatyp(:,3); flag=zeros(size(S,1),1); for i=1:(size(S,1)) if Datatyp(i)==3 flag(i)=0; else flag(i)=1; end end datatype=zeros(size(S,1),1); for i=1:(size(S,1)) if Datatyp(i)==3 datatype(i)=0; else if Datatyp(i)==2 datatype(i)=1; else datatype(i)=2; end end end if type==1 depth=zeros(size(S,1),1); for i=1:(size(S,1)) depth(i,1)=halfspacedepth(s1(i,1),s2(i,1),s1,s2); end end result=struct('center',tukm,'depth',depth,'datatype',datatype,'flag',flag); %----------- function[pins]=rdraw(n,ntot) pin=unidrnd(ntot,1,n); pins=sort(pin); uu=find(not(diff(pins)==0)); pins=pins(uu); no=length(pins); if no=1 || sum(isnan(y))>=1 error('Missing values are not allowed') end if sum(x==x(1))==n error('All data points ly on a vertical line.') elseif sum(y==y(1))==n error('All data points ly on a horizontal line.') else R=corrcoef(x,y); if abs(R(1,2))==1 error('All data points are collineair.') end end % % Check whether the data is in general position. If not, add a very small random % number to each of the data points. % [x,y, Index, angl, ind1,ind2]=dithering(x,y); % % Main part % if (n==1)&&(d==1) kount=n; ADK=[x,y]; empty=0; return end % if (d>floor(n/2)) kount=0; ADK=0; empty=1; return end % if n<=3 kount=n; ADK=[x,y]; empty=1; return end % nrank(Index)=(1:n); % % Let the line rotate from zero to angle(1) % ncirq=Index; kount=1; halt=0; M=length(angl); if angl(1)>(pi/2) L=1; D1=ind1(L); IV1=nrank(D1); D2=ind2(L); IV2=nrank(D2); IV=ncirq(IV1); ncirq(IV1)=ncirq(IV2); ncirq(IV2)=IV; IV=IV1; nrank(D1)=IV2; nrank(D2)=IV; % if ((IV1==d) && (IV2==(d+1)))||((IV2==d) && (IV1==(d+1)))||((IV1==(n-d)) && (IV2==(n-d+1)))||((IV2==(n-d)) && (IV1==(n-d+1))) if angl(L)<(pi/2) dum=angl(L)+(pi/2); else dum=angl(L)-(pi/2); end if (IV1==d && IV2==(d+1))||(IV2==d && IV1==(d+1)) if dum<=(pi/2) alfa(kount)=angl(L)+pi; else alfa(kount)=angl(L); end end if or((IV1==(n-d) && IV2==(n-d+1)),(IV2==(n-d) && IV1==(n-d+1))) if dum<=(pi/2) alfa(kount)=angl(L); else alfa(kount)=angl(L)+pi; end end kand1(kount)=ind1(L); kand2(kount)=ind2(L); D(kount)=sin(alfa(kount))*x(ind1(L))-cos(alfa(kount))*y(ind1(L)); kount=kount+1; end halt=1; end % L=2; stay=1; % jflag keeps track of which angle we have to test next while stay==1 stay=0; kontrol=0; if (pi<=(angl(L)+(pi/2))) && ((angl(L)-(pi/2))< angl(1)) D1=ind1(L); IV1=nrank(D1); D2=ind2(L); IV2=nrank(D2); IV=ncirq(IV1); ncirq(IV1)=ncirq(IV2); ncirq(IV2)=IV; IV=IV1; nrank(D1)=IV2; nrank(D2)=IV; % if ((IV1==d) && (IV2==(d+1)))||((IV2==d) && (IV1==(d+1)))||((IV1==(n-d)) && (IV2==(n-d+1)))||((IV2==(n-d)) && (IV1==(n-d+1))) if angl(L)<(pi/2) dum=angl(L)+(pi/2); else dum=angl(L)-(pi/2); end if (IV1==d && IV2==(d+1))||(IV2==d && IV1==(d+1)) if dum<=(pi/2) alfa(kount)=angl(L)+pi; else alfa(kount)=angl(L); end end if or((IV1==(n-d) && IV2==(n-d+1)),(IV2==(n-d) && IV1==(n-d+1))) if dum<=(pi/2) alfa(kount)=angl(L); else alfa(kount)=angl(L)+pi; end end kand1(kount)=ind1(L); kand2(kount)=ind2(L); D(kount)=sin(alfa(kount))*x(ind1(L))-cos(alfa(kount))*y(ind1(L)); kount=kount+1; end kontrol=1; end L=L+1; if kontrol==1 halt=1; end if (L==(M+1)) && (kontrol==1) jflag=1; stay=2; end if not(stay==2) if ((halt==1)&&(kontrol==0))||(L==(M+1)) stay=3; else stay=1; end end end if not(stay==2) if (L>1) jflag=L-1; else jflag=M; end end % halt2=0; if not(stay==2) J=0; % % If the first switch didnt occur between 0 and the angle angl(1) look for it % between the following angles. % stay2=1; if (L==M+1) && (kontrol==0) halt=0; halt2=0; J=J+1; if J==(M+1) J=1; end L=J+1; if L==(M+1) L=1; end while stay2==1 stay2=0; kontrol=0; if (angl(L)+pi/2)pi angl(1)=angl(1)-pi; end D1=ind1(L); IV1=nrank(D1); D2=ind2(L); IV2=nrank(D2); IV=ncirq(IV1); ncirq(IV1)=ncirq(IV2); ncirq(IV2)=IV; IV=IV1; nrank(D1)=IV2; nrank(D2)=IV; % if ((IV1==d) && (IV2==(d+1)))||((IV2==d) && (IV1==(d+1)))||((IV1==(n-d)) && (IV2==(n-d+1)))||((IV2==(n-d)) && (IV1==(n-d+1))) if angl(L)<(pi/2) dum=angl(L)+(pi/2); else dum=angl(L)-(pi/2); end if (IV1==d && IV2==(d+1))||(IV2==d && IV1==(d+1)) if dum<=(pi/2) alfa(kount)=angl(L)+pi; else alfa(kount)=angl(L); end end if or((IV1==(n-d) && IV2==(n-d+1)),(IV2==(n-d) && IV1==(n-d+1))) if dum<=(pi/2) alfa(kount)=angl(L); else alfa(kount)=angl(L)+pi; end end kand1(kount)=ind1(L); kand2(kount)=ind2(L); D(kount)=sin(alfa(kount))*x(ind1(L))-cos(alfa(kount))*y(ind1(L)); kount=kount+1; end kontrol=1; end if angl(1)>pi angl(1)=angl(1)-pi; end if L==M L=1; else L=L+1; end if kontrol==1 halt=1; end if (halt==1)&&(kontrol==0) if halt2==1 stay2=2; end if not(stay2==2) if L>1 jflag=L-1; else jflag=M; end stay2=0; end else if L==jj if jj==1 halt2=1; end J=J+1; if J==(M+1) J=1; end L=J+1; if L==(M+1) L=1; end stay2=1; else stay2=1; end end end end end % if not(stay2==2) % % The first switch has occurred. Now start looking for the next ones, % between the following angles. % for i=(J+1):(M-1) L=jflag; stay=1; while stay==1 stay=0; kontrol=0; if ((angl(L)+pi/2)=d)>=1) NDK=1; end if (hdep1IW1)&&(Jfull==0) kornr(IW1:(IW2-1),1)=kand1(IW1); kornr(IW1:(IW2-1),2)=kand2(IW1); kornr(IW1:(IW2-1),3)=kand1(IW2); kornr(IW1:(IW2-1),4)=kand2(IW2); else if IW2>IW1 i=IW1; stay3=1; while stay3==1 if (kornr(i,1)==kand1(IW1))&&(kornr(i,2)==kand2(IW1))&&(kornr(i,3)==kand1(IW2))&&(kornr(i,4)==kand2(IW2)) stay3=0; else m1=(y(kornr(i,2))-y(kornr(i,1)))/(x(kornr(i,2))-x(kornr(i,1))); m2=(y(kornr(i,4))-y(kornr(i,3)))/(x(kornr(i,4))-x(kornr(i,3))); if not(m1==m2) xcord1=(m1*x(kornr(i,1))-y(kornr(i,1))-m2*x(kornr(i,3))-y(kornr(i,3)))/(m1-m2); ycord1=(m2*(m1*x(kornr(i,1))-y(kornr(i,1)))-m1*(m2*x(kornr(i,3))-y(kornr(i,3))))/(m1-m2); end if (abs(xcord1-xcord)0)&&(stay4>0)&¬(stay2==1) % % The intersection point is not the correct one, try the next % special k-divider. % IW2=IW2+1; if IW2==(num+1) IW2=1; end stay2=1; end % % Look for the next vertex of the convex figure. % if (stay3>0)&&(stay4>0)&¬(stay2==1) IW1=IW2; IW2=IW2+1; if IW2==(num+1) IW2=1; end stay2=1; end end % % Scan kornr and ascribe the coordinates of the vertices to the variable % ADK. % kount=0; % if NDK==0 % % The requested depth region is empty % ADK=0; empty=1; return else empty=0; end % i=1; E1=y(kornr(i,2))-y(kornr(i,1)); F1=x(kornr(i,1))-x(kornr(i,2)); G1=x(kornr(i,1))*(y(kornr(i,2))-y(kornr(i,1)))-y(kornr(i,1))*(x(kornr(i,2))-x(kornr(i,1))); E2=y(kornr(i,4))-y(kornr(i,3)); F2=x(kornr(i,3))-x(kornr(i,4)); G2=x(kornr(i,3))*(y(kornr(i,4))-y(kornr(i,3)))-y(kornr(i,3))*(x(kornr(i,4))-x(kornr(i,3))); xcord(i)=(-F2*G1+F1*G2)/(E2*F1-E1*F2); ycord(i)=(-E2*G1+E1*G2)/(E1*F2-E2*F1); DK(i,:)=[xcord(i),ycord(i)]; Juisteind(i)=i; xcord1=xcord(i); ycord1=ycord(i); xcordp=xcord(i); ycordp=ycord(i); kount=kount+1; i=i+1; % while not(i==num+1) if (kornr(i,1)==kornr(i-1,1))&&(kornr(i,2)==kornr(i-1,2))&&(kornr(i,3)==kornr(i-1,3))&&(kornr(i,4)==kornr(i-1,4)) i=i+1; else if (kornr(i,1)==kornr(1,1))&&(kornr(i,2)==kornr(1,2))&&(kornr(i,3)==kornr(1,3))&&(kornr(i,4)==kornr(1,4)) pp=find(not(Juisteind==0)); ADK=DK(pp,:); empty=0; return else E1=y(kornr(i,2))-y(kornr(i,1)); F1=x(kornr(i,1))-x(kornr(i,2)); G1=x(kornr(i,1))*(y(kornr(i,2))-y(kornr(i,1)))-y(kornr(i,1))*(x(kornr(i,2))-x(kornr(i,1))); E2=y(kornr(i,4))-y(kornr(i,3)); F2=x(kornr(i,3))-x(kornr(i,4)); G2=x(kornr(i,3))*(y(kornr(i,4))-y(kornr(i,3)))-y(kornr(i,3))*(x(kornr(i,4))-x(kornr(i,3))); xcord(i)=(-F2*G1+F1*G2)/(E2*F1-E1*F2); ycord(i)=(-E2*G1+E1*G2)/(E1*F2-E2*F1); if ((abs(xcord(i)-xcordp)=1 || sum(isnan(y))>=1 error('Missing values are not allowed') end if sum(x==x(1))==n error('All data points ly on a vertical line.') elseif sum(y==y(1))==n error('All data points ly on a horizontal line.') else R=corrcoef(x,y); if abs(R(1,2))==1 error('All data points are collineair.') end end % % Looking for optional argument % if nargin>2 if strcmp(varargin{1},'kstar') kstar=varargin{2}; if length(kstar)>1 error('kstar must be a number, not a vector.') end else error('Only kstar can be provided as an optional argument') end else kstar=0; end if kstar>=floor(n/2) error('kstar must be smaller than floor(n/2) because the depth region corresponding with kstar is empty') end % % Check whether the data are in general position. If not, add a very small random % number to each of the data points. % [x,y, Index, angl, ind1,ind2]=dithering(x,y); % %Calculation of the Tukey median % if n<=3 xsum=sum(x); ysum=sum(y); tukmed=[xsum/n,ysum/n]; return end % if kstar==0 ib=ceil(n/3); else ib=kstar; end ie=floor(n/2); stay=1; while stay==1 le=ie-ib; if le<0 le=0; end if le==0 stay=0; end if stay==1 [kou,dk,empty]=isodepth(x,y,ib+ceil(le/2)); if empty==1 ie=ib+ceil(le/2); end if empty==0 ib=ib+ceil(le/2); end if le==1 stay=0; end end end [kount,DK,empty]=isodepth(x,y,ib); xsum=sum(DK(:,1)); if not(DK==0) ysum=sum(DK(:,2)); else ysum=0; end wx=DK(:,1); if not(DK==0) wy=DK(:,2); else wy=0; end % % The maximal depth is now ib. % % % Calculation of the center of gravity % som=0; tukmed=0; if kount>1 wx=wx-(xsum/kount); wy=wy-(ysum/kount); for i=1:(kount-1) som=som+abs(wx(i)*wy(i+1)-wx(i+1)*wy(i)); tukmed=tukmed+[(wx(i)+wx(i+1))*abs(wx(i)*wy(i+1)-wx(i+1)*wy(i)),(wy(i)+wy(i+1))*abs(wx(i)*wy(i+1)-wx(i+1)*wy(i))]; end som=som+abs(wx(kount)*wy(1)-wx(1)*wy(kount)); tukmed=tukmed+[(wx(kount)+wx(1))*abs(wx(kount)*wy(1)-wx(1)*wy(kount)),(wy(kount)+wy(1))*abs(wx(kount)*wy(1)-wx(1)*wy(kount))]; tukmed=(tukmed/(3*som))+[(xsum/kount),(ysum/kount)]; else tukmed=[xsum,ysum]; end %-------------- function result=bagp(x,y,sizesubset) % BAGP is an algoritm that makes the necessary computations to construct % the bagplot of a bivariate dataset. This function is especially used in % bagplot.m. First, the data points are standardized. If the dataset is % too large (n > 200), then a subset is taken. On the other hand, if the % dataset is too small (n < 10), then no bag can be constructed. The Tukey % median (see halfmed.m) is also calculated, so that we can center the data. % Now, the bag lies between two consecutive depth regions. Therefore, one must % search for the right depth k. Once the k-th and the (k-1)-th depth regions % are constructed (see isodepth), the bag is the interpolation between the % vertices of the 2 depth regions. Finally, all the data points are caracterized % by their position compared to the bag with an integer 0,1,2 or 3. % % Required input arguments: % x : vector containing the first coordinates of all the data % points % y : vector containing the second coordinates of all the data % points % % I/O: result = bagp(x,y); % % The output of bagp is a structure containing % % result.tukmed : Tukey median % result.datatyp : is 2 for observations in the bag, 1 for % observations in the fence and 0 for outliers % result.interpol : The coordinates of the bag. % result.depth : The halfspacedepth of each observation % % This function is part of the Matlab Library for Robust Analysis, % available at: % http://wis.kuleuven.be/stat/robust.html % % Last Update: 29/04/2005 n=length(x); eps=0.0000001; nointer=0; ntot=n; % % Checking input % if length(x)==1 error('x is not a vector') elseif not(length(x)==length(y)) error('The vectors x and y must have the same length.') end if sum(isnan(x))>=1 || sum(isnan(y))>=1 error('Missing values are not allowed') end if sum(x==x(1))==n error('All data points ly on a vertical line.') elseif sum(y==y(1))==n error('All data points ly on a horizontal line.') else R=corrcoef(x,y); if abs(R(1,2))==1 error('All data points are collineair.') end end % % Standardization of the data set % xmean=mean(x); ymean=mean(y); xdev=sqrt(var(x)); ydev=sqrt(var(y)); if xdev>eps x=(x-xmean)/xdev; end if ydev>eps y=(y-ymean)/ydev; end xoris=x; yoris=y; xori=x; yori=y; wx=x; wy=y; wx1=x; wy1=y; % % If n is large, take a subset % nsub=sizesubset; if n>nsub ntot=n; n=nsub; a=rdraw(n,ntot); x=wx1(a); y=wy1(a); wx=x; wy=y; end % % Check whether the data is in general position. If not, add a very small random % number to each of the data points. % [x,y, Index, angl, ind1,ind2]=dithering(x,y); % numdep(1:n)=0; kstar=0; for i=1:n hdep=halfspacedepth(x(i),y(i),x,y); if hdep>kstar kstar=hdep; end numdep(hdep)=numdep(hdep)+1; end % % Calculation of the Tukey median % tukmed=halfmed(x,y,'kstar',kstar); % % Calculation of correct value of k % nc=floor(n/2); j=kstar+1; stay8=1; while stay8==1 stay8=0; j=j-1; if numdep(kstar)<=nc numdep(kstar)=numdep(kstar)+numdep(j-1); stay8=1; else k=j+1; numk1=numdep(kstar); numk=numk1-numdep(k-1); lambdanc=(nc-numk)/(numk1-numk); end end % % Calculation of the vertices of Dk % [kount1,Dk1,empty1]=isodepth(x,y,k); wx1=Dk1(:,1); if Dk1==0 wy1=0; else wy1=Dk1(:,2); end % % Calculation of the vertices of Dk-1 % [kount2,Dk2,empty2]=isodepth(x,y,k-1); wx2=Dk2(:,1); if Dk2==0 wy2=0; else wy2=Dk2(:,2); end if corrcoef(wx2,wy2)>0.98 error('Dk-1 is a line segment. Too many data points coincide.') end % if n>=10 wx1=wx1-tukmed(1); wy1=wy1-tukmed(2); wx2=wx2-tukmed(1); wy2=wy2-tukmed(2); x(1:n)=x(1:n)-tukmed(1); y(1:n)=y(1:n)-tukmed(2); xori(1:ntot)=xori(1:ntot)-tukmed(1); yori(1:ntot)=yori(1:ntot)-tukmed(2); % % Compute the angles of the data points. % numdattm=0; in=1:n; for i=1:n if (abs(x(i))abs(ycord) if xcord>=0 angz(i)=asin(ycord); if angz(i)<0 angz(i)=angz(i)+pi*2; end else angz(i)=pi-asin(ycord); end else if ycord>=0 angz(i)=acos(xcord); else angz(i)=pi*2-acos(xcord); end end if angz(i)>=(2*pi-eps) angz(i)=0; end end end % % numdattm is the number of datapoints that are equal to the Tukey median % [angz,optel]=sort(angz); in=in(optel); n=n-numdattm; % % Compute the angles of the vertices of the depth region Dk. % if not(kount1==1) ind=1:kount1; for i=1:kount1 dist=sqrt(wx1(i)^2+wy1(i)^2); if dist>eps xcord=wx1(i)/dist; ycord=wy1(i)/dist; if abs(xcord)>abs(ycord) if xcord>=0 angy1(i)=asin(ycord); if angy1(i)<0 angy1(i)=angy1(i)+pi*2; end else angy1(i)=pi-asin(ycord); end else if ycord>=0 angy1(i)=acos(xcord); else angy1(i)=pi*2-acos(xcord); end end if angy1(i)>=(pi*2-eps) angy1(i)=0; end else nointer=1; end end [angy1,optel]=sort(angy1); ind=ind(optel); end % % Compute the angles of the vertices of the depth region Dk-1. % jnd=1:kount2; for i=1:kount2 dist=sqrt(wx2(i)^2+wy2(i)^2); if dist>eps xcord=wx2(i)/dist; ycord=wy2(i)/dist; if abs(xcord)>abs(ycord) if xcord>=0 angy2(i)=asin(ycord); if angy2(i)<0 angy2(i)=angy2(i)+pi*2; end else angy2(i)=pi-asin(ycord); end else if ycord>=0 angy2(i)=acos(xcord); else angy2(i)=pi*2-acos(xcord); end end if angy2(i)>=(pi*2-eps) angy2(i)=0; end else nointer=1; end end [angy2,optel]=sort(angy2); jnd=jnd(optel); % % Calculation of arrays px and py for Dk % if not(kount1==1) jk=0; wx1(kount1+1)=wx1(1); wy1(kount1+1)=wy1(1); angy1(kount1+1)=angy1(1); ind(kount1+1)=ind(1); if angz(1)=(angy1(1)-eps) j=1; end for i=1:n while (angz(i)>=(angy1(j+1)-eps))&&(jk==0) j=j+1; if j==kount1 jk=1; end if j==(kount1+1) j=1; end end if (abs(wx1(ind(j+1))-wx1(ind(j)))>eps)&&(abs(x(in(i)))>eps) dist=y(in(i))/x(in(i))-(wy1(ind(j+1))-wy1(ind(j)))/(wx1(ind(j+1))-wx1(ind(j))); px(i,1)=(wy1(ind(j))*wx1(ind(j+1))-wx1(ind(j))*wy1(ind(j+1)))/(wx1(ind(j+1))-wx1(ind(j))); px(i,1)=px(i,1)/dist; py(i,1)=px(i,1)*y(in(i))/x(in(i)); else if abs(wx1(ind(j+1))-wx1(ind(j)))<=eps px(i,1)=wx1(ind(j)); py(i,1)=px(i,1)*y(in(i))/x(in(i)); else px(i,1)=0; py(i,1)=((wy1(ind(j))-wy1(ind(j+1)))*wx1(ind(j))/(wx1(ind(j+1))-wx1(ind(j))))+wy1(ind(j)); end end end end % % Calculation of arrays px and py for Dk-1 % jk=0; wx2(kount2+1)=wx2(1); wy2(kount2+1)=wy2(1); angy2(kount2+1)=angy2(1); jnd(kount2+1)=jnd(1); if angz(1)=(angy2(1)-eps) j=1; end for i=1:n while (angz(i)>=(angy2(j+1)-eps))&&(jk==0) j=j+1; if j==kount2 jk=1; end if j==(kount2+1) j=1; end end if (abs(wx2(jnd(j+1))-wx2(jnd(j)))>eps)&&(abs(x(in(i)))>eps) dist=(y(in(i))/x(in(i)))-((wy2(jnd(j+1))-wy2(jnd(j)))/(wx2(jnd(j+1))-wx2(jnd(j)))); px(i,2)=(wy2(jnd(j))*wx2(jnd(j+1))-wx2(jnd(j))*wy2(jnd(j+1)))/(wx2(jnd(j+1))-wx2(jnd(j))); px(i,2)=px(i,2)/dist; py(i,2)=px(i,2)*y(in(i))/x(in(i)); else if abs(wx2(jnd(j+1))-wx2(jnd(j)))<=eps px(i,2)=wx2(jnd(j)); py(i,2)=px(i,2)*y(in(i))/x(in(i)); else px(i,2)=0; py(i,2)=((wy2(jnd(j))-wy2(jnd(j+1)))*wx2(jnd(j))/(wx2(jnd(j+1))-wx2(jnd(j))))+wy2(jnd(j)); end end end if kount1==1 px(:,1)=wx1(1); py(:,1)=wy1(1); end % % Mergesort of angy1 and angy2 to obtain gamma and calculation of arrays px % and py % if kount1==1 gamma=angy2; px(:,3)=wx1; py(:,3)=wy1; px(:,4)=wx2; py(:,4)=wy2; else ja=1; jb=1; i=1; stay9=1; while stay9==1 if angy1(ja)<=angy2(jb) if ja<=kount1 gamma(i)=angy1(ja); px(i,3)=wx1(ind(ja)); py(i,3)=wy1(ind(ja)); if jb==1 wxjb1=wx2(jnd(kount2)); wyjb1=wy2(jnd(kount2)); else wxjb1=wx2(jnd(jb-1)); wyjb1=wy2(jnd(jb-1)); end if (abs(wx2(jnd(jb))-wxjb1)>eps)&&(abs(wx1(ind(ja)))>eps) dist=(wy1(ind(ja))/wx1(ind(ja)))-((wy2(jnd(jb))-wyjb1)/(wx2(jnd(jb))-wxjb1)); px(i,4)=(wyjb1*wx2(jnd(jb))-wxjb1*wy2(jnd(jb)))/(wx2(jnd(jb))-wxjb1); px(i,4)=px(i,4)/dist; py(i,4)=px(i,4)*wy1(ind(ja))/wx1(ind(ja)); else if abs(wx2(jnd(jb))-wxjb1)<=eps px(i,4)=wxjb1; py(i,4)=px(i,4)*wy1(ind(ja))/wx1(ind(ja)); else px(i,4)=0; py(i,4)=((wyjb1-wy2(jnd(jb)))*wxjb1/(wx2(jnd(jb))-wxjb1))+wyjb1; end end ja=ja+1; i=i+1; else angy1(ja)=angy1(ja)+10; end else if jb<=kount2 gamma(i)=angy2(jb); px(i,4)=wx2(jnd(jb)); py(i,4)=wy2(jnd(jb)); if ja==1 wxja1=wx1(ind(kount1)); wyja1=wy1(ind(kount1)); else wxja1=wx1(ind(ja-1)); wyja1=wy1(ind(ja-1)); end if (abs(wx1(ind(ja))-wxja1)>eps)&&(abs(wx2(jnd(jb)))>eps) dist=(wy2(jnd(jb))/wx2(jnd(jb)))-((wy1(ind(ja))-wyja1)/(wx1(ind(ja))-wxja1)); px(i,3)=(wyja1*wx1(ind(ja))-wxja1*wy1(ind(ja)))/(wx1(ind(ja))-wxja1); px(i,3)=px(i,3)/dist; py(i,3)=px(i,3)*wy2(jnd(jb))/wx2(jnd(jb)); else if abs(wx1(ind(ja))-wxja1)<=eps px(i,3)=wxja1; py(i,3)=px(i,3)*wy2(jnd(jb))/wx2(jnd(jb)); else px(i,3)=0; py(i,3)=((wyja1-wy1(ind(ja)))*wxja1/(wx1(ind(ja))-wxja1))+wyja1; end end jb=jb+1; i=i+1; else angy2(jb)=angy2(jb)+10; end end if i<=(kount1+kount2) stay9=1; else stay9=0; end end end % % Interpolation of two arrays px and py % c=3; if nointer==1 kount1=0; end if nointer==0 wx2(1:(kount1+kount2))=lambdanc*px(1:(kount1+kount2),4)+(1-lambdanc)*px(1:(kount1+kount2),3); wy2(1:(kount1+kount2))=lambdanc*py(1:(kount1+kount2),4)+(1-lambdanc)*py(1:(kount1+kount2),3); end if xdev>eps xcord=(wx2(1:(kount1+kount2))+tukmed(1))*xdev+xmean; else xcord=(wx2(1:(kount1+kount2))+tukmed(1)); end if ydev>eps ycord=(wy2(1:(kount1+kount2))+tukmed(2))*ydev+ymean; else ycord=wy2(1:(kount1+kount2))+tukmed(2); end interpol(1:(kount1+kount2),1)=xcord; interpol(1:(kount1+kount2),2)=ycord; % if nointer==1 if xdev>eps xcord=(x(in(1:n))+tukmed(1))*xdev+xmean; else xcord=x(in(1:n))+tukmed(1); end if ydev>eps ycord=(y(in(1:n))+tukmed(2))*ydev+ymean; else ycord=y(in(1:n))+tukmed(2); end datatyp(1:n,1)=xcord; datatyp(1:n,2)=ycord; datatyp(1:n,3)=1; if xdev>eps xcord=(x(dattm(1:numdattm))+tukmed(1))*xdev+xmean; else xcord=x(dattm(1:numdattm))+tukmed(1); end if ydev>eps ycord=(y(dattm(1:numdattm))+tukmed(2))*ydev+ymean; else ycord=y(dattm(1:numdattm))+tukmed(2); end datatyp((n+1):(n+numdattm),1)=xcord; datatyp((n+1):(n+numdattm),2)=ycord; datatyp((n+1):(n+numdattm),3)=0; return end % % Repeat some calculations for the whole data set % if ntot>nsub n=ntot; x=xoris; y=yoris; % % Angles of the data points % x=x-tukmed(1); y=y-tukmed(2); numdattm=0; in=1:n; for i=1:n if (abs(x(i))abs(ycord) if xcord>=0 angz(i)=asin(ycord); if angz(i)<0 angz(i)=angz(i)+pi*2; end else angz(i)=pi-asin(ycord); end else if ycord>=0 angz(i)=acos(xcord); else angz(i)=pi*2-acos(xcord); end end if angz(i)>=(pi*2-eps) angz(i)=0; end end end [angz,optel]=sort(angz); in=in(optel); n=n-numdattm; % % Calculation of arrays px and py for B % jk=0; wx2(kount2+kount1+1)=wx2(1); wy2(kount2+kount1+1)=wy2(1); gamma(kount2+kount1+1)=gamma(1); if angz(1)=(gamma(1)-eps) j=1; end for i=1:n while (angz(i)>=gamma(j+1)-eps)&&(jk==0) j=j+1; if j==(kount2+kount1) jk=1; end if j==(kount2+kount1+1) j=1; end end if (abs(wx2(j+1)-wx2(j))>eps)&&(abs(x(in(i)))>eps) dist=(y(in(i))/x(in(i)))-((wy2(j+1)-wy2(j))/(wx2(j+1)-wx2(j))); px(i,1)=(wy2(j)*wx2(j+1)-wx2(j)*wy2(j+1))/(wx2(j+1)-wx2(j)); px(i,1)=px(i,1)/dist; py(i,1)=px(i,1)*y(in(i))/x(in(i)); else if abs(wx2(j+1)-wx2(j))<=eps px(i,1)=wx2(j); py(i,1)=px(i,1)*y(in(i))/x(in(i)); else px(i,1)=0; py(i,1)=((wy2(j)-wy2(j+1))*wx2(j)/(wx2(j+1)-wx2(j)))+wy2(j); end end end end % % Decide the type of each data point % c=3; num=0; num1=0; num2=0; num3=0; lopen=1; i=1; while lopen==1 if ntot<=nsub px(i,1)=lambdanc*px(i,2)+(1-lambdanc)*px(i,1); py(i,1)=lambdanc*py(i,2)+(1-lambdanc)*py(i,1); end if (px(i,1)^2+py(i,1)^2)>eps lambda(i)=sqrt(x(in(i))^2+y(in(i))^2)/sqrt(px(i,1)^2+py(i,1)^2); else if (abs(x(in(i)))c num3=num3+1; typ(i)=3; end i=i+1; if i==(n+1) lopen=0; end end if xdev>eps xcord=(x(in(1:n))+tukmed(1))*xdev+xmean; else xcord=x(in(1:n))+tukmed(1); end if ydev>eps ycord=(y(in(1:n))+tukmed(2))*ydev+ymean; else ycord=y(in(1:n))+tukmed(2); end datatyp(1:n,1)=xcord; datatyp(1:n,2)=ycord; typ=typ.'; datatyp(1:n,3)=typ; % if not(numdattm==0) num=num+numdattm; typ(n+(1:numdattm))=0; lambda(n+(1:numdattm))=0; px(n+(1:numdattm),1)=x(dattm); py(n+(1:numdattm),1)=y(dattm); if xdev>eps xcord=(x(dattm)+tukmed(1))*xdev+xmean; else xcord=x(dattm)+tukmed(1); end if ydev>eps ycord=(y(dattm)+tukmed(2))*ydev+ymean; else ycord=y(dattm)+tukmed(2); end datatyp(n+(1:numdattm),1)=xcord; datatyp(n+(1:numdattm),2)=ycord; datatyp(n+(1:numdattm),3)=typ(n+(1:numdattm)); end else datatyp((1:n),1)=(x+tukmed(1))*xdev+xmean; datatyp((1:n),2)=(y+tukmed(2))*ydev+ymean; datatyp((1:n),3)=0; interpol=0; end % if xdev>eps tukmed(1)=tukmed(1)*xdev+xmean; end if ydev>eps tukmed(2)=tukmed(2)*ydev+ymean; end result=struct('tukmed',tukmed,'datatyp',datatyp,'interpol',interpol,'depth',hdep); %----------------------------- function [x,y,Index,angl,ind1,ind2]=dithering(x,y) %DITHERING is used to check whether the data points are in general position. % If not, then a very small random number is added to each of % the data points. Also the angles formed by pairs of data points are % computed here. This file is used in the functions isodepth.m, halfmed.m % and bagp.m. % % Required input arguments: % x : vector containing the first coordinates of all the data % points % y : vector containing the second coordinates of all the data % points if not(length(x)==length(y)) error('The vectors x and y must have the same length.') end if sum(isnan(x))>=1 || sum(isnan(y))>=1 error('Missing values are not allowed') end n=length(x); i=0; blijf3=1; dith=1; xorig=x; yorig=y; while dith==1 [xs,Index]=sort(x); ys=y(Index); dith=0; while blijf3==1 blijf3=0; i=i+1; if (i+1)>n blijf3=2; else j=i+1; if not(xs(i)==xs(j)) blijf3=1; else if ys(i)==ys(j) dith=1; blijf3=0; % two datapoints coincide else if ys(i)=1 spec=find(hoek<=0); hoek(spec)=hoek(spec)+pi; end ind1((p+1):m)=i; ind2((p+1):m)=rest; end % % Sort all the angles and permute ind1 and ind2 in the same way. % [angl,In]=sort(hoek); % ind1=ind1(In); ind2=ind2(In); % % Test wether any three datapoints are collinear. % ppp=diff(angl); k=find(ppp==0); % if sum(ind1(k)==ind1(k+1))>=1 % There are 3 or more datapoints collineair. dith=1; fac=100000000; ran=randn(n,2); x=xorig+ran(:,1)/fac; wx=x; y=yorig+ran(:,2)/fac; wy=y; else x=x; y=y; end end end