Está en la página 1de 50

Curso introductorio de R:

Por Raúl Vaquerizo Romero.

Capítulo 1: Descarga, instalación y primeras sentencias.

Capítulo 2: Funciones gráficas básicas.

Capítulo 3: Medidas de estadística descriptiva.

Capítulo 4: Trabajo con datos I.

Capítulo 5: Inferencia estadística. Ejemplos.

Capítulo 6: Primeros ejemplos prácticos.

Capítulo 7: Regresión lineal con R.

Capítulo 8: Más ejemplos de regresión lineal.

Capítulo 9: Análisis de Componentes Principales.

Capítulo 10: Análisis de conglomerados (cluster) I.

Capítulo 11: Análisis de conglomerados (cluster) II.

Capítulo 12: Introducción al análisis de la varianza.


Capítulo 1: Descarga, instalación y primeras
sentencias.

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.

En la página web http://www.r-project.org/ tenéis un estupendo manual más completo y


más bonito, pero el mío va directamente al grano y no entra en todas las exquisiteces
que tiene este excelente programa.

¡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:

> felipe<-1 Creamos el objeto felipe


> felipe Le llamamos
[1] 1 R nos lo ofrece
> objects() Listamos objetos sin parámetros no entro en las posibilidades por
no liarme
[1] "felipe" Solo tenemos un objeto que es felipe

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

Sobra decir que R sobrescribe objetos ya creados.

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:

> fichero <- read.table(“a:\\datos”) modo mas simple


> fichero <- read.table(“a:\\datos”,header=T) si las variables o los datos contienen
nombre o cabecera.

Capitulo 2: Funciones gráficas básicas.


El siguiente paso en el pequeño manual que sigo construyendo es el manejo de las
funciones gráficas de bajo nivel, sin entrar en todas las posibilidades que tiene R (de
nuevo comentar que en http://www.r-project.org/ tenéis un completísimo y
aburrido manual) os voy a plantear algunos usos muy interesantes para posteriores
aplicaciones donde quizá veamos más en profundidad alunos aspectos.

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:

> piechart (datos) Diagrama de sectores


> hist (datos, nclass=n) Histograma con número de barras
> barplot (datos) Diagrama de barras
> boxplot(datos) Diagrama de cajas y bigotes

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)

(datos, main="titulo") Añadir título


(datos, xlab="etiqueta", ylab="etiqueta") Etiquetas en ejes
(datos,type="l") Realiza un gráfico de líneas.
(datos,col="nombre") Colores de los gráficos
(datos,breaks=numero) Intervalos

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.

Capítulo 3: Medidas de estadística descriptiva.


Comenzamos a trabajar con medidas estadísticas, de momento pondré las medidas
clásicas y posteriormente añadiré diversas funciones para que podamos trabajar con
métodos robustos, estas medidas robustas las tendremos que programar nosotros (en
este caso yo) así que su fiabilidad puede dejar algo que desear pero si alguien se atreve a
programar conmigo.. . De todas formas recomendaros el curso de la UNED de Experto
Universitario en Estadística Aplicada. Aun así espero poner a vuestra disposición mis
pequeños conocimientos sobre el tema y también explicaros como añadir módulos a
vuestro programa R aunque de nuevo si vais a la página web del proyecto R y os
entretenéis en leer un ratito no creo que os cueste mucho.

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

El símbolo # no tiene ninguna función estética, es la forma de poner comentarios


mediante R. por otro lado si quisiéramos las medidas de posición más comunes
emplearíamos el comando summary(datos) y tendríamos recogidos las medidas
anteriores.

Medidas de dispersión
Cuasivarianza > var(datos)

Como medida de dispersión R nos ofrece la cuasivarianza, si queremos obtener la


varianza o la desviación típica tenemos que transformar lo que podemos obtener con R
a nuestro antojo. A partir de este momento vamos a programar nuestras propias
funciones.

La varianza como me imagino que sabreis es [(n-1)/n]*cuasivarianza y la desviación


típica es su raiz cuadrada; en R es del siguiente modo:

Varianza > ((length(datos)-1)/length(datos))*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:

> varianza<-function(x) { ((length(x)-


Editamos la función varianza
1)/length(x))*var(x) }
varianza(datos) Comprobamos su
funcionamiento

Veamos más en profundidad como se editan funciones en R. Asignamos a un objeto


varianza el valor de una función que recibe un único parámetro x esa función viene
editada entre llaves { }. Para comprobar como funciona basta con ejecutarla como otra
función cualquiera.

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.

Capitulo 4: Trabajo con datos I.


Como paso previo a la creación de conjuntos de datos cabe señalar que con R podemos
importar datos tanto de otras aplicaciones como SAS, SPSS,... como de ficheros de
texto planos. Digo esto porque nos sería muy complicado el crear un fichero de datos
más o menos grande con las funciones de R que conocemos hasta la fecha ya que sería
muy engorroso, además en la mayoría de las ocasiones que realicemos un estudio los
datos serán un fichero ASCII.

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

Simplemente nos limitamos a ir introduciendo los datos, seguidamente pulsamos intro y


en este caso R nos indica con 4: que ya llevamos 3 elementos y que el siguiente
elemento es el cuarto, si pulsamos dos veces intro salimos de la función y R nos indica
que ha leido 7 items. Es otra forma de introducir los datos un poco más cómoda que la
que habíamos visto hasta ahora pero que sigue teniendo sus limitaciones como por
ejemplo que no podemos trabajar con variables alfanuméricas. Esta función scan puede
contener como argumentos el fichero ASCII del cual provienen los datos:

