% Options for packages loaded elsewhere
\PassOptionsToPackage{unicode}{hyperref}
\PassOptionsToPackage{hyphens}{url}
%
\documentclass[
]{ctexart}
\usepackage{amsmath,amssymb}
\usepackage{iftex}
\ifPDFTeX
  \usepackage[T1]{fontenc}
  \usepackage[utf8]{inputenc}
  \usepackage{textcomp} % provide euro and other symbols
\else % if luatex or xetex
  \usepackage{unicode-math} % this also loads fontspec
  \defaultfontfeatures{Scale=MatchLowercase}
  \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}
\fi
\usepackage{lmodern}
\ifPDFTeX\else
  % xetex/luatex font selection
\fi
% Use upquote if available, for straight quotes in verbatim environments
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
\IfFileExists{microtype.sty}{% use microtype if available
  \usepackage[]{microtype}
  \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
}{}
\makeatletter
\@ifundefined{KOMAClassName}{% if non-KOMA class
  \IfFileExists{parskip.sty}{%
    \usepackage{parskip}
  }{% else
    \setlength{\parindent}{0pt}
    \setlength{\parskip}{6pt plus 2pt minus 1pt}}
}{% if KOMA class
  \KOMAoptions{parskip=half}}
\makeatother
\usepackage{xcolor}
\usepackage{color}
\usepackage{fancyvrb}
\newcommand{\VerbBar}{|}
\newcommand{\VERB}{\Verb[commandchars=\\\{\}]}
\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
% Add ',fontsize=\small' for more characters per line
\usepackage{framed}
\definecolor{shadecolor}{RGB}{248,248,248}
\newenvironment{Shaded}{\begin{snugshade}}{\end{snugshade}}
\newcommand{\AlertTok}[1]{\textcolor[rgb]{0.94,0.16,0.16}{#1}}
\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{#1}}
\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.00,0.00,0.81}{#1}}
\newcommand{\BuiltInTok}[1]{#1}
\newcommand{\CharTok}[1]{\textcolor[rgb]{0.31,0.60,0.02}{#1}}
\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textit{#1}}}
\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{#1}}
\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{\textbf{#1}}}
\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{#1}}
\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.00,0.00,0.81}{#1}}
\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
\newcommand{\ErrorTok}[1]{\textcolor[rgb]{0.64,0.00,0.00}{\textbf{#1}}}
\newcommand{\ExtensionTok}[1]{#1}
\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.00,0.00,0.81}{#1}}
\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{\textbf{#1}}}
\newcommand{\ImportTok}[1]{#1}
\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{\textbf{#1}}}
\newcommand{\NormalTok}[1]{#1}
\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.81,0.36,0.00}{\textbf{#1}}}
\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{#1}}
\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textit{#1}}}
\newcommand{\RegionMarkerTok}[1]{#1}
\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.81,0.36,0.00}{\textbf{#1}}}
\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.31,0.60,0.02}{#1}}
\newcommand{\StringTok}[1]{\textcolor[rgb]{0.31,0.60,0.02}{#1}}
\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.00,0.00,0.00}{#1}}
\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.31,0.60,0.02}{#1}}
\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
\usepackage{graphicx}
\makeatletter
\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}
\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}
\makeatother
% Scale images if necessary, so that they will not overflow the page
% margins by default, and it is still possible to overwrite the defaults
% using explicit options in \includegraphics[width, height, ...]{}
\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}
% Set default figure placement to htbp
\makeatletter
\def\fps@figure{htbp}
\makeatother
\setlength{\emergencystretch}{3em} % prevent overfull lines
\providecommand{\tightlist}{%
  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
\setcounter{secnumdepth}{5}
\usepackage[most]{tcolorbox}
\definecolor{boxidea}{HTML}{6c8aa5}
\definecolor{boxwarn}{HTML}{b58266}
\definecolor{boxtip}{HTML}{8aa085}
\newtcolorbox{concept}[1][]{enhanced, breakable, colback=boxidea!7, colframe=boxidea, coltitle=white, fonttitle=\bfseries, title=#1, arc=2pt, left=8pt, right=8pt, top=4pt, bottom=4pt}
\newtcolorbox{pitfall}[1][]{enhanced, breakable, colback=boxwarn!7, colframe=boxwarn, coltitle=white, fonttitle=\bfseries, title=#1, arc=2pt, left=8pt, right=8pt, top=4pt, bottom=4pt}
\newtcolorbox{keypoint}[1][]{enhanced, breakable, colback=boxtip!7, colframe=boxtip, coltitle=white, fonttitle=\bfseries, title=#1, arc=2pt, left=8pt, right=8pt, top=4pt, bottom=4pt}
\renewcommand{\and}{\\}
\ifLuaTeX
  \usepackage{selnolig}  % disable illegal ligatures
\fi
\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}}
\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
\urlstyle{same}
\hypersetup{
  pdftitle={Clustering},
  pdfauthor={Rui},
  hidelinks,
  pdfcreator={LaTeX via pandoc}}

\title{Clustering}
\author{Rui}
\date{May 26, 2026}

\begin{document}
\maketitle

{
\setcounter{tocdepth}{2}
\tableofcontents
}
\hypertarget{ux8fd9ux7ae0ux5728ux8bb2ux4ec0ux4e48}{%
\section{这章在讲什么}\label{ux8fd9ux7ae0ux5728ux8bb2ux4ec0ux4e48}}

聚类分析（clustering）是\textbf{无监督学习}的入门：手里只有一堆样本的特征，没有「正确答案」标签，目标是把样本分成若干组，让组内尽量相似、组间尽量不同。心理学里常用来：把人格特征分群（找「人格类型」）、把消费者分群（市场细分）、把脑区分群（神经科学）。

\begin{concept}[两大主流方法的选择]
\textbf{层次聚类}（hierarchical clustering）：从每个样本各自一类开始，反复合并最近的两类，直到所有样本合成一类。结果是一棵\textbf{树状图}（dendrogram），用户根据树的高度切一刀决定 $k$。优点：不需要预设 $k$、可视化直观。缺点：$O(n^3)$ 复杂度、对大数据慢；一旦合并不可回退（greedy）。

\textbf{$k$-means}：预设类数 $k$，先随机选 $k$ 个中心，反复「分配最近中心 → 重新计算中心」直到收敛。优点：快、$O(nki)$。缺点：要预设 $k$、对初始值敏感（多次随机初始化取最优）、对球形 / 等方差簇假设强。

\textbf{$k$ 选择}：层次聚类看树状图肘部；$k$-means 看\textbf{轮廓系数}（silhouette）或 elbow 法。在 R 里 \texttt{factoextra::fviz\_nbclust(data, kmeans, method = "silhouette")} 一行画出 $k = 2 \sim 10$ 的得分图。
\end{concept}

\textbf{距离度量也很关键}：欧氏距离对量纲敏感（必须先标准化）、曼哈顿距离对异常值更稳健、Gower
距离能处理混合类型变量（数值 +
分类）。聚类前先想清楚「相似」在你的场景下是什么意思。

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{library}\NormalTok{(}\StringTok{"parameters"}\NormalTok{)  }\CommentTok{\#for clustering summary}
\FunctionTok{library}\NormalTok{(}\StringTok{"see"}\NormalTok{)}
\FunctionTok{library}\NormalTok{(}\StringTok{"factoextra"}\NormalTok{)  }\CommentTok{\#for clustering plotting}
\FunctionTok{library}\NormalTok{(bruceR)}
\FunctionTok{library}\NormalTok{(tidyverse)}
\end{Highlighting}
\end{Shaded}

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{athlete }\OtherTok{=} \FunctionTok{import}\NormalTok{(}\StringTok{"data13{-}02.xlsx"}\NormalTok{) }\SpecialCharTok{\%\textgreater{}\%} \FunctionTok{select}\NormalTok{(}\SpecialCharTok{{-}}\DecValTok{1}\NormalTok{)}
\end{Highlighting}
\end{Shaded}

\begin{verbatim}
## ✔ Successfully imported: 10 obs. of 4 variables
\end{verbatim}

\hypertarget{k-means}{%
\section{K-Means}\label{k-means}}

\hypertarget{computation}{%
\subsection{Computation}\label{computation}}

\begin{itemize}
\tightlist
\item
  \texttt{x}: numeric matrix-like data
\item
  \texttt{centers}: either the number of clusters, say kk, or a set of
  initial (distinct) cluster centres. If a number, a random set of
  (distinct) rows in x is chosen as the initial centres.
\item
  \texttt{iter.max}: the maximum number of iterations allowed.
\item
  \texttt{nstart}: if centers is a number, how many random sets should
  be chosen. Trying several random starts is often recommended.
\end{itemize}

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{kmean\_results }\OtherTok{=} \FunctionTok{kmeans}\NormalTok{(athlete, }\AttributeTok{centers =} \DecValTok{4}\NormalTok{, }
                       \AttributeTok{iter.max =} \DecValTok{10}\NormalTok{, }\AttributeTok{nstart =} \DecValTok{1}\NormalTok{)}
\end{Highlighting}
\end{Shaded}

kmeans returns an object of class ``kmeans'' which has a print and a
fitted method. It is a list with at least the following components:

\begin{itemize}
\tightlist
\item
  \texttt{cluster} : A vector of integers (from 1:k) indicating the
  cluster to which each point is allocated.
\item
  \texttt{centers}: A matrix of cluster centres.
\item
  \texttt{totss}: The total sum of squares.
\item
  \texttt{withinss}: Vector of within-cluster sum of squares, one
  component per cluster.
\item
  \texttt{tot.withinss} :Total within-cluster sum of squares,
  i.e.~sum(withinss).
\item
  \texttt{betweenss}: The between-cluster sum of squares,
  i.e.~\texttt{totss}-\texttt{tot.withinss}.
\item
  \texttt{size}: The number of points in each cluster.
\end{itemize}

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{kmean\_results}\SpecialCharTok{$}\NormalTok{cluster  }\CommentTok{\#group labels for each observation}
\end{Highlighting}
\end{Shaded}

\begin{verbatim}
##  [1] 3 2 4 3 2 1 4 2 4 1
\end{verbatim}

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{kmean\_results}\SpecialCharTok{$}\NormalTok{centers  }\CommentTok{\#centers}
\end{Highlighting}
\end{Shaded}

\begin{verbatim}
##         x1       x2       x3
## 1 120.5000 19.00000 44.50000
## 2 121.6667 18.33333 43.00000
## 3 124.5000 20.00000 44.50000
## 4 121.0000 17.00000 41.66667
\end{verbatim}

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{kmean\_results}\SpecialCharTok{$}\NormalTok{totss  }\CommentTok{\# total variance}
\NormalTok{kmean\_results}\SpecialCharTok{$}\NormalTok{withinss  }\CommentTok{\# within{-}group variance}
\NormalTok{kmean\_results}\SpecialCharTok{$}\NormalTok{tot.withinss }\CommentTok{\# sum of within SS}
\NormalTok{kmean\_results}\SpecialCharTok{$}\NormalTok{betweenss  }\CommentTok{\#between{-}group variance}
\end{Highlighting}
\end{Shaded}

\begin{verbatim}
## [1] 51.6
## [1] 1.000000 1.333333 1.000000 2.666667
## [1] 6
## [1] 45.6
\end{verbatim}

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{kmean\_results}\SpecialCharTok{$}\NormalTok{size  }\CommentTok{\# how many cases in each cluster}
\end{Highlighting}
\end{Shaded}

\begin{verbatim}
## [1] 2 3 2 3
\end{verbatim}

\hypertarget{visualization}{%
\subsection{Visualization}\label{visualization}}

Use \texttt{factoextra::fviz\_cluster(object,\ data)}. For more details
about useful parameters, see the help document. Remember that
\texttt{object} and \texttt{data} are two most indispensable parameters.

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{fviz\_cluster}\NormalTok{(kmean\_results, }\AttributeTok{data =}\NormalTok{ athlete)}
\end{Highlighting}
\end{Shaded}

\begin{verbatim}
## Registered S3 methods overwritten by 'broom':
##   method            from  
##   tidy.glht         jtools
##   tidy.summary.glht jtools
\end{verbatim}

\includegraphics{r-cluster-analysis_files/figure-latex/unnamed-chunk-8-1.pdf}

One way to start is from random centers; another way is to specify a few
sets of centers and start from them.

Clearly, starting from different centers, either random or specified,
the results may vary, though not significant. If the iteration will
converge eventually, then given sufficiently-large iteration time, the
center will be determined and fixed.

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{initial\_centers }\OtherTok{=} \FunctionTok{import}\NormalTok{(}\StringTok{"data13{-}02a.xlsx"}\NormalTok{) }\SpecialCharTok{\%\textgreater{}\%} \FunctionTok{select}\NormalTok{(}\SpecialCharTok{{-}}\DecValTok{1}\NormalTok{)}
\end{Highlighting}
\end{Shaded}

\begin{verbatim}
## ✔ Successfully imported: 4 obs. of 4 variables
\end{verbatim}

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{kmean\_results\_initialized }\OtherTok{=} \FunctionTok{kmeans}\NormalTok{(athlete, initial\_centers , }
                                   \AttributeTok{iter.max =} \DecValTok{10}\NormalTok{, }\AttributeTok{nstart =} \DecValTok{1}\NormalTok{) }
\FunctionTok{fviz\_cluster}\NormalTok{(kmean\_results\_initialized, }\AttributeTok{data =}\NormalTok{ athlete)}
\end{Highlighting}
\end{Shaded}

\includegraphics{r-cluster-analysis_files/figure-latex/unnamed-chunk-9-1.pdf}

\hypertarget{hierachical-clustering}{%
\section{Hierachical Clustering}\label{hierachical-clustering}}

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{automobile }\OtherTok{=} \FunctionTok{import}\NormalTok{(}\StringTok{"data13{-}01.xlsx"}\NormalTok{) }\SpecialCharTok{\%\textgreater{}\%} 
  \FunctionTok{select}\NormalTok{(}\FunctionTok{c}\NormalTok{(}\StringTok{\textquotesingle{}type\textquotesingle{}}\NormalTok{,}\StringTok{\textquotesingle{}price\textquotesingle{}}\NormalTok{,}\StringTok{\textquotesingle{}engine\_s\textquotesingle{}}\NormalTok{,}\StringTok{\textquotesingle{}horsepow\textquotesingle{}}\NormalTok{,}
           \StringTok{\textquotesingle{}wheelbas\textquotesingle{}}\NormalTok{,}\StringTok{\textquotesingle{}width\textquotesingle{}}\NormalTok{,}\StringTok{\textquotesingle{}length\textquotesingle{}}\NormalTok{,}\StringTok{\textquotesingle{}curb\_wgt\textquotesingle{}}\NormalTok{,}
           \StringTok{\textquotesingle{}fuel\_cap\textquotesingle{}}\NormalTok{,}\StringTok{\textquotesingle{}mpg\textquotesingle{}}\NormalTok{)) }\SpecialCharTok{\%\textgreater{}\%} \FunctionTok{drop\_na}\NormalTok{() }\SpecialCharTok{\%\textgreater{}\%} \FunctionTok{scale}\NormalTok{()}
\end{Highlighting}
\end{Shaded}

\begin{verbatim}
## ✔ Successfully imported: 157 obs. of 27 variables
\end{verbatim}

Use ``\texttt{hclust()}'' from base R and transmit a
\textbf{dissimilarity} structure produced by ``\texttt{dist()}''.

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{distMat }\OtherTok{=} \FunctionTok{dist}\NormalTok{(automobile, }\AttributeTok{method =} \StringTok{"euclidean"}\NormalTok{) }\CommentTok{\# Euclidean distance matrix}
\NormalTok{hc }\OtherTok{=} \FunctionTok{hclust}\NormalTok{(distMat)  }\CommentTok{\# hierarchical clustering, using the default method}
\end{Highlighting}
\end{Shaded}

Use ``\texttt{plot(hclust\_obj)}'' to visualize the hierarchical
clustering. Note that you should specify ``\texttt{hang\ =\ -1}'' to
ensure all nodes touch the same horizontal line and looks decent. If the
sample isn't that large, set ``\texttt{labels\ =\ TRUE}'' (by default)
to see the corresponding observations.

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{plot}\NormalTok{(hc,}\AttributeTok{labels=}\ConstantTok{FALSE}\NormalTok{,}\AttributeTok{hang =} \SpecialCharTok{{-}}\DecValTok{1}\NormalTok{)}
\end{Highlighting}
\end{Shaded}

\includegraphics{r-cluster-analysis_files/figure-latex/unnamed-chunk-12-1.pdf}

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{plot}\NormalTok{(hc,}\AttributeTok{labels=}\ConstantTok{FALSE}\NormalTok{)}
\end{Highlighting}
\end{Shaded}

\includegraphics{r-cluster-analysis_files/figure-latex/unnamed-chunk-12-2.pdf}

Moreover, you can draw dendrogram with grouping.

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{fviz\_dend}\NormalTok{(hc,}\AttributeTok{k=}\DecValTok{3}\NormalTok{, }\AttributeTok{rect =}\NormalTok{ T)}
\end{Highlighting}
\end{Shaded}

\includegraphics{r-cluster-analysis_files/figure-latex/unnamed-chunk-13-1.pdf}

Also, you can also check how many members for each cluster and make a
frequency table.

Note that the grouping might change if we change cluster number. And
this in essence is the pros of hierarchical clustering.

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{memberLabels }\OtherTok{=} \FunctionTok{cutree}\NormalTok{(hc,}\DecValTok{3}\NormalTok{)}
\FunctionTok{table}\NormalTok{(memberLabels)}
\end{Highlighting}
\end{Shaded}

\begin{verbatim}
## memberLabels
##  1  2  3 
## 71 71 10
\end{verbatim}

Then, we can get the centers of cluters by ``\texttt{mean}'' summary
statistics. Use ``\texttt{aggregate()}'' to achieve that.

\begin{itemize}
\tightlist
\item
  \texttt{x}: usually a data frame.
\item
  \texttt{by}: a list of grouping elements, each \textbf{as long} as the
  variables in the data frame x. The elements are coerced to factors
  before use.
\item
  \texttt{FUN}: a function to compute the summary statistics which can
  be applied to all data subsets.
\end{itemize}

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{aggregate}\NormalTok{(automobile,}\FunctionTok{list}\NormalTok{(memberLabels),mean)}
\end{Highlighting}
\end{Shaded}

\begin{verbatim}
##   Group.1       type      price   engine_s   horsepow   wheelbas      width
## 1       1 -0.4362472 -0.4985325 -0.7231739 -0.6579479 -0.6259158 -0.6459818
## 2       2  0.5201409  0.1193177  0.5017194  0.3293009  0.6601116  0.5979645
## 3       3 -0.5956452  2.6924245  1.5723270  2.3333938 -0.2427902  0.3409229
##        length   curb_wgt   fuel_cap        mpg
## 1 -0.65105171 -0.7853229 -0.7200528  0.6620751
## 2  0.65553921  0.7236353  0.6270241 -0.5592928
## 3 -0.03186123  0.4379815  0.6605042 -0.7297543
\end{verbatim}

Moreover, we can use Silhouette plot to check whether some cases are
outliers.

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{library}\NormalTok{(cluster)}
\FunctionTok{plot}\NormalTok{(}\FunctionTok{silhouette}\NormalTok{(}\FunctionTok{cutree}\NormalTok{(hc,}\DecValTok{3}\NormalTok{), distMat))}
\end{Highlighting}
\end{Shaded}

\includegraphics{r-cluster-analysis_files/figure-latex/unnamed-chunk-16-1.pdf}

\hypertarget{no.-of-clusters}{%
\section{No.~of Clusters}\label{no.-of-clusters}}

\hypertarget{within-cluster-ss}{%
\subsection{Within-Cluster SS}\label{within-cluster-ss}}

Looking for the ``elbow'' where the SS starts to slow down its drop.

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{fviz\_nbclust}\NormalTok{(automobile, kmeans, }\AttributeTok{method =} \StringTok{"wss"}\NormalTok{, }\AttributeTok{print.summary=}\ConstantTok{TRUE}\NormalTok{)}
\end{Highlighting}
\end{Shaded}

\includegraphics{r-cluster-analysis_files/figure-latex/unnamed-chunk-17-1.pdf}

here suggests 2 or 3.

\hypertarget{silhouette-method}{%
\subsection{Silhouette Method}\label{silhouette-method}}

Looking for the value that sets the highest average silhouette width,
which indicates the optimal number of clusters.

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{fviz\_nbclust}\NormalTok{(automobile, kmeans, }\AttributeTok{method =} \StringTok{"silhouette"}\NormalTok{,}\AttributeTok{print.summary=}\ConstantTok{TRUE}\NormalTok{)}
\end{Highlighting}
\end{Shaded}

\includegraphics{r-cluster-analysis_files/figure-latex/unnamed-chunk-18-1.pdf}

\hypertarget{majority-rule}{%
\subsection{Majority Rule}\label{majority-rule}}

\texttt{n\_clusters()} is the main function to find out the optimal
numbers of clusters present in the data based on the maximum consensus
of a large number of methods.

Essentially, there exist many methods to determine the optimal number of
clusters, each with pros and cons, benefits and limitations. The main
\texttt{n\_clusters()} function proposes to run all of them, and find
out the number of clusters that is suggested by the \textbf{majority} of
methods (in case of ties, it will select the most parsimonious solution
with fewer clusters).

Note that we also implement some specific, commonly used methods, like
the Elbow or the Gap method, with their own visualization
functionalities.

Also note that the \texttt{n\_clusters()} function will do the
normalization automatically (by default).

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{n\_clusters}\NormalTok{(}\FunctionTok{data.frame}\NormalTok{(automobile))}
\end{Highlighting}
\end{Shaded}

\hypertarget{method-agreement-procedure}{%
\section{Method Agreement Procedure:}\label{method-agreement-procedure}}

The choice of 2 clusters is supported by 8 (27.59\%) methods out of 29
(Elbow, Silhouette, Ch, Ratkowsky, Mcclain, SDindex, Mixture (VEV),
Mixture (EEV)).

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{plot}\NormalTok{(}\FunctionTok{n\_clusters}\NormalTok{(}\FunctionTok{data.frame}\NormalTok{(automobile)))}
\end{Highlighting}
\end{Shaded}

\includegraphics{r-cluster-analysis_files/figure-latex/unnamed-chunk-19-1.pdf}

\hypertarget{two-step-clustering}{%
\section{Two Step Clustering}\label{two-step-clustering}}

Some people prefer using hierarchical methods first to obtain the number
of clusters and their centroids. Then use these as inputs to run
non-hierarchical analysis. This approach is called Two-Step Clustering.

\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{\# two step clustering in R, not required}
\FunctionTok{library}\NormalTok{(prcr)}
\NormalTok{d }\OtherTok{\textless{}{-}}\NormalTok{ pisaUSA15}
\NormalTok{m3 }\OtherTok{\textless{}{-}} \FunctionTok{create\_profiles\_cluster}\NormalTok{(d,}
\NormalTok{                              broad\_interest, enjoyment, instrumental\_mot, self\_efficacy,}
                              \AttributeTok{n\_profiles =} \DecValTok{3}\NormalTok{)}
\FunctionTok{summary}\NormalTok{(m3)}
\end{Highlighting}
\end{Shaded}

\hypertarget{clustering-for-cases-and-variables}{%
\section{Clustering for Cases and
Variables}\label{clustering-for-cases-and-variables}}

Infrastructure construction includes various dimensions such as
transportation, postal and telecommunications, water supply and power
supply. ``construction.xlsx'' records the development level of 16
infrastructure construction aspects in 7 countries. Please answer the
following questions:

\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\item
  Please use hierarchical methods to determine how many different types
  of infrastructure construction are included in these 16 indicators,
  and briefly explain the possible meanings of each type.
\item
  Calculate the average value of each type of indicator for each country
  in the previous question as the overall measure of infrastructure
  construction for that type (assuming this operation is reasonable).
  Use the k-means method to cluster the 7 countries based on their
  different overall indicators, distinguish between developed and
  developing countries, and determine which countries belong to each
  category.
\end{enumerate}

\hypertarget{q1}{%
\subsection{Q1}\label{q1}}

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{library}\NormalTok{(factoextra)}
\FunctionTok{library}\NormalTok{(showtext)}
\FunctionTok{showtext\_auto}\NormalTok{()}
\end{Highlighting}
\end{Shaded}

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{cons }\OtherTok{=} \FunctionTok{import}\NormalTok{(}\StringTok{\textquotesingle{}construction.xlsx\textquotesingle{}}\NormalTok{)}
\end{Highlighting}
\end{Shaded}

\begin{verbatim}
## ✔ Successfully imported: 16 obs. of 8 variables
\end{verbatim}

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{rownames}\NormalTok{(cons) }\OtherTok{=}\NormalTok{ cons[,}\DecValTok{1}\NormalTok{]}
\NormalTok{cons }\OtherTok{=}\NormalTok{ cons }\SpecialCharTok{\%\textgreater{}\%} \FunctionTok{select}\NormalTok{(}\SpecialCharTok{{-}}\DecValTok{1}\NormalTok{)}
\FunctionTok{attach}\NormalTok{(cons)}
\end{Highlighting}
\end{Shaded}

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{distance }\OtherTok{=} \FunctionTok{dist}\NormalTok{(cons)}
\NormalTok{hc }\OtherTok{=} \FunctionTok{hclust}\NormalTok{(distance)}
\end{Highlighting}
\end{Shaded}

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{plot}\NormalTok{(hc,}\AttributeTok{hang =} \SpecialCharTok{{-}}\DecValTok{1}\NormalTok{)}
\end{Highlighting}
\end{Shaded}

\includegraphics{r-cluster-analysis_files/figure-latex/unnamed-chunk-24-1.pdf}

From the cluster dendrogram above, it's suggested to classify all 16
indexes into 3 grand categories. From indexes contained in each
category, we can infer that the three dimensions are:

\begin{itemize}
\tightlist
\item
  Medical resources
\item
  Education level
\item
  Traffic capacity
\end{itemize}

\hypertarget{q2}{%
\subsection{Q2}\label{q2}}

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{grouplabel }\OtherTok{=} \FunctionTok{cutree}\NormalTok{(hc,}\AttributeTok{k =} \DecValTok{3}\NormalTok{)}
\end{Highlighting}
\end{Shaded}

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{km\_country }\OtherTok{=} \FunctionTok{aggregate}\NormalTok{(cons,}\FunctionTok{list}\NormalTok{(grouplabel),mean) }\SpecialCharTok{\%\textgreater{}\%} 
  \FunctionTok{select}\NormalTok{(}\SpecialCharTok{{-}}\DecValTok{1}\NormalTok{) }\SpecialCharTok{\%\textgreater{}\%} \FunctionTok{t}\NormalTok{() }\SpecialCharTok{\%\textgreater{}\%} 
  \FunctionTok{kmeans}\NormalTok{(}\AttributeTok{centers =} \DecValTok{2}\NormalTok{)}
\NormalTok{country\_label }\OtherTok{=}\NormalTok{ km\_country}\SpecialCharTok{$}\NormalTok{cluster}
\NormalTok{country\_label}
\end{Highlighting}
\end{Shaded}

\begin{verbatim}
## A B C D E F G 
## 1 1 1 2 2 2 1
\end{verbatim}

From the \(k\)-means method, we can see that the seven countries are
classified into two grand categories, developed and developing
countries, where the first group consists of D, E \& F, and all else as
the second group. However, clustering analysis doesn't directly tell us
the attributes of two groups, therefore, we have to ``label'' the groups
by checking the data.

Note that here D, E \& F are labeled as group ``2''.

\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{cons }\SpecialCharTok{\%\textgreater{}\%} \FunctionTok{t}\NormalTok{() }\SpecialCharTok{\%\textgreater{}\%} \FunctionTok{as.data.frame}\NormalTok{() }\SpecialCharTok{\%\textgreater{}\%} \FunctionTok{mutate}\NormalTok{(}
  \AttributeTok{develop =}\NormalTok{ country\_label}
\NormalTok{) }\SpecialCharTok{\%\textgreater{}\%} \FunctionTok{group\_by}\NormalTok{(develop) }\SpecialCharTok{\%\textgreater{}\%} \FunctionTok{summarise\_all}\NormalTok{(mean) }\SpecialCharTok{\%\textgreater{}\%} 
\NormalTok{  stargazer}\SpecialCharTok{::}\FunctionTok{stargazer}\NormalTok{(}\AttributeTok{header =} \ConstantTok{FALSE}\NormalTok{,}
                       \AttributeTok{title =} \StringTok{\textquotesingle{}Index Comparison Between Groups\textquotesingle{}}\NormalTok{,}
                       \AttributeTok{flip =}\NormalTok{ T,}\AttributeTok{summary =} \ConstantTok{FALSE}\NormalTok{)}
\end{Highlighting}
\end{Shaded}

\begin{table}[!htbp] \centering 
  \caption{Index Comparison Between Groups} 
  \label{} 
\begin{tabular}{@{\extracolsep{5pt}} ccc} 
\\[-1.8ex]\hline 
\hline \\[-1.8ex] 
 & 1 & 2 \\ 
\hline \\[-1.8ex] 
develop & $1$ & $2$ \\ 
每十万人医疗机构数 & $361.035$ & $214.980$ \\ 
每十万人医疗技术人员数 & $617.005$ & $244.910$ \\ 
高速公路总里程 & $351.375$ & $112.713$ \\ 
铁路总里程 & $374.023$ & $119.360$ \\ 
每十万人教师数 & $158.267$ & $78.060$ \\ 
每十万人学校数 & $63.805$ & $26.087$ \\ 
每千人文盲数 & $115.995$ & $63.923$ \\ 
高等教育入学率 & $26.145$ & $6.663$ \\ 
在学儿童数量 & $129.545$ & $62.687$ \\ 
航空里程数 & $244.132$ & $103.263$ \\ 
航运总里程 & $290.225$ & $135.253$ \\ 
铁路客运量 & $260.318$ & $95.403$ \\ 
公路客运量 & $296.095$ & $113.263$ \\ 
教育投入总费用 & $220.273$ & $75.360$ \\ 
卫生投入总费用 & $489.022$ & $229.947$ \\ 
每十万人医疗床位数 & $495.518$ & $182.137$ \\ 
\hline \\[-1.8ex] 
\end{tabular} 
\end{table}

From the summarization table, apparently that among all the 16 indexes,
group 1 outbeats group 2 (i.e., D, E \& F). Therefore, we can say

\begin{itemize}
\tightlist
\item
  Developing countries: D, E, F;
\item
  Developed countries: A, B, C, G.
\end{itemize}

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{fviz\_cluster}\NormalTok{(km\_country,}
             \AttributeTok{data =} \FunctionTok{aggregate}\NormalTok{(cons,}\FunctionTok{list}\NormalTok{(grouplabel),mean) }\SpecialCharTok{\%\textgreater{}\%} 
               \FunctionTok{select}\NormalTok{(}\SpecialCharTok{{-}}\DecValTok{1}\NormalTok{) }\SpecialCharTok{\%\textgreater{}\%} \FunctionTok{t}\NormalTok{())}
\end{Highlighting}
\end{Shaded}

\includegraphics{r-cluster-analysis_files/figure-latex/unnamed-chunk-28-1.pdf}

All done. Finally,

\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{detach}\NormalTok{(cons)}
\end{Highlighting}
\end{Shaded}

\hypertarget{ux5bb9ux6613ux8e29ux7684ux5751}{%
\section{容易踩的坑}\label{ux5bb9ux6613ux8e29ux7684ux5751}}

\begin{pitfall}[聚类最常见的几个误区]
\begin{enumerate}
\item \textbf{不标准化就跑欧氏距离}：当变量量纲差异大（如「年龄」0--100 vs「月收入」1000--50000），月收入的差异会主导距离计算，年龄几乎被忽略。解法：聚类前先 \texttt{scale()} 或者用相关距离 \texttt{1 - cor()}。
\item \textbf{结果稳定 = 聚类正确}：聚类没有「对错」，只有「在某种距离 + 算法下的最稳定划分」。同一份数据用 $k$-means 和 hierarchical 可能得出截然不同的分组——所以要交叉验证：bootstrap 重抽 + 比较结果是否一致（\texttt{fpc::clusterboot}）。
\item \textbf{把聚类当作"自动的因子分析"}：聚类是把\textbf{样本}分群，因子分析是把\textbf{变量}降维。要给被试分人格类型，是聚类；要把 50 道人格量表题归到 5 个潜在维度，是 EFA。不要混了。
\item \textbf{聚类结果直接当作组别变量做 ANOVA}：聚类是数据驱动出来的「组」，组内方差被最小化、组间方差被最大化——再拿这些组去跑 ANOVA 几乎一定显著（循环论证）。要验证聚类有效性，应该用\textbf{未参与聚类的外部变量}做组间比较。
\end{enumerate}
\end{pitfall}

\end{document}
