analisis.conglomerados.fnc

Objetivo

El análisis de conglomerados, clasifica una muestra de entidades (individuos o variables) en un número pequeño de grupos de forma que las observaciones pertenecientes a un grupo sean muy similares entre sí y muy disimilares del resto. A diferencia del Análisis discriminante se desconoce el número y la composición de dichos grupos (Wikipedia).

La función analisis.conglomerados.fnc lleva a cabo análisis de conglomerados (cluster) de tipo:

  1. Particionado (kmedoid) y Particionado fuzzy

  2. Jerárquico Aglomerativo o Divisivo$p.val.conglomerado



1.- analisis.conglomerados.fnc - tipo Particionado

METODO DE PARTICIONADO ESTANDAR

En el análisis de conglomerados (AC) por el método de particionado, se divide la matriz de datos introducida en k conglomerados definidos obligatoriamente por el usuario.

El método de particionado, requiere que todas las variables sean numéricas. En caso de no incluir el argumento n.conglomerados la función llevará a cabo una estimación a modo de scree-test del análisis factorial.

Utilizaremos como ejemplo de AC la base de datos ruspini (E. H. Ruspini (1970) Numerical methods for fuzzy clustering. Inform. Sci. 2, 319–350) disponible en la librería cluster.

head(ruspini) dim(ruspini)

x y [1] 75 2

1 4 53

2 5 63

3 10 59

4 9 77

5 13 49

6 13 69

Queremos clasificar 75 registros, utilizando para ello las distancias (Euclidianas) de los registros en las dos variables de la base de datos: x e y. Llamaremos inicialmente a la función utilizando exclusivamente el argumento variables.

grafica.xy.fnc(ruspini, variables=1:2)

Vemos en la gráfica de puntos de ambas variables la clara existencia de 4 grupos de datos, claramente delimitados en los cuatro cuadrantes.

analisis.conglomerados.fnc(ruspini, variables=1:2)

analisis.conglomerados.fnc(ruspini, variables=1:2, tipo='particionado')

Por defecto se llevará a cabo un AC de tipo particionado. Ambas llamadas a la función generarán la misma salida.

#--------------------------------------------------------------------------------

# ANALISIS DE CONGLOMERADOS PARTICIONADO

#--------------------------------------------------------------------------------

*** No has indicado el numero de conglomerados que deseas estimar.

*** Utiliza el siguiente grafico para ayudarte a decidir el numero

*** de conglomerados a retener e incluye dicho valor en el argumento

*** n.conglomerados.

*** Ej: n.conglomerados=3

Number_clusters Value_Index

KL 4 130.6993

CH 4 425.3273

Hartigan 4 194.3143

CCC 4 23.9950

Scott 4 149.8575

Marriot 4 2012218216.7469

TraceW 4 35450.6409

Rubin 4 -41.0712

DB 4 0.4003

Silhouette 4 0.7377

Duda 4 0.4007

PseudoT2 4 22.4352

Beale 4 1.4022

PtBiserial 4 0.8136

Dunn 4 0.5047

SDindex 4 0.0387

TrCovW 3 4553187823.6151

Cindex 3 0.3063

Ratkowsky 3 0.4923

Ball 3 27647.7577

Hubert 0 0.0000

Dindex 0 0.0000

Frey 1 NA

McClain 2 0.4167

Friedman 6 102.8219

SDbw 10 0.0163

Among all indices:

===================

* 2 proposed 0 as the best number of clusters

* 1 proposed 1 as the best number of clusters

* 1 proposed 2 as the best number of clusters

* 4 proposed 3 as the best number of clusters

* 16 proposed 4 as the best number of clusters

* 1 proposed 6 as the best number of clusters

* 1 proposed 10 as the best number of clusters


Conclusion

=========================

* According to the majority rule, the best number of clusters is 4

Dado que no hemos incluido el argumento obligatorio n.conglomerados, la función lleva a cabo la estimación del número de cluster mas adecuado a partir de múltiples índices de bondad. Tal y como puedes ver (también en la gráfica inferior) el número óptimo de conglomerados es 4 en la mayoría de los índices.