Conjunto de datos datos.txt:

2.3 4.5 6.7 3.5 5.6 8


> vector.ej<-scan(c:\\ruta completa\\datos.txt)

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:

Nombre Apellidos Salario Edad


Fernando Torres 12000 45
Arturo Fernandez 30000 56
Felipe Miñambres 24000 34
David Tejero 10000 23

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:

> empresas <- read.table("C:\empresa.dat",header=TRUE)


Warning message:
incomplete final line found by readTableHeader on `C:empresa.dat'
> empresas
Nombre Apellidos Salario Edad
1 Fernando Torres 12000 45
2 Arturo Fernandez 30000 56
3 Felipe Miñambres 24000 34
4 David Tejero 10000 23

Obtenemos un mensaje de error que no debe preocuparnos (espero) ya que el conjunto


de datos empresas aparece completo como deseábamos. Con esta función hemos creado
una estructura de datos (que ya referenciábamos en el primer capítulo del manual)
llamada data frame que puede leer objetos de varios tipos por columnas. Posteriormente
con estos objetos podemos realizar los pertinentes estudios. Otra nota a añadir es que R
nos indexa las observaciones si no le indicamos una columna índice esto se realiza con
al función row.names=1.

A partir de este momento estamos en disposición de empezar a trabajar más en


profundidad con R, estamos en disposición de realizar estudios estadísticos y contrastes
de muchos y variados tipos y posteriormente importar datos de otras aplicaciones y
realizar análisis muy completos con una herramienta gratuita y de fácil manejo. Si no
tienes SAS en casa tranquilo que puedes defenderte estupendamente con R.

Capitulo 5: Inferencia estadística.


En este capítulo voy a hacer memoria y recordar algunos términos y conceptos básicos
de estadística. En primer lugar hacemos inferencia a partir de unas observaciones
obtenidas a partir de la población a las que vamos a extraer unas propiedades que se
denominan estadísticos muestrales. Además vamos a conocer la distribución de
dichos estadísticos (generalmente distribución normal) por lo que hacemos inferencia
paramétrica.

La inferencia paramétrica puede recogerse en una vertiente o en otra según el


parámetro a estimar; tenemos por un lado la estadística clásica (que es en la que nos
vamos a centrar) y por otro lado la estadística ballesiana.

La estadística paramétrica clásica plantea tres tipos de problemas:


• Estimación puntual en la que pretendemos dar un valor al parámetro a estimar.
• Estimación por intervalos (buscamos un intervalo de confianza)
• Contrastes de hipótesis donde buscamos contrastar información acerca del
parámetro.

Tenemos un experimento, lo repetimos varias veces y obtenemos una muestra con


variables aleatorias independientes idénticamente distribuidas con función de
distribución conocida. (Por ejemplo tenemos las alturas de 30 varones españoles y
estimo que la altura media de los españoles es 1,77 estamos ante una estimación
puntual). Pues cualquier función de la muestra que no dependa del parámetro a estimar
es un estadístico y aquel estadístico que se utiliza para inferir sobre el parámetro
desconocido es un estimador. Ejemplos de estadísticos son el total muestral, la media
muestral, la varianza muestral, la cuasivarianza muestral, los estadísticos de orden,...

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:

Z1, Z2 ,Z3 ,Z4 variables aleatorias independientes idénticamente


distribuidas bajo una N(0,1)
Z1 / [(Z2+Z3+Z4)/3]^1/2 esto se distribuye según una t de Student de
3 grados de libertad

La F de Snedecor se crea a partir de dos chi-cuadrado independientes dividivas por sus


respectivos grados de libertad, así la F de Snedecor tiene dos parámetros que indican sus
grados de libertad:

X se distribuye como chi-cuadrado

con m grados de libertad

==> F=(X/m)/(Y/m) es F de
snedecor con m,n grados de libertad

Y se distribuye como chi-cuadrado

con n grados de libertad


Me dejo en el tintero muchos aspectos como las distribuciones de los estadísticos o los
métodos de construcción de contrastes e intervalos pero me podría extender mucho, y
me extenderé pero hasta aquí os cuento de momento. Aun así recomendaros una
bibliografía básica por si queréis profundizar más en el tema. También estoy a expensas
de poder publicar archivos LaTeX para que los aspectos matemáticos queden mejor
resueltos pero de momento conformaros con los ejemplos de más abajo.

Bueno pues comencemos con R, la función que nos ofrece tanto estimaciones puntuales
como intervalos de confianza como contrastes de hipótesis es:

> t.test (datos_x, datos_y =NULL, alternative = "two.sided", mu = 0,

paired =FALSE, var.equal = FALSE, conf.level= 0.95)

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.

El argumento alternative indica el tipo de contraste, bilateral two.sided, si la hipótesis


alternativa es mayor (Ho: menor o igual) se utiliza greater, si la hipótesis alternativa es
menor (Ho: mayor o igual) entonces se usa less.

En mu indicamos el valor de la hipótesis nula.

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.

Por último tenemos el argumento conf.level en el que indicamos el el nivel de confianza


del test.

Si deseáramos hacer el contraste para la igualdad de varianzas (cociente de varianzas=1)


habríamos de emplear la función var.test:

var.test(x, y, ratio = 1, alternative = c("two.sided", "less",


"greater"),

conf.level = 0.95, ...)

Los argumentos son los mismos que en la función t.test.

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()

1: 1.77 1.80 1.65 1.69 1.86 1.75 1.58

8: 1.79 1.76 1.81 1.91 1.78 1.80 1.69 1.81

16:

Read 15 items

> t.test(alturas)
One Sample t-test
data: alturas

t = 82.3296, df = 14, p-value = < 2.2e-16

alternative hypothesis: true mean is not equal to 0

95 percent confidence interval:

1.717396 1.809270

sample estimates:

mean of x

1.763333

El intervalo es [1.71,1.80]. La función t.test no tiene ningún argumento opcional puesto


que los necesarios son los que recoge por defecto. Ahora imaginemos que lo que
queremos es estimar si la altura media de los españoles es de 1.77 metros hay que
introducir algunas modificaciones:

> t.test(alturas,mu=1.77)
One Sample t-test
data: alturas

t = -0.3113, df = 14, p-value = 0.7602

alternative hypothesis: true mean is not equal to 1.77

95 percent confidence interval:

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

Admitiendo que el número de pólizas contratadas mensualmente por los dos


trabajadores son variables aleatorias independientes y distribuidas normalmente: ¿Tiene
igual varianza? ¿Se puede aceptar la hipótesis del director de la sucursal en función de
los resultados de la tabla y a un nivel de confianza del 99%?

Primero comprobamos si los datos tienen igual varianza:

> 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

F = 3.0357, num df = 4, denom df = 4, p-value = 0.3075

alternative hypothesis: true ratio of variances is not equal to 1

95 percent confidence interval:

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:

> t.test (agente_A,agente_B, paired=T, conf.level=0.99)


Paired t-test
data: agente <- A and agente <- B

t = -2.1518, df = 4, p-value = 0.09779

alternative hypothesis: true difference in means is not equal to 0

99 percent confidence interval:

-8.163151 2.963151

sample estimates:

mean of the differences

-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.

Capitulo 6:Primeros ejemplos prácticos.


Bueno hasta ahora he tratado de mostraros algunas funciones de R para que empezarais
a tomar contacto con la herramienta, no he trabajado con ningún ejemplo concreto a
excepción del capítulo 5 donde os presenté la función t.test y sus argumentos con algún
caso aplicado. Pues bien, en este capítulo voy a trabajar con ejemplos de todo lo que
hemos visto hasta ahora para que sirva además de leve repaso.

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:

> plot (visitas,type="l",main="Que poco me visitais")

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.

Si quiero hacer un gráfico de sectores por las visitas por semana:

> 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,...

Si quisiéramos hallar la varianza habríamos de crearnos la función ya que R calcula la


cuasivarianza muestral, esto ya lo vimos en el capítulo 3. De todas formas el programa
sería:

> varianza<-function(x) { ((length(x)-1)/length(x))*var(x) }


> varianza(visitas)
[1] 67.64412
> sqrt(varianza(visitas))
[1] 8.224605

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.

> llamadas<-read.table ("c:\datos\\calls.dat")


> llamadas
V1 V2 V3 V4
1 1 1 Mon 9
2 1 2 Mon 16
...
164 11 2 Fri 41
165 11 3 Fri 53

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.

> names(llamadas)<-c("Semanas", "Turno", "Dia", "Llamadas")


Es conveniente hacer un sumario para que podáis ver los valores que toman las
variables que componen el conjunto de datos:

> 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

Capitulo 7: Regresión Lineal.


En este capítulo vamos a ver como realiza el análisis de regresión R. Los modelos de
regresión lineal son modelos probabilísticos basados en una función lineal, expresamos
una variable en función otro conjunto de variables. Los pasos básicos a seguir en el
estudio de un modelo lineal son:

1. Escribir el modelo matemático con todas sus hipótesis.


2. Estimación de los parámetros del modelo.
3. Inferencias sobre los parámetros.
4. Diagnóstico del modelo.

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:

lm(formula, data, subset, weights,


method = "qr", model = TRUE, x = FALSE, y = FALSE, qr = TRUE,
contrasts = NULL, ...)

En formula ponemos el modelo expresado: y ~ x1+x2+...+xn

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.

En weights especificamos los pesos, útil si hacemos mínimos cuadrados ponderados.

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 model con TRUE decimos a R que ha de guardarse en el objeto, la matriz del


modelo, la frame,...

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:

Nº usuarios Tiempo de ejecución


10 1
15 1.2
20 2
20 2.1
25 2.2
30 2
30 1.9

Se pretende ajustar un modelo lineal sin término independiente, construir la tabla


ANOVA y comparar el modelo con el de término independiente. Comencemos:

> 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

Los modelos se escriben de la forma dependiente~indepentiente1+independiente2+...


+independienten con -1 le indicamos a R que es un modelo sin término independiente.
En este caso el modelo resultante sería: tiempo de ejecución=0.0794usuarios, también
decir que es un excelente modelo lineal ya que el Multiple R-Squared: 0.9614
(coeficiente de determinación ajustado) es bastante próximo a 1 (el mejor valor posible).
Para construir la tabla del análisis de la varianza hemos de emplear la instrucción
anova(objeto). El objeto lógicamente va a ser nuestro modelo lineal:

> 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:

Variable Tipo Column Descripción añadida


as

ID del estudiante alfanumérico 1-3

genero alfanumérico 5 f=emenino m=masculino

clase numérico 7 2=alevín 3=junior 4=senior

puntuación de test numérico 9-10 puntos máximos = 50

puntuación del examen 1 numérico 12-14 puntos máximos = 100

puntuación del examen 2 numérico 16-18 puntos máximos = 100

puntuación de laboratorio numérico 20-22 puntos máximos = 100

puntuación del examen numérico 25-27 puntos máximos = 200


final
Comencemos a trabajar con R:

> archivo<-read.table("c:\\datos\\GRADES.TXT") #leemos el archivo


> nombres<-c("ID","sexo","clase","test","exam1","exam2","labo","final")
> names(archivo)<-nombres #nombramos las variables
> ejemplo7.2<-lm(final~test+exam1+exam2+labo,data=archivo) #hacemos el
modelo
> summary(ejemplo7.2) #sumarizamos
Call:
lm(formula = final ~ test + exam1 + exam2 + labo, data = archivo)
Residuals:
Min 1Q Median 3Q Max
-75.5711 -10.5697 0.7903 15.8257 32.6372
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -17.8277 50.2996 -0.354 0.72471
test 0.8606 0.7650 1.125 0.26672
exam1 0.6709 0.2413 2.781 0.00795 **
exam2 0.4316 0.3667 1.177 0.24547
labo 0.2924 0.6182 0.473 0.63855
---
Signif. codes: 0 `***' 0.001 `**' 0.01 `*' 0.05 `.' 0.1 ` ' 1
Residual standard error: 21.06 on 44 degrees of freedom
Multiple R-Squared: 0.4716, Adjusted R-squared: 0.4236
F-statistic: 9.818 on 4 and 44 DF, p-value: 9.142e-06

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:

