Skip to content

Commit

Permalink
silhouette: workaround to omit plotting figure when called from Silho…
Browse files Browse the repository at this point in the history
…uetteEvaluation to avoid issue with failing tests
  • Loading branch information
pr0m1th3as committed Aug 27, 2024
1 parent af61352 commit 42d002a
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 27 deletions.
6 changes: 3 additions & 3 deletions inst/Clustering/SilhouetteEvaluation.m
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,13 @@
endif

## get the silhouette values for every clustering
set (0, 'DefaultFigureVisible', 'off'); # temporarily disable figures
for iter = 1 : length (this.InspectedK)
## do it only for the specified K values
if (any (this.InspectedK(iter) == K))
## Custom call to silhouette to avoid plotting any figures
this.ClusterSilhouettes{iter} = silhouette (UsableX, ...
this.ClusteringSolutions(:, iter));
this.ClusteringSolutions(:, iter), ...
"sqeuclidean", "DoNotPlot");
if (strcmpi (this.ClusterPriors, "empirical"))
this.CriterionValues(iter) = mean (this.ClusterSilhouettes{iter});
else
Expand All @@ -281,7 +282,6 @@
endif
endif
endfor
set (0, 'DefaultFigureVisible', 'on'); # enable figures again

[~, this.OptimalIndex] = max (this.CriterionValues);
this.OptimalK = this.InspectedK(this.OptimalIndex(1));
Expand Down
66 changes: 42 additions & 24 deletions inst/silhouette.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Copyright (C) 2016 Nan Zhou <zhnanx@gmail.com>
## Copyright (C) 2021 Stefano Guidoni <ilguido@users.sf.net>
## Copyright (C) 2024 Andreas Bertsatos <abertsatos@biol.uoa.gr>
##
## This file is part of the statistics package for GNU Octave.
##
Expand Down Expand Up @@ -50,12 +51,13 @@
##
## Optional input value @var{Metric} is the metric used to compute the distances
## between data points. Since @code{silhouette} uses @code{pdist} to compute
## these distances, @var{Metric} is quite similar to the option @var{Metric} of
## pdist and it can be:
## these distances, @var{Metric} is similar to the @var{Distance} input argument
## of @code{pdist} and it can be:
## @itemize @bullet
## @item A known distance metric defined as a string: @qcode{Euclidean},
## @qcode{sqEuclidean} (default), @qcode{cityblock}, @qcode{cosine},
## @qcode{correlation}, @qcode{Hamming}, @qcode{Jaccard}.
## @item A known distance metric defined as a string: @qcode{euclidean},
## @qcode{squaredeuclidean} (default), @qcode{seuclidean}, @qcode{mahalanobis},
## @qcode{cityblock}, @qcode{minkowski}, @qcode{chebychev}, @qcode{cosine},
## @qcode{correlation}, @qcode{hamming}, @qcode{jaccard}, or @qcode{spearman}.
##
## @item A vector as those created by @code{pdist}. In this case @var{X} does
## nothing.
Expand All @@ -73,12 +75,25 @@
##
## @seealso{dendrogram, evalclusters, kmeans, linkage, pdist}

function [si, h] = silhouette (X, clust, metric = "sqeuclidean", varargin)
function [si, h] = silhouette (X, clust, metric = "squaredeuclidean", varargin)
## check the input parameters
if (nargin < 2)
print_usage ();
endif

## Check for last argument being 'DoNotPlot' to prevent from opening a figure
## Undocumented feature to avoid issues with faiing tests. It is only used by
## SilhouetteEvaluation class.
DisplayPlot = true;
if (numel (varargin) > 0)
if (ischar (varargin{end}))
if (strcmp (varargin{end}, "DoNotPlot"))
DisplayPlot = false;
varargin{end} = [];
endif
endif
endif

n = size (clust, 1);

## check size
Expand All @@ -95,8 +110,9 @@
switch (metric)
case "sqeuclidean"
metric = "squaredeuclidean";
case { "euclidean", "cityblock", "cosine", ...
"correlation", "hamming", "jaccard" }
case {"euclidean", "squaredeuclidean", "seuclidean", "mahalanobis", ...
"cityblock", "minkowski", "chebychev", "cosine", "correlation", ...
"hamming", "jaccard", "spearman"}
;
otherwise
error ("silhouette: invalid metric '%s'", metric);
Expand Down Expand Up @@ -169,24 +185,26 @@

## plot
## a poor man silhouette graph
vBarsc = zeros (m, 1);
vPadding = [0; 0; 0; 0];
Bars = vPadding;

for i = 1 : m
vBar = si(find (clust == clusterIDs(i)));
vBarsc(i) = length (Bars) + (length (vBar) / 2);
Bars = [Bars; (sort (vBar, "descend")); vPadding];
endfor
if (DisplayPlot)
vBarsc = zeros (m, 1);
vPadding = [0; 0; 0; 0];
Bars = vPadding;

for i = 1 : m
vBar = si(find (clust == clusterIDs(i)));
vBarsc(i) = length (Bars) + (length (vBar) / 2);
Bars = [Bars; (sort (vBar, "descend")); vPadding];
endfor

figure();
h = barh (Bars, "hist", "facecolor", [0 0.4471 0.7412]);
figure();
h = barh (Bars, "hist", "facecolor", [0 0.4471 0.7412]);

xlabel ("Silhouette Value");
ylabel ("Cluster");
set (gca, "ytick", vBarsc, "yticklabel", clusterIDs);
ylim ([0 (length (Bars))]);
axis ("ij");
xlabel ("Silhouette Value");
ylabel ("Cluster");
set (gca, "ytick", vBarsc, "yticklabel", clusterIDs);
ylim ([0 (length (Bars))]);
axis ("ij");
endif
endfunction


Expand Down

0 comments on commit 42d002a

Please sign in to comment.