Tratamos de valorar que número de conglomerados (clusters) consiguen reducir de forma óptima la suma de cuadrados intra-conglomerados. Tal y como podemos ver en la gráfica derecha, podemos "retener" cuatro conglomerados, dado que se produce una clara inflexión en ese número en cuanto a la reducción de varianza intra se refiere. Repetiremos la llamada a la función, incluyendo el argumento n.conglomerados=4.


analisis.conglomerados.fnc(ruspini, variables=1:2, n.conglomerados=4)


#------------------------------------------------------------------

# ANALISIS DE CONGLOMERADOS -particionado

#------------------------------------------------------------------

*** Si deseas guardar el conglomerado de pertenencia para cada registro,

*** incluye el argumento guarda.cong=T y no olvides asignar la salida a

*** la base de datos que desees.


$Tipo

[1] "Particionado"

$Tipificado

[1] FALSE

$Variables

[1] "x" "y"


$n.registros

[1] 75


$n.NA

[1] 0


$Centroides

Conglomerado x y

1 1 20.15000 64.9500

2 2 45.30435 146.3913

3 3 96.29412 114.4118

4 4 68.93333 19.4000


$Descriptivos

size max_diss av_diss diameter separation

Cong.1 20 27 8.150000 39 6

Cong.2 23 15 5.217391 24 4

Cong.3 17 22 7.235294 34 4

Cong.4 15 16 5.666667 27 18


$Anova.conglomerado.part

gl1 gl2 F p.val eta2

x 3 71 204.87 7.0419e-35 0.89644

y 3 71 698.62 1.3267e-52 0.96723

Podemos ver que el algoritmo ha asignado 20, 23, 17 y 15 registros a los cuatro conglomerados respectivamente. El gráfico de silueta, puedes ver que tiene 3 líneas discontinuas verticales situadas en los anchos de silueta 0.25 (rojo), 0.50 (azul) y 0.70 (verde). Podemos tomar esos tres valores como referencias genéricas de malas, aceptables y buenas agrupaciones. Los cuatro cluster dan valores de silueta claramente superiores a 0.7. El gráfico inferior muestra las agrupaciones que como podemos observar presentan muy poco solapamiento.

La tabla final de anovas, muestra el análisis de la varianza realizado a cada variable utilizada en el procedimiento clasificatorio con el conglomerado (con cuatro niveles) utilizado como factor intergrupo. En este sentido vemos que ambas variables presentan valores de tamaños de efectos muy grandes. Indicativos de una importancia similar en la clasificación.


Guardar Conglomerado de Pertenencia para cada registro

Una vez que lleguemos a una solución que consideremos aceptable, podemos estar interesados en guardar el número de conglomerado asignado a cada cluster por el algoritmo. Lo haremos incluyendo el argumento guarda.cong=T. Es muy importante resaltar que en ese caso deberías asignar la salida de la función a la base de datos que deseas añadir dicha nueva variable.

ruspini = analisis.conglomerados.fnc(ruspini, variables=1:2,

        n.conglomerados=4, guarda.cong=T)

Dado que hemos solicitado guardar el cluster de pertenencia de cada registro incluyendo el argumento guarda.cong=T la función nos preguntará si hemos asignado la salida a una base de datos y nos pedirá C para continuar o A para abortar (si no hubiésemos asignado dicha salida).

*** Has solicitado guardar el conglomerado de pertenencia para cada registro. ***

*** Para que se guarde de hecho, asegurate de haber ASIGNADO de forma correcta ***

*** la salida de esta funcion a un objeto. ***

*** Ej. datos=analisis.conglormerado.fnc(datos, n.conglom=3, guarda.cong=T) ***

**** PULSA C (en la consola) PARA CONTINUAR o A para ABORTAR **** ?

Podemos comprobar como se ha añadido la nueva variable (conglomerado.part).

head(ruspini); tail(ruspini)

x y conglomerado.part x y conglomerado.part

1 4 53 1 70 69 21 4

2 5 63 1 71 66 23 4

3 10 59 1 72 61 25 4

4 9 77 1 73 76 27 4

5 13 49 1 74 72 31 4

6 13 69 1 75 64 30 4

grafica.xy.fnc(ruspini, variables=1:2, que.factor='conglomerado.part')

En la gráfica superior derecha, podemos comprobar como el algoritmo de particionado, ha separado claramente los cuatro grupos de valores conjuntos de las dos variables implicadas.