test exam1 exam2 labo


test 0.53 0.48 0.60
exam1 0.52 0.033
exam2 0.23
labo

No están todas altamente correladas, debe de existir alguna combinación lineal de


algunas de ellas pero a simple vista no se detecta. Habríamos de buscar un modo de ver
como se "infla" la varianza si quitamos alguna variable regresora. De momento no sé el
modo de hacerlo con R pero espero poder solventarlo pronto. También desconozco
como seleccionar el modelo de regresión más adecuado. En cuanto al análisis de
residuos me lo reservo para un posterior capítulo porque sería interesante conocer
algunas posibilidades gráficas que tiene R.

Capitulo 8: Más ejemplos de Regresión Lineal.


En este capítulo nos vamos a centrar en ver más ejemplos de regresión y en ver las
posibilidades gráficas que tiene R al respecto, las posibilidades que son todas las que se
quieran ya que como hemos visto en capítulos anteriores es muy fácil programar tus
própios análisis estadísticos. Digo esto por si alguien no está acostumbrado a seguir una
metodología distinta a la hora de realizar los modelos. Además el programar tus propios
métodos hace que puedas comprender mejor las salidas por pantalla y los pasos que
sigue el programa. En el primer ejemplo que vamos a ver partimos del ejemplo 7.2 del
capítulo 7 que si recordamos era un modelo de regresión múltiple donde teníamos
problemas de multicolinealidad.

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:

> modelo8.1<-lm(final~test+exam1+exam2+labo,data=archivo) #modelo lineal


> step(modelo8.1,direction="forward") #seleccionamos
hacia delante
Start: AIC= 303.37
final ~ test + exam1 + exam2 + labo

Df Sum of Sq RSS AIC


- labo 1 99.2 19612.9 301.6
- test 1 561.2 20074.9 302.8
- exam2 1 614.5 20128.2 302.9
<none> 19513.7 303.4
- exam1 1 3429.8 22943.5 309.3

Step: AIC= 301.61


final ~ test + exam1 + exam2

Df Sum of Sq RSS AIC


- exam2 1 661.8 20274.7 301.2
<none> 19612.9 301.6
- test 1 1645.0 21258.0 303.6
- exam1 1 3601.0 23213.9 307.9

Step: AIC= 301.24


final ~ test + exam1

Df Sum of Sq RSS AIC


<none> 20274.7 301.2
- test 1 2511.8 22786.5 305.0
- exam1 1 5469.7 25744.4 310.9

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.

Veamos este modelo como sería:

> 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:

> par(mfrow = c(2,2)) #con esto ponemos los 4


gráficos en la misma ventana
> plot(modelo.FINAL) #pedimos los gráficos del
modelo

Obteniendo en la ventana de gráficos:

Figura 1

Parece que el modelo presenta heterocedasticidad como vemos en el gráfico de residuos


studentizados frente a las predicciones y también vemos como hay algunas
observaciones (las número 18, 36 y 45) que podrían ser potencialmente influyentes
como nos indica el gráfico de las distancias de Cook Sin embargo el modelo si cumple
las hipótesis de media 0 y distribución normal de los residuos.
La distancia de Cook del caso i-ésimo consiste en buscar la distancia entre los
parámetros estimados si incluyen la observación i-ésima y si no la incluyen. Cada
observación tiene su distancia y se considera significativa si es mayor que 1. Esta
distancia se calcula con R con la función cooks.distance(objeto):

> 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:

> matriz.modelo<-model.matrix(modelo.FINAL) #creamos la matriz de diseño


> potenciales<-hat(matriz.modelo)
> potenciales<-hat(matriz.modelo) #creamos potenciales que contiene la
matriz hat del modelo
> plot(potenciales) #hacemos un gráfico de potenciales para ver los
mayores
> identify(potenciales) #identificamos sobre el gráfico el nº de la
observación
Esas son las observaciones con unos potenciales más altos, nos interesa que las
observaciones tengan un potencial similar de aproximadamente el cociente de las
variables regresoras (más uno por la columna de unos de X) entre el número de
observaciones. Si se dobla esta cantidad estaríamos ante casos que hay que estudiar con
detalle. Si además miramos el gráfico de las distancias de Cook (Figura 1) vemos que
las observaciones problemáticas son la número 45 y 36. Estos casos podían influir en
nuestro modelo.

