⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mdsgui.m

📁 常用ROBUST STATISTICAL
💻 M
字号:
function mdsgui(arg,typ)
% MDSGUI   Multi-dimensional Scaling GUI
%
% This GUI function drives the Multi-Dimensional Scaling methods. These
% include Classical MDS and Metric MDS. 
%
% MDS seeks to find a representation of the data in a lower-dimensional
% space such that observations that are close toghether in full dimensions
% are also close together in the lower-dimensional space. 
%
% One can call it from the edagui GUI or stand-alone from the command
% line. To call from the command line use
%
%       mdsgui
%
%   Exploratory Data Analysis Toolbox, April 2005
%   Martinez and Martinez, Exploratory Data Analysis with MATLAB
%   CRC Press

% First set up the layout if it does not exist.
flg = findobj('tag','mdsgui');
if isempty(flg)
    % then create the gui
    mdslayout
elseif nargin == 0
    % bring it forward
    figure(flg)
end

if nargin == 0
    arg = ' ';
end
if strcmp(arg,'docmds')
    % Start the Classical MDS process.
    docmds
    
elseif strcmp(arg,'domds')
    % Do the Metric and Non-metric MDS procedures.
    domds   
    
elseif strcmp(arg,'geda')
    % Bring up the graphical EDA GUI
    gedagui
    % Added the following, Sep 14
    tg = findobj('Tag','gedagui');
    H = get(tg,'userdata');  % To reference H.data
    ud = get(0,'userdata');  % To reference ud.dimred
    ind = strmatch(typ,ud.dimred,'exact');
    set(H.data,'value',ind)
    
    
elseif strcmp(arg,'cmdsout')
    % output CMDS-projected data to the workspace.
    tg = findobj('tag','mdsgui');
    H = get(tg,'userdata');
    ud = get(0,'userdata');
    [n,p] = size(ud.X);
    % get the number of dimensions 
    d = round(str2num(get(H.cmdsdim,'string')));
    if d < 2 | d > p
        errordlg('Dimensions d must be in the interval 2 <= d <= p')
        return
    end
    if ~isempty(ud.cmds)
        data = ud.cmds(:,1:d);
    else
        errordlg('You have not done the scaling yet.')
        return
    end
    promptstrg = 'Specify variable name:';
    titlestrg = 'Output Data from Classical MDS to Workspace';
    def = {'data'};
    saveinfo(promptstrg,titlestrg,def,data)

elseif strcmp(arg,'mdsout')
    % Export projected data to the workspace.
    % First get the data and project.
    tg = findobj('tag','mdsgui');
    H = get(tg,'userdata');
    ud = get(0,'userdata');
    [n,p] = size(ud.X);
    if ~isempty(ud.mds)
        data = ud.mds;
    else
        errordlg('You have not reduced the data yet.')
        return
    end
    promptstrg = 'Specify variable name:';
    titlestrg = 'Output Data from Current Projection Plane to Workspace';
    def = {'data'};
    saveinfo(promptstrg,titlestrg,def,data)
    

elseif strcmp(arg,'close')
    % in other gui's we will do some housekeeping. With this gui, we do not
    % have to do so. Obviously, the user will want to keep the data from
    % the loadgui for other applications. That is the purpose.
    tg = findobj('tag','mdsgui');
    H = get(tg,'userdata');
    if ~isempty(H.plots)
        button = questdlg('Closing this GUI will close the associated plot windows.',...
            'Closing GUI Warning','OK','Cancel','Cancel');
        if strcmp(button,'Cancel')
            return
        else
            close(H.plots)
        end
    end
    delete(tg)
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function domds
% Do metric/nonmetric MDS
% This uses the EDA Toolbox functions for MDS.
% The SMACOF function is used for metric MDS.
% The Kruskal function is used for non-metric - with minkowski metric of 2.

% first get the data
ud = get(0,'userdata');
if isempty(ud.X)
    errordlg('You must load some data first.')
    return