METODO DE PARTICIONADO FUZZY

El método de particionado estandar asigna cada registro a un cluster de forma exclusiva. Es decir cada caso pertenecerá a un conglomerado y cada conglomerado tendrá al menos un caso. Si seleccionamos en el argumento tipo el particionado.fuzzy (borroso), esto dará lugar a un valor probabilístico de conglomerado de pertenencia, que puede ser muy útil a la hora de eliminar registros que presenten una probabilidad de pertenencia muy similar en los k cluster solicitados por el usuario (4).

analisis.conglomerados.fnc(ruspini, variables=1:2, tipo='particionado.fuzzy',

n.conglomerados = 4)

El método de particionado fuzzy (borroso) asignará cada registro a uno de los cuatro conglomerados, utilizando para ello el valor de probabilidad de pertenencia mayor según la siguiente tabla, que forma parte del output.

$p.val.conglomerado

[,1] [,2] [,3] [,4]

1 0.65700251 0.10241150 0.09105386 0.14953212

2 0.71377401 0.09277800 0.07872431 0.11472369

3 0.76033966 0.07322710 0.06478832 0.10164492

4 0.68607739 0.11470341 0.08986369 0.10935550

5 0.67857295 0.08770821 0.08227772 0.15144112

6 0.79842858 0.06712726 0.05676770 0.07767647

.

.

.

71 0.05243252 0.02353703 0.03041345 0.89361699

72 0.09555129 0.03992594 0.05043407 0.81408869

73 0.09673152 0.04828669 0.06629964 0.78868216

74 0.11367653 0.05369059 0.07298550 0.75964738

75 0.11731903 0.04977991 0.06446637 0.76843470

Vemos las probabilidades de pertenencia de cada registro a cada uno de los 4 clusters solicitados. Dada la clara separación entre los grupos, todos los registros presentan valores claros de pertenencia inequívoca a un cluster. Evidentemente en este ejemplo, la solución de particionado estandar y la fuzzy coinciden.

Si incluimos el argumento guarda.cong=T, no solo se guardará el conglomerado de pertenencia (por máxima probabilidad) sino que además se guardarán 4 nuevas variables relativas a las probabilidades de pertenencia de cada registro a cada uno de los cuatro conglomerados.


ruspini=analisis.conglomerados.fnc(ruspini, variables=1:2, tipo='particionado.fuzzy',

n.conglomerados = 4, guarda.cong=T)


head(ruspini)

x y p.cong.1 p.cong.2 p.cong.3 p.cong.4 conglomerado.fuz

1 4 53 0.6570025 0.10241150 0.09105386 0.14953212 1

2 5 63 0.7137740 0.09277800 0.07872431 0.11472369 1

3 10 59 0.7603397 0.07322710 0.06478832 0.10164492 1

4 9 77 0.6860774 0.11470341 0.08986369 0.10935550 1

5 13 49 0.6785730 0.08770821 0.08227772 0.15144112 1

6 13 69 0.7984286 0.06712726 0.05676770 0.07767647 1


LA IMPORTANCIA DE LAS UNIDADES DE MEDIDA DE LAS VARIABLES

La siguiente base de datos simulada, nos va a ser de gran utilidad en la valoración de la importancia crítica que tiene las unidades de medida de las variables utilizadas para llevar a cabo el análisis de conglomerados. Crearemos dos variables con distribución normal pero con diferentes unidades de medida aunque con relación nula entre ellas (independientes u ortogonales).


set.seed(1345678)


datos=data.frame(x1=rnorm(n=240, mean=100, sd=15),

x2=rnorm(n=240, mean=10, sd=1.5))


head(datos)

x1 x2

1 97.24455 8.791035

2 96.16044 9.525664

3 94.25047 7.299452

4 107.58935 11.013576

5 98.24981 9.780234

6 92.04928 8.699254


descriptivos.fnc(datos, simple=T)

media dt n

x1 99.08 16.25 240

x2 10.17 1.63 240


correlacion.fnc(datos)

$correlacion

x1 x2

x1 1.000 0.062

x2 0.062 1.000

grafica.xy.fnc(datos, variables = 1:2)