Capitulo 9: Análisis de Componentes Principales.


El análisis de componentes principales puede encuadrarse dentro del conjunto de
técnicas multivariantes conocidas como métodos factoriales (también se incluyen el
análisis de factores y el análisis de correspondencias). Pretendemos sintetizar un gran
conjunto de datos, crear estructuras de interdependencia entre variables cuantitativas
para crear unas nuevas variables que son función lineal de las originales y de las que
podemos hacer una representación gráfica. El objetivo del análisis de componentes
principales será el reducir la dimensión de un conjunto de p variables a un conjunto m
de menor número de variables para mejorar la interpretabilidad de los datos.
Las nuevas variables, las componentes principales, determinan lo esencial de las
variables originales, son una combinación lineal de ellas que además tienen unas
propiedades interesantes:

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

Si hay relaciones estocásticas entre las p variables originales entonces podíamos


condensar esa información en otras m variables que explican sólo la variación del
sistema descartando la información redundante. Geométricamente el subespacio que
creamos con las m primeras componentes da el mejor ajuste posible al conjunto de
datos medido mediante la suma de los cuadrados de las distancias perpendiculares desde
cada punto al subespacio. El subespacio de menor dimensionalidad sería m=1
componente podíamos hacer la representación en un sólo eje pero el conjunto inicial se
podía distorsionar, así introduciríamos un nuevo eje para definir un subespacio m=2,
perderíamos menos información. Si m=p tendríamos el mismo número de variables, no
reduciríamos la dimensión, sólo haríamos una rotación rígida del conjunto de datos.

No voy a entrar en el algoritmo matemático para la obtención de las componentes, si


haré alguna reseña en algún momento a términos matemáticos pero de momento no
quiero entrar en fórmulas ni ecuaciones. Lo que si es cierto que con R las componentes
se obtienen mediante cálculo matricial. Vamos a ver la forma de obtenerlas mediante un
ejemplo:

Ejemplo 9.1:

Partimos del siguiente conjunto de datos: Se trata de datos de coches de importación y


nacionales [Douglas Montgomery and David Friedman, "Prediction Using Regession
Models with Multicollinear Predictor Variables" IIE Transactions (Mayo, 1993) vol. 25
nº 3, 73-85, Montgomery D.C. & Peck E.A., Introduction to Linear Regression
Analysis, 2ª edición, J. Wiley and Sons, N.Y. (1992)] bajaté el archivo. Este conjunto de
datos contiene las siguientes variables:

Variable Tipo Columnas Descripción añadida


desplazamiento numérico 1-5 en pulgadas cúbicas
potencia numérico 7-9 en ft-lbs
par motor numérico 11-13 en ft-lbs
razón de compresión numérico 15-17
razón árbol trasero numérico 19-21
nº de carburadores numérico 23
velocidades numérico 25 cuantas
longitud del coche numérico 27-31 en pulgadas
anchura del coche numérico 33-36 en pulgadas
peso del coche numérico 38-41 en lbs
tipo de transmisión numérico 43 0=manual 1=automático
recorrido gasolina numérico 45-48 en millas por galón de gasolina

Tenemos 12 variables de las que sólo seleccionaremos algunas, comencemos a trabajar


con R:

> conjunto.datos<-read.table("c:\\datos\\GAS.TXT") #leemos el


archivo
> conjunto.datos
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12
1 318.0 140 255 8.5 2.7 2 3 215.3 76.3 4370 1 19.7
2 440.0 215 330 8.2 2.9 4 3 184.5 69.0 4215 1 11.2
...
30 133.6 96 120 8.4 3.9 2 5 171.5 63.4 2535 0 23.9

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.

Componentes a partir de la matriz de correlaciones:.

Si calculamos las componentes a partir de la matriz de correlaciones tendremos las


componentes sobre las observaciones tipificadas de este modo nos evitamos los
problemas de escala. Para la obtención de la matriz de componentes principales a partir
de la matriz de correlaciones tendremos primero que hallar la matriz de correlaciones y
esto se hace con la función cor que creo que ya vimos en algún capítulo anterior:

> 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

El objeto componentesI recoge los autovalores y los autovectores de la matriz de


correlaciones, el número de autovalores no nulos proporciona la dimensión del espacio
en el que se encuentran las observaciones; un autovalor nulo revelaría la existencia de
una dependencia lineal entre las variables originales. Pues si Z es la matriz de datos
tipificados y R es la matriz de correlaciones con pares de autovalores y autovectores
(l1,e1),(l2,e2),...,(lp,ep) entonces la i-ésima componente muestral viene dada por y=ei Z=e1i
z1+...+epi zp donde los autovalores son una observación genérica de las variables
Z1,Z2,...Zp. La varianza total es la suma de los autovalores, y la varianza que explica la j-
ésima componente es el autovalor j-ésimo dividido por el número de variables:

> componentesI$values[1]/7
[1] 0.8847402

Con la primera componente explica ya un 88% de la variabilidad que es una cantidad


más que suficiente para explicar correctamente las variables del conjunto de datos. Si
queremos saber cuanto explicamos con la primera y la segunda variable:

> (componentesI$values[1]+componentesI$values[2])/7
[1] 0.9419923