end
[n,p] = size(ud.X);
% Get the information from the GUI.
tg = findobj('tag','mdsgui');
H = get(tg,'userdata');
% First see if the data matrix is a 'distance' matrix.
if ~isequal(ud.X',ud.X)
    % then it is not a distance matrix.
    % So, calculate the distances.
    % Get type of distance chosen.
    distyp = get(H.mdsdist,'value');
    switch distyp
        case 1
            diststr = 'euclidean';
        case 2
            diststr = 'seuclidean';
        case 3
            diststr = 'cityblock';
        case 4
            diststr = 'mahalanobis';
        case 5
            diststr = 'minkowski';
    end
    dist = squareform(pdist(ud.X,diststr));
else
    dist = ud.X;
end
% Get the number of dimensions.
d = round(str2num(get(H.mdsdim,'string')));
if d < 2 | d > p
    errordlg('Dimensions d must be in the interval 2 <= d <= p')
    return
end
% Get the desired starting configuration type.
starttyp = get(H.starttype,'value');
ud.mds = smacof(dist,starttyp,d);
set(0,'userdata',ud);

% Note that the projections are over-written. The user must save to the
% workspace for other structures. The user can call up the GEDA GUI and
% view the current restults. (so it is good that we are saving to the
% userdata first.) The user can then run it again, view it again, etc. 
ud = get(0,'userdata');
ud.dimred = unique([ud.dimred,{'MDS'}]);
% reset the popupmenu on the clustering/GEDA GUIs if open.
updatemenu(ud.dimred)
set(0,'userdata',ud)

helpdlg({'MDS is finished.'},'MDS Status')

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function docmds
% Do classical MDS

% first get the data
ud = get(0,'userdata');
if isempty(ud.X)
    errordlg('You must load some data first.')
    return
end
[n,p] = size(ud.X);
% Get the information from the GUI.
tg = findobj('tag','mdsgui');
H = get(tg,'userdata');
% First see if the data matrix is a 'distance' matrix.
if ~isequal(ud.X',ud.X)
    % then it is not a distance matrix.
    % So, calculate the distances.
    % Get type of distance chosen.
    distyp = get(H.cmdsdist,'value');
    switch distyp
        case 1
            diststr = 'euclidean';
        case 2
            diststr = 'seuclidean';
        case 3
            diststr = 'cityblock';
        case 4
            diststr = 'mahalanobis';
        case 5
            diststr = 'minkowski';
    end
    dist = squareform(pdist(ud.X,diststr));
else
    dist = ud.X;
end

% Do classical MDS. ud.cmds contains the n by p matrix of coordinates in
% the principal coordinate space - classical MDS.
[ud.cmds,eigvals] = cmdscale(dist);
set(0,'userdata',ud);

% Do the scree plot
hf = figure;
set(hf,'numbertitle','off','name','EDA: Classical MDS Scree Plot')
% Upon figure close, this should delete from the array.
set(hf,'CloseRequestFcn',...
    'tg = findobj(''tag'',''mdsgui''); H = get(tg,''userdata''); H.plots(find(H.plots == gcf)) = []; set(tg,''userdata'',H); delete(gcf)')
H.plots = [H.plots, hf];
set(tg,'userdata',H)
plot(eigvals(1:10), 'bo-'); 
ylabel('Eigenvalue'); 
xlabel('Dimensionality'); 
    
% Note that the projections are over-written. The user must save to the
% workspace for other structures. The user can call up the GEDA GUI and
% view the current restults. (so it is good that we are saving to the
% userdata first.) The user can then run it again, view it again, etc. 
ud = get(0,'userdata');
ud.dimred = unique([ud.dimred,{'CMDS'}]);
% reset the popupmenu on the clustering/GEDA GUIs if open.
updatemenu(ud.dimred)
set(0,'userdata',ud)

helpdlg({'CMDS is finished.'},'CMDS Status')

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function saveinfo(promptstrg,titlestrg,def,data)

% data is the information to be saved to the workspace
answer = inputdlg(promptstrg,titlestrg,1,def);

if ~isempty(answer)
	assignin('base',answer{1},data)
% else
% 	assignin('base','data,H.data')
end

function X = smacof(D,starttyp,d)
% Function for doing the SMACOF algorithm for metric MDS. This is used in
% the GUI system only.
% Note that D is the full interpoint distance matrix.
% starttyp is a flag indicating the type of starting configuration:
% RANDOM or CLASSICAL MDS.
% The third argument 'd' is the number of dimensions.

% This is a full interpoint distance matrix.
[n,p] = size(D);
% Turn off this warning...
warning off MATLAB:divideByZero

% Get the first term of stress.
% This is fixed - does not depend on the configuration.
stress1 = sum(sum(D.^2))/2;  
% Now find an initial configuration - randomly generate.
% First need to compute the random starting point.
switch starttyp
    case 1
        % This is the classical MDS solution.
        Y = cmdscale(D);
        Z = Y(:,1:d);
    case 2
        % Random starting point 
        Z = unifrnd(-2,2,n,d);
end
% Find the stress for this.
DZ = squareform(pdist(Z));
stress2 = sum(sum(DZ.^2))/2;
stress3 = sum(sum(D.*DZ));
oldstress = stress1 + stress2 - stress3;

% Iterate until stress converges.
tol = 10^(-6);
dstress = realmax;
numiter = 1;
dstress = oldstress;
while dstress > tol & numiter <= 1000
    numiter = numiter + 1;
    % Now get the update
    BZ = -D./DZ;
    for i = 1:n
        BZ(i,i) = 0;
        BZ(i,i) = -sum(BZ(:,i));
    end
    X = n^(-1)*BZ*Z;
    Z = X;
    % Now get the distances
    % Find the stress
    DZ = squareform(pdist(Z));
    stress2 = sum(sum(DZ.^2))/2;
    stress3 = sum(sum(D.*DZ));
    newstress = stress1 + stress2 - stress3;
    dstress = oldstress - newstress;
    oldstress = newstress;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5
function updatemenu(strg)
% This updates the popupmenus for any of the GUIs that can use the
% dim-reduced data.
tg =  findobj('tag','agcgui');
if ~isempty(tg)
    H = get(tg,'userdata');
    set(H.data,'string',strg);
end
tg =  findobj('tag','kmeansgui');
if ~isempty(tg)
    H = get(tg,'userdata');
    set(H.data,'string',strg);
end
tg =  findobj('tag','mbcgui');
if ~isempty(tg)
    H = get(tg,'userdata');
    set(H.data,'string',strg);
end
tg =  findobj('tag','gedagui');
if ~isempty(tg)
    H = get(tg,'userdata');
    set(H.data,'string',strg);
end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -