function result=mona(x,banner) %MONA returns clusters according to mona (monothetic %clustering) % %The algorithm is fully described in: % Kaufman, L. and Rousseeuw, P.J. (1990), % "Finding groups in data: An introduction to cluster analysis", % Wiley-Interscience: New York (Series in Applied Probability and % Statistics), ISBN 0-471-87876-6. % % Required input argument: % x : Data matrix (rows = observations, columns = variables) % containing only binary values. % The missing values are indicated by the value 2 % % Optional input argument: % banner : draws picture % Possible values are 0 : do not create a banner % 1 : create a banner % (in case banner is not given, banner = 0) % I/O: % result=mona(x,1) % % Example (subtracted from the referenced book) % load animal.mat % result=mona(animal,1); % % The output of MONA is a structure containing % result.matrix : revised matrix xx (contains only 0 and 1 and missing % values are estimated) % result.number : number of observations % result.var : number of variables % result.ner : order of objects % result.lava : variable used for separation % result.nban : seperation step % (The value on the ith index is the stepnumber from % the seperation of the elements with index 1 to i % from the elements with index i+1 to result.number) % If it equals zero, then there was no separation % % And MONA will create the plot banner if banner equals 1. % % This function is part of LIBRA: the Matlab Library for Robust Analysis, % available at: % http://wis.kuleuven.be/stat/robust.html % % Written by Wai Yan Kong (May 2006) resl=[]; % Check whether the number of input is correct if (nargin<1) error('One input argument required (datamatrix)') elseif (nargin<2) banner=0; elseif (nargin>2) error('Too many input arguments') end % Define number of observations and variables S=size(x); S1=S(1); S2=S(2); resl.number=S(1); resl.var=S(2); % Check whether x is a matrix containing only binary values % and whether x has missing values % We make a revised matrix xx missing=zeros(1,S2); for j = 1:S2 for i= 1:S1 if (x(i,j)==0 | x(i,j)==1) missing(j)=missing(j); xx(i,j)=x(i,j); elseif (x(i,j)==2) missing(j)=missing(j)+1; for k=1:S2 a=0; b=0; c=0; d=0; if k~=j if x(i,k) ~= 2 for t=1:S1 if (x(t,j)==1 & x(t,k)==1) a=a+1; elseif (x(t,j)==1 & x(t,k)==0) b=b+1; elseif (x(t,j)==0 & x(t,k)==1) c=c+1; elseif (x(t,j)==0 & x(t,k)==0) d=d+1; end end end end association(k)=abs(a*d-b*c); resinbetween(k)=a*d-b*c; [C,I]=max(association); if resinbetween(I)>0 xx(i,j)=x(i,I); elseif resinbetween(I)<0 xx(i,j)=1-x(i,I); end end else error('inputmatrix must have binary values or value 2 for missing values') end end end TotalMissing=sum(missing); fprintf(1,'This inputmatrix has %d missing values\n',TotalMissing) % Check situations where Mona is not applicable One=0; for j=1:S2 if missing(j)>=1 One=One+1; end end if One==S2 error('each variable has at least one missing value') end for j=1:S2 if (missing(j)>= (S1/2)) fprintf(1,'Variable %d has %d missing values\n',j,missing(j)) error('The number of missing values for some variable equals or is more than half of the number of objects') end gelijk=0; for s=1:S1-1 if xx(s,j)==xx(s+1,j) gelijk=gelijk+1; end end if gelijk==S1-1 fprintf(1,'Variable %d has identical values\n',j) error('all values are identical for some variable') end end % We make the rowvector kx by reading the revised matrix xx % row by row Lengte=S1*S2; kx=zeros(1,Lengte); for i = 1:S1 for j= 1:S2 kx((i-1)*S2+j) = xx(i,j); end end % Actual calculations [ner,lava,nban]=monac(resl.number,resl.var,kx); % We want lava and nban to be vectors of length S1-1 lava2=zeros(1,S1-1); nban2=zeros(1,S1-1); for i = 1:S1-1 lava2(i) = lava(i+1); nban2(i) = nban(i+1); end % Create a banner if (banner==1) whitebg([1 1 1]); stepmax=max(nban2)+1; Y=nban2; Y(find(Y==0))=stepmax; Y1=fliplr(Y); barh(Y1,1) title 'Banner of Mona' xlabel('Separation Step') XT=0:stepmax; set(gca,'XTick',XT); set(gca,'XTickLabel',XT); axis([0,stepmax,0.5,S1-0.5]) ylabel('Objects') La1=num2str(lava2); La2=fliplr(La1); for k=1:S1-1 La3(k)=La2(k+((k-1)*2)); end for i=1:S1-1 if(Y1(i)