Con dos componentes retenidas explicamos ya un 94% de la variabilidad total. El


número de componentes a retener depende de la cantidad de varianza que expliquen, en
ese caso con la primera componente creo que sería suficiente. Algunas aplicaciones
retienen las componentes cuyos autovalores asociados tienen un valor mayor que 1.
Ahora nos queda por ver cual sería la componente:

> 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

Pues aquí tenemos la componente principal: Z1=-0.3926desplazamiento-


0.3734potencia-0.3914par-0.3744longitud-0.356anchura-
0.3966peso+0.359recorrido; toma valores muy parecidos para todas las variables
excepto recorrido que es positiva esto se puede interpretar como a menor valor tome la
variable componente mejor será el coche aunque hay que tener en cuenta que los coches
buenos hacen un recorrido menor que los coches pequeños. Para ver como se comporta
la componente hemos de introducir esta variable en el conjunto de datos para ver que
valor toma para cada observación, esto lo podemos hacer introduciendo la fórmula para
crear la nueva variable componente o con cálculo matricial. Lo voy a hacer con el
cálculo matricial para que veáis como se trabaja con matrices en R:

> x<-as.matrix(conjunto) #x es la matriz del


conjunto de datos 30x7
> y<-as.matrix(componente.vector) #y es la matriz 7x1 con los valores
de la componente
> x %*% y
#multiplicamos matrices y obtenemos una matriz 30x1 con los valores de
la componente

[,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:

> componete.datos<-as.matrix(x %*% y ) #matriz de componentes


> conjunto.final<-cbind(conjunto,componete.datos) #unimos matrices con
la función cbind
> conjunto.final
desplazamiento potencia par longitud anchura peso recorrido
componete.datos
1 318.0 140 255 215.3 76.3 4370 19.7
-2110.7416
2 440.0 215 330 184.5 69.0 4215 11.2
-2143.4584
3 351.0 143 255 199.9 74.0 3890 18.3
-1928.3765
4 360.0 180 290 214.2 76.3 4250 21.5
-2107.2210
5 140.0 83 109 168.8 69.4 2700 20.3
-1280.0348
6 85.3 80 83 160.6 62.2 2009 36.5
-961.7679
7 350.0 165 260 200.3 69.9 3910 18.9
-1944.5619
8 96.9 75 83 162.5 65.0 2320 30.4
-1091.6923
9 351.0 148 243 215.5 78.5 4540 13.9
-2192.3495
10 440.0 215 330 231.0 79.7 5185 14.9
-2548.0378
11 171.0 109 146 170.4 66.9 2655 21.5
-1297.8304
12 302.0 129 220 199.9 74.0 3890 17.8
-1890.3878
13 350.0 155 250 196.7 72.2 3910 17.8
-1936.7795
14 318.0 145 255 197.6 71.0 3666 16.4
-1826.0833
15 231.0 110 175 179.3 65.4 3050 23.5
-1491.8465
16 96.9 75 83 165.2 61.8 2275 31.9
-1073.1790
17 500.0 190 360 224.1 79.8 5290 14.4
-2613.2788
18 231.0 110 175 179.3 65.4 3020 22.1
-1480.4516
19 350.0 170 275 199.6 72.9 3860 17.0
-1933.9594
20 250.0 105 185 196.7 72.2 3510 20.0
-1693.9764
21 225.0 95 170 194.0 71.8 3365 20.1
-1615.8603
22 89.7 70 81 155.7 64.0 1905 34.7
-917.1865
23 350.0 155 250 195.4 74.4 3885 16.5
-1927.6283
24 258.0 110 195 171.5 77.0 3375 19.7
-1641.7412
25 460.0 223 366 228.0 79.8 5430 13.3
-2669.6199
26 360.0 195 295 209.3 77.4 4215 13.8
-2102.2203
27 262.0 110 200 179.3 65.4 3180 21.5
-1566.0791
28 350.0 165 255 185.2 69.0 3660 16.5
-1838.3459
29 351.0 148 243 216.1 78.5 4715 13.3
-2262.1919
30 133.6 96 120 171.5 63.4 2535 23.9
-1218.8272

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.

Componentes principales a partir de la matriz de covarianzas:

Calcular las componentes a partir de la matriz de covarianzas no difiere mucho de


calcularlas a partir de la matriz de correlaciones, elegir uno u otro método depende de
las variables que tenemos en nuestro conjunto de datos. Variables con varianzas grandes
tienden a asociarse con autovalores grandes y variables con varianzas pequeñas tiende a
asociarse con autovalores pequeños, así pues sería conveniente el tipificar las unidades
muestrales para que las variables sean comparables. Veamos que sucede en nuestro
conjunto de datos:

> 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:

> tipificar<-function(x){ (x-mean(x))/varianza(x)}

No tiene mayor complicación poco que comentar, la función varianza ya la teníamos


creada en el capítulo 3; a partir de aquí vamos a realizar el análisis de componentes
principales sin olvidar que estamos trabajando con los datos tipificados. El proceso es
el mismo que con la matriz de correlaciones:

> 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

Ahora la proporción de varianza debida a la k-ésima componente es lk/( l1 + l2 +...+ lp ) Esto


traducido en R nos queda:
> componentesII$values[1]/sum(componentesII$values)
[1] 0.986523

De nuevo espectacular el resultado obtenido con la primera componente, explicamos


con sólo una componente el 98% de la variabilidad de las variables que componen el
conjunto de datos. A partir de aquí el trabajo sería completamente análogo al realizado
con la matriz de correlaciones si bien con este método el análisis de componentes
principales es aun mejor que con la matriz de correlaciones. Nos faltaría por analizar
algún gráfico de componentes, seguro que en próximos capítulos veremos más
posibilidades del análisis de componentes.

Capitulo 10: Análisis de conglomerados (cluster) I.


El proposito del análisis de conglomerados (cluster en terminología inglesa) es el
agrupar las observaciones de forma que los datos sean muy homogéneos dentro de los
grupos (mínima varianza) y que estos grupos sean lo más heterogéneos posible entre
ellos (máxima varianza). De este modo obtenemos una clasificación de los datos
multivariante con la que podemos comprender mejor los mismos y la población de la
que proceden. Podemos realizar análisis cluster de casos, un análisis cluster de variables
o un análisis cluster por bloques si agrupamos variables y casos. El análisis cluster se
puede utilizar para:

• La taxonomía, agrupar especies naturales.


• Para el marketing, clasificar consumidores tipo.
• Medicina, clasificar seres vivos con los mismos síntomas y características
patológicas.
• Técnicas de reconocimiento de patrones.
• Formar grupos de pixels en imágenes digitalizadas enviadas por un satélite
desde un planeta para identificar los terrenos.
• ...

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

Tenemos un conjunto de datos con 30 observaciones y una variable. En todo análisis


cluster existen dos fases; en una primera fase a parir de los datos construimos una
matriz de distancias o similaridades y después relaizamos el proceso de agrupación de
individuos. Como paso previo es interesante realizar una representación gráfica de los
datos para ver si se puede reconocer algún grupo:

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)