Tal y como podemos observar, tenemos dos variables que muestran un patrón conjunto de independencia mutua (incorrelacionado) donde la variable x1 tiene una variabilidad 10 veces superior a la que presenta la variable x2. Si observas ambas figuras, verás que la distribución conjunta y ortogonal, permite apresar la existencia de cuatro grupos de casos claramente situados en cada uno de los cuatro cuadrante de la figura de la derecha (cuadrante 1: bajos en x1 y altos en x2, cuadrante 2: altos en x1 y x2, etc).

Si aplicamos el análisis de conglomerados de particionado a esta matriz de datos, solicitaríamos 4 conglomerados a la función.

analisis.conglomerados.fnc(datos, variables=1:2,  n.conglomerados=4)

Vemos que la asignación de los casos a los cuatro conglomerados no ha seguido en absoluto el patrón esperado en los cuadrantes de la figura anterior. Es obvio desde la figura derecha que la variable con mayor varianza (x1) es la única utilizada por el algoritmo para asignar los casos. Incluiremos seguidamente el argumento tipifica=T. Con el, estamos solicitando a la función que lleva a cabo la estimación de la matriz de disimilaridad a partir de las puntuaciones típicas de las p variables incluídas en el análisis.

analisis.conglomerados.fnc(datos, variables=1:2, n.conglomerados=4, tipifica=T)

Una vez tipificadas las variables, vemos como el algoritmo ha concedido a ambas variables la misma importancia en la asignación de los casos a los grupos (conglomerados o clusters).

ANÁLISIS DISCRIMINANTE O DE ARBOL DE DECISIÓN SOBRE LOS CLUSTER GENERADOS

Si incluyes los argumentos discriminante=T o arbol=T, o ambos. La función llevará a cabo un análisis discriminante utilizando como variables predictoras las incluidas en el análisis de conglomerados y como variable de agrupación el factor conglomerados generado o un análisis de árbol de decisión que será de gran utilidad a la hora de comprender el "proceso" o la forma en que las variables se combinan para separar a los "grupos" (conglomerados) creados.

analisis.conglomerados.fnc(datos, variables=1:2, n.conglomerados=4, tipifica=T,

discriminante=T, arbol=T)

$Discriminante

$Discriminante$Manova

Df Pillai approx F num Df den Df Pr(>F)

conglomerado.part 3 1.328407 155.6022 6 472 1.78119e-108

Residual 236 NA NA NA NA NA

$Discriminante$Funciones

Autovalor Canonica Wilks F.val df.n df.d p.val

func.1 2.098969 0.8229897 0.3226880 152.0889 3 236 0

func.2 1.866110 0.8069046 0.3489049 159.8307 3 236 0

$Discriminante$Coef.Tipicos

LD1 LD2

x1 -0.6441810 -0.7662869

x2 0.7905696 -0.6136281

$Discriminante$Coef.Est

LD1 LD2

x1 -0.6136210 -0.7900071

x2 0.7656684 -0.6432494

$Discriminante$Clasificacion

Predicho

Observado 1 2 3 4

1 72 0 4 0

2 1 67 0 1

3 0 0 54 2

4 0 0 0 39

$Discriminante$Tabla.prop

Predicho

Observado 1 2 3 4

1 0.947 0.000 0.053 0.000

2 0.014 0.971 0.000 0.014

3 0.000 0.000 0.964 0.036

4 0.000 0.000 0.000 1.000

$Arbol.Decision

Conditional inference tree with 6 terminal nodes

Response: as.factor(conglomerado.part)

Inputs: x1, x2

Number of observations: 240

1) x2 <= 10.01318; criterion = 1, statistic = 161.352

2) x1 <= 92.08133; criterion = 1, statistic = 79.368

3)* weights = 41

2) x1 > 92.08133

4) x1 <= 120.51; criterion = 1, statistic = 22.188

5)* weights = 70

4) x1 > 120.51

6)* weights = 9

1) x2 > 10.01318

7) x1 <= 97.73428; criterion = 1, statistic = 80.566

8) x2 <= 10.56233; criterion = 1, statistic = 22.138

9)* weights = 15

8) x2 > 10.56233

10)* weights = 39

7) x1 > 97.73428

11)* weights = 66

El gráfico de árbol de decisión muestra la forma en que se combinan las variables para separar los conglomerados estimados.

2.- analisis.conglomerados.fnc - tipo Jerárquico