New features
-
fviz_dend()gains ahighlightargument to emphasize the branches leading to
specific leaves (withhighlight.col/highlight.lwd); it layers on top of
the cluster colouring, so highlighted branches stand out while every other
branch keeps its colour.highlight = NULL(default) is unchanged. For other
branch styling (e.g. dashed branches) pass a pre-styleddendextendobject,
whichfviz_dend()honours (see?fviz_dend). -
New
fviz_umap()andfviz_tsne()to visualize a 2-D UMAP or t-SNE embedding
(fromuwot,Rtsne,umap, or a plain coordinate matrix) with factoextra's
grouping, ellipse and palette styling, including colouring points by a
continuous feature value. An embedding has no eigenvalues, so the axes are
labelledUMAP1/UMAP2(tSNE1/tSNE2) without a percentage and there is no
scree plot, loadings or correlation circle; when requested, the group outline
defaults to a convex hull rather than a normal confidence ellipse (which would
assume a metric the embedding does not preserve).uwotandRtsneare
Suggests. -
as_factoextra_pca()gainsrecipeandworkflowmethods, so a PCA fitted
inside a tidymodelsrecipe(recipes::step_pca()) or a fittedworkflow
plots directly with thefviz_pca_*/fviz_eig/fviz_contrib/fviz_cos2
family:prep(rec) |> as_factoextra_pca() |> fviz_pca_biplot(). Scores,
loadings and the full set of eigenvalues are extracted through the public
recipes/workflows API, so the scree plot and axis percentages are honest even
when only a few components are kept. When inputs are provably centered,
variable-component correlations and cos2 are recovered separately from the
loading-times-component-SD arrow coordinates; the two coincide for centered,
unit-scaled inputs.recipesandworkflowsare Suggests. -
New
factoextra_palette()andtheme_factoextra().factoextra_palette("okabe")
returns the Okabe-Ito colorblind-safe categorical colors as a vector to pass to
the existingpaletteargument (e.g.fviz_cluster(res, palette = factoextra_palette("okabe")));theme_factoextra()is a clean publication theme
with a light coordinate grid, passed viaggthemeor added with+. Both are
explicit and stateless (no global option). The Okabe-Ito colors are those of
grDevices::palette.colors("Okabe-Ito"). -
fviz_nbclust()andfviz_gap_stat()gain amark_optimalargument. Set
mark_optimal = TRUEto mark the elbow of the"wss"plot with a dashed guide
line (a deterministic maximum-distance heuristic; see?fviz_nbclust);
mark_optimal = FALSEomits the optimal-cluster guide line for every method.
The default (NULL) keeps each method's existing behavior: the guide line is
shown for"silhouette"and"gap_stat"and omitted for"wss". -
fviz_cos2()andfviz_contrib()gain adisplayargument.display = "heatmap"
draws a grid with one tile per element and dimension, filled and labelled by the
per-dimension cos2/contribution, so the quality/contribution across several
dimensions can be read at once. The default (display = "bar") is unchanged. -
fviz_pca_ind(),fviz_cluster()(and the other individual / row / column
plots) gain amax.pointsargument for large datasets. When there are more
thanmax.pointspoints, a reproducible random subset of that many is drawn so
labels, colours and ellipses stay readable instead of over-plotting. When points
are grouped (e.g.habillage, or clusters infviz_cluster()) the draw is
stratified so every group keeps a minimum number of points and none is
decimated, and a message reports how many points are shown. Only the drawn
points are thinned: any ellipse (addEllipses/ the cluster frame) and the
group/cluster centres are still computed on the full data, so a convex hull or
confidence ellipse is not distorted by dropping the extreme points a random
draw tends to lose. A continuous colour, fill or size mapping (e.g.col.ind = "cos2") and its legend are likewise pinned to the full-data range, so a
point's colour, fill and size do not depend on how many points are drawn. The
draw does not disturb the caller's random stream.
max.points = NULL(default) draws every point, andsample.seedcontrols
which subset is chosen. -
fviz_mca_ind()andfviz_mca_biplot()gain aquanti.supargument. Set
quanti.sup = TRUEto overlay the supplementary quantitative variables of a
FactoMineR MCA on the map as correlation arrows, so a continuous covariate's
direction can be read against the category/individual cloud. Each arrow's length
is proportional to the variable's absolute correlation with the dimensions
(relative to the cloud extent). The default (quanti.sup = FALSE) leaves the map
unchanged. -
The
select.ind/select.var(andselect.row/select.col) lists gain a
unionelement. When several ofname/cos2/contribare supplied they
are combined with AND by default (each condition further narrows the selection,
as before);union = TRUEcombines them with OR instead, so named elements are
kept together with the top-cos2or top-contribones, e.g.select.var = list(name = c("V1", "V2"), contrib = 10, union = TRUE). The same result can
still be obtained by precomputing the set and passing it asname;unionis a
convenience for building it inline. The default (nounion, orunion = FALSE)
is unchanged. Thanks to @qfazille (#53).
Main changes
-
get_pca_ind(): individual contributions forprcompobjects, and forade4
PCA objects with non-uniform row weights, are now normalized to sum to 100
percent per axis, matchingFactoMineR::PCA(). Previouslyprcompindividual
contributions were divided by the (n-1)-normalized eigenvalue and summed to
100 * (n - 1) / ninstead of 100. This changes the individual contribution
values returned for those objects (and anyfviz_contrib()/fviz_pca()
colouring derived from them).princompindividual contributions,
coordinates, and cos2 are unchanged for ordinary finite inputs. Variable
contributions are unchanged on nonzero, ordinarily scaled axes; zero-inertia
and extreme-magnitude axes now return stable finite values instead of NaN or
overflow. For a rank-truncatedprcompobject, individual cos2 is explicitly
defined within the retained component subspace because discarded row inertia
is not stored in the fit. The corrected values matchFactoMineR::PCA()and
ade4::inertia.dudi(). Thanks to @erdeyl (#274). -
fviz_pca_biplot():biplot.type = "form"andbiplot.type = "covariance"
now use the exact Gabriel biplot factorization, matching
stats::biplot(scale = 0)andstats::biplot(scale = 1)respectively, instead
of the previous display heuristic. The usualbiplot.type = "auto"scaling
algorithm is otherwise unchanged. Rank-truncatedprcompfits now use only
the retained component standard deviations when computing variable
coordinates, avoiding recycled values and incorrect arrows. The exact modes
also handle formula fits withna.exclude; covariance mode usesn.obsfor
princomp, matchingstats::biplot(). The exact modes require aprcomp/
princompobject. Thanks to @erdeyl (#274). -
as_factoextra_pca()recipe / workflow methods (tidymodels): variable-component
correlations and cos2 are now recovered from the full PCA inertia, so they match
FactoMineR::PCA()of the same data even whenstep_pca()keeps only a few
components (previously the cos2 was normalized within the retained subspace and
matched only when all components were kept).scale.unitis set toTRUEonly
when every PCA input is both centered and unit-scaled at the PCA boundary.
When the metrics cannot be recovered (e.g. a barestep_pca()or a
zero-inertia variable),get_pca_var()returnsNULLfor its correlation and
cos2 entries instead of synthesizing them from the retained coordinates.
Scores, eigenvalues, variable coordinates and contributions remain available,
so ordinary variable arrows still work; correlation/cos2-dependent displays
fail explicitly, the correlation circle is omitted, and a warning gives the
applicable centering or zero-inertia remedy. For fully normalized inputs, the
recovered metrics matchFactoMineR::PCA(). To keep scores consistent with the
fitted loadings and eigenvalues,step_pca()must be the final recipe step.
Case-weighted fits fail explicitly until their weights can be propagated into
individual contributions. Thanks to @erdeyl (#274). -
get_clust_tendency(): the Hopkins statistic now samples the observed points
without replacement (the previous code sampled with replacement, which could
draw the same observation more than once), counts a duplicated row as a valid
zero-distance neighbour, and is computed on a normalized distance scale for
numerical stability. Zero-range columns are ignored, so adding a redundant
constant variable does not change the statistic. This changes the Hopkins value
returned for a givenseed.
It now errors clearly when every nearest-neighbour distance is zero (the
statistic is undefined). Thanks to @erdeyl (#274). -
fviz_eig(parallel = TRUE)(Horn's parallel analysis, an opt-in overlay):
the simulated eigenvalue thresholds now use a corrected reference distribution.
Covariance PCA (prcomp(scale. = FALSE)/princomp(cor = FALSE)) previously
simulated unit-variance random data, giving statistically wrong thresholds; the
reference now matches the fitted object's marginal variances. Full-rank
correlation PCA is unaffected in distribution (parallel analysis is a
Monte-Carlo procedure, so exact threshold values depend on the seed);
wide (n <= p) fits now simulate over the original variable count. A
rank-truncated correlation fit is accepted only when a retained formula call
proves literalscale. = TRUE; default-method and custom/symbolic scale fits
cannot be distinguished from the truncated object and fail closed. Other fits
whose reference distribution cannot be reconstructed (uncentered fits,
rank-truncated covariance fits, ambiguousprincompcor) also error clearly
instead of returning misleading thresholds. Separately,fviz_eig()warns when a
FactoMineR PCA object stores an incomplete eigenvalue spectrum (refit with a
largerncpfor a complete scree plot). Thanks to @erdeyl (#274). -
fviz_gap_stat()(andfviz_nbclust(method = "gap_stat")): when a partial
maxSElist is supplied without amethod, the fallback is now"firstSEmax"
(the documented default andcluster::maxSE's default) instead of"firstmax".
This only affects callers who pass, e.g.,maxSE = list(SE.factor = 2)with no
method; the previous"firstmax"fallback silently ignored theSE.factor
they set (that rule does not use it). Default calls and calls that pass a
methodare unchanged.eclust()'s internal gap default is aligned for
consistency. Thanks to @erdeyl (#274).
Minor changes
fviz_dend(): corrected the documentation of thetypeargument, which listed
a"triangle"value that the function does not accept (the valid values are
"rectangle","circular"and"phylogenic"). Thanks to @Nelson-Gon (#144).?fviz_dendnow documents how to compare two dendrograms (a tanglegram) with
dendextend::tanglegram()/untangle()/entanglement(), which factoextra
already depends on.- Fixed a typo in the default title of
fviz_cos2()/fviz_contrib()for
quantitative variables ("quantitive" -> "quantitative"). - Clarified and corrected documentation across several help pages: the
contribution-based selection help now says "highest contributions" (was
"highest cos2"),fviz_famd()'shabillagehelp refers to a FAMD (not MFA)
object, the ExPosition class name is spelledexpoOutputinfviz_ca()/
fviz_mca(), the generatedggthemehelp no longer claims a single default
that disagrees with function signatures, and theclean_lock_files()example
is now self-contained. The HMFA selection help now includes the supported
unionoption.
Thanks to @erdeyl (#274). - Clearer, earlier input validation for edge cases, so mistakes fail with an
informative message instead of a downstream error:fviz_umap()/fviz_tsne()
require two distinct positive integerdims;fviz_nbclust()validates
k.max;fviz_dend()validatesk/hagainst the tree;get_clust_tendency()
checksnand requires finite data; oversized axis indices are rejected before
integer conversion; andas_factoextra_pca()validatesscale.unitand the
supplied eigenvalues. Valid calls are unaffected.
Thanks to @erdeyl (#274). as_factoextra_pca()now derives cos2, contributions, and eigenvalue
percentages on rescaled intermediate values and infers omitted eigenvalues
without premature overflow, so representable results remain stable at very
small or very large magnitudes. Its PCA-variable print method lists only
metrics that are actually available while preserving the established
descriptions for metrics that remain present.get_eigenvalue()(and thefviz_eig()scree plot) computes the variance
percentages on a rescaled intermediate, so an extreme-magnitude eigenvalue
spectrum returns finite percentages instead ofNaNor an overflow. Ordinary
spectra are unchanged to floating-point precision.get_pca_var(): forade4dudi.pcaobjects, thecoordandcontrib
components are now returned as plain numeric matrices, matching theprcomp
andprincompoutput; the values are unchanged.- Function help pages and the
READMEnow link to the corresponding Datanovia
tutorial for each method, and the retiredsthda.comdocumentation links were
refreshed to their currentdatanovia.comlocations.
Bug fixes
fviz_dend(): thecexargument now scales the leaf-label size for the
"rectangle"and"circular"types. The label size was mapped through
ggplot2's default continuous size scale, which collapsed a single per-plot
cexvalue to a fixed size, socexhad no visible effect; leaf labels are
now sized directly fromcex(and a per-leaflabels_cexset through
dendextend is honoured). At the defaultcex = 0.8the labels are marginally
smaller than before. Thanks to @dir21 (#281).fviz_ca_biplot()/fviz_ca():invisible = "col.sup"now hides
supplementary columns (the column branch was keyed off the row-supplementary
flag, so supplementary columns stayed visible). Thanks to @erdeyl (#274).fviz_mclust()now applies theggthemeargument to every plot type
("classification","uncertainty","BIC"); it previously ignored it and
always usedtheme_classic(). The default is unchanged. Thanks to @erdeyl (#274).fviz_cluster()now aligns a named clustering to the plotted data by row name
when both carry complete, unique, matching names, so points are not
mis-coloured whendatais ordered differently from the clustering; it also
accepts aclusteringcomponent (as produced bypam()/clara()) in a custom
list(data=, clustering=)object. Assignments that do not line up by name are
used positionally, as before, except thatpam()/fanny()andhcut()
objects fitted on a dissimilarity reject complete non-matching row-name sets
because positional use would mis-colour observations. Thanks to @erdeyl (#274).invisible = "all"now hides all plotted elements (it was silently accepted
but had no effect); on the individual and variable maps, a selection byname
that includes names not present now warns instead of silently dropping them.
fviz_pca_var()/fviz_pca_biplot()now draw a FactoMineR PCA's
supplementary quantitative variables, which were previously omitted because the
wrong result slot was read; their names are also recognised by the selection
validation, so aselect.*list naming one no longer warns or silently drops
it.select.indnow also
limits MFA/HMFA partial-point and segment overlays, including union selections,
instead of leaving every individual's partial geometry visible. A lone
unavailable contribution condition wrapped inunion = TRUEnow gives the
same explicit unavailable-metric error as the ordinary single-condition path.
Thanks to @erdeyl (#274).