Ya estamos en disposición de poder empezar a realizar los cálculos pertinentes para


nuestro análisis. Como hemos dicho antes lo primero es calcular la matriz de distancias
y para ello tenemos la función dist:

> matriz.distancias<-dist(comp.obs)

Hemos creado una matriz diagonal de 30x30 a partir de la matriz de componente


principales donde vienen recogidas las distancias. Por defecto dist calcula la distancia
euclídea entre observaciones, si ejecutáis ?dist el archivo de ayuda os presenta las
distintas distancias que se pueden calcular. Una vez obtenida esta matriz hemos de
emplear la función hclust(<matriz_de_distancias>,method). En method indicamos por
que método queremos que R realice los agrupamientos, veamos gráficamente los
métodos más comunes:

Cluster completo
Cluster simple method="single" Cluster promedio method="centroid"
method="complete"

También tenemos el método Ward que es una técnica inferencial de formación de


conglomerados que se basa en la minimización de la suma de cuadrados dentro de los
cluster que se pueden formar. Por defecto el método que tieene hclust en "complete".
Veamos como funciona hclust:

> 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".

Este es el análisis mediante el método completo, veamos el dendograma para el método


promedio:

> 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.

Capitulo 11: Análisis de conglomerados (cluster) II.


En este capítulo vamos a ver un par de ejemplos más de análisis de conglomerados con
R. En el ejemplo del capítulo 10 partíamos de un conjunto de una sola variable que era
la primera componente principal de un conjunto de datos que recogía características
técnias de una serie de coches que se vendían es Estados Unidos, ahora vamos a ver dos
ejemplo más donde tabajaremos con otras posibilidades de R.

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

1: 1 1.6 1.2 3.5 1.4 1.8 3.8 3.7 4.5


10: 1.8 2.2 3.8 2.5 1 1.2
16:
Read 15 items

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

cálculo de la matriz de distancias es el método Manhattan que


se utiliza habitualmente en variables dicotómbicas pero para que sigais conociendo
posibilidades vamos a trabajar con ella:

> datos.inflacion<-cbind(indices,tasa)
> matriz11.1<-dist(datos.inflacion,method="manhattan")

Veamos el gráfico de dispersión para identificar visualmente algún cluster:


Si se identifican los cluster, arriba a la derecha tenemos los países con mayor tasa y
abajo a la izquierda los de menor tasa de acumulación, ahora sólo nos queda plasmar
esta idea inicial en R y ver la forma de agrupamiento de los países. Para realizar el
algoritmo de las k-medias R dispone de la función
kmeans(<matriz_distancias>,<num_cluster>), donde ambos argumentos son
obligatorios ya que el número de cluster está prefijado:

> 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

El problema lo hemos encontrado con el cordero que se ha unido al cluster 2 y en el


análisis jerárquico se había unido al cluster 1. Como siguiente paso en nuestro ejemplo
vamos a buscar una regla de funcionamiento para la agrupación de observaciones y esto
lo hacemos sumarizando el objeto cluster11.2b que creamos con anterioridad:

> 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"...

Capitulo 12: Introducción al análisis de la varianza.


Este capítulo quizá debía haber sido el siguiente a los capítulos dedicados a la
modelización pero por ser muy extenso lo he ido dejando porque me parecía interesante
manejar matrices (Capítulo 9: Componentes principales) y manejar paquetes y análisis
gráficos de mayor nivel (Capítulos 10 y 11). El análisis de la varianza nos es
imprescindible para posteriormente desarrollar los capítulos dedicados al muestreo y
métodos de remuestreo que pretendo que sean los capítulos estrella de este pequeño
curso que voy contruyendo en mis ratos libres.

Comencemos estableciendo conceptos. Lo primero que hacemos es plantear una


