Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Curso Intro Duc To Rio de R
Curso Intro Duc To Rio de R
Bien, como lo prometido es deuda a partir del día de hoy estoy manos a la obra para
prepararos un pequeño manual de R. Espero que os lo halláis descargado si no haced
clic aquí y comenzareis a formar parte de la comunidad de R; la parte del módulo base
para empezar os la podéis descargar en en este sitio. Tenéis el módulo base y las
contribuciones. R es un programa con código totalmente libre, se puede contribuir a su
mejora ofreciendo nuevos paquetes que los programadores cuelgan en Internet, de
momento no vamos a analizar los paquetes y las contribuciones personales a R pero es
este el aspecto más importante de esta aplicación, R es totalmente libre y podemos
programar nuestros análisis y tareas más comunes de una forma sencilla y práctica esto
hace de R la herramienta para la estadística más barata y asequible sin olvidarnos que
las contribuciones personales hacen de R cada vez más completo y potente.
¡Fuera introducciones! Comenzamos a manejar datos para ello sólo es necesario tener el
módulo base que ya os habéis instalado en vuestra máquina:
Con R creamos objetos, hasta aquí todo muy bien nadie se pierde y los creamos del
siguiente modo:
La forma que tiene R de almacenar los datos se basa en esta creación de objetos y a
partir de ella creamos nuestros conjuntos de datos en función de nuestras necesidades.
Los conjuntos de datos que yo suelo emplear son vectores (vector) y matrices (matrix).
Más adelante funcionamiento del modo lista (list) y los data frame.
Un vector:
> felipe<-c(1,2,3,4)
> felipe
[1] 1 2 3 4
Una matriz:
2 6 4
5 8 9
0 2 0
> datos<-matrix(c(2,5,0,6,8,2,4,9,0),ncol=3)
> datos
[,1] [,2] [,3]
[1,] 2 6 4
[2,] 5 8 9
[3,] 0 2 0
Sólo podemos manejarnos con datos numéricos. Si queremos nombrar las columnas
tenemos que trabajar más la sentencia matrix:
> datos<-matrix(c(2,5,0,6,8,2,4,9,0),ncol=3,
+ dimnames=list(c("Matematicas","Lengua","Ingles"),
+ c("Juan","Lucia","Serafin")))
> datos
Juan Lucia Serafin
Matematicas 2 6 4
Lengua 5 8 9
Ingles 0 2 0
Esta sentencia también puede servir para tomar contacto con la estructura de datos lista.
Nos limitamos a poner nombre por fila y por columna mediante instrucciones, el
símbolo + nos lo ofrece el sistema automáticamente cuanto pulsamos intro y significa
que espera más instrucciones o parámetros. Si nos equivocamos al teclear las sentencias
con las teclas cursor podemos retomar las sentencias anteriores y corregir los fallos
además de acceder rápidamente a las instrucciones anteriores, R también acepta contar y
pegar así que para ir practicando podéis cortar y pegar de esta página (a buenas horas os
lo digo).
También podéis leer de ficheros planos pero ahora mismo no tengo ningún ejemplo a
mano... os indico como se hace:
Gráficos de dispersión:
> x<-c(1,2,3)
> y<-c(4,5,6)
> plot(x,y)
Obtenemos el mas básico de todos los gráficos. Espero que lo vayais haciendo vosotros
a l vez con vuestro R porque sólo pienso poneros los gráficos que merezca la pena
reseñar. Continúo con la representación gráfica de funciones donde además podéis ver
como actúan las sentencias function y seq, imaginemos que deseamos representar la
función f(x,y)=x+3y:
>x<-seq(-10,10,lenght=20)
> y<-seq(-10,10,lenght=20)
> ejem<-function (x, y){x+3*y}
> persp(x,y, outer(x,y, fun=ejem))
Podéis comprobar que os ofrece un estupendo gráfico en tres dimensiones donde une los
puntos de x e y formando un plano. Por supuesto también existe la posibilidad de hacer
funciones más complejas con cuadrados, cubos, etc... en R basta con poner el símbolo ^
para representar potencias. Ahora vamos a pasar a la parte de la estadística descriptiva
para la representación de datos unidimensionales:
Por supuesto que estas funciones gráficas tienen muchas posibilidades más pero de
momento estoy con una simple introducción, pero posteriormente me iré adentrando en
las esquisiteces de estas funciones que son muchas. A continuación os expongo algunas
de las opciones con las que podéis contar, para añadir estas opciones sólo tenéis que
incluirlas a continuación del conjunto de datos;
funcion_grafica(datos,opcion=parámetro)
Las posibilidades que nos ofrece R son muy amplias y poco a poco las iremos viendo
con mayor detenimiento aplicadas a ejemplos más concretos.
Pues bien, aquí tenéis las funciones estadísticas más comunes con R:
Medidas de dispersión
Frecuencias
> cumsum(datos)
acumuladas
Media aritmética > mean (datos)
Mediana > median(datos)
> cuantile(datos) #obtenemos los cinco
cuantiles
Cuantiles
> cuantile(datos,prob=p) #obtenemos un
cuantil concreto
Medidas de dispersión
Cuasivarianza > var(datos)
De nuevo tenemos nuevas funciones. La función length sirve para conocer el tamaño de
un vector, para conocer el número de observaciones n. Pues si cada vez que queramos
determinar la varianza tenemos que hacer esto lo llevamos claro. Soy un poco
exagerado, tampoco hay que escribir tanto, pero es una ocasión estupenda para que
podais empezar a programar en R:
Ahora bien si queremos conservar la función editada al cerrar nuestra sesión de R nos
aparecerá un mensaje qestion que nos pregunta si queremos guardar la imagen (Save
workspace image?) nosotros decimos que si y la aplicación nos guarda todo lo que
hemos hecho hasta el momento en la presente sesión de R. ¿Por qué no os lo comenté
antes? Pues simplemente porque se me ha olvidado... Tendré que dedicarme en algún
otro capítulo al manejo de archivos y a la lectura de datos, pero es que eso me aburre un
montón.
Por otra parte si queremos introducir los datos mediante R también podemos emplear la
función scan(); creamos el vector vector.ej:
> vector.ej<-scan()
1: 2.3 4.5 6.7
4: 3 .5 5.6 8
8:
Read 7 items
Deciros que no me he equivocado y que en la ruta hay que poner \\ en vez de \. Esta es
la forma que tiene R de leer los datos. Pero de nuevo tiene sus limitaciones ya que para
leer datos de esta forma el fichero plano tiene que tener una estructura de lo más básica.
Si por ejemplo la estructura fuera del tipo:
Se puede ver que la primera fila contiene los nombres de las variables, la función R
apropiada para estos casos es read.table que tiene una estructura muy sencilla:
Conocemos los conceptos básicos para comenzar a trabajar, también sabemos que las
observaciones del experimento generalmente tienen distribución normal (esto es
inferencia paramétrica). Ahora bien, necesitamos determinar unas distribuciones en el
muestreo que estén asociadas con la distribución normal. Estas distribuciones son la chi-
cuadrado, la t de Student y la F de Snedecor.
"La chi-cuadrado es una suma de normales al cuadrado" más o menos se podía definir
así ya que si calculamos la distribución de una variable normal al cuadrado no podemos
aplicar cambio de variable y a partir de su función de distribución llegamos a una
función de densidad de una gamma con parámetros 1/2 y 1/2 que es una chi-cuadrado
con 1 grado de libertad. La gamma es reproductiva respecto al primer parámetro por lo
que sumas de normales (0,1) nos proporcionan gammas de parámetros n/2 y 1/2 o lo
que es lo mismo chi-cuadrado con n grados de libertad.
La t de Student se crea a partir de una normal (0,1) y una chi-cuadrado con n grados de
libertad independientes. Una variable se distribuye bajo una t de Student si se puede
definir como normal(0,1) dividido por la raíz cuadrada de una chi-cuadrado partida por
sus grados de libertad; difícil de comprender así mejor veamos un ejemplo:
==> F=(X/m)/(Y/m) es F de
snedecor con m,n grados de libertad
Bueno pues comencemos con R, la función que nos ofrece tanto estimaciones puntuales
como intervalos de confianza como contrastes de hipótesis es:
Las opciones indicadas son todas las ofrecidas por defecto. Podemos poner sólo un
conjunto de datos para muestras unidimensionales (estimaciones puntuales) los dos
conjuntos para comparación de muestras.
En paired=T estamos ante una situación de datos no apareados para indicar que
estamos ante datos apareados poner paired=F.
Con var.equal estamos estamos trabajando con los casos de igualdad o no de varianzas
que sólo se emplean en comparación de dos poblaciones. Si var.equal=T las varianzas
de las dos poblaciones son iguales si var.equal=F las varianzas de ambas poblaciones
no se suponen iguales.
Ejemplo 5.1:
Con objeto de estimar la altura de los varones españoles menores de 25 años se recogió
una muestra aleatoria simple de 15 individuos que cumplían ese requisito. Suponiendo
que la muestra se distribuye normalmente determinar un intervalo de confianza al 95%
para la media.
Tenemos una variable con distribución normal de media y desviación típica
desconocidas por ello el intervalo de confianza ha de ser:
Veamos el programa R:
> alturas<-scan()
16:
Read 15 items
> t.test(alturas)
One Sample t-test
data: alturas
1.717396 1.809270
sample estimates:
mean of x
1.763333
> t.test(alturas,mu=1.77)
One Sample t-test
data: alturas
1.717396 1.809270
sample estimates:
mean of x
1.763333
Como se puede ver p-value = 0.7602 indica que con un nivel de significación del 5% se
acepta la hipótesis de que las altura media de los españoles es de 1.77 metros.
Ejemplo 5.2:
El director de una sucursal de una compañía de seguros espera que dos de sus mejores
agentes consigan formalizar por término medio el mismo número de pólizas mensuales.
Los datos de la tabla adjunta indican las pólizas formalizadas en los últimos cinco
meses por ambos agentes.
Agente A Agente B
12 14
11 18
18 18
16 17
13 16
> agente_A<-c(12,11,18,16,13)
> agente_B<-c(14,18,18,17,16)
> var.test(agente_A,agente_B)
F test to compare two variances
data: agente <- A and agente <- B
0.3160711 29.1566086
sample estimates:
ratio of variances
3.035714
Los datos recogidos tienen igual varianza ya que no se rechaza la hipótesis de igualdad
de varianzas. Como los datos están distribuidos normalmente y las varianzas son iguales
los agentes harán la misma cantidad de pólizas si la diferencia de sus medias es
estadísticamente distinta de 0, esta es la hipótesis de partida. Esta hipótesis de rechaza
cuando:
-8.163151 2.963151
sample estimates:
-2.6
Por poco pero se puede aceptar la hipótesis nula ya que el p-value = 0.09779 es superior
al 0.01 que establecimos de partida.
Mi página existe desde finales de junio de 2002 y siempre he querido saber cual ha sido
el número medio de visitas, geocities me ofrece estadísticas desde finales de julio así
que voy a tomar como referencia el mes de agosto. La media de visitas a la página en el
mes de agosto fueron:
> visitas<-scan()
1: 27 27 13 9 21 42 26 20 28 23 10 34 19 19 15 13 9
18: 10 17 22 17 9 21 4 9 20 20 31 21
30: 16 16
32:
Read 31 items
> mean(visitas)
[1] 18.96774
¡Sólo 19 visitas diarias a mi página! con lo que me la estoy currando, a ver si venís más
de vez en cuando sólo para que vaya bien el contador. El caso es que tiene altos y bajos,
vamos a verlo en un gráfico:
Como vemos R conserva el orden ya que en el eje de ordenadas aparece index, para que
la función plot una por líneas le añadimos type="l" y con main indicamos el título. Los
gráficos no tienen una resolución gráfica excelente y además el trabajar con ellos es un
poco engorroso pero son más que suficientes para presentar un informe escrito con
cualquier editor de texto ya que basta con cortar y copiar.
> semanas<-scan()
1: 31 31 31 31
5: 32 32 32 32 32 32 32
12: 33 33 33 33 33 33 33
19: 34 34 34 34 34 34 34
26: 35 35 35 35 35 35
32:
Read 31 items
> pie(visitas,col=semanas)
Se puede añadir leyenda con la función legend pero eso espero lo guardo para un
capítulo posterior donde veremos otras funciones, como cambiar colores, ver varios
gráficos en una sola ventana,...
Imaginemos ahora que tenemos un fichero ASCII que recoge llamadas a un número de
ayuda. Queremos saber si el número de llamadas de los usuarios difiere según los
turnos, las semanas o los días.
R indexa si no le indicamos lo contrario, además nombra las variables como V1, V2, V3
y V4. Si queremos nombrar las variables debemos emplear la función names.
> summary(llamadas)
Semanas Turno Dia Llamadas
Min. : 1 Min. :1 Fri:33 Min. : 8.0
1st Qu.: 3 1st Qu.:1 Mon:33 1st Qu.: 67.0
Median : 6 Median :2 Thu:33 Median :129.0
Mean : 6 Mean :2 Tue:33 Mean :113.5
3rd Qu.: 9 3rd Qu.:3 Wed:33 3rd Qu.:153.0
Max. :11 Max. :3 Max. :550.0
También puede interesarnos sólo el saber el número medio de llamadas, para ello
tenemos que acceder a la variable de un data frame, esto se hace con el símbolo $
después del nombre del objeto data frame:
> mean(llamadas$Llamadas)
[1] 113.4545
No nos vamos a detener en todos los pasos puesto que si lo hiciéramos el capítulo
quedaría demasiado extenso. Vamos a analizar las posibilidades que tenemos con R y
para que nos pueden servir los modelos lineales.
La función que realiza los modelos lineales en R es lm "lineal model". Pero esta función
no nos ofrece ninguna salida por pantalla si no que nos crea un objeto, o mejor dicho,
nosotros creamos un objeto que va a ser un modelo de regresión lineal. Este objeto
puede ser referenciado por cualquier función para realizar un análisis de la varianza, un
modelo autoregresivo,... La función lm tiene la siguiente sintaxis:
En data especificamos el data frame que contiene las variables del modelo en el caso de
que trabajemos con un data frame.
En subset especificamos un subconjunto de observaciones para validar posteriormente
el modelo.
Con method especificamos el método. No entramos puesto que con el módulo base sólo
es posible obtener el modelo por mínimos cuadrados.
En contrast podemos especificar objetos con los que realizar contrastes sobre los
parámetros.
Tiene múltiples opciones, para ver cuales son podéis poner en la línea de comandos ?lm
y accederéis a la ayuda de R sobre el procedimiento lm. En este caso para conocer mejor
su funcionamiento vamos a ver ejemplos ya que es la forma más apropiada de ir
aprendiendo:
Ejemplo 7.1:
El timepo que tarda un sistema informático en red en ejecutar una instrucción depende
del número de usuarios conectados a él. Si no hay usuarios el tiempo es 0. Tenemos los
siguientes datos:
> tiempo<-c(1,1.2,2,2.1,2.2,2,1.9)
> usuarios<-c(10,15,20,20,25,30,30)
> ejemplo7.1<-lm(tiempo~usuarios-1) #se crea un objeto con el modelo
lineal
> summary(ejemplo7.1) #sumarizamos el objeto para ver
el modelo
Call:
lm(formula = tiempo ~ usuarios - 1)
Residuals:
Min 1Q Median 3Q Max
-0.4831 -0.1873 0.2056 0.3127 0.5113
Coefficients:
Estimate Std. Error t value Pr(>|t|)
usuarios 0.079437 0.006496 12.23 1.82e-05 ***
---
Signif. codes: 0 `***' 0.001 `**' 0.01 `*' 0.05 `.' 0.1 ` ' 1
Residual standard error: 0.3871 on 6 degrees of freedom
Multiple R-Squared: 0.9614, Adjusted R-squared: 0.955
F-statistic: 149.5 on 1 and 6 DF, p-value: 1.821e-05
> anova(ejemplo7.1)
Analysis of Variance Table
Response: tiempo
Df Sum Sq Mean Sq F value Pr(>F)
usuarios 1 22.4011 22.4011 149.53 1.821e-05 ***
Residuals 6 0.8989 0.1498
---
Signif. codes: 0 `***' 0.001 `**' 0.01 `*' 0.05 `.' 0.1 ` ' 1
Ejemplo 7.2:
Nos han enviado por correo electrónico un archivo de texto que contiene las notas de la
asignatura de estadística de un centro universitario. Nos piden que hagamos un modelo
para predecir las notas finales a partir de las notas de los exámenes previos, el test y la
puntuación del laboratorio. Pincha aquí para ver el archivo. La descripción del archivo
viene recogida en la siguiente tabla:
He aquí el modelo resultante del que como podemos ver sólo nos quedaríamos con la
variable exam1 ya que los contrastes para las restantes estimaciones de parámetros no se
rechaza la hipótesis de partida de nulidad del parámetro. Quizá estemos ante un
problema de multicolinealidad ya que habrá una alta dependencia lineal entre las
variables regresoras. Para ver la dependencia lineal hemos de ver el coeficiente de
correlación, la forma en que se haya la matriz de correlaciones es la siguiente:
> co1<-cor(archivo$test,archivo$exam1)
> co2<-cor(archivo$test,archivo$exam2)
> co3<-cor(archivo$test,archivo$labo)
> co4<-cor(archivo$exam1,archivo$exam2)
> co5<-cor(archivo$exam1,archivo$labo)
> co6<-cor(archivo$exam2,archivo$labo)
La forma no es muy ortodoxa, pero no se me ocurre otra forma mejor de hacerlo, como
vemos creamos objetos que contienen los coeficientes de correlación se crean con la
función cor. Los listamos y construimos la matriz de correlaciones con nuestros medios
o con la función matix. Yo lo hago manualmente y la matriz queda:
Ejemplo 8.2:
Si recordamos en el ejemplo 7.2 nos pedían que hicieramos un modelo para predecir las
notas finales a partir de las notas de los exámenes previos, el test y la puntuación del
laboratorio. Teníamos una variable dependiente que era la nota final y cuatro variables
regresoras. Vimos que el modelo presentaba múltiples lagunas (multicolinealidad, un
modelo con un r cuadrado bajo,...). Pues ahora nos piden mejorar el modelo. Es difícil
mejorarlo en precisión porque no tenemos más variables regresoras en el conjunto de
datos por eso podemos mejorarlo haciéndolo más sencillo y recogiendo una cantidad de
información lo más grande posible con un modelo lo más reducido posible, es decir,
vamos a seleccionar un modelo de regesión. Para hacer esto contamos con la función
step que selecciona un modelo de regresión a partir del criterio de información de
Akaike (AIC, siglas en inglés). Creamos un estadístico que permite decidir el orden de
un modelo. AIC toma en consideración tanto la medida en que el modelo se ajusta a las
series observadas como el número de parámetros utilizados en el ajuste. Búscamos el
modelo que describa adecuadamente las series y tenga el mínimo AIC. Veamos como lo
presenta R:
Call:
lm(formula = final ~ test + exam1, data = archivo)
Coefficients:
(Intercept) test exam1
25.9520 1.3026 0.7172
La forma que tiene de trabajar R parece bastante comprensible pero en mi caso estoy
más acostumbrado a emplear el método forward de otro modo. Primero selecciono la
variable candidata a entrar (la que mayor coeficiente de correlación lineal tenga con la
variable dependiente) y posteriormente busco la variable que menor suma del cuadrado
del error me produzca y después contrastamos si esa variable debe permanecer en el
modelo. R lo que hace es marcar un AIC referencia y entran en el modelo todas las
variables que tengan mayor AIC que ese valor referencia. En este caso por este método
el modelo sería final=1.3test+0.71exam1, sólo se ha quedado con dos variables
regresoras.
> modelo.FINAL<-lm(final~test+exam1,data=archivo)
> summary(modelo.FINAL,cor=T) #incluimos cor=T para ver la correlación
de los coeficientes
Call:
lm(formula = final ~ test + exam1, data = archivo)
Residuals:
Min 1Q Median 3Q Max
-72.627 -12.149 2.902 16.257 34.708
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 25.9520 20.3937 1.273 0.209573
test 1.3026 0.5457 2.387 0.021143 *
exam1 0.7172 0.2036 3.523 0.000977 ***
---
Signif. codes: 0 `***' 0.001 `**' 0.01 `*' 0.05 `.' 0.1 ` ' 1
Residual standard error: 20.99 on 46 degrees of freedom
Multiple R-Squared: 0.451, Adjusted R-squared: 0.4271
F-statistic: 18.89 on 2 and 46 DF, p-value: 1.024e-06
Correlation of Coefficients:
(Intercept) test
test -0.7179
exam1 -0.1935 -0.5326
Ahora imaginemos que nos interesa ver como funciona el modelo final de dos variables
regresoras; si cumple las hipótesis (media del error 0, homocedasticidad, incorrelación,
distribución normal del error). Esto fundamentalmente se puede ver de forma gráfica,
las funciones R son muy sencillas, veámoslas:
Figura 1
> cook<-cooks.distance(modelo.FINAL)
> significativas<-cook>1
> significativas
1 2 3 4 5 6 7 8 9 10 11 12
13
FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
FALSE
14 15 16 17 18 19 20 21 22 23 24 25
26
FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
FALSE
27 28 29 30 31 32 33 34 35 36 37 38
39
FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
FALSE
40 41 42 43 44 45 46 47 48 49
FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
He creado el vector cook con las distancias y después el vector significativas que recoge
una variable lógica. Como vemos ninguna observación supera el valor referencia 1,
ninguna observación es potencialmente influyente. Otra forma de ver si una observación
es potencialmente influyente es ver el potencial que tiene el caso i-ésimo, el peso que
tiene la observación i-ésima a la hora de estimar la predicción. Si el potencial de una
observación es alto tiene mucho peso a la hora de dar la predicción. Estos potenciales se
obtienen matricialmente como la diagonal principal de la matriz HAT que se calcula a
partir de la matriz de diseño del modelo que es la matriz de datos con la 1ª columna de
unos. Hat es H, X es la matriz de diseño: H=X(X'X)-1X'. La matriz de diseño se crea
con la función model.matrix(objeto) y hat se crea a partir de esta matriz de diseño. Los
elemento de la diagonal principal de hat son los potenciales sobre los que continuamos
nuestro estudio:
1. son ortogonales (cada componente representa una dirección del espacio de las
variables originales)
2. cada puntuación está incorrelada con la anterior
3. la primera componente es la que más varianza contiene y la j-ésima tiene más
varianza que la j-1 ésima...
4. las primeras j componentes dan la solución de mínimos cuadrados del modelo
Y=X B+E
Ejemplo 9.1:
De todas estas variables que contiene el archivo seleccionamos las que nos van a
interesar y descartamos otras que no tienen mucha funcionalidad como puedan ser el
número de marchas, el tipo de la trasmisión,... para quedarnos con otras características
de los coches que nos permitan ver que tipos de coches tenemos e incluso clasificarlos.
Nos quedamos con el desplazamiento, la potencia, el par motor, la longitud, la anchura,
el peso y el recorrido en gasolina.
> attach(conjunto.datos)
> conjunto<-data.frame(V1,V2,V3,V8,V9,V10,V12)
> detach(conjunto.datos)
> nombres<-
c("desplazamiento","potencia","par","longitud","anchura","peso","recorrido")
> names(conjunto)<-nombres
Ya tenemos el conjunto de datos con el que vamos a trabajar, también en este ejemplo
se puede ver la función attach función que sirve para "atacar" un conjunto de datos, de
este modo nos evitamos el llamar al conjunto con el símblo $. Sobre estas tres variables
vamos a realizar el análisis de componentes principales muestrales. Para llevar a cabo
este análisis hemos de realizar cálculos matriciales con la matriz de correlaciones y la
matriz de varianzas covarianzas, estas dos matrices determinan los dos modos de
obtención de las componentes, es decir, componentes principales a partir de la matriz de
correlaciones y componentes principales a partir de la matriz de covarianzas.
> matriz.correlaciones<-cor(conjunto)
> matriz.correlaciones
desplazamiento potencia par longitud
anchura
desplazamiento 1.0000000 0.9406456 0.9895851 0.8670281
0.8001582
potencia 0.9406456 1.0000000 0.9643592 0.8042467
0.7105117
par 0.9895851 0.9643592 1.0000000 0.8662469
0.7881284
longitud 0.8670281 0.8042467 0.8662469 1.0000000
0.8828869
anchura 0.8001582 0.7105117 0.7881284 0.8828869
1.0000000
peso 0.9531800 0.8879129 0.9435772 0.9559969
0.8994470
recorrido -0.8718188 -0.7965605 -0.8493416 -0.7552211
-0.7624550
peso recorrido
desplazamiento 0.9531800 -0.8718188
potencia 0.8879129 -0.7965605
par 0.9435772 -0.8493416
longitud 0.9559969 -0.7552211
anchura 0.8994470 -0.7624550
peso 1.0000000 -0.8526911
recorrido -0.8526911 1.0000000
Se aprecian unas altas correlaciones entre las variables, esto nos beneficia a la hora de
realizar el análisis de componentes ya que se detectarán relaciones lineales entre
variables y podemos investigar los patrones que unen las diferentes variables para crear
unas nuevas variables que nos describan de forma más simple el conjunto de datos de
coches con el que estamos trabajando. Ahora queda obtener las componentes, éstas son
las combinaciones lineales de las variables que hacen máxima su varianza y esto se
consigue obteniendo los autovalores y los autovectores de la matriz de correlaciones, no
voy a explicar el razonamiento matemático, existen algunas páginas en la red donde os
lo explican con bastante detalle. Sigamos trabajando con R:
> componentesI<-eigen(matriz.correlaciones)
> componentesI
$values
[1] 6.193181539 0.400764875 0.244830693 0.094091951 0.046951262
0.015094646
[7] 0.005085034
$vectors
recorrido peso anchura longitud par
potencia
desplazamiento -0.3926641 0.2475231 0.05234234 0.03567111 0.61407897
0.01657661
potencia -0.3733929 0.4647583 0.29963669 0.28335837 -0.65342114
-0.11954685
par -0.3914349 0.2911694 0.16717164 0.11038560 0.28865783
0.44120895
longitud -0.3744302 -0.3980948 0.31799457 -0.64622375 -0.22495520
0.33416791
anchura -0.3560523 -0.6557118 -0.12419209 0.63919813 -0.04914155
0.11797501
peso -0.3965847 -0.1523398 0.09815214 -0.17000242 0.15186737
-0.81350329
recorrido 0.3590553 -0.1621960 0.86795951 0.22620880 0.19115713
-0.05826262
desplazamiento
desplazamiento 0.63495457
potencia 0.18235333
par -0.66624254
longitud 0.14256169
anchura 0.05420171
peso -0.31004382
recorrido 0.01766344
> componentesI$values[1]/7
[1] 0.8847402
> (componentesI$values[1]+componentesI$values[2])/7
[1] 0.9419923
> componetesI$vectors[1:7]
desplazamiento potencia par longitud
anchura
-0.3926641 -0.3733929 -0.3914349 -0.3744302
-0.3560523
peso recorrido
-0.3965847 0.3590553
[,1]
1 -2110.7416
2 -2143.4584
...
29 -2262.1919
30 -1218.8272
Se puede ver que para realizar operaciones con matrices es necesario incluir el símbolo
%, ahora nos interesa ver la evolución de la componente en el conjunto de
observaciones, para ello tenemos que unir matrices:
Vemos que los coches más potentes tienen un valor de la componente más bajo que los
menos potentes, sin embargo recorren mucho menos espacio que éstos, se confirman los
planteamientos que se hicieron con anterioridad. Con esta componente podemos saber
que tipo de coche es cada uno sin necesidad de analizar todas las variables, si
dispusiéramos de precios podíamos saber cual es más caro o más barato e incluso
podemos ubicar otras observaciones.
> cov(conjunto)
desplazamiento potencia par longitud
anchura peso recorrido
desplazamiento 13463.3826 4873.3970 9538.3428 2128.3800
527.21145 104071.183 -633.53025
potencia 4873.3970 1993.6885 3576.9276 759.7257
180.14897 37305.897 -222.74678
par 9538.3428 3576.9276 6900.5759 1522.3807
371.76759 73756.207 -441.86448
longitud 2128.3800 759.7257 1522.3807 447.5874
106.06593 19031.538 -100.06382
anchura 527.2114 180.1490 371.7676 106.0659
32.24510 4806.024 -27.11503
peso 104071.1828 37305.8966 73756.2069 19031.5379
4806.02414 885435.586 -5024.97931
recorrido -633.5303 -222.7468 -441.8645 -100.0638
-27.11503 -5024.979 39.22185
Vemos que las unidades son difícilmente comparables, sería conveniente el tipificar las
observaciones. Desconozco si hay alguna función de R con la que podamos tipificar
variables, por eso la mejor opción va a ser programarla:
> datos.tipificados<-tipificar(conjunto)
> componentesII<-eigen(cov(datos.tipificados))
> componentesII
$values
[1] 578.5921014 3.1441794 1.7077434 1.2076084 1.0943170
0.5415443 0.2088097
$vectors
recorrido peso anchura longitud
par potencia
desplazamiento 2.510359e-03 -0.019586489 0.106248291 -0.025785327
-0.982859312 0.145815869
potencia 4.687239e-05 -0.589985214 0.792848158 0.107833661
0.097845596 0.026642031
par -2.982895e-03 -0.797331687 -0.567048694 -0.061191845
-0.065755761 -0.160532844
longitud 1.175570e-03 0.016218362 -0.116217484 0.991844352
-0.041956706 -0.022501828
anchura -4.361458e-03 0.116691682 0.153377013 -0.012443462
-0.070359659 -0.668265795
peso -9.999782e-01 0.001688000 0.001079292 0.001363264
-0.001682031 0.005744282
recorrido 2.827855e-03 -0.043739740 -0.039073016 0.007117519
0.115656021 0.710731059
desplazamiento
desplazamiento -0.019539430
potencia 0.037384301
par -0.094180712
longitud -0.014393132
anchura -0.714951066
peso 0.001379889
recorrido -0.691365696
Nosotros vamos a estudiar el análisis cluster de casos para el que podíamos partir de un
análisis de componentes principales para evitar introducir variables no relevantes, puede
servirnos de ejemplo el análisis de componentes principales que se realizó en el capítulo
9.
Ejemplo 10.1:
De nuevo empleo los ejemplos para introducir la metodología del análisis. Recordemos
que realizamos un análisis de componentes principales a un conjunto de datos donde
aparecían las carácterísticas de técnicas de distintos coches, a partir de la matriz de
correlaciones se vió que con una componente podíamos explicar el 88% de la varianza
total del conjunto de datos. Pues ahora vamos a realizar sobre el valor que toma esta
componente para cada observación un análisis de agrupamiento. Primero de todo
creamos el conjunto de datos sobre el que vamos a trabajar:
> x<-as.matrix(conjunto)
> y<-componentesI$vectors[1:7]
> comp.obs<-x %*% y
> comp.obs
[,1]
1 -2110.7416
...
30 -1218.8272
No parecen que se formne grupos diferenciados pero prosigamos para ver si podemos
aplicar una regla de agrupamiento. Disponemos de dos técnicas de formación de cluster:
técnicas jerárquicas aglo:merativas de formación de conglomerados y técnicas no
jerárquicas. En este ejemplo vamoa a emplear la técnica jerárquica que consiste en
considerar en primera instancia cada observación como un cluster y posteriormente
agrupar las obsevarciones más "similares", las observaciones que menos disten las unas
de las otras, por eso lo primero que debemos hacer es calcularnos una matriz de
distancias entre pares de observaciones. En este punto hago un inciso para explicar un
aspecto de R que no había comentado hasta ahora. Con R podemos hacer multitud de
análisis estadísticos y además existe un grupo de programadores que colaboran con más
paquetes y más programas. Para poder emplear estos paquetes es necesario tenerlos en
una librería library que en mi caso está en: C:\Archivos de
programa\R\rw1051\library En esta librería tengo todos los paquetes de los que puedo
disponer, pero cuando tu abres una sesión de R es necesario que carges el paquete que
vas a emplear. Para hacer esto está la función library(nombre_librería) o bien abrimos
el menú Packages de R y seleccionamos el paquete que queremos utilizar. Os he
contado esto porque para realizar el análisis cluster necesitamos cargar en paquete mva:
> library(mva)
> matriz.distancias<-dist(comp.obs)
Cluster completo
Cluster simple method="single" Cluster promedio method="centroid"
method="complete"
> clusterI<-hclust(matriz.distancias)
> summary(clusterI)
Length Class Mode
merge 58 -none- numeric
height 29 -none- numeric
order 30 -none- numeric
labels 30 -none- character
method 1 -none- character
call 2 -none- call
dist.method 1 -none- character
Hemos creado un objeto clusterI que contiene 7 variables a partir de las cuales
realizaremos el análisis. R nos ha hecho las tareas de cálculo pero ahora somos nosotros
los que tenemos que continuar determinando cuantos grupos se deben tomar y como
analizar los grupos creados. Comenzamos "atacando" el objeto clusterI creado viendo la
variable merge. Esta variable merge indica como se han ido formando los cluster:
> attach(clusterI)
> merge
[,1] [,2]
[1,] -3 -23 #se unen la obs 3 y la obs 23 que forman el
cluster '1'
[2,] -13 -19 #se unen las 13 y 19 formando el '2'
[3,] -1 -4 #la 1 y la 4
[4,] -26 3 #la 26 con el cluster 3 (observaciones 1 y 4)
formando el '4'
[5,] 1 2 #el cluster 1 y 2 formando de este modo el
cluster '5'
...
[27,] 24 25 #se unen el cluster 24 y 25
[28,] 20 26 #el 20 y el 26
[29,] 27 28 #el 27 y el 28
Esto nos ofrece una idea de la forma en la que se van uniendo, pero no podemos
establecer una regla de unión entre observaciones, nos sería más útil ordenar el conjunto
de datos de menor a mayor de forma que pudieramos hacer una regla de unión entre
observaciones (recordemos que cuanto menor es el valor de la componente más potente
y más grande es el coche) y de este modo podíamos ver intuitivamente la forma que
tienen de unirse los datos. Para ordenar los datos empleamos la función sort:
> ordenado<-sort(comp.obs)
> dist.ordenado<-dist(ordenado)
> clusterII<-hclust(dist.ordenado)
> attach(clusterII)
> merge
[,1] [,2]
[1,] -13 -14
[2,] -11 -12
[3,] -7 -8 #los gama media
[4,] -9 3 #enseguida se unen
[5,] 1 2
[6,] -22 -23 #los más simples
[7,] -16 -17 #se van uniendo
[8,] -10 5
[9,] -24 -25
[10,] -27 -28
[11,] -19 -20
[12,] -6 4
[13,] -29 -30
[14,] -15 8
Parece que los coches de gama media se unen enseguida, insistimos en que la
componente principal ofrecía una medida de la potencia-prestaciones-tamaño de los
coches, cuanto menor era la componente más potente, más rápido y más grande era el
coche. Pues como decíamos los gama media se unen con facilidad, también ocurre esto
con los coches más pequeños que son los siguientes en agruparse, por último son los
coches "buenos" los que se van agrupando. Poco a poco los gama media se acercan a los
coches buenos dejando de lado a las observaciones superiores a la 20ª como se puede
ver en los pasos [18] con observaciones 24,25,26; [23] con observaciones 27,28,29,30 y
[24] cuyas observaciones son 22,23,18,21,19,20 posteriormente en [25] y [27] se unen.
Determinar el número de cluster con esta variable merge es bastante complicado por eso
no puede servir mejor para analizar como se van creando los grupos. ¿Cómo determinar
el número de cluster? En mi opinión la mejor manera es el análisis gráfico, el
dendograma que es un gráfico de formación de cluster, para hacerlo se emplea la
función plot.hclust(clusterII):
Este dendograma creo que puede admitir dos cortes que os expongo de manera gráfica
para que me entendais mejor, los cortes los he realizado yo con el paint de windows, ya
os explicaré como se puede hacer con R:
Estas son las 2 opciones que yo planteo: en la primera opción se puede por un lado
formar dos grupos donde tendríamos los coches medianos-grandes donde las
observaciones 1, 2 y 3 parece que les cuesta unirse (son coches muy potentes y grandes)
y donde las observaciones de 4 a la 16 son muy parecidos; y por el otro lado tenemos
los coches utilitarios (observaciones de la 18 a la 30) que si se pueden considerar
bastante parecidos entre sí aunque los hay un poco mejores. La segunda opción sería el
hacer los cuatro grupos donde el grupo I encuadraría a los coches "menos malos" el
grupo II a lo "malos", el grupo III a los "mejores" y el grupo IV a los "buenos".
> clusterIII<-hclust(dist.ordenado,method="centroid")
> plot.hclust(clusterIII)
A la vista de este gráfico también podemos hacer tres grupos, además por este método
se distinguen muy claramente las tres primeras observaciones como los mejores coches
quedando más unidos los coches "menos malos" con los "buenos" con lo que se podía
establecer un grupo que podían ser los utilitarios dentro de los cuales los hay mejoresy
peores... Bueno de todas formas ya os he introducido a la metodología del análisis
cluster con R así que debéis de ser vosotros los que hagais vuestro estudio y os planteéis
vuestros objetivos y la forma de trabajar.
Ejemplo 11.1:
En este ejemplo vamos a trabajar con los datos de inflación de países de la Unión
Europea. Los datos obtenidos a través de la página web del Instituto Nacional de
Estadística de España vienen recogidos en un archivo excell, desconozco si existe algún
paquete que me permita importar datos de excel a R (si lo hay para importar archivos
SAS y SPSS), podemos trabajar con ficheros de texto pero al tratarse de 15 países y 3
variables (país, índice e incremento interanual) me parece más adecuado el introducirlos
directamente en R creando tres vectores y uniéndolos de la forma más apropiada:
> nombres<-
c("Alemania","Austria","Bélgica","España","Finlandia","Francia","Grecia"
,"Holanda""Irlanda","Italia","Luxemburgo","Portugal","Dinamarca","Reino
Unido","Suecia")
> indices<-scan() #indice de precios al consumo
1: 109 108.9 111.3 117.3 112.4 108.7
7: 125.8 119.5 122.4 114.3 113 119.1
13: 114.1 108.7 110.2
16:
Read 15 items
> tasa<-scan() #Incremento de la tasa
interanual
En este ejemplo vamos a separar los países inflacionistas de los no inflacionistas, ese va
a ser nuestro objetivo, por ello partimos de un número predeterminado de cluster en este
caso 2 (inflacionistas y no inflacionistas, insisto) y asignamos a cada individuo a un
cluster mediante una técnica de ubicación iterativa a esta técnica se la conoce como el
algoritmo de las k-medias. Pretendemos mejorar las clasificaciones minimizando las
distancias utilizadas en la formación de los conglomerados. Sería siempre interesante
empezar por la aglomeración jerárquica pero en este caso el objetivo de nuestro
agrupamiento parece bastante claro y no es necesario comprobar cuantos cluster se
pueden formar.
El siguiente paso con R es unir los dos vectores que contienen datos numéricos para
formar el conjunto de datos sobre el que vamos a calcular la matriz de distancias con la
que posteriormente realizaremos el análisis de agrupamiento. En este caso el método de
> datos.inflacion<-cbind(indices,tasa)
> matriz11.1<-dist(datos.inflacion,method="manhattan")
> kmeans(matriz11.1,2)
$cluster
(1)
[1] 1 1 1 2 1 1 2 2 2 1 1 2 1 1 1
$centers
(2)
1 2 3 4 5 6 7
8
1 2.356353 2.364722 2.035462 6.551598 2.266588 2.530643 14.912252
8.715068
2 12.174428 12.140668 9.906339 3.547262 8.798775 12.300583 4.995479
2.386100
9 10 11 12 13 14 15
1 11.720213 3.325348 2.554850 8.355977 3.273403 2.530059 2.024244
2 3.010035 6.879040 8.009260 2.462113 6.872028 12.465291 10.963804
$withinss
[1] 545.6604 591.0740
$size
(3)
[1] 10 5
Esto es lo que no ofrece R. en (1) tenemos a que cluster se une cada observación, en (2)
las distancias de cada observación al cluster y en (3) el tamaño de cada cluster. También
aparece una función withinss que no sé para que sirve pero que ahí está, si alguien lo
averigua que por favor me mande un correo. Ahora nos queda ver a que cluster
pertenece cada país para ello unimos el vector nombres que creamos con anterioridad
con la variable $cluster de el análisis, también unimos tasa e indices para ver mejor
como funciona:
> kmedias<-kmeans(matriz11.1,2)
> cbind(nombres,kmedias$cluster,tasa,indices)
nombres tasa indices
[1,] "Alemania" "1" "1" "109"
[2,] "Austria" "1" "1.6" "108.9"
[3,] "Bélgica" "1" "1.2" "111.3"
[4,] "España" "2" "3.5" "117.3"
[5,] "Finlandia" "1" "1.4" "112.4"
[6,] "Francia" "1" "1.8" "108.7"
[7,] "Grecia" "2" "3.8" "125.8"
[8,] "Holanda" "2" "3.7" "119.5"
[9,] "Irlanda" "2" "4.5" "122.4"
[10,] "Italia" "1" "1.8" "114.3"
[11,] "Luxemburgo" "1" "2.2" "113"
[12,] "Portugal" "2" "3.8" "119.1"
[13,] "Dinamarca" "1" "2.5" "114.1"
[14,] "Reino Unido" "1" "1" "108.7"
[15,] "Suecia" "1" "1.2" "110.2"
Los menos inflacionistas los ha clasificado en el cluster 1 y los más inflcionistas como
Holanda, Portugal,... y por supuesto mi querida España en el cluster 2. Si quisieramos
ver este análisis de forma gráfica emplearíamos la función plot a la que la incluiremos
unos argumentos para reconocer los cluster visualmente:
> plot(datos.inflacion,col=kmedias$cluster,pch=17,main="Agrupamiento")
En plot los argumentos que he añadido son los colores que van unidos al cluster
asignado, el tipo de de símbolo que se cambia con pch (de 1 a 18) y el título con main,
por lo demás comprobar que observaciones se unen con los cluster, si se quieren
identificar sólo hay que emplear la función identify que ya vimos en un capítulo
anterior.
Ejemplo 11.2:
En este ejemplo vamos a agrupar distintos tipos de alimentos según sus aportes en
calorías, proteínas, grasas y calcio. El conjunto de datos está en mi disco duro como un
archivo de texto en el directorio datos (haz click aquí para ver el archivo) hemos de
emplear la función read.table para importar el archivo a R:
> alimentos<-read.table("c:\\datos\\alimentos.txt",header=TRUE)
> alimentos
Alimentos Calorias Proteinas Grasas Calcio
1 Hamburguesas 245 21 27 9.0
2 Buey 420 15 39 7.0
3 Pollo 115 20 3 8.0
4 Cordero 280 18 22 9.0
5 JamónAhumado 340 20 28 9.0
6 Cerdo 340 19 29 9.0
7 ChuletaCerdo 355 19 30 9.0
8 PescadoAzul 135 22 4 25.0
9 Sardinas 180 22 9 16.7
10 AtúnLata 170 25 7 12.3
11 MejillonesLata 155 16 9 15.7
12 MejillonesHervidos 200 19 13 15.0
Hay que reseñar el hecho de que para leer variables alfanuméricas no podemos tener
espacios en blanco ya que la función read.table podía darnos problemas, para poder
poner espacios en blanco en las variables alfanuméricas hay que dar un formato de
entrada que todavía no hemos visto, por eso recomiendo siempre un vistazo previo al
conjunto de entrada para evitar problemas. Como podéis ver en mi caso las
observaciones de la variable Alimentos no tienen espacios en blanco y he juntado
palabras para evitar estos problemas. es posible leer datos en blanco, leer archivos con
diferentes delimitadores, cambiar el punto decimal por coma,... pero esto lo veremos en
posteriores capítulos.
Ya tenemos el conjunto de datos con el que vamos a trabajar, como siempre tenemos la
pega de que este conjunto tiene una variable caracter y a la hora de realizar cálculos
sobre él nos puede plantear trastornos por eso hemos de separar la variable Alimentos o
como suelo hacer yo unir el resto de variables (Calorías, Proteínas, Grasas y Calcio) en
una matriz con la función cbind:
> attach(alimentos)
> alimentos.2<-as.matrix(cbind(Calorías, Proteínas, Grasas, Calcio))
> alimentos.2
Calorias Proteinas Grasas Calcio
[1,] 245 21 27 9.0
[2,] 420 15 39 7.0
[3,] 115 20 3 8.0
[4,] 280 18 22 9.0
[5,] 340 20 28 9.0
[6,] 340 19 29 9.0
[7,] 355 19 30 9.0
[8,] 135 22 4 25.0
[9,] 180 22 9 16.7
[10,] 170 25 7 12.3
[11,] 155 16 9 15.7
[12,] 200 19 13 15.0
> detach()
Ya podemos empezar a realizar nuestra labor matemática que en este caso vamos a
emplear para el agrupamiento las medidas de disimilitud con base en la distancia
euclidea pero que son todo lo contrario a las medidas de similitud que empleamos para
los anteriores ejemplos, para hacer este ejemplo hemos de cargar la librería cluster:
> library(cluster)
> disimilar<-daisy(alimentos.2)
> disimilar
Dissimilarities :
[1] 175.524927 132.204387 35.482390 95.010526 95.042096 110.059075
[7] 113.516519 67.891752 77.793894 92.162302 47.549974 307.159568
[13] 141.074448 80.932070 80.746517 65.772335 287.789854 242.163354
[19] 252.293658 266.836448 221.711524 166.105388 226.386837 226.501656
[25] 241.518115 26.343880 65.883913 55.538185 41.367741 85.877820
[31] 60.332413 60.415230 75.432089 147.040811 101.214080 111.287421
[37] 125.868543 80.734132 1.414214 15.165751 207.028983 161.320457
[43] 171.396879 186.136751 140.932608 15.033296 207.159359 161.456774
[49] 171.554335 186.222689 141.039002 222.128341 176.449114 186.549966
[55] 201.233422 156.044865 46.031402 37.473858 23.398504 66.445466
[61] 11.504782 25.729361 20.685502 17.932094 31.293610 45.282337
Metric : euclidean
Number of objects : 12
Esa es la matriz de disimilaridades entre los valores de las observaciones que calcula R,
a partir de ella vamos a hacer el agrupamiento, vamos a ver gráficamente el
comprotamiento de ese agrupamiento y posteriormente determinaremos el número de
cluster necesarios para llevar a buen puerto nuestro estudio:
> cluster11.2<-hclust(disimilar)
> plot.hclust(cluster11.2)
>
data.frame(alimentos$Alimentos,cluster11.2$order)
alimentos.Alimentos cluster11.2.order
1 Hamburguesas 2
2 Buey 7
3 Pollo 5
4 Cordero 6
5 JamónAhumado 1
6 Cerdo 4
7 ChuletaCerdo 12
8 PescadoAzul 9
9 Sardinas 10
10 AtúnLata 3
11 MejillonesLata 8
12 MejillonesHervidos 11
Es bastante claro que tenemos dos cluster, por un lado están las observaciones 2, 7, 5, 6
y por el otro las restantes, para ver que alimentos son esas observaciones he unido la
variable order (orden del dendograma) de cluster11.2 con el nombre de los alimentos
para poder realizar una correspondencia visual entre los grupos y los nombres de los
alimentos así el primer cluster sería buey, chuleta de cerdo, jamón ahumado y cerdo, es
un extraño cluster pero continuemos con el estudio para ver porque se produce esta
asociación.. ¿Qué ocurriría si tuvieramos una gran cantidad de observaciones y una
referencia visual planterara problemas? En ese caso tras identificar el número de cluster
emplearíamos una técnica por medios divisorios (Partitioning methods en terminología
anglosajona) que situaría cada observación en los alguno de los cluster de forma que se
minimizara la suma de las disimilaridades. Esto se hace con R del siguiente modo:
> cluster11.2b<-pam(alimentos.2,2)
> cluster11.2b
Medoids:
Calorias Proteinas Grasas Calcio
[1,] 170 25 7 12.3
[2,] 340 19 29 9.0
Clustering vector:
[1] 1 2 1 2 2 2 2 1 1 1 1 1
Objective function:
build swap
37.89533 32.42881
Available components:
[1] "medoids" "clustering" "objective" "isolation"
"clusinfo"
[6] "silinfo" "diss" "call" "data"
La función pam permite hacer lo que señalabamos antes, pero en este caso nos
encontramos con que los cluster formados son distintos a los que formábamos con los
métodos jerárquicos ya que el tamaño de los cluster es distinto que el tamaño anterior,
como siempre veámoslo gráficamente que es como mejor se puede ver como trabajan
las distintas funciones de R:
> par(mfrow=c(2,2))
> plot(cluster11.2b)
> plot(cluster11.2)
Hemos dicho a R que nos ofrezca los gráficos en una pantalla dividida en 4 celdas con
la función par y después graficamos los análisis con plot, vemos que la función pam
ofrece 2 gráficos: uno de componentes principales y otro de distancias entre los
centroides de los cluster. Vemos que cada método ha establecido distintos grupos, ahora
comparemos las dos formas de agrupamiento:
>
data.frame(alimentos$Alimentos,cluster11.2$order
,cluster11.2b$clustering)
alimentos.Alimentos cluster11.2.order
cluster11.2b.clustering
1 Hamburguesas 2
1
2 Buey 7
2
3 Pollo 5
1
4 Cordero 6
2
5 JamónAhumado 1
2
6 Cerdo 4
2
7 ChuletaCerdo 12
2
8 PescadoAzul 9
1
9 Sardinas 10
1
10 AtúnLata 3
1
11 MejillonesLata 8
1
12 MejillonesHervidos 11
1
Métodos
Alimento Jerárquicos
divisorios
Hamburguesa 1 1
Buey 2 2
Pollo 1 1
Cordero 1 2(*)
Jamón ahumado 2 2
Cerdo 2 2
Chuleta de cerdo 2 2
Pescado azul 1 1
Sardinas 1 1
Atún en lata 1 1
Mejillones en lata 1 1
Mejillones hervidos 1 1
> summary(cluster11.2b)
Medoids:
Calorias Proteinas Grasas Calcio (1)
[1,] 170 25 7 12.3
[2,] 340 19 29 9.0
Clustering vector: (2)
[1] 1 2 1 2 2 2 2 1 1 1 1 1
Objective function:
build swap
37.89533 32.42881
Numerical information per cluster: (3)
size max_diss av_diss diameter separation
[1,] 7 77.79389 33.07663 132.2044 35.48239
[2,] 5 80.74652 31.52185 141.0744 35.48239
Isolated clusters:
L-clusters: character(0)
L*-clusters: character(0)
Silhouette plot information: (4)
cluster neighbor sil_width
11 1 2 0.7879602
10 1 2 0.7839538
9 1 2 0.7648888
8 1 2 0.7563286
3 1 2 0.7093818
12 1 2 0.6655977
1 1 2 0.1340588
7 2 1 0.7681916
6 2 1 0.7680220
5 2 1 0.7675267
2 2 1 0.6322059
4 2 1 0.2312497
Average silhouette width per cluster:
[1] 0.6574528 0.6334392
Average silhouette width of total data set:
[1] 0.6474471
Dissimilarities :
[1] 175.524927 132.204387 35.482390 95.010526 95.042096
110.059075
[7] 113.516519 67.891752 77.793894 92.162302 47.549974
307.159568
[13] 141.074448 80.932070 80.746517 65.772335 287.789854
242.163354
[19] 252.293658 266.836448 221.711524 166.105388 226.386837
226.501656
[25] 241.518115 26.343880 65.883913 55.538185 41.367741
85.877820
[31] 60.332413 60.415230 75.432089 147.040811 101.214080
111.287421
[37] 125.868543 80.734132 1.414214 15.165751 207.028983
161.320457
[43] 171.396879 186.136751 140.932608 15.033296 207.159359
161.456774
[49] 171.554335 186.222689 141.039002 222.128341 176.449114
186.549966
[55] 201.233422 156.044865 46.031402 37.473858 23.398504
66.445466
[61] 11.504782 25.729361 20.685502 17.932094 31.293610
45.282337
Metric : euclidean
Number of objects : 12
Available components:
[1] "medoids" "clustering" "objective" "isolation"
"clusinfo"
[6] "silinfo" "diss" "call" "data"
En (1) tenemos la media de cada variable dentro del cluster, los alimentos "sanos" con
menor aporte calórico, menos grasas y más calcio forman el cluster 1 y los "menos
sanos" forman el cluster 2. En (2) tenemos el vector que coloca cada observación en un
cluster. En (3) tenemos información numérica sobre cada cluster como el tamaño,
distancias medias y máximas,... En (4) tenemos como funciona el algoritmo que
clasifica las observaciones, le funcionamiento es análogo a la función hclust. Este ha
sido el estudio que al final nos ha ofrecido una buena función clasificatoria de alimentos
aunque en un principio planteara algunas dudas, de todas formas yo sigo sin entender
como ha clasificado a las hamburguesas como un alimento "sano"...
*PEÑA, D.: Estadística: Modelos y Métodos, vol. II: Modelos Lineales y Series
Temporales, Alianza Universidad Textos, 1992
Conceptos y definiciones:
Unidades experimentales: Sujetos sometidos a los tratamientos sobre los que se mide
la variable respuesta.
Para diseñar un experimento se tienen en cuenta como son las unidades experimentales
y la asignación de tratamientos. Según esto tenemos estructuras de diseño y estructuras
de tratamiento:
Estructuras de diseño:
Estructuras de tratamiento:
• Diseño unifactorial.
• Diseño bifactorial.
• Diseño n factorial.
• Diseño 2^n.
• diseño anidado.
Para realizar el análisis de la varianza con R hemos de determinar el modelo con el que
queremos trabajar. Si recordamos en el capítulo 7 para crear el objeto modelo lineal
empleábamos la función lm(Y~X), creábamos el modelo probabilístico Y=X+e de
variables cuantitativas, ahora vamos a crear otro modelo probabilístico
Yij=media_i+e_ij donde la media_i es una constante conocida que es la respuesta media
bajo el tratamiento i y e_ij es la parte probabilísitica que cumple una serie de
condiciones. Sobre este modelo realizaremos el análisis de la varianza con la función
aov(Y~X) donde Y es la variable respuesta que es la variable cuantitativa asociada al
experimento y X es la condición bajo la cual mido la variable respuesta, X es el factor.
Ejemplo 12.1:
Hemos creado dos vectores presion que recoge la variable respuesta y grupos que
recoge el factor, para su creación hemos de emplear la función factor con ella R
reconoce el tipo de variable que contiene ese vector creando un vector de factores.
Realicemos el análisis de la varianza, con él haremos el contraste de igualdad de medias
para establecer si hay diferencias significativas entre las medias de los distintos grupos:
> unifact<-aov(presion~grupos)
> summary(unifact)
Df Sum Sq Mean Sq F value Pr(>F)
grupos 3 2492.61 830.87 8.5262 0.0002823 ***
Residuals 31 3020.93 97.45
---
Signif. codes: 0 `***' 0.001 `**' 0.01 `*' 0.05 `.' 0.1 ` ' 1
Se rechaza la hipótesis nula de igualdad de medias en *** que planteamos con el test F
así pues hay diferencias entre los tratamientos. Para ver cual de estos tratamientos son
diferentes contamos con métodos de test de recorrido estudentizado y con métodos de
contrastes múltiples. Con R podemos programar el test que nos interese, pero el módulo
base tiene test de recorrido estudentizado. En este caso vamos a ver el test de Tuckey
que compara todas las posibles medias dos a dos y basándose en una distribución q
alfa(k,n) del rango estudentizado determina una diferencia mínima significativa para
que dos medias sean distintas. En R el test de Tukey se realiza con la función
TuckeyHSD:
> TukeyHSD(unifact)
Tukey multiple comparisons of means
95% family-wise confidence level
Fit: aov(formula = presion ~ grupos)
$grupos
diff lwr upr
AB-A -13.925000 -26.6337332 -1.216267
B-A -2.000000 -13.9819085 9.981909
P-A -21.157143 -34.3605630 -7.953723
B-AB 11.925000 -0.7837332 24.633733
P-AB -7.232143 -21.0985076 6.634222
P-B -19.157143 -32.3605630 -5.953723
> (qtukey(0.05,4,31))*sqrt(97.45/7)
[1] 2.819698
En resumen se puede determinar que los pacientes que han tomado placebo o la
convinación entre ambos medicamentos AB han tenido una mayor reducción de la
presión diastólica desde el estado basal (inicio del tratamiento) hasta el estado al cabo
de una semana de tratamiento, siendo el placebo el tratamiento que más ha hecho
reducir dicha presión.