hipótesis que va a motivar un experimento, elegimos el diseño para nuestro experimento
y recogemos los datos y los analizamos mediante el análisis de la varianza que
consiste en descomponer la variabilidad total de los datos en sumandos cada uno de
ellos asignable a una fuente de variación; posteriormente ya sacamos conclusiones. Lo
que voy a contar viene recogido en los libros:

*MONTGOMERY, D.C.: Diseño y Análisis de Experimentos. Grupo Editorial


Iberoamérica, 1991.

*PEÑA, D.: Estadística: Modelos y Métodos, vol. II: Modelos Lineales y Series
Temporales, Alianza Universidad Textos, 1992

En concreto "el montgomery" es el lbro que seguí en mi etapa de estudiante de


estadística y es el que empleo para hacer estas líneas.

Conceptos y definiciones:

Variable repuesta: Variable cuantitativa sobre la que realizamos el estudio asociada al


experimento.

Factor: Condiciones que se manipulan en un experimento que afectan a la variable


respuesta.

Nivel de un factor: Maneras de presentarse un factor

Tratamientos: Condiciones bajo las cuales se realiza el experimento, son


convinaciones de factores.

Unidades experimentales: Sujetos sometidos a los tratamientos sobre los que se mide
la variable respuesta.

Réplica: observación adicional de un mismo tratamiento.

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:

• Diseño completamente aleatorizado.


• Diseño por bloques aleatorizados completos.
• Diseño de cuadrados latinos.

Estructuras de tratamiento:

• Diseño unifactorial.
• Diseño bifactorial.
• Diseño n factorial.
• Diseño 2^n.
• diseño anidado.

Comenzamos con el diseño más básico de todos:

Diseño unifactorial completamente aleatorizado:

Partimos de unidades experimentales homogéneas y queremos estudiar la influencia de


un solo factor midiendo la variable respuesta. La tabla del análisis de la varianza
(ANOVA) es:

Sumas de Grados de Cuadrados


Fuente de variación Test F
cuadrados Libertad Medios
Factor grupos
SCTr a-1 CMTr=SCTr/a-1 U=CMTr/CME
tratamientos(BETWEEN)
Error(WITHIN) SCE N-a CME=SCE/N-a
Total SCT N-1

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.

Como siempre veamos como trabajar con R mediante un ejemplo:

Ejemplo 12.1:

En un tratamiento contra la hipertensión se seleccionaron 40 enfermos de características


similares. A cada enfermo se le administró uno de los fármacos P, A, B, AB, al azar,
formando 4 grupos. El grupo P tomó placebo (fármaco inocuo), el grupo A tomó un
fármaco "A", el grupo B un fármaco "B" y el grupo AB una asociación entre "A" y "B".
Para valorar la eficacia de los tratamientos, se registró el descenso de la presión
diastólica desde el estado basal (inicio del tratamiento) hasta el estado al cabo de una
semana de tratamiento. Los resultados, después de registrarse algunos abandonos,
fueron los siguientes:
P: 10, 0, 15, -20, 0, 15, -5
A: 20, 25, 33, 25, 30, 18, 27, 0, 35, 20
B: 15, 10, 25, 30, 15, 35, 25, 22, 11, 25
AB: 10, 5, -5, 15, 20, 20, 0, 10

¿Tenemos diferencias entre los tratamientos?

Introducimos los datos:

> presion<-c(10, 0, 15, -20, 0, 15, -5


+ ,20, 25, 33, 25, 30, 18, 27, 0, 35, 20
+ ,15, 10, 25, 30, 15, 35, 25, 22, 11, 25,
+ 10, 5, -5, 15, 20, 20, 0, 10 )
> grupos<-c("P","P","P","P","P","P","P","A","A","A","A","A","A","A","A","A","A",
+
"B","B","B","B","B","B","B","B","B","B","AB","AB","AB","AB","AB","AB","AB","AB")
> grupos<-factor(grupos)
> grupos
[1] P P P P P P P P A A A A A A A A A A B B B B B B B
[26] B B B AB AB AB AB AB AB AB AB
Levels: A AB B P

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

Ya tenemos las diferencias, ahora necesitamos compararlas con la diferencia mínima


que se considera significativa, para esto contamos con la distribución q de recorrido
estudentizado, que se determina en R con: qtukey(p, nmeans, df), donde p es la
probabilidad (alfa), nmeans es el número de niveles y df los grados de libertad que serán
N-a como en el error. Al valor de esta distribución hay que multiplicarle la raiz
cuadrada de la división de la estimación de la varianza (CME=SCE/N-a ) por el número de
tratamientos, esto es por la forma en que creamos la diferencia de medias. En caso de
tener un diseño balanceado dividimos por el mínimo de tratamientos como es nuestro
caso. Todo esto traducido a R:

> (qtukey(0.05,4,31))*sqrt(97.45/7)
[1] 2.819698

Este es el valor referencia, valores absolutos por encima de éste ya consideramos


diferencias significativas. De nuevo repetir como se halla este número:
qtukey(0.05,4,31) calcula el valor de la distribución q de Tukey para 0.05 ya que
estamos con una confianza del 95%, 4 niveles y 31 grados de libertad; sqrt(97.45/7)
97.5 es la estimación de la varianza (el cuadrado medio del error) que se encuentra en la
tabla ANOVA y 7 el mínimo número de tratamientos que son los pacientes que tomaron
placebo. El valor de de 2.82 luego sólo la diferencia entre A y B se puede considerar
que no es significativa, no hay diferencias entre los pacientes que tomaban A o B, sin
embargo si hay diferencias entre todos los demás.

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.

También podría gustarte