Documente Academic
Documente Profesional
Documente Cultură
5-
Análisis de datos con R aplicado a la
-0
economía, la empresa y la industria
19
Emilio López Cano – con contribuciones de: Javier M. Moguerza, Miguel
Ángel Tarancón Morán, Matías Gámez Martínez
20
2019-05-07
or
ad
rr
Bo
2
Bo
rr
ad
or
20
19
-0
5-
07
Índice general
07
Prefacio 7
Agradecimientos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
5-
I Análisis de datos básico 11
-0
1. Introducción al análisis de datos con R 13
1.1. R y su ecosistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
19
1.2. Componentes de R y RStudio . . . . .
1.3. Estructuras de datos y su tratamiento
1.4. Importación y exportación de datos . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
19
37
53
20
1.5. Informes reproducibles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
1.6. Programación básica en R . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
1.7. Prácticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
or
3
4 ÍNDICE GENERAL
07
5.2. Cálculo de distancias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
5.3. Métodos jerárquicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
5.4. Métodos no jerárquicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
5-
5.5. Caracterización de grupos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
5.6. Más análisis cluster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
-0
5.7. Prácticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331
19
6.1. Introducción al análisis de correspondencias . . . . . . . . . . . . . . . . .
6.2. Asociación entre atributos . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.3. Análisis de correspondencias simples . . . . . . . . . . . . . . . . . . . . .
.
.
.
377
378
381
20
6.4. Análisis de correspondencias múltiple . . . . . . . . . . . . . . . . . . . . . . 397
6.5. Prácticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
Práctica 6.1: Ejemplo de color de ojos y pelo . . . . . . . . . . . . . . . . . . . . . 407
Práctica 6.2: Análisis de correspondencias simple con los datos de la encuesta . . . 411
or
07
A. Símbolos 425
A.1. Letras griegas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
A.2. Símbolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
5-
B. Créditos 427
-0
19
20
or
ad
rr
Bo
6
Bo
rr
ad
or
20
19
-0
5-
07
ÍNDICE GENERAL
Prefacio
07
Este libro es el resultado de la experiencia del autor con el software estadístico y lenguaje
de programación R en los ámbitos de la docencia, la investigación y la transferencia. Trata
5-
de compilar los distintos materiales que se han ido utilizando en publicaciones, cursos en
empresas y docencia oficial. Un poco por poner orden en el caos de materiales dispersos
que se van acumulando en el propio proceso de (auto-)aprendizaje-enseñanza. También me
-0
mueve el hecho de que, si bien hay mucho material sobre R en inglés, no hay obras en español
que traten el análisis de datos con R en una extensión amplia.
19
Los primeros capítulos son muy introductorios, casi divulgativos. A medida que avance el
libro, se tratarán temas más complejos tanto desde el punto de vista de los métodos estadís-
ticos como desde el punto de vista del uso y programación de R. En todo caso, el espíritu de
20
esta obra es eminentemente práctico, por lo que profundidad matemático-teórica se limitará
en la mayoría de los casos a lo mínimo imprescindible para aplicar los métodos con cier-
ta solvencia, proporcionando referencias donde corresponda pare consultar los fundamentos
teóricos, detalles y demostraciones.
or
Los contenidos de este libro se basan en dos paradigmas que están presentes en los intereses
de investigación y docencia del autor: los estándares y el software libre. En lo que se
refiere a estándares, la notación utilizada, definiciones y fórmulas se ajustarán el máximo
ad
y gratuito con el que se realizan todos los análisis. El primer capítulo del libro está dedicado
a su aprendizaje y comprensión.
Bo
Las normas son clave para el desarrollo económico de un país. Estudios en diversos países,
incluido España, han demostrado que la aportación de la normalización a su economía es del
1 % del PIB2 . La Asociación Española de Normalización (UNE) es el organismo legalmente
responsable del desarrollo y difusión de las normas técnicas en España. Además, representa
a España en los organismos internacionales de normalización como ISO3 y CEN4 .
Las normas sobre estadística que surgen de ISO las elabora el Technical Committee ISO TC
1
http://www.r-project.org
2
http://www.aenor.es/DescargasWeb/normas/como-beneficia-es.pdf
3
https://www.iso.org/
4
https://www.cen.eu/
7
8 ÍNDICE GENERAL
695 Statistical Methods. Por su parte, el subcomité técnico de normalización CTN 66/SC 36 ,
Métodos Estadísticos, participa como miembro nacional en ese comité ISO. Las normas que
son de interés en España, se ratifican en inglés o se traducen al español como normas UNE.
Para una descripción más completa de la elaboración de normas, véase Cano et al. (2015).
07
sessionInfo()
5-
## Running under: macOS Mojave 10.14.4
##
-0
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib
##
##
##
locale: 19
[1] es_ES.UTF-8/es_ES.UTF-8/es_ES.UTF-8/C/es_ES.UTF-8/es_ES.UTF-8
20
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
or
Normalmente, antes del código de ejemplo se incluye un bloque con el siguiente aspecto
rr
explicando el ejemplo:
Bo
5
http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_tc_browse.htm?commid=49742
6
http://www.aenor.es/aenor/normas/ctn/fichactn.asp?codigonorm=AEN/CTN%2066/SC%203
ÍNDICE GENERAL 9
Estos bloques están pensados para incluir información curiosa o complementaria para
poner en contexto las explicaciones.
El material se proporciona bajo licencia CC-BY-ND-NC. Todos los logotipos y marcas co-
merciales que puedan aparecer en este texto son propiedad de sus respectivos dueños y se
incluyen en este texto únicamente con fines didácticos. Se ha puesto especial cuidado en la
adecuada atribución del material no elaborado por el autor, véase el Apéndice B. Aún así,
si detecta algún uso indebido de material protegido póngase en contacto con el autor y será
07
retirado.
Sobre el autor: http://blog.uclm.es/emiliolcano
5-
-0
Análisis de datos con R aplicado a la economía, la empresa y la industria de Emilio López
Cano está licenciado bajo Creative Commons Attribution-NonCommercial-ShareAlike 4.0
International License.
Agradecimientos
19
20
Aunque gran parte del material lo he elaborado con anterioridad con diversos propósitos, la
decisión de abordar este nuevo formato la ha provocado la preparación del primer seminario
de análisis de datos con R organizado en la Facultad de Derecho y Ciencias Sociales de la
or
y en especial a Miguel Ángel Tarancón Morán, María Jesús Ruiz Fuensanta y Juan José
Rubio por su confianza.
Agradezco también a Víctor Casero Alonso, compañero y amigo del departamento de Ma-
rr
Bo
rr
ad
or
20
19
-0
5-
07
ÍNDICE GENERAL
07
5-
Parte I
-0
19
Análisis de datos básico
20
or
ad
rr
Bo
11
Bo
rr
ad
or
20
19
-0
5-
07
Capítulo 1
07
Introducción al análisis de datos con
R
5-
-0
1.1. R y su ecosistema
1.1.1. Introducción 19
20
El análisis estadístico de datos es una tarea fundamental en la economía aplicada. Siempre
lo ha sido, pero en la actualidad la disponibilidad de datos, la cantidad de los mismos, y
la velocidad con la que se requieren resultados, está haciendo necesario el capacitar a los
investigadores y profesionales para el análisis de datos avanzado con nuevas herramientas.
Nuevas tendencias (muchas veces malinterpretadas) como Big Data, Industria 4.0, Internet
or
of Things (IoT), o Data Science, aumentan el interés por parte de las empresas, los profesio-
nales y los investigadores en estas técnicas. El análisis estadístico de datos requiere el uso
ad
de software avanzado. Aunque algunas tareas se pueden realizar eficazmente con programas
de hoja de cálculo como Excel1 , se debería utilizar software especializado para el análisis de
datos. Existen distintos paquetes estadísticos comerciales, como SPSS, Statgraphics, Stata
(muy popular en el análisis económico), o Minitab (líder en análisis de datos para metodolo-
rr
gías de calidad). En los últimos años se ha abierto camino el software estadístico y lenguaje
de programación R2 (R Core Team, 2019). R es software libre, pero su gratuidad solo es
Bo
una de sus ventajas3 , como se verá a lo largo del libro. El gran inconveniente es la curva de
aprendizaje: no es tan fácil de aprender y usar como un software de ventanas, ya que el uso
de R se basa en expresiones que hay que ejecutar desde scripts. No obstante, una vez que se
tienen las nociones básicas es fácil ir aplicando nuevos métodos.
En este capítulo nos centraremos en los primeros pasos para empezar a utilizar R, y en
perderle el miedo a una aplicación con la cual no se interactúa mediante ventanitas y menús,
sino mediante una consola y scripts de código.
1
Por ejemplo, son una buena herramienta para mecanizar y almacenar datos.
2
http://www.r-project.org
3
R is FOSS (Free and Open Source Software). Free as in free beer, and free as in free speech.
13
14 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
En el análisis económico, empresarial o industrial, siempre o casi siempre tenemos que tra-
bajar con datos. Tras leer este capítulo, el lector será capaz de crear, acceder y modificar
datos con R, y realizar un tratamiento básico con ellos. Esto sentará las bases para una pos-
terior profundización en el uso de R para usos específicos, tales como estimación, predicción,
visualización, etc.
Respecto a los datos, veremos en este capítulo cómo crear estructuras de datos desde R.
También trabajaremos con ficheros de datos de ejemplo. La estructura y formato de estos
ficheros tiene una importancia crucial al trabajar con R o con cualquier software de análisis
de datos.
07
En resumen, R es una de las alternativas4 al software comercial para el análisis de datos. R
es:
5-
Un sistema para computación estadística: software de análisis de datos, gráficos
y lenguaje de programación
-0
Ampliamente utilizado en investigación y docencia, grandes empresas lo usan: Google,
Pfizer, …
19
La evolución del trabajo de los laboratorios Bell con el lenguaje S (Venables and Ripley,
2002), llevado al mundo del software libre por Ross Ihaka y Robert Gentleman.
La web del proyecto R (http://www.r-project.org/, véase la figura 1.1), aunque austera,
20
contiene una gran cantidad de recursos para el uso de R. El apartado de documentación
y la revista de R (The R Journal) contienen gran cantidad de documentos generales y
específicos para ciertas tareas. Los recursos oficiales se encuentran en el repositorio CRAN
(The Comprehensive R Archive Network, véase la figura 1.2). Aquí es donde se descarga la
or
librería del sistema, con los paquetes base, y una librería de usuario, con los paquetes que
se van instalando. Las librerías por defecto5 se encuentran en la carpeta de usuario, en el
directorio R.
Para poner un poco de orden en esta ingente cantidad de recursos, tenemos las task views
(véase la figura 1.3), que son una especie de recopilaciones de recursos sobre un tema concreto6 .
4
Hay otras alternativas, pero en la mayoría de los casos, o son parciales referidas a un ámbito concreto,
o son más lenguajes de programación que software estadístico, como Python.
5
R crea una para cada versión intermedia de R, por ejemplo, para R.4.x y R.5.x
6
Según CRAN “provide some guidance which packages on CRAN are relevant for tasks related to a certain
topic.”
1.1. R Y SU ECOSISTEMA 15
07
5-
-0
19
Figura 1.1: Captura de pantalla de la web del proyecto R: http://www.r-project.org
20
or
ad
rr
Bo
07
5-
-0
19
Figura 1.3: Captura de pantalla de las tasks views en CRAN
Por ejemplo, si vamos a la task view Econometrics (figura 1.4), encontramos recursos
20
agrupados por subtemas (series temporales, modelos de panel, etc.) relacionados con los
métodos cuantitativos para la economía: libros, paquetes, funciones, bases de datos, enlaces,
etc.
CRAN no es el único repositorio de paquetes de R. Los siguientes son algunos de los más
or
importantes7 :
Bioconductor: (http://www.bioconductor.org/packages/).
ad
Github: (https://github.com/trending/r).
R-Forge: (https://r-forge.r-project.org/).
Omegahat: (http://www.omegahat.net/).
rr
metría, etc. Para poder publicar una librería en estos repositorios oficiales los autores deben
seguir unas reglas estrictas en cuanto a programación y documentación, por lo que estos
paquetes cumplen unos estándares mínimos de calidad. Algunos autores no publican los pa-
quetes en los repositorios oficiales, sino que los hacen públicos en sus propias webs o en
repositorios genéricos. Uno de los más prolíficos es github9 , con la ventaja de que se pue-
den instalar directamente en R gracias al paquete devtools. Además, es habitual que los
autores suban a github las versiones en desarrollo de los paquetes, aunque aún no los hayan
7
Para el alcance de este libro trabajaremos solo con CRAN, el lector puede visitar los enlaces a los
repositorios para aprender más.
8
http://www.bioconductor.org
9
http://www.github.com
1.1. R Y SU ECOSISTEMA 17
07
5-
-0
19
Figura 1.4: Captura de pantalla de la task view de econometría
publicado en CRAN.
20
1.1.3. Comunidad
El mundo del software libre genera recelos en las empresas (algunas veces con motivos funda-
or
dos). La primera pregunta es ¿quién mantiene todo esto? Los principales pilares que sustentan
el proyecto R son los siguientes:
ad
R Foundation.
R Core Team.
R Contributors.
Institute for Statistics and Mathematics of WU (Wirtschaftsuniversität Wien, Vienna
rr
07
5-
-0
19
Figura 1.5: Captura de pantalla de la web de la comunidad R Hispano: http://r-es.org/
R. Una simple búsqueda en Internet sobre algún tema concreto de análisis de datos añadien-
20
do “R” a la búsqueda, nos proporcionará provechosos enlaces. De especial interés son los
siguientes:
Documentación.
or
Listas de correo.
Stackoverflow.
ad
The R Journal.
R Pubs.
rr
Es gratis. En inglés se suele decir free as in free beer, and free as in free speech.
Amplia comunidad de usuarios que proporciona recursos.
Es multiplataforma.
Se usa cada vez en más empresas e instituciones.
Es posible obtener soporte comercial (TIBCO, R Studio, …).
Se ha alcanzado una masa crítica de usuarios que lo hace confiable.
07
Es extensible (desde pequeñas funciones, hasta paquetes).
Se puede implementar la innovación inmediatamente. En software comercial hay que
esperar a nuevas versiones, en el mejor de los casos.
5-
Posee características de Investigación reproducible. Veremos más adelante qué implica
este enfoque.
-0
Una característica que hace R universal es el hecho de que cada usuario puede decidir hasta
dónde quiere llegar. Las funciones de R están diseñadas para que, con muy poco esfuerzo,
19
se consigan resultados básicos. A partir de ahí, a medida que necesitamos más complejidad,
podemos añadir opciones, por medio de argumentos a las funciones, uso de otras funciones,
etc. Se puede llegar a resultados muy elaborados, como libros, aplicaciones web, widgets, etc.
20
Como nada es perfecto, R también tiene sus inconvenientes. El más importante es la llamada
curva de aprendizaje. Como muestra la figura 1.6, cuesta mucho aprender a utilizar R al
principio, especialmente para analistas que no están acostumbrados a programar o a utilizar
software que se basen en el uso de scripts, como por ejemplo MATLAB. Pero una vez se
or
aprenden los principios básicos, la productividad aumenta. Aunque parezca que no se avanza
porque se le dedica más tiempo, en realidad lo que está pasando es que cada vez se quieren
hacer cosas más elaboradas. Llega un momento en que se aprende muy rápido hasta que
ad
datos en memoria y no en disco, lo que a priori dificulta trabajar con grandes cantidades de
datos, han sido superados con las últimas versiones y paquetes especializados.
Bo
Soy un experto
Conocimiento de R
Sé un montón
Sé algo
No sé nada
07
0 5 10 15
Tiempo
5-
Figura 1.6: La curva de aprendizaje de R. La escala de tiempo dependerá de cada usuario.
-0
Una expresión lógica.
Una llamada a una función12 .
Una asignación.
19
20
Si la expresión está incompleta, el intérprete de R queda a la espera hasta que la expresión
se complete. Si la expresión está completa, el intérprete la evalúa, produciendo un resultado.
Este resultado puede mostrar algunas salidas al usuario, que puede ser texto o gráficos.
Algunas expresiones no producen ninguna salida visible, y su resultado puede ser, entre
or
pacio de trabajo. Veremos más adelante estos detalles. Pero aunque R trabaje con los datos
en memoria, necesitaremos usar archivos en disco de diversas formas, principalmente para
importar datos y escribir código. Los ficheros estarán siempre referenciados al directorio
de trabajo.
rr
1.2.2. Componentes
Bo
07
5-
Figura 1.7: Interfaz de usuario de R por defecto para Windows
-0
El espacio de trabajo.
El directorio de trabajo.
19
La figura 1.7 muestra el interfaz gráfico de usuario (GUI) por defecto de R. Podemos ver la
consola, la salida gráfica y el editor de código, pero el resto de los componentes mencionados
20
no están visibles.
1.2.3. RStudio
or
El interfaz de usuario de R (R GUI, Graphical User Interface) cumple las funciones bási-
cas para interactuar con R, pero es muy pobre a la hora de trabajar con él. En su lugar,
utilizaremos el interfaz de usuario RStudio13 , que es como un envoltorio del sistema R con
ad
las cuales esta compañía ofrece soporte y otros servicios. La ventana del programa RStudio
se divide en cuatro partes o paneles (panes), véase la figura 1.8:
Bo
07
5-
-0
19
Figura 1.8: interfaz de usuario de RStudio
20
encuentra el espacio de trabajo de la sesión actual, y el historial. Las versiones más
recientes incluyen también pestañas para conectar con bases de datos y otras tareas
avanzadas.
or
• La salida gráfica de R.
• Los paquetes disponibles.
rr
• La ayuda.
• Un visualizador de aplicaciones y documentos web.
Bo
Esta es la distribución por defecto, se puede cambiar la disposición de los distintos paneles
de RStudio en la configuración global mediante el menú Tools/Global Options.
Existen otros interfaces para usar R, tanto del tipo de RStudio, es decir, entornos de desa-
rrollo (IDE, Integrated development Environment) como interfaces gráficos de usuario (GUI).
Estas otras opciones quedan fuera del alcance de este libro, pero se recomienda probarlos
para elegir el que mejor se adapte a las necesidades de cada uno. Algunos de estos interfaces
son:
Con menús y ventanas:
• Rcommander: http://www.rcommander.com/
1.2. COMPONENTES DE R Y RSTUDIO 23
• Deducer: http://www.deducer.org
• RKWard: https://rkward.kde.org/
De desarrollo
• Eclipse + statET: http://www.walware.de/goto/statet
• Microsoft Visual Studio: https://www.visualstudio.com/vs/rtvs/
• EMACS: https://ess.r-project.org/
El enfoque de este libro es el de utilizar entornos de desarrollo como RStudio. En opinión
del autor, el analista debe tener control total sobre todo el proceso de análisis de datos, y el
enfoque IDE es el más adecuado. Para usuarios no cualificados que sólo necesiten interpretar
07
resultados, se pueden desarrollar interfaces a medida de forma relativamente fácil con Shiny14
o RStudio Addins15 . El uso de menús y ventanas al estilo tradicional del software estadístico
es un punto intermedio que por una parte no evita tener que formar al usuario, pero por
5-
otra el usuario no sabrá lo que está haciendo realmente. No obstante en algunos entornos de
investigación o docencia puede ser adecuado utilizarlos.
-0
Realice la práctica 1.1 cuyo guión se encuentra en el apartado 1.7 para instalar R y
RStudio.
La sesión de R
19
20
Cuando abrimos R (directamente o con RStudio), iniciamos una Sesión de R. La sesión de
R se inicia en un directorio de trabajo (working directory). Las expresiones introducidas
en la consola se van guardando en el Historial, véase la figura 1.9. Se puede acceder al
historial desde la consola simplemente utilizando las flechas arriba y abajo del teclado. En
or
RStudio, además, podemos ver todo el historial en la pestaña History del panel superior
derecho, y realizar otras operaciones como buscar, limpiar, guardar, abrir, o pasar líneas a la
consola o al editor de código. Por defecto, RStudio guarda siempre el historial de la sesión en
ad
La consola de R
Bo
07
5-
-0
Figura 1.9: El historial de R en RStudio
CTRL + ESPACIO dentro de una función muestra los argumentos posibles y su signifi-
cado como un mensaje emergente al movernos a través de ellos.
ad
CTRL + ESPACIO dentro de comillas muestra los ficheros del directorio de trabajo.
La tecla ESC cancela la expresión actual.
rr
La combinación CTRL + ESPACIO y el TAB permite también insertar snippets, que son
una especie de plantillas de fragmentos de código para tareas repetitivas, como crear bucles
o condiciones.
En la consola podemos introducir expresiones que son evaluadas una a una. Una expresión
de R puede ser una llamada a una función, de hecho es la expresión que más utilizamos.
La llamada a una función es siempre igual: el nombre de la función más (obligatoriamente)
paréntesis de apertura y cierre, y, dentro de los paréntesis, los argumentos de la función
separados por comas. Los argumentos de las funciones se pueden declarar de varias formas:
Por el orden en el que están definidos en la propia función.
1.2. COMPONENTES DE R Y RSTUDIO 25
07
5-
-0
Figura 1.10: La Consola de R en RStudio
19
Por el nombre con el que están definidos en la propia función. R tiene una caracte-
rística llamada partial matching que permite escribir sólo los primeros caracteres del
20
nombre.
La función mean calcula la media del vector de números y acepta un argumento na.rm
rr
el mismo resultado, aunque la especificación de los argumentos sea distinta. Vea la ayuda de
la función mean y averigüe por qué.
set.seed(1)
unvector <- rnorm(10)
mean(unvector)
mean(x = unvector)
mean(x = unvector, na.rm = FALSE)
mean(na.rm = FALSE, x = unvector)
mean(unvector, na.rm = FALSE)
mean(unvector, na = FALSE)
26 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
07
5-
-0
Figura 1.11: El entorno de trabajo (workspace) en RStudio
El espacio de trabajo de R
19
Una de las características de R es que todos los datos con los que trabaja se encuentran en
memoria. Cuando hay grandes volúmenes de datos (realmente grandes) es necesario utilizar
20
tecnologías Big Data, como por ejemplo Spark 17 , que este libro no cubre. No obstante, la
mayoría de los problemas de análisis de datos a los que nos enfrentamos en el día a día no
son realmente Big Data.
Los objetos que creemos con R se guardan en el espacio de trabajo (workspace), véase la
or
figura 1.11. Para crear un objeto en el espacio de trabajo utilizamos el operador de asignación
<-. Nótese que es como una flecha hacia la izquierda, con la que asignamos al símbolo que
ad
pestaña Environment en el panel superior derecho desde donde también es posible importar
un fichero de datos19 mediante el cuadro de diálogo Import Dataset.
Bo
En la barra superior del espacio de trabajo tenemos iconos para guardar, abrir y limpiar
el espacio de trabajo. Los espacios de trabajo se guardan con extensión .RData. También
se pueden utilizar las funciones save.image, save y load para guardar todo el espacio de
trabajo, algunos objetos del espacio de trabajo, o recuperar un espacio de trabajo respecti-
vamente. Podemos mostrar los objetos que hay en el espacio de trabajo con la función ls,
eliminarlos con la función rm, o ver su estructura con la función str.
17
https://spark.apache.org/
18
Se puede utilizar el símbolo = en R para la asignación. Algunos usuarios prefieren utilizar este símbolo,
pero en este texto utilizamos el símbolo específico de R <-.
19
Formatos CSV, Excel, Stata, SPSS, SAS.
1.2. COMPONENTES DE R Y RSTUDIO 27
07
5-
-0
Figura 1.12: Salida gráfica de RStudio
La salida gráfica
19
Cuando el resultado de una expresión de R es una salida gráfica, se muestra en la pestaña
Plots del panel inferior derecho, véase la figura 1.12. Desde este pastaña se pueden exportar los
20
gráficos en varios formatos (pdf, imagen, portapapeles) eligiendo opciones como la resolución.
Los gráficos se van guardando en un histórico por el que se puede navegar y limpiar. También
podemos sacar el gráfico a otra ventana con el icono zoom.
or
La ayuda
ad
Ya hemos visto una de las formas de obtener ayuda contextual con RStudio, a través del
atajo CTRL + ESPACIO dentro de una función. De esta forma podemos ver la descripción
de la función y el significado de los argumentos que acepta. Para ver la documentación
rr
completa de la función podemos pulsar la tecla F1 con el cursor situado sobre el nombre de
una función o cualquier otro objeto de R que tenga documentación, por ejemplo un conjunto
Bo
de datos. La documentación se abre en la pestaña Help del panel inferior derecho (véase la
figura 1.13). Podemos ir directamente a este panel con el atajo CTRL + 3. En esta pestaña,
tenemos opciones para buscar dentro de la documentación abierta, o buscar documentación
de otros temas, además de poder imprimir y navegar por la documentación. Un tipo de
documento especial son las llamadas Vignettes, que pueden incluir ejemplos y explicaciones
más extensas, incluidos gráficos. También podemos buscar ayuda interactivamente con las
funciones apropos, help, vignette, example y demo.
Realice la práctica 1.2 cuyo guión se encuentra en el apartado 1.7 para interactuar
con la consola de R en RStudio.
28 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
07
5-
-0
Figura 1.13: Ayuda de RStudio
Paquetes
19
La funcionalidad de R se organiza en librerías que contienen paquetes (packages). R puede
tener varias librerías y dentro de estas librerías se instalan los paquetes, que después se
20
pueden cargar. Al abrir R, los paquetes base se cargan automáticamente y están disponibles.
Para utilizar funciones de otros paquetes es necesario cargar antes el paquete en la sesión.
Los paquetes se cargan con la función library20 con el nombre del paquete como argumento,
no son necesarias comillas.
or
El paquete nortest (Gross and Ligges, 2015) sirve para realizar contrastes de nor-
malidad sobre conjuntos de datos. Contiene una función llamada ad.test para realizar el
ad
set.seed(1)
x <- rpois(50, 4)
Bo
library(nortest)
ad.test(x)
##
## Anderson-Darling normality test
##
## data: x
## A = 0.77845, p-value = 0.04038
20
La función require también se utiliza para cargar paquetes, aunque su comportamiento es ligeramente
diferente y más adecuado para utilizar dentro de otras funciones, véase la ayuda ?require.
1.2. COMPONENTES DE R Y RSTUDIO 29
07
5-
-0
Figura 1.14: Gestión de paquetes en RStudio
19
Nötese que el paquete debe estar instalado previamente como se explica más abajo.
Una alternativa a cargar el paquete con la función library sería llamar a la función
20
con la sintaxis paquete::funcion(). Esto es útil en muchas ocasiones, por ejemplo si solo
necesitamos llamar a la función una vez y no necesitaremos más funciones del paquete.
Además, sirve para asegurarnos de que la función corresponde al paquete que queremos usar,
ya que podría haber una función con el mismo nombre en otro paquete cargado que haga
or
nortest::ad.test(x)
ad
##
## Anderson-Darling normality test
rr
##
## data: x
## A = 0.77845, p-value = 0.04038
Bo
Por otra parte, para poder cargar un paquete tiene que estar instalado en el sistema. Podemos
realizar estas opciones con el interfaz gráfico de RStudio que tenemos en la pestaña Packages
del panel inferior derecho como se refleja en la figura 1.14. La instalación, actualización y
eliminación de paquetes es más cómoda desde RStudio, aunque también se puede hacer in-
teractivamente con las funciones intsall.packages, update.packages y remove.packages
respectivamente. Sin embargo, para cargar paquetes, una vez establecemos la rutina, lo nor-
mal es cargarlas al principio del script mediante la función library, o bien justo antes de
utilizar funciones del paquete. En resumen, para utilizar una función de un paquete, este
tiene que estar cargado, y para cargar el paquete, tiene que estar instalado. La instalación
solo hay que realizarla una vez, pero es necesario cargar el paquete en cada sesión de R.
30 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
El directorio de trabajo
Una sesión de R tiene asignado un directorio de trabajo para aquellas tareas relacionadas
con ficheros en disco. Por ejemplo, para trabajar con datos, trabajar con código, o exportar
gráficos. Cuando en alguna expresión de R intervienen ficheros, se puede proporcionar la
ubicación del fichero de dos formas distintas:
Mediante la ruta absoluta. Es decir, la ubicación en el disco duro del ordenador con la
ruta completa.
Mediante la ruta relativa. Es decir, la ubicación en el disco duro del ordenador a partir
07
del directorio de trabajo.
Una ayuda importante con RStudio es que podemos acceder a los ficheros y carpetas del
5-
directorio de trabajo desde la consola o desde el editor de código pulsando la combinación
de teclas CTRL + ESPACIO estando el cursor dentro de comillas.
-0
IMPORTANTE: En R, el carácter \ no se puede utilizar tal cual. Por lo tanto, para indicar
las rutas de ficheros en Windows, tenemos que utilizar la barra normal (/), o bien poner doble
barra invertida (\\) para separar directorios. Esto es importante cuando copiamos y pegamos
19
una ruta del explorador de archivos de Windows.
## Correcto:
setwd("C:/micodigo")
setwd("C:\\micodigo")
ad
## Incorrecto:
setwd("C:\micodigo")
rr
Además, en la pestaña Files del panel inferior derecho (véase la figura 1.15) disponemos de un
explorador de archivos que podemos vincular al directorio de trabajo mediante la flecha en la
Bo
barra de título de la consola. La operación inversa también es posible: buscamos una carpeta
mediante el icono ... arriba a la derecha, y a continuación seleccionamos Set as working
directory en el icono More. Otras opciones son crear carpetas, copiar, mover, cambiar nombre,
o abrir la carpeta con el explorador de archivos en una nueva ventana. Por último, también es
posible establecer como directorio de trabajo el que contiene un script abierto en el editor de
código, mediante el menú Session. En las opciones globales de RStudio se puede configurar el
directorio de trabajo al abrir la aplicación, por defecto “Mis Documentos”, que se representa
con el símbolo21 ~. Aunque el interfaz de usuario es útil para trabajar con ficheros y con
21
Este símbolo se obtiene en el teclado con la combinación de teclas Alt Gr + 4. Es posible que tenga
que pulsar la barra espaciadora después de la combinación de teclas.
1.2. COMPONENTES DE R Y RSTUDIO 31
07
5-
-0
Figura 1.15: Explorador de ficheros de RStudio
El editor de RStudio
ad
es un fichero de texto con expresiones de R. Trabajar con scripts permite, entre otras cosas,
reutilizar código, automatizar tareas de análisis de datos, o registrar los análisis realizados.
Un script de R es “texto plano” y por tanto se puede utilizar cualquier editor de texto para
Bo
crearlos o verlos. El GUI de R incluye un editor de código simple desde el que se pueden
crear scripts. No obstante, el editor de código de RStudio (véase la figura 1.16) proporciona
mucha más funcionalidad. Por ejemplo, dispone de sintaxis coloreada, es decir, los distintintos
elementos de una expresión (números, cadenas de texto, nombres de funciones, …) aparecen
en distintos colores22 . Además, todas las ayudas explicadas anterioremente para la consola,
funcionan en el editor de RStudio (TAB o CTRL + ESPACIO). El atajo de teclado CTRL +
1 sitúa el cursor en el editor de RStudio. Otras características útiles son la búsqueda, la
posibilidad de crear secciones y visualizar un índice (outline) o de “desacoplar” ventanas del
panel para trabajar más cómodamene.
22
En las opciones de RStudio se puede elegir el tema.
32 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
07
5-
-0
Figura 1.16: Editor de código de RStudio
Los scripts de R tienen extensión .R. Para crear un script, utilizamos el menú File o el
19
icono justo debajo de este menú. Vemos que hay más tipos de archivos que se pueden crear
en el editor, pero de momento nos fijamos solo en el R Script. El código de un script se
puede ejecutar de diversas formas, aunque en definitiva se trata de enviar al intérprete, bien
20
expresión a expresión a través de la consola, bien como bloque a través de la función source.
Las expresiones pueden ocupar una o varias líneas. De hecho cuando las expresiones son
muy largas es preferible usar varias líneas para que se lean mejor. El editor de RStudio las
or
autoindenta. Se puede escribir más de una expresión en la misma línea si las separamos con
punto y coma (;). Se pueden incluir también comentarios en el código mediante el carácter
#. Lo importante es seguir un estilo consistente en cuanto a nombres de objetos, espacios en
ad
blanco y distribución del código en el script, véase por ejemplo la guía de estilo de Hadley
Wickam23 (Wickham, 2015).
Como se ha dicho anteriormente, existen diversas formas de ejecutar código de un script:
rr
Para ejecutar una línea del script que está abierto, situamos el cursor en cualquier
posición de la línea y pulsamos CTRL + INTRO o hacemos clic en el icono Run de la
Bo
07
Figura 1.17: Esquema de un script
5-
En el menú Code hay varias opciones y atajos de teclado para ejecutar porciones del
script, por ejemplo para ejecutar un script completo sin tener que seleccionar todas las
-0
líneas, podemos utilizar el atajo CTRL + S.
Para ejecutar un script completo desde el sistema operativo (sin abrir R ni RStudio),
operativo. 19
se utiliza la llamada al programa RScript desde la línea de comandos del sistema
Para moverse de forma ágil dentro de los scripts y de los informes se puede usar el índice (1)
20
que se va creando automáticamente o el selector de apartados (2), véase la figura 1.17. Las
entradas de índice se pueden crear con el menú Code/Insert section…, o bien directamente
escribiendo una línea de comentario que termine en cuatro o más guiones medios, por ejemplo:
or
# Apartado 1 ----
ad
Realice la práctica 1.3 cuyo guión se encuentra en el apartado 1.7 para trabajar con
scripts.
rr
principal ventaja de utilizar R Studio es el ahorro de tiempo para el analista, por lo que
si se está dedicando más tiempo a tareas sin valor como corregir errores, leer datos, haciendo
muchos clics con el ratón, etc. que a tareas que sí aportan valor como pensar en el problema
y su aplicación, es que las cosas se deberían hacer de otra forma. En los proyectos de análisis
de datos lo importante son los métodos y su comprensión, no la herramienta. En los primeros
días de uso de R uno de los principales obstáculos que surgen es la estructura y localización
de los ficheros. También se propone una estructura eficiente de ficheros, que obviamente se
debe adaptar al estilo de trabajo del analista y al propio proyecto, pero lo importante es
sobre todo que se puedan cargar los datos a la primera.
Trabajar con proyectos en R Studio tiene varias ventajas. Una de ellas es que, una vez que
34 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
07
5-
Figura 1.18: Inicio de RStudio sin abrir proyecto
-0
entendemos cómo funcionan los proyectos, no tenemos que preocuparnos del directorio de
trabajo. Cuando abrimos R Studio desde el icono del escritorio, pueden pasar dos cosas: que
19
se abra directamente un proyecto, o que se abra R Studio sin ningún proyecto. En este último
caso veríamos en la parte superior derecha “Project: (None)”, véase la figura 1.18.
En el triángulo de la derecha podemos abrir un menú para gestionar los proyectos. Para crear
20
un proyecto, hay que elegir una carpeta en la que se va a crear (del equipo o de una memoria
extraíble si se utiliza, por ejemplo, el ordenador de un aula de informática). Dentro de esa
carpeta, se va a crear otra con el nombre que se le pongas al proyecto, y dentro de esa nueva
carpeta se creará un archivo con el mismo nombre y extensión “.RProj”. Muy importante:
or
no se le debe cambiar el nombre a la carpeta una vez creado el proyecto ya que debe tener
el mismo nombre que el archivo .RProj24 . Por otra parte, se recomienda utilizar nombres de
proyecto (incluida su ruta de carpetas) que no contengan espacios ni caracteres no ASCII
ad
(por ejemplo acentos y eñes), ya que podrían provocar algún errore en algunas funciones de
importación de datos.
rr
Cuando tenemos un proyecto de RStudio abierto (figura 1.19) nuestro directorio de trabajo
aparece siempre en la barra de título de la consola (1), que se muestra por defecto en el panel
de archivos (2) por el que podemos desplazarnos arriba (3) por la ruta (4) o buscando una
Bo
carpeta (5). También entrando en las carpetas, una vez se hayan creado. Siempre podemos
volver a nuestro directorio de trabajo utilizando la flecha de la barra de título de la consola
(6).
Es importante organizar bien los ficheros de un proyecto de análisis de datos, especialmente
cuando el proyecto gana complejidad. Una estructura de carpetas comúnmente aceptada
como buenas prácticas en análisis de datos incluiría las siguientes carpetas:
datos: Aquí se guardan todos los ficheros de datos.
informes: Para los archivos que incluyan análisis, como ficheros .Rmd, R Markdown.
24
Y si se hace, cambiar también el nombre del archivo .Rproj para que sean iguales.
1.2. COMPONENTES DE R Y RSTUDIO 35
07
5-
-0
Figura 1.19: Poner nombre al proyecto
19
scripts: para los scripts, ficheros .R.
Estas tres carpetas serían lo mínimo que habría que tener para tener organizado el proyecto.
Otras carpetas útiles según la naturaleza del proyecto serían:
20
img: Para imágenes.
ref: Para referencias.
subcarpetas dentro de las anteriores.
or
Y en definitiva, cualesquiera que sean útiles para el proyecto. En general, se deben evitar
en los nombres de carpetas y ficheros caracteres no ASCII y espacios en blanco. Aunque el
ad
sistema operativo pueda trabajar con ellos, es posible que el software de análisis de datos dé
algún problema inesperado.
Las carpetas se crean desde el panel de ficheros de R Studio mediante el icono “New Folder”
rr
(figura 1.20).
El flujo de trabajo a partir de aquí será a través de un proyecto. Antes de empezar a trabajar,
Bo
hay que asegurarse de que estamos en el proyecto deseado. El proyecto cargado aparece en
la parte superior derecha como en la figura 1.21.
Si al abrir R Studio al retomar el trabajo no se abre el proyecto automáticamente, hay que
buscarlo con la opción “Open Project” de ese mismo menú, o directamente abrirlo haciendo
doble clic en el archivo del proyecto (extensión .RProject) dentro de la carpeta desde el
explorador de archivos del sistema operativo, figura 1.22.
Una vez está el proyecto abierto realizaremos tareas como:
1. Copiar ficheros de datos en la carpeta “datos”.
2. Crear scripts en la carpeta “scripts”. Importante: aunque estén en otra carpeta, el
36 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
07
5-
Figura 1.20: Crear nueva carpeta
-0
19
20
or
07
htmlwidgets: permite crear informes dinámicos, por ejemplo con mapas o tablas nave-
gables.
Aplicaciones shiny: para crear interfaces de usuario que funcionan en el navegador.
5-
Addins: para crear menús personalizables dentro de RStudio.
Se recomienda visitar el sitio web de RStudio para aprender más sobre cualquiera de estos
-0
aspectos.
19
Realice la práctica 1.4 cuyo guión se encuentra en el apartado 1.7 para crear un
proyecto de RStudio.
20
1.3. Estructuras de datos y su tratamiento
En R, los datos de una variable26 pueden ser de un tipo determinado, por ejemplo números
or
o texto. Estas variables pueden a su vez estar integradas en otras estructuras. La forma más
simple es en forma de vector para una sola variable. Las matrices son vectores con más de
una dimensión. Las listas pueden contener objetos de distinto tipo y longitud. Los objetos de
ad
tipo data frame contienen variables de distinto tipo con el mismo número de observaciones,
y es el formato más adecuado para el análisis de datos.
rr
cal (Verdadero/Falso), integer (Número entero), double (Número real) o character (Cadena
de texto). Hay otros tipos como complex, raw, NULL, o closure que son menos habituales
en análisis de datos. El modo de almacenamiento es básicamente igual, aunque los tipos
integer y double tienen el modo numeric.
## [1] "integer"
mode(un_vector)
## [1] "numeric"
Por otra parte, todos los objetos de R tienen una clase (class). En el caso de vectores de datos,
la clase será cualquiera de los modos indicados antes, u otros más complejos como: factor
07
(vector categórico, es decir, niveles + etiquetas); table (tabla de frecuencias); Date (fecha);
POSIXct (fecha y hora); ts, xts o zoo (series temporales); S3 o S4 (clases personalizadas,
definidas en un paquete, función, etc, por ejemplo lm, spatial).
5-
La clase del vector creado anteriormente coincide con su tipo. Examinemos también
-0
el objeto AirPassengers, conjunto de datos de ejemplo de los proporcionados en el paque-
te datasets. Vemos que la clase es ts (time series), pero el modo de almacenamiento es
numeric.
class(un_vector) 19
20
## [1] "integer"
class(AirPassengers)
## [1] "ts"
or
mode(AirPassengers)
## [1] "numeric"
ad
Podemos crear vectores introduciendo todos sus elementos, o generando secuencias. La fun-
ción c crea un vector cuyos elementos serán los que pasemos como argumentos. El intérprete
Bo
de R asigna al objeto la clase más conveniente. El operador : (dos puntos) entre dos números
enteros genera una secuencia de números enteros entre ambos. La función seq, de la que
ya hemos visto algún ejemplo, genera secuencias a intervalos regulares. La función rep crea
repeticiones de valores o vectores. Con la función scan podemos crear vectores a partir de
un fichero, texto dentro de la propia función, o interactivamente en la consola.
Además de vectores numéricos y de texto, podemos crear vectores con valores lógicos o con
factores (variables categóricas). Un valor lógico resulta de una comparación, que se puede
07
hacer entre dos valores o como resultado de una función. Para comparar si dos valores27 son
iguales utilizamos el doble símbolo de igualdad ==. Para comparar si dos valores son distintos,
utilizamos el símbolo !=. Utilizamos los símbolos >, <, >= y <= para las comparaciones “ma-
5-
yor que”, “menor que”, “mayor o igual que” y “menor o igual que” respectivamente. Estas
expresiones devuelven un valor lógico, TRUE o FALSE. Podemos combinar múltiples compara-
ciones lógicas con los símobolos &, && (‘AND’, se tienen que cumplir las dos condiciones a
-0
ambos lados del símbolo para que la expresión sea TRUE) y |, || (‘OR’, se tiene que cumplir
una de las dos condiciones, o las dos a la vez, para que la expresión sea TRUE). La diferencia
19
entre el operador simple y doble es que el operador sencillo realiza la comparación “elemen-
to a elemento”, mientras que el operador doble realiza la comparación únicamente entre el
primer elemento de los dos vectores a comparar.
20
Los siguientes ejemplos evalúan expresiones lógicas con los vectores creados en el ejem-
plo anterior. Vea las diferencias y comprenda los resultados obtenidos. La última expresión
crea un vector lógico v5.
or
v1 > 5
ad
## [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
v3 == 1 && v3 > 5
## [1] FALSE
27
Nos referimos en general a dos valores pero puede ser cualquier objeto de R.
40 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
v3 == 0 | v4 != "Menorca"
## [1] TRUE TRUE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE
Los factores se crean con las funciónes factor y gl, y se pueden generar todas las combina-
ciones de varios factores con la función expand.grid.
07
pero en la función gl se pueden especificar más argumentos. Nótese que es el primer vector
que vemos ocupando más de una línea de la salida de la consola. Aquí podemos ver el sentido
del número entre corchetes al principio de cada línea: indica el índice del primer elemento de
5-
la línea. La última expresión genera una tabla con las combinaciones posibles de dos factores
(máquina y tratamiento) con dos niveles cada uno.
-0
f1 <- factor(rep(v4, 2))
gl(n = 5, k = 2, labels = v4)
## máquina tratamiento
or
## 1 a 0
## 2 b 0
## 3 a 1
ad
## 4 b 1
Los vectores siempre tienen longitud, y sus elementos pueden tener o no nombres. La longitud
rr
del vector se puede obtener con la función length, aunque con RStudio lo más cómodo es
examinar el Environment. Los vectores aparecen en el grupo Values y se muestra la misma
información que proporciona la función str: junto al símbolo del vector, el tipo de datos,
Bo
entre corchetes los índices del primer y último elemento28 , y una muestra de los primeros
elementos del vector. Podemos asignar nombres a cada elemento del vector con la función
names. Los vectores están indexados, y podemos acceder a ellos mediante su índice o su
nombre. El acceso a objetos indexados se realiza mediante los corchetes ‘[ ]’. Esta selección
puede ser de múltiples elementos. En R es de especial importancia la selección de elementos
de un vector (o una lista) mediante vectores lógicos. Si dentro de los corchetes incluimos un
vector lógico, el resultado será un vector con los elementos cuyo índice es verdadero en el
vector lógico.
28
por tanto, la longitud del vector es el segundo de estos números
1.3. ESTRUCTURAS DE DATOS Y SU TRATAMIENTO 41
length(v1)
## [1] 4
str(v1)
## num [1:4] 2 4 6 8
07
names(v1) <- c("a", "b", "c", "d")
v1
5-
## a b c d
## 2 4 6 8
-0
v4[2]
## [1] "Menorca"
v4[2:3] 19
20
## [1] "Menorca" "Ibiza"
v1[v1 > 5]
## c d
or
## 6 8
Los elementos de un vector tienen un orden. Hay dos funciones relacionadas con el orden
ad
de los elementos de un vector, con la función sort obtenemos el vector ordenado, y con la
función order obtenemos los índices que ocupan los valores ordenados, es decir, el primer
elemento del vector es el índice del mínimo valor, y así sucesivamente. Se puede invertir el
orden con la función rev.
rr
Bo
Se pueden realizar dos tipos de operaciones con vectores: operaciones sobre todo el vector
que devuelven un solo valor, y operaciones sobre cada elemento del vector que devuelven
otro vector de la misma longitud. Las operaciones aritméticas sobre un vector realmente son
operaciones entre dos vectores. Si no tienen la misma longitud, R recicla los valores del más
pequeño hasta completar la longitud del más grande. Si la longitud del más grande no es
múltiplo de la longitud del más corto, se realiza la operación pero lanza un mensaje de ad-
vertencia (warning). Además de operaciones aritméticas, cuando un vector es argumento de
una función, el resultado puede ser un solo valor u otro vector, dependiendo de la naturaleza
de la función.
42 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
## a b c d
## 4 6 8 10
07
v2 + v3
## [1] 1 2 4 5 5 6 8 9 9 10
5-
v1 + v2
-0
## de uno menor
## [1] 3 6 9 12 7 10 13 16 11 14
mean(v1)
## [1] 5
19
20
sqrt(v1)
## a b c d
## 1.414214 2.000000 2.449490 2.828427
or
Una matriz es una estructura de datos bidimensional, organizada en filas y columnas. Pode-
mos ver la matriz como un vector que colocamos en columnas de una determinada longitud.
ad
Así, cada fila y cada columna de la matriz es también un vector. Las matrices se crean con la
función matrix, a partir de un vector con todos los datos e indicando el número de filas y/o
columnas. Por defecto, se crea la matriz por columnas, pero esto se puede cambiar con el
rr
argumento byrow = TRUE. La selección de elementos se realiza también con los corchetes, en
este caso indicando los índices de cada una de las dimensiones, filas y columnas, separados
por una coma. Si no indicamos índices en una de las dimensiones, quiere decir que queremos
Bo
En la pestaña Environment de RStudio, las matrices aparecen en el grupo Data. Esto permite
abrir la matriz en el visualizador si hacemos clic en el icono de la cuadrícula a la derecha.
En el código a continuación creamos una matriz de dos filas con los datos que hay en
el vector v2, y seleccionamos algunos elementos.
## [1] 1 3 5 7 9
m1[, 1]
## [1] 1 2
07
m1[1, 2:3]
## [1] 3 5
5-
Podemos asignar nombres a las filas y columnas de una matriz, y realizar cálculos sobre filas
o columnas, como veremos en la práctica más adelante.
-0
colnames, rownames, dimnames: Obtiene o establece nombres de filas y/o columnas de
una matriz.
matriz. 19
rowSums, colSums: Obtiene un vector con la suma por filas o por columnas de una
rowMeans, colMeans: Obtiene un vector con las medias por filas o por columnas de
20
una matriz.
Podemos tener datos organizados en más de dos dimensiones. Por ejemplo para tres dimen-
siones la primera dimensión sería la fila de una matriz, la segunda la columna, y la tercera
estaría compuesta por matrices con filas y columnas, y así sucesivamente. En los contenidos
or
ser otros objetos ya creados. Las listas también están indexadas y se puede acceder a sus
elementos por índice o por nombre. En este último caso, el acceso por nombre se puede hacer
Bo
mediante el operador $. La importancia de las listas radica en que muchos objetos creados
como resultado de operaciones estadísticas son del tipo lista, con varios elementos a los que
se accede posteriormente. El acceso a los elementos de la lista, a diferencia de los vectores,
se realiza con dobles corchetes. También se puede utilizar el corchete simple, pero en este
caso no obtendríamos el elemento de la lista, sino una lista con los elementos indicados (algo
poco habitual para el alcance de este libro).
En el siguiente ejemplo creamos una lista con tres elementos. La selección con corchete
doble es equivalente a la selección con nombre. la selección con corchete simple nos da una
lista.
44 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
## $pares
## a b c d
## 2 4 6 8
##
## $islas
## [1] "Mallorca" "Menorca" "Ibiza" "Formentera" "Cabrera"
07
##
## $matriz
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 3 5 7 9
5-
## [2,] 2 4 6 8 10
l1$pares
-0
## a b c d
## 2 4 6 8
l1[[1]] 19
20
## a b c d
## 2 4 6 8
l1[1:2]
or
## $pares
## a b c d
## 2 4 6 8
ad
##
## $islas
## [1] "Mallorca" "Menorca" "Ibiza" "Formentera" "Cabrera"
rr
nos mostraría la misma información que la función str. Además, podemos explorar la lista
haciendo clic en el icono de la lupa a la derecha, en cuyo caso se abre en el visualizador la
lista de elementos y podemos explorarlos por separado, por ejemplo si hay un data frame, se
abre en otra pestaña del panel superior izquierdo.
La organización más adecuada para análisis de datos es en forma de tabla o data frame,
en la cual cada columna se corresponde con una variable, y cada fila se corresponde con una
observación (individuo, fecha, etc.). Para esta organización R tiene la clase data.frame. Lo
normal será que importemos los datos de archivos en disco como veremos en el siguiente
apartado, si bien podemos crear nuestras propias tablas de datos con la función data.frame.
Un data frame es una mezcla de las estructuras que hemos visto hasta ahora:
1.3. ESTRUCTURAS DE DATOS Y SU TRATAMIENTO 45
Es como una matriz en el sentido de que tiene dos dimensiones. Podemos acceder a
sus elementos con corchetes, tenemos nombres de filas y columnas, y podemos operar
con ellas. Se diferencian en que las matrices tienen un único tipo de datos, mientras
que en el data frame cada columna puede ser de un tipo distinto.
Es como una lista porque cada columna tiene un nombre y podemos acceder a ellas con
el símbolo $. Se diferencian en que todas las columnas de un data frame son vectores
con la misma longitud.
Cada columna del data frame es un vector29 , que puede ser numérico, factor, carácter
07
o lógico.
Por tanto, todo lo que hemos visto hasta ahora se aplica al data frame o a sus columnas.
5-
El conjunto de OrchardSprays del paquete datasets contiene datos sobre un expe-
rimento en agricultura (véase ?OrchardSprays). A continuación se muestran ejemplos de
-0
acceso a datos y características del data frame.
str(OrchardSprays)
OrchardSprays[5:10, 1]
## [1] 92 90 15 2 84 6
ad
OrchardSprays$decrease[5:10]
## [1] 92 90 15 2 84 6
rr
29
En realidad pueden ser objetos de otra clase, pero para los efectos de este libro no nos interesan.
46 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
nrow(OrchardSprays)
## [1] 64
En la pestaña Environment de RStudio, los data frames aparecen en el grupo Data. Podemos
expandir el data frame para ver las columnas que lo componen igual que hacíamos con las
listas, o abrirlos en el visualizador igual que hicimos con las matrices.
Es importante destacar que las variables (columnas) sólo existen en el environment del data
frame. Por eso tenemos que usar el símbolo $ para acceder a ellas. Existen dos formas de
07
escribir sólo el nombre de la variable. Una es utilizando las funciónes attach y detach
con el data frame como argumento. Esto puede tener efectos secundarios en otros objetos y
funciones, por lo que en general se recomienda usarla con cautela. La otra es utilizando la
5-
función with, con el data frame como primer argumento y el conjunto de expresiones entre
corchetes como segundo. En este libro preferimos usar nombres cortos para los conjuntos de
datos y el nombre completo (df$var) para las variables.
-0
En el código a continuación se muestran tres ejemplos para obtener la media de la
19
variable decrease del data frame OrchardSpays. Las tres producen el mismo resultado, el
analista debe elegir uno de los estilos y ser consistente con él.
20
mean(OrchardSprays$decrease)
## [1] 45.42188
attach(OrchardSprays)
or
mean(decrease)
## [1] 45.42188
ad
## Otras expresiones
detach(OrchardSprays)
rr
with(OrchardSprays, {
mean(decrease)
## otras expresiones
Bo
})
## [1] 45.42188
Podemos obtener subtotales del data frame con la función aggregate. El primer argumento
de la función aggregate es una fórmula, una clase de objetos muy importante en R que es la
primera vez que aparece en este texto. Las fórmulas en R consisten en dos expresiones una
a cada lado del símbolo ~, y en general y ~ x se puede interpretar como “y depende de x”.
En el contexto de la función aggregate, realizaremos subtotales de la variable y agrupando
por los valores de x. Los subtotales no se limitan a sumas, sino que puede ser el resultado
de aplicar cualquier función que realice un cálculo de agregación (media, máximo, etc.)
1.3. ESTRUCTURAS DE DATOS Y SU TRATAMIENTO 47
La siguiente expresión obtiene la media de la variable decrease para cada valor del
factor treatment en el conjunto de datos OrchardSprays.
## treatment decrease
## 1 A 4.625
## 2 B 7.625
07
## 3 C 25.250
## 4 D 35.000
## 5 E 63.125
5-
## 6 F 69.000
## 7 G 68.500
## 8 H 90.250
-0
Otras operaciones muy comunes con los data frames son filtrar y ordenar datos. Ya hemos
visto algunos ejemplos de cómo filtrar utilizando los corchetes de selección, pero la función
19
subset proporciona una forma más intuitiva de hacerlo.
20
Las dos primeras expresiones a continuación realizan filtrado de datos con la función
subset y expresiones lógicas sobre el conjunto de datos OrchardSprays. La tercera ordena
los datos de uno de estos subconjuntos en orden descendente de la variable decrease.
## 8 2 8 1 A
## 14 2 6 2 A
## 19 5 3 3 A
rr
## 26 4 2 4 A
## 36 5 4 5 A
Bo
## 41 12 1 6 A
## 53 4 5 7 A
## 63 3 7 8 A
B <- subset(OrchardSprays, decrease >= 100)
B
A veces lo que nos interesa es unir varios data frames. Las funciones rbind y cbind unen
por filas o por columnas, respectivamente, dos o más data frames o matrices.
07
En el ejemplo anterior, unimos los dataframes A y B con la siguiente expresión.
5-
rbind(A, B)
-0
## decrease rowpos colpos treatment
## 8 2 8 1 A
##
##
##
##
14
19
26
36
2
5
4
5
6
3
2
4
2
3
4
5
19
A
A
A
A
20
## 41 12 1 6 A
## 53 4 5 7 A
## 63 3 7 8 A
## 11 127 3 2 H
or
## 25 130 1 4 H
## 27 114 3 4 E
## 58 114 2 8 F
ad
nombre de columna. De igual forma podemos sustituir una columna por nuevos valores, o
eliminarla asignando el valor NULL. Estas nuevas columnas, pueden ser calculadas a partir
de las ya existentes en el data frame. La modificación de un valor individual o de un rango
Bo
07
conjunto de datos. Los nombres de filas por defecto son los índices que identifican cada fila.
Se pueden asignar nuevos nombres tanto a las columnas, es decir, renombrar variables, como
a las filas, utilizando las funciones colnames y rownames, respectivamente.
5-
1.3.4. Valores especiales
-0
Los valores perdidos o missing values son un problema frecuente en el análisis de datos. Su
consideración y tratamiento es muy importante en algunas técnicas, y especialmente en la
19
fase de limpieza de datos. Los valores faltantes o perdidos se representan en R mediante el
símbolo NA (not available). Si intentamos hacer cálculos sobre vectores que contienen NAs,
por ejemplo la media, obtendremos NA a menos que incluyamos el argumento na.rm = TRUE.
En algunas ocasiones querremos imputar a los valores NA otro valor, por ejemplo porque si no
20
está el valor significa que es cero. La función is.na sirve para identificar los valores faltantes
en un vector.
En R disponemos además de algunos valores especiales y constantes. Ya hemos visto NULL
or
utilizándolo para eliminar una columna de un data.frame. Este valor puede aparecer también
cuando un objeto no existe. Los valores Inf y -Inf son devueltos en expresiones como
por ejemplo 1/0, y algunas funciones los aceptan como argumentos. Se puede √ trabajar con
ad
vector, como el número π, pi, las letras del alfabeto inglés, letters y LETTERS y los nombres
y abreviaturas de los meses, month.name y month.abb31 .
Bo
vector entre sí, entonces tenemos que utilizar el argumento collapse indicando la cadena
que separará los elementos.
a <- letters[1:5]
b <- 1:5
paste(a, b)
07
## [1] "a 1" "b 2" "c 3" "d 4" "e 5"
paste0(a,b)
5-
## [1] "a1" "b2" "c3" "d4" "e5"
paste0(a,b, collapse = "-")
-0
## [1] "a1-b2-c3-d4-e5"
paste(a, b, sep = ".")
anterioremente.
h <- "Universidad de Castilla-La Mancha"
nchar(h)
rr
## [1] 33
Bo
## [1] "Castilla"
strsplit(h, " ")
## [[1]]
## [1] "Universidad" "de" "Castilla-La" "Mancha"
grep("ember", month.name)
## [1] 9 11 12
1.3. ESTRUCTURAS DE DATOS Y SU TRATAMIENTO 51
Los ficheros de texto almacenan números y cadenas de texto. El software, por su parte, al-
macena las fechas como números, generalmente como número de días transcurridos desde
una fecha determinada. Las fechas por tanto son consideradas como cadenas de texto o como
factores, y para que R entienda que es una fecha, hay que transformar la variable. Utilizamos
07
para ello la función as.Date. En general, es una buena idea trabajar con fechas en formato
ISO, es decir, año-dia-mes, por ejemplo “2000-01-01”. El software suele entender este for-
mato sin necesidad de más explicaciones, y la ordenación será correcta aunque se guarden
5-
como tipo carácter. Siempre se puede especificar el formato indicando una especificación
de conversión, véase ?strptime. Cuando tenemos datos con fechas, además, puede ser útil
-0
tener columnas con el año, el mes, el año-mes y la semana para realizar análisis de datos
secuenciales y por grupos de fechas. Es decir, hacer la transformación inversa con la función
format. Es importante que las columnas de tipo fecha en un data frame sean de la clase
correcta ya que en otro caso
19
20
En el código a continuación, creamos dos objetos de tipo carácter con un solo elemento
que representa una fecha. Nótese que podríamos trabajar igual con vectores de mayor tamaño.
La primera fecha está en formato ISO y por tanto la función as.Date interpreta sin más la
fecha. A la segunda fecha le tenemos que especificar dónde está cada componente para que
la convierta correctamente.
or
## [1] "character"
fecha1b <- as.Date(fecha1)
rr
class(fecha1b)
## [1] "Date"
Bo
## [1] "2000-01-01"
format(fecha1b, "%Y-%m")
## [1] "2000-01"
Los datos de tipo tiempo (fecha + hora exacta) hay que guardarlos como tipo de datos
POSIXct, de forma similar a las fechas.
52 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
07
## [1] "Son las 10:23"
5-
Los paquetes stringr (Wickham, 2019) y lubridate (Spinu et al., 2018), pertene-
cientes al tidyverse, contienen funciones específicas para realizar operaciones más complejas
con cadenas de caracteres y fechas de forma sencilla.
-0
1.3.6.
19
Conversión entre tipos de datos
Al crear objetos, R intentará deducir el tipo de datos que contiene (numérico, texto, …)
20
y su clase (data.frame, factor, …). Se pueden convertir estructuras de datos de un tipo a
otro. Si existiera algún problema, R lo intenta solucionar. Por ejemplo, si tenemos un vector
de cadenas de texto donde hay números pero también alguna cadena extraña, los textos
correspondientes a números los convierte en números y las cadenas que no puede convertir
las convierte en valores faltantes. Podemos consultar la clase de un determinado objeto con la
or
función class, comprobar si es de un determinado tipo con las funciones is.x (por ejemplo
is.matrix) o forzar a ser de un determinado tipo con las funciones as.x (por ejemplo
ad
as.data.frame).
Un caso especial de conversión de tipos es cuando queremos transformar una variable numé-
rica en un factor según ciertos intervalos. Para ello utilizamos la función cut, que divide los
rr
En este libro vamos a utilizar el estilo y las funciones clásicas de R. Actualmente se está
convirtiendo en una tendencia utilizar los paquetes del llamado tidyverse para trabajar con
estructuras de datos, especialmente dplyr (Wickham et al., 2019b) y tidyr (Wickham and
Henry, 2019). Una vez dominados los aspectos básicos de R-base, recomendamos profundizar
en este estilo más productivo con el libro de Wickham and Grolemund (2016).
1.4. IMPORTACIÓN Y EXPORTACIÓN DE DATOS 53
Realice la práctica 1.5 cuyo guión se encuentra en el apartado 1.7 para trabajar con
estructuras de datos.
07
almacenados en ficheros. Recordemos aquí la importancia de referenciar a ficheros en la ruta
adecuada a partir del directorio e trabajo. En los sucesivos ejemplos, asumimos que tenemos
una carpeta “datos” dentro del directorio de trabajo donde se encuentran los ficheros. Si el
5-
fichero de datos está en Internet, podemos descargarlo a nuestro ordenador con la función
download.file.
-0
El siguiente código descarga los ficheros de ejemplo a la carpeta “datos” del directorio
de trabajo desde la web del libro.
19
download.file(url = "http://emilio.lcano.com/b/adr/p/datos/RRHH.xlsx",
destfile = "datos/RRHH.xlsx",
20
mode = "wb")
download.file(url = "http://emilio.lcano.com/b/adr/p/datos/ejDatos.csv",
destfile = "datos/ejDatos.csv")
download.file(url = "http://emilio.lcano.com/b/adr/p/datos/merma.RData",
destfile = "datos/merma.RData",
or
mode = "wb")
download.file(url = "http://emilio.lcano.com/b/adr/p/datos/merma.rds"
ad
destfile = "datos/merma.rds",
mode = "wb")
Con el argumento mode nos aseguramos de que los ficheros binarios se descargan correcta-
rr
07
Si el data frame se guardó en un archivo “rds”, con el siguiente código asignamos al
objeto “mermards” dicho data frame.
5-
1.4.2. Importación de datos en ficheros de texto
-0
La forma más segura de trabajar con datos externos es hacerlo en formato de texto plano.
19
Los ficheros de texto plano pueden tener cualquier extensión, pero las más habituales son
“.txt” y “.csv”. Los datos dentro del fichero estarán organizados según una estructura, de la
que hay que tener en cuenta los siguientes valores:
20
Separador de columnas. Los valores más habituales suelen ser:
• El “tabulador”, representado en R por \t
• La coma, que se utiliza en los ficheros CSV (Comma Separated Values) que utili-
zan el punto como símbolo decimal.
or
• El punto y coma, que se utiliza en los ficheros CSV (Comma Separated Values)
que utilizan la coma como punto decimal.
Separador decimal. Suele ser el punto. En sistemas cuyo lenguaje no es el inglés,
ad
capaz de exportar datos en formato CSV. Por ejemplo, la hoja de cálculo Microsoft Excel
exporta en formato CSV separado por punto y coma, utilizando la coma como símbolo
decimal, y con encabezados. Si Excel está configurado para idioma inglés, entonces genera el
CSV separado por comas y utilizando el punto como símbolo decimal. A R le es indiferente,
ya que puede trabajar con cualquier tipo de ficheros, siempre y cuando se utilicen las opciones
adecuadas a cada caso.
Una consideración importante cuando se trabaja con ficheros de texto es la codificación.
Si el fichero de datos contiene caracteres “no ASCII”, por ejemplo acentos o eñes, podemos
32
De hecho, tiene su origen en las antiguas tarjetas perforadas.
1.4. IMPORTACIÓN Y EXPORTACIÓN DE DATOS 55
07
5-
Figura 1.23: Asistente de importación de texto de RStudio
-0
obtener resultados no esperados si la codificación de texto del sistema es diferente a la codifi-
19
cación de texto del fichero. Sin entrar en mayores consideraciones, digamos que los sistemas
Unix como Linux o Mac utilizan la codificación UTF-8, mientras que los sistemas Windows
utilizan la codificación ISO-8859-1, abreviados respectivamente como utf8 y latin1. Por
20
tanto, si el fichero que queremos importar tiene una codificación distinta a la de nuestro
sistema, tendremos que indicárselo a la función que importa el texto, normalmente con el
argumento fileEncoding = 'utf8' o fileEncoding = 'latin1', según proceda.
La importación de datos mediante código se realiza con la función read.table o sus méto-
or
dos abreviados read.csv (separados por comas) o read.csv2 (separados por punto y coma).
Desde RStudio se pueden importar ficheros CSV con el cuadro de diálogo “Import Dataset”
disponible en la pestaña Environment del panel superior derecho, véase la figura 1.23. Aquí,
ad
escribimos el nombre del objeto donde se importarán los datos (Name). Se pueden configurar
fácilmente las opciones si no se detectan automáticamente. Por ejemplo, si las primeras líneas
del fichero no se corresponden con datos propiamente dichas, podemos “saltárnoslas” (Skip);
rr
si el fichero contiene encabezados o no (First Row as Names); cuáles son los caracteres sepa-
rador (Delimiter, para CSV en español, el punto y coma es semicolon). El símbolo decimal y
Bo
07
5-
Figura 1.24: Visor de datos de RStudio
-0
library(readr)
19
ejDatos <- read_delim("datos/ejDatos.csv",
";", escape_double = FALSE, locale = locale(decimal_mark = ",",
grouping_mark = "."), trim_ws = TRUE)
View(ejDatos)
20
La primera expresión carga el paquete readr, la segunda importa el fichero y asigna los
datos a un objeto data frame con el nombre asignado en el asistente, mientras que la tercera
visualiza los datos.
or
El asistente de RStudio utiliza el paquete readr (Wickham et al., 2018), pero, como se ha
ad
read.csv2 utiliza las opciones para importar utilizando la coma como símbolo decimal y el
punto y coma como separador, utilizado en sistemas con idioma español (entre otros).
Bo
La elección de unos paquetes u otros dependerá en definitiva del gusto del analista. Las
funciones del paquete readr serán más rápidas para ficheros grandes, y presentan la ventaja
de contar con el asistente y una gestión fácil de los tipos de datos. Además, el data.frame
importado tiene estructura tibble, que se utiliza en otros paquetes de RStudio y del conocido
1.4. IMPORTACIÓN Y EXPORTACIÓN DE DATOS 57
como tidyverse33 .
Para ficheros con datos separados por tabuladores, el argumento sep de la función
read.table o delim de la función read_delim se indicará como \t. Si el fichero contiene
caracteres no ASCII (acentos, eñes, etc.) es posible que sea necesario indicar la codificación
del fichero tal y como se ha comentado anteriormente.
Una vez importados los datos, ya están en el espacio de trabajo y podemos trabajar directa-
mente con ellos.
07
Una vez tenemos el data frame en el workspace podemos obtener un resumen de la
variable merma1 con la función summary.
5-
summary(ejDatos$merma1)
-0
## Length Class Mode
## 0 NULL NULL
19
Para concluir, se pueden incluir los datos a importar en la propia llamada a la función.
Esto puede ser útil para crear ejemplos reproducibles sin necesidad de más ficheros, cuando
20
tenemos pocos datos, o porque convenga tener los datos dentro del propio script.
2017-09-25;2;755,3
2017-09-26;1;749,9
Bo
2017-09-25;2;751,2")
datos_en_script
33
https://www.tidyverse.org/
58 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
07
y read_stata para ficheros de Stata, read_spssy read_sav para ficheros de SPSS. De nuevo,
podemos utilizar el asistente como hemos hecho antes, o importarlo directamente en el script
con la función read_excel.
5-
La siguiente expresión importa el fichero RRHH.xlsx al data frame datos_excel.
-0
library(readxl)
datos_excel <- read_excel("datos/RRHH.xlsx")
19
Existen varios paquetes más para leer y escribir ficheros Excel que no describimos aquí por
cuestión de espacio34 .
20
Cabe destacar que las funciones de los paquetes readr, readxl y haven aceptan como ruta
del fichero tanto una ruta local del ordenador como una URL para descargar el fichero de
Internet antes de importarlo. Además, si el archivo es un fichero comprimido, la propia
or
Lapsley, 2017) permite importar datos de fuentes ODBC (Open Database Connectivity).
Otro tipo de formatos estructurados como XML o json también se pueden tratar fácilmente
en R. Existe un manual en la documentación incluida con R dedicado íntegramente a este
rr
utiliza el paquete DBI (R Special Interest Group on Databases (R-SIG-DB) et al., 2018) y
el paquete correspondiente al servidor utilizado, por ejemplo para un servidor de bases de
datos MySQL, el paquete RMySQL (Ooms et al., 2018).
34
Véase, por ejemplo A million ways to connect R and Excel
35
incluidos Minitab, SAS, SPSS y Stata.
1.4. IMPORTACIÓN Y EXPORTACIÓN DE DATOS 59
## Crear conexión
con <- dbConnect(MySQL(), user = "profesor",
password = "****", dbname = "curso",
host = "127.0.0.1")
07
## Definición de la consulta a la base de datos
sqlstr <- "SELECT * FROM curso.datos1"
res <- dbSendQuery(con, sqlstr)
5-
## Creación del data frame
wdata <- fetch(res, n = -1)
-0
dbClearResult(res)
y coma respectivamente. Por defecto, R guarda también los nombres de fila, casi siempre
los identificadores de fila, lo que normalmente no es aconsejable. El argumento row.names
indica si se guardan los nombres de fila como primera columna sin nombre. En general, es
ad
Las siguientes expresiones son equivalentes para generar un fichero csv que se abrirá
correctamente en Excel36 :
Bo
write.table(x = ejDatos,
file = "datos/miFichero.csv",
sep = ";", dec = ",",
col.names = TRUE,
row.names = FALSE)
write.csv2(ejDatos, "datos/mifichero.csv",
row.names = FALSE)
También podemos guardar los datos en forma de workspace de R (.RData). En este caso
60 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
07
Para exportar un único objeto en formato .rds, utilizamos la función saveRDS.
5-
dentro de la carpeta “datos”, que luego podemos cargar con la función readRDS:
-0
19
Si lo que queremos es exportar los datos a una hoja de cálculo, debemos utilizar alguno
de los paquetes disponibles para ello. El paquete XLConnect (?) contiene gran cantidad de
funciones para crear sofisticados ficheros Excel (véase la documentación del paquete). El
20
paquete openxlsx (Walker, 2018) es otra opción sencilla
El siguiente código guarda el conjunto de datos ejDatos en la hoja “datos” del libro
Exel “miLibro.xlsx” dentro de la carpeta “datos”:
or
library(openxlsx)
write.xlsx(x = ejDatos,
ad
file = "datos/miLibro.xlsx",
sheetName = "datos",
row.names = FALSE)
rr
Para exportar datos a ficheros de otros programas estadísticos podemos utlizar las funciones
del paquete haven (Wickham and Miller, 2019), de igual forma que se vio anteriormente para
la importación. Así, las funciones write_dta, write_sas y write_sav guardan los datos en
formatos de Stata, SAS y SPSS respectivamente. Por su parte, los interfaces de bases de
datos permiten escribir en los distintos servidores mediante sentencias SQL.
Realice la práctica 1.6 cuyo guión se encuentra en el apartado 1.7 para importar y
exportar ficheros de datos.
1.5. INFORMES REPRODUCIBLES 61
07
5-
-0
Figura 1.25: Esquema del proceso de información de análisis de datos
1.5.
1.5.1.
Informes reproducibles
Problema y enfoques
19
20
El resultado final de nuestro proyecto de análisis de datos terminará comunicándose a dis-
tintos niveles, tanto aguas arriba como aguas abajo. Esta comunicación, digamos en general
informes que pueden tener distintos formatos de destino, estará compuesta de múltiples ele-
mentos como texto, gráficos, resultados numéricos, tablas, etc. Además, es posible que haya
or
tados del análisis como base de un informe escrito, posiblemente con algunas iteraciones del
proceso si el proyecto tiene cierta envergadura. El software estadístico suele incluir formas
de generar resultados listos para integrar en un informe, pero siempre bajo este paradigma
Bo
07
Figura 1.26: Flujo de trabajo reproducible
5-
de datos con datos experimentales de forma que los resultados se puedan volver a obtener,
entender mejor y verificar.
-0
Un concepto muy relacionado que utilizamos en R es la programación “literaria”38 , mediante
la cual combinamos un lenguaje de programación como R con documentación de todo tipo
(por ejemplo comentarios en el código).
19
Con el enfoque de la investigación reproducible, lo que hacemos es darle la vuelta al enfoque
corta-pega, de forma que se escribe el informe a la vez que se realiza el análisis, incrustando
20
el código dentro del propio informe. Obviamente es necesario un sistema que consolide el
informe con los resultados del código, y esto es lo que nos permite R y RStudio mediante
archivos R Markdown.
El flujo de trabajo sería el siguiente (véase la figura 1.26): los contenidos se encuentran
or
en ficheros de código. Estos ficheros fuente, se compilan y producen los materiales en los
formatos necesarios. Los cambios se hacen una vez, y todos los materiales son actualizados
adecuadamente.
ad
mano.
Cualquier cambio en un punto del análisis (por ejemplo, añadir una variable a un
modelo) se puede realizar de una sola vez y los cambios en los resultados y gráficos se
actualizarán automáticamente.
Los resultados se pueden verificar por terceros en caso necesario. Un caso paradigmático
fue el escándalo de los ensayos de cáncer en Duke en 201139 . No obstante es un tema
38
Literate programming is a methodology that combines a programming language with a documentation
language (Knuth, 1984).
39
http://www.nytimes.com/2011/07/08/health/research/08genes.html
1.5. INFORMES REPRODUCIBLES 63
que cada vez se demanda más en otros campos fuera de la investigación clínica (por
ejemplo en publicaciones de cualquier tipo).
A continuación nos centraremos en el enfoque reproducible. Para el otro enfoque, simplemente
copie los resultados de la consola y los gráficos de la pestaña Plots en del panel inferior derecho
en su editor de textos favorito.
07
circunstancia, con una sintaxis muy simple que permite leerlo directamente por las personas,
o ser convertido por un ordenador en otro formato más elaborado como HTML (página
web). En RStudio, se pueden crear ficheros Rmarkdown utilizando esta sintaxis para las
5-
explicaciones de nuestro análisis, e incluir dentro “trozos” (chunks) de código de forma que
al generar el informe, el resultado de ese código queda incluido en el informe. Así, si una vez
terminado el informe se nos ha olvidado, por ejemplo, incluir un gráfico, sólo tenemos que
-0
añadir las líneas de código que lo crean y volver a generar el informe.
Al crear un nuevo documento R Markdown, se crea una plantilla automáticamente (véase
19
la figura 1.27) donde podemos ver lo fácil que es crear el informe. Hay una guía rápida
de markdown disponible en la ayuda de RStudio, así como enlaces a la Cheatsheet. Incluir
títulos, énfasis en el texto y listas es muy sencillo, y a menudo no necesitamos nada más
20
para realizar un informe. El código de R se inserta mediante el icono insert del editor40 . Un
chunk consta de unos marcadores de inicio y final del chunk, entre los cuales se insertan
expresiones de R que se ejecutarán al generar el documento de salida. El marcador de inicio
son cuatro símbolos de acento grave (backticks, “‘ ) seguidos de unas llaves con la letra r
or
07
5-
-0
19
Figura 1.27: Archivo R Markdown en RStudio
20
se puede generar cualquiera de los formatos independientemente del que se haya elegido al
crear el fichero. Para generar el documento, utilizamos el icono de “bordado” (knit). Si en
vez de pulsarlo directamente hacemos clic en el triángulo de la derecha, podemos selccionar
el formato de salida (hrml, pdf o Word). El formato PDF requieren tener instalada una
or
Podemos compilar el informe cuantas veces queramos con el icono knit (bordado). Para
ad
trabajo en curso, se recomienda ir previsualizando en formato HTML, y una vez sea definitivo
generar el archivo Word. El formato HTML se puede publicar, bien internamente, bien
públicamente, por ejemplo en el servicio RPubs^{http://rpubs.com/}.
rr
---
title: "Ejemplo informe de análisis de datos"
author: "Emilio L. Cano"
date: "31/01/2019"
output: word_document
---
41
Se puede instalar una distribución ligera de LaTeX con el paquete tinytex, ejecutando
tinytex::install_tinytex() habiendo instalado el paquete.
1.5. INFORMES REPRODUCIBLES 65
07
5-
Figura 1.28: Nuevo documento R Markdown
-0
Este es mi primer ejemplo de informe generado con RStudio. Voy a crear un
conjunto de datos:
```{r} 19
pdensity <- c(10.6817, 10.6040, 10.5709, 10.7858,
20
10.7668, 10.8101, 10.6905, 10.6079,
10.5724, 10.7736, 11.0921, 11.1023,
11.0934, 10.8530, 10.6774, 10.6712,
10.6935, 10.5669, 10.8002, 10.7607,
or
Y este es su histograma:
```{r, echo=FALSE}
rr
hist(data = pdensity)
```
Bo
Un aspecto muy importante al trabajar con ficheros R Markdown es que al generar los
documentos, es que los chunks no se evalúan en el directorio de trabajo, sino en el directorio
donde se encuentra el archivo R Markdown. Por tanto, si vamos a utilizar ficheros, por
ejemplo para importar datos, y el fichero R Markdown no está en el directorio raíz del
proyecto sino en una carpeta, tenemos dos opciones:
1. Hacer referencia a los ficheros desde la ubicación del fichero R Markdown. Por ejemplo,
si el fichero R Markdown está en la carpeta ‘informes’ y los datos en la carpeta ‘datos’,
la ruta al fichero sería “../datos/[fichero de datos]”
66 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
07
Ejemplo informe de análisis de datos
Emilio L. Cano
2019-01-27
5-
Este es mi primer ejemplo de informe generado con RStudio. Voy a crear un conjunto
de datos:
pdensity <- c(10.6817, 10.6040, 10.5709, 10.7858,
10.7668, 10.8101, 10.6905, 10.6079,
-0
10.5724, 10.7736, 11.0921, 11.1023,
11.0934, 10.8530, 10.6774, 10.6712,
10.6935, 10.5669, 10.8002, 10.7607,
10.5470, 10.5555, 10.5705, 10.7723)
Y este es su histograma:
19
20
or
ad
rr
¡Funcionó! Usar R para análisis de datos es genial.
Bo
2. Cambiar el comportamiento por defecto del paquete knitr para que los chunks se
evalúen en el directorio de trabajo del proyecto, como en el ejemplo que se verá más
adelante. En este caso, la ruta al fichero sería igual que en un script normal: “da-
tos/[fichero de datos]”
07
echo Mostrar código en informe
error Mostrar mensajes de error
5-
warning Mostrar mensajes de advertencia
message Mostrar mensajes
eval Evaluar el chunk
-0
fig.align Alineación de los gráficos
fig.width Ancho del gráfico generado (en pulgadas, por defecto 7)
19
fig.height Alto del gráfico generado (en pulgadas, por defecto 7)
out.width Ancho del espacio que ocupa el gráfico en el informe
out.height Alto del espacio que ocupa el gráfico en el informe
fig.keep Mantener los gráficos en el informe
20
include Mostrar salida de texto al ejecutar el código
results Forma de mostrar los resultados
Podemos manejar el aspecto que tendrá finalmente el resultado de los chunks en el informe
or
mediante un gran número de opciones. Las más habituales se pueden configurar en el cuadro
que aparece al hacer clic en el icono Modify chunk options (la ruedecita) arriba a la derecha
de cada chunk. Las opciones se pueden fijar para todos los chunks de un archivo R Markdown
ad
en el primer chunk del fichero, como se muestra en el ejemplo a continuación. Además de las
opciones de los chunks, también se pueden fijar opciones de configuración del paquete. La
lista completa de opciones tanto de chunks como del paquete se encuentra en https://yihui.
rr
Como en cualquier script, dentro de un chunk podemos ejecutar otros scripts mediante la
función source, por ejemplo para la importación de datos u otras acciones rutinarias, y dejar
el código en el informe lo más limpio posible.
corrplot
07
En el siguiente chunk, que no muestra ninguna salida (include=FALSE), se fija para
todos los chunks que no se muestre el código (echo=FALSE), y a nivel del paquete, que el
directorio de trabajo sea el anterior al que contiene el informe (por ejemplo, porque nuestro
5-
archivo R Markdown está dentro de la carpeta ‘informes’ del proyecto). Además, se ejecuta
el script ‘utiles.R’ que se encuentra en la carpeta ‘scripts’ del proyecto y carga el paquete
corrplot
-0
```{r config, include=FALSE}
knitr::opts_chunk$set(echo=FALSE)
knitr::opts_knit$set(root.dir = "..")
source("scripts/utiles.R")
19
20
library(corrplot)
```
Otra opción muy interesante para personalizar los informes con R Markdown, es el uso de
parámetros. Los parámetros se pueden incluir en el encabezado del documento R Markdown
or
y utilizar en los chunks como valores almacenados en el espacio de trabajo. Por ejemplo, pode-
mos tener un parámetro llamado “fichero” y acceder a él en un chunk como params$fichero,
por ejemplo para cargar distintos conjuntos de datos42 .
ad
1.5.4. Presentaciones
rr
Al crear un archivo R Markdown, podemos seleccionar que el tipo de documento sea una
presentación, véase la figura 1.30. Al igual que con los informes, podemos hacer presentaciones
tres formatos: html, pdf o PowerPoint43 . Para html tenemos dos opciones distintas, mientras
Bo
que para pdf se utiliza la clase Beamer de LaTeX. Igual que antes, no es necesario tener
conocimientos de LaTeX, aunque si se quieren incluir diseños elaborados es recomendable.
Las presentaciones en formato HTML incluyen las imágenes embebidas, y se podrá visualizar
en cualquier navegador moderno, por ejemplo Google Chrome, o “imprimir” en PDF. Igual
que para los documentos, las presentaciones en pdf requieren tener instalada una distribución
del sistema de edición libre LaTeX.
42
Véase otro ejemplo en https://rmarkdown.rstudio.com/lesson-6.html
43
Las presentaciones en Power Point están disponibles en la versión 1.2 de RStudio, que en el momento
de escribir este documento se puede obtener en versión “preview” aquí: https://www.rstudio.com/products/
rstudio/download/preview/
1.5. INFORMES REPRODUCIBLES 69
07
5-
-0
Figura 1.30: Nueva presentación R Markdown
Markdown son: 19
Al igual que para los documentos, las principales ventajas de realizar presentaciones con R
pega”.
La sintaxis es muy sencilla para las tareas más habituales, y también se pueden per-
feccionar incluyendo diseños más impactantes.
ad
Una opción más para crear presentaciones impactantes presentando resultados de análisis de
datos es utilizar el paquete xaringan (Xie, 2019c). Una vez instalado el paquete, creamos el
rr
Utilizar markdown para realizar informes de análisis de datos es la opción más sencilla tanto
por su uso como porque no se requieren otras aplicaciones instaladas. A continuación se
incluyen a modo de referencia otras opciones muy interesantes para comunicar resultados de
análisis de datos.
07
R Sweave: Permitir escribir documentos con sintaxis LaTeX y chunks de código R.
R HTML: Permite incrustar chunks de código en documentos html “puros”.
5-
R Presentation: Es un tipo de presentación nativa de RStudio similar a las creadas
con un nuevo R Markdown44 .
-0
1.5.5.2. Proyectos con múltiples documentos
19
R y RStudio ofrecen varias posibilidades para crear estructuras más complejas de documentos
con propósitos de comunicar resultados de análisis de datos. Los más importantes son:
R Markdown websites: Permite crear varios documentos relacionados con menús y
20
enlaces con una mínima estructura (véase el apartado 10.5 de (Xie et al., 2018a)).
blogdown: Permite una mayor complejidad para construir websites con estructura
de carpetas, posts y páginas con el paquete blogdown (Xie, 2019a), véase (Xie et al.,
2017).
or
2016).
coplejidad requieren, al igual que los proyectos de desarrollo de software, una adecuada
gestión y control de las versiones. El control de versiones en un proyecto de análisis de datos
permite registrar qué cambios se han hecho en el código (o en los informes) quién los hizo, y
(si está bien documentado) por qué.
Aunque hay varios sistemas de control de versiones, el más popular en el mundo del análisis de
datos es el repositorio GitHub (https://github.com) que, además, se integra perfectamente
en RStudio y permite enviar y recibir los cambios desde la propia aplicación. En Bryan (2019)
se puede encontrar un extraordinario recurso para utilizar GitHub y RStudio.
44
Véase una descripción más completa en https://support.rstudio.com/hc/en-us/articles/
200486468-Authoring-R-Presentations
1.6. PROGRAMACIÓN BÁSICA EN R 71
07
Una característica muy útil de R Markdown es que permite introducir ecuaciones y fórmulas
en formato LaTeX, que al generar el informe se incrustan también en el informe o presentación
de salida. Así, podemos incluir la especificación de un modelo o cualquier otra expresión
5-
matemática con esta sintaxis.
Por último, señalar que se pueden utilizar reference docs a modo de plantillas para crear
-0
documentos Word y Power Point con archivos R Markdown45 .
19
Realice la práctica 1.7 cuyo guión se encuentra en el apartado 1.7 para crear un
informe RMarkdown.
20
1.6. Programación básica en R
Al ser R un lenguaje de programación, los scripts pueden contener estructuras de control
or
como bucles y condiciones. Por otra parte, podemos crear nuestras propias funciones. A
continuación se muestran algunos ejemplos a modo ilustrativo, aunque no es el objetivo de
esta obra. Para profundizar más, véase la ayuda con help("function") y help(Çontrol").
ad
Existen snippets con plantillas para muchas estructuras de programación, véase Tools/Global
options -> Code -> snippets. Por ejemplo si en un script escribimos fun y pulsamos el
tabulador, se crea el esqueleto de una función. Aunque en algunos ejemplos del resto del libro
rr
En el primero de los siguientes fragmentos de código creamos una función que suma
∑
los elementos de un vector elevados al cuadrado ( x2i ). En el segundo, si un vector tiene
más de 10 elementos, asignamos al objeto grande el valor TRUE, y en otro caso le asignamos
FALSE. En el tercero, para cada elemento del vector, mostramos en la salida de la consola
(función cat) su valor al cuadrado.
sum(x^2)/length(x)
}
a2(unvector)
## [1] 38.5
if (length(unvector) > 10){
grande = TRUE
} else {
grande = FALSE
07
}
for (i in 1:10){
cat(un_vector[i]^2, sep="\n")
5-
}
-0
## 1
## 4
## 9
##
##
##
16
25
36
19
20
## 49
## 64
## 81
## 100
or
Un tipo de funciones especiales son las funciones anónimas: no se almacenan con un nombre,
sólo se utilizan temporalmente en el entorno en el que se crean (normalmente dentro de otra
función). Son especialmente útiles en las funciones “vectorizadas”.
ad
El siguiente código devuelve las diferencias de los valores de un vector con su media,
rr
elevadas al cuadrado.
sapply(unvector,
Bo
function(x) {
(x - mean(unvector))^2
})
## [1] 20.25 12.25 6.25 2.25 0.25 0.25 2.25 6.25 12.25 20.25
Las funciones vectorizadas aplican una función a los elementos de una lista o vector de n
elementos. En el ejemplo anterior, sapply devuelve el resultado en el formato más compacto
que puede. Otras funciones vectorizadas son:
lapply: Devuelve una lista de tamaño n
vapply: Especifica el tipo de salida
1.7. PRÁCTICAS 73
07
1.7. Prácticas
5-
En este apartado se presentan las prácticas a las que se han hecho referencia durante el
capítulo. La reproducibilidad del código ha sido comprobada con la sesión de R que se
-0
detalla en el Prefacio. El lector puede teclear el código o copiarlo y pegarlo en la consola o
el editor. También se puede descargar el script con el código de todas las prácticas con la
siguiente expresión:
19
download.file("http://emilio.lcano.com/b/adr/practicas/01-intro.R",
destfile = "01-intro.R")
20
Algunas expresiones pueden aparece comentadas (empezando por ##). Para ejecutarlas, selec-
cione la expresión sin los comentarios, o elimínelos. En cada práctica se proporciona código
para descargar los ficheros de datos de ejemplo, en caso de ser necesarios.
or
En esta primera práctica revisaremos el proceso de instalación del software necesario para
seguir el libro. Se describe el proceso para Windows, véase la documentación en la web de
R para otros sistemas. Los programas se deben instalar en el mismo orden en que aparecen.
rr
Descarga de R
Bo
Ve a http://www.r-project.org;
Haz click en el enlace Download R;
Selecciona un mirror próximo a tu localización;
Haz click en el enlace Download R for Windows;
Haz click en el enlace base;
Haz click en el enlace Download R 3.x.x for Windows;
Guarda el fichero .exe en una carpeta de tu ordenador.
74 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
Instala R
Instalación de R
Abre la carpeta donde guardaste el fichero .exe;
Haz doble click en el fichero R-3.x.x-win.exe;
Acepta las opciones por defecto en el asistente de instalación.
Descarga de RStudio
07
Ve a http://www.rstudio.com;
Haz click en el enlace Download bajo RStudio;
Haz click en el botón Download de la primera columna (“Open Source License”);
5-
Haz click en el enlace RStudio x.xx.xxx - Windows Vista/7/8/10;
Guarda el fichero .exe en una carpeta de tu elección.
-0
Instalación de RStudio
Abre la carpeta donde guardaste el fichero .exe;
19
Haz doble click en el fichero RStudio-x.xx.xxx.exe;
Acepta las opciones por defecto del asistente de instalación.
20
Iniciar programas
Abre el interfaz por defecto de R
Interactúa con la consola, prueba las siguientes expresiones:
or
1/6
ad
## [1] 0.1666667
set.seed(1)
x <- rnorm(30, 10, 2)
rr
summary(x)
Expresiones
La principal forma de interactuar con R es a través de la consola. La consola es un intérprete
de expresiones que espera a que introduzcamos una expresión cada vez, después la evalúa,
y produce un resultado (con salida visible o no). La consola espera que escribamos una
expresión tras el símbolo > Una vez escrita la expresión, pulsamos la tecla de retorno de
línea, si está completa la evalúa. Por ejemplo, la expresión más sencilla posible es escribir un
número (practica tú mismo todas las expresiones en la consola):
1
07
## [1] 1
Vemos que el resultado de esta expresión es una línea de texto con el número 1 entre corchetes
y a continuación el número 1. El número 1 entre corchetes es un identificador que se explicará
5-
más adelante. El resultado es el mismo número que hemos escrito. Un paso más sería hacer
un cálculo numérico, por ejemplo:
-0
1 + 1
## [1] 2
19
Podemos hacer operaciones aritméticas con números en la consola. ¿Qué pasa si la expresión
está incompleta?
20
1 +
Como podemos comprobar, el símbolo > cambia a +, indicando que la expresión no está
completa. El sistema queda así hasta que completamos la expresión, o pulsamos la tecla ESC,
que cancela la instrucción.
or
5 > 6
## [1] FALSE
rr
Por último, habíamos dicho que una llamada a una función es también una expresión. La
siguiente expresión es un ejemplo sencillo de una llamada a una función:
Bo
log(pi)
## [1] 1.14473
donde pi es a su vez una expresión que obtiene el valor del objeto interno que contiene el
valor de π = 3,14159 . . ..
pi
## [1] 3.141593
La función log obtiene el logaritmo de un número. La llamada a una función es siempre igual:
76 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
07
Siguiendo con el ejemplo del logaritmo, podemos ver los argumentos que puede recibir me-
diante la función str46 , o pulsando CTRL + ESPACIO después del paréntesis de apertura:
5-
str(log)
-0
Por tanto, log es una función que admite dos argumentos: x, que no tiene ningún valor
predeterminado, y base, cuyo valor predeterminado es la expresión:
exp(1)
## [1] 2.718282
19
20
es decir, el número e. Por tanto el valor que obtenemos con la función log es el logaritmo
natural (con base e) del número que le pasemos como primer argumento, o con otra base si
se la pasamos como argumento base. Por ejemplo el logaritmo decimal sería:
or
## [1] 3
ad
## Error in eval(expr, envir, enclos): el argumento "x" está ausente, sin valor por omis
Lo que pasa es que como no hay un valor predeterminado para el argumento x, la función
Bo
devuelve un error indicando que se necesita un argumento. El mensaje suele tener indicaciones
para resolver el problema. Algunas funciones pueden devolver el resultado sin necesidad de
ningún argumento. Por ejemplo, la función seq genera secuencias de números:
str(seq)
## function (...)
Los tres puntos (…) indican que la función acepta un número indeterminado de argumentos.
¿Qué pasa si la ejecutamos sin argumentos?
46
Esta función devuelve la estructura (structure) de cualquier objeto de R
1.7. PRÁCTICAS 77
seq()
## [1] 1
Obtenemos una secuencia de números desde el 1 hasta el 1 por intervalos de 1. Es decir,
simplemente un 1. Veremos más adelante cómo obtener ayuda sobre los argumentos de una
función.
Como la función no necesita ningún argumento para funcionar, ¿la podríamos usar sin los
paréntesis?
07
seq
## function (...)
5-
## UseMethod("seq")
## <bytecode: 0x7ff9a3f42880>
## <environment: namespace:base>
-0
La respuesta es no, porque para R, todos los símbolos son objetos. La expresión seq sin parén-
tesis es el símbolo de la función seq, y lo que devuelve el intérprete de R es el “contenido””de
la función, es decir, su código47 .
19
Podemos averiguar más sobre los argumentos que espera una función pulsando la tecla F1
con el cursor sobre la función, o llamando a la ayuda de R con cualquiera de las siguientes
20
expresiones:
help("seq")
?seq
or
O también con la ayuda contextual pulsando CTRL + ESPACIO tras escribir su nombre y
dentro de los paréntesis.
ad
Creación de objetos
Hasta ahora hemos utilizado expresiones pero no tenenos ningún objeto guardado en el
rr
x <- log(pi)
asigna al objeto cuyo símbolo es x el resultado de la expresión log(pi). Vemos que en este
caso no tenemos ninguna salida. Ahora bien, R ha almacenado en el objeto llamado x el valor
de esa expresión, como podemos comprobar en la pestaña Environment del panel superior
derecho. Los símbolos de objetos que vamos creando son expresiones en sí, y podemos mostrar
su valor simplemente escribiéndolos:
x
## [1] 1.14473
47
En este caso no se muestra todo el código porque es una función compilada.
78 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
A partir del momento en que lo hayamos creado, podemos utilizarlo para cualquier cálculo
posterior. Vamos a crear más objetos:
r <- 5
y <- x * r
Ahora tenemos tres objetos en nuestro espacio de trabajo. Podemos ver cómo los objetos van
apareciendo en la pestaña Environment del panel superior derecho. También podemos ver
una lista de los objetos desde la consola:
ls()
07
## [1] "r" "x" "y"
Mediante expresiones también podemos borrar objetos e incluso todo el directorio de trabajo.
5-
Guardo lo que llevo hecho:
save.image("~/tmp.RData")
-0
Limpio el espacio de trabajo:
rm(list = ls())
## character(0)
Creo un nuevo objeto llamado “mivariable” al que asigno 50 valores aleatorios de una distri-
or
Miro su estructura:
str(mivariable)
rr
Vemos que los objetos guardados se han añadido al espacio de trabajo actual, manteniendo
el objeto existente “mivariable”. No obstante, téngase en cuenta que si el espacio de trabajo
cargado contiene un objeto con el mismo nombre que otro existente en el Global Environment,
este último será sustituido por el que se importa.
48
función rnorm
1.7. PRÁCTICAS 79
ls()
Salida gráfica
Vamos a hacer un par de sencillos gráficos para ver cómo se producen y exploran las salidas
gráficas:
boxplot(mivariable)
07
plot(mivariable, type = "l")
Examina los gráficos en la pestaña Plots del panel inferior derecho. Utiliza las flechas de
5-
navegación de la barra superior.
-0
1.7.0.1. Ayuda
Por último, vamos a explorar la ayuda que proporciona RStudio. Podemos buscar nombres
19
de funciones con un texto determinado, por ejemplo “lm”:
apropos("lm")
20
## [1] ".colMeans" ".lm.fit" "colMeans"
## [4] "confint.lm" "contr.helmert" "dummy.coef.lm"
## [7] "getAllMethods" "glm" "glm.control"
## [10] "glm.fit" "KalmanForecast" "KalmanLike"
or
Nótese que el número de funciones disponibles dependerá de los paquetes instalados en cada
versión de R, por lo que puede no coincidir con los que se muestran aquí.
Bo
Y a los ejemplos:
example(boxplot)
07
Antes de iniciar la práctica, asegúrate de que tu espacio de trabajo está vacío, para centrarnos
solo en lo que hace esta práctica. Si no lo está, vacíalo con el icono de la escoba en la pestaña
5-
Environment.
Aunque es más cómodo gestionar los paquetes en la pestaña Packages de RStudio, vamos a
-0
instalar el paquete micEcon (Henningsen, 2017) desde la consola. Nótese que el nombre del
paquete para la instalación debe ir entre comillas.
## Instalar paquete
install.packages("micEcon")
19
Para cargar un paquete, utilizamos la función library. En este caso, el nombre del paquete
20
puede ir o no ir entre comillas:
library(micEcon)
or
##
## If you have questions, suggestions, or comments regarding one of the 'micEcon' packag
## https://r-forge.r-project.org/projects/micecon/
ad
Los paquetes se instalan en librerías. Podemos consultar las librerías disponibles en nuestra
instalación de R:
Bo
Mediante código se pueden realizar operaciones con ficheros, por ejemplo la siguiente expre-
sión devuelve una lista de ficheros en el directorio de trabajo:
1.7. PRÁCTICAS 81
dir()
No obstante, a menos que sea con propósitos de programación, casi siempre es suficiente con
utilizar la pestaña Files para trabajar con ficheros, siempre teniendo en cuenta que el botón
Delete elimina de forma permanente los ficheros y carpetas seleccionados, sin pasar por la
papelera. En una práctica posterior importaremos ficheros de datos al espacio de trabajo.
Vamos ahora a crear un script. Utiliza el menú File/New File/R Script o el icono que hay
debajo de este menú. Escribe las siguientes expresiones en el mismo:
07
## Esto es un comentario explicativo
## El siguiente es un comentario temporal, para no ejecutar la expresión
# mean(x)
set.seed(1)
5-
unvector <- round(rnorm(10, 10, 2), 2)
mean(unvector)
-0
unvector^2
cat("fin del fichero")
Guarda el script con el nombre “rutina.R”49 . Ejecuta las expresiones una a una desde el
19
editor, bien con CTRL + INTRO o con el icono Run.
Cierra el script y ejecútalo desde la consola con la función source:
20
source("rutina.R", print.eval = TRUE)
menú de nuevo proyecto (figura 1.31). Elegimos “New Directory” (figura 1.32) y, a continua-
ción, “Empty Project” (figura 1.33)50 .
En la última ventana (figura 1.34):
rr
1. Escribe el nombre del directorio (que va a ser también el nombre del proyecto y no se
debe cambiar después).
Bo
07
5-
-0
19
20
Figura 1.31: Crear un nuevo proyecto en RStudio
or
ad
rr
Bo
07
5-
-0
19
Figura 1.33: Nuevo proyecto vacío
20
or
ad
rr
Bo
Crea las siguientes carpetas dentro del proyecto con el icono New Folder de la pestaña Files:
datos: Aquí guardaremos todos los ficheros de datos.
practicas: guardaremos los archivos fuente de las prácticas, que contienen el código
(generalmente ficheros .R, scripts).
scripts: aquí podemos guardar los scripts que queramos hacer de pruebas, por ejemplo
(ficheros .R).
informes: aquí guardaremos los informes que hagamos.
A partir de este momento, asegúrate siempre de que estás trabajando en un proyecto de
RStudio para seguir correctamente los ejemplos y prácticas del libro.
07
Práctica 1.5: Estructuras de datos
5-
Objetivo
En esta práctica vamos a trabajar con estructuras de datos en gran medida creándolos de
-0
cero desde el código. Lo practicado aquí servirá también para aplicar a datos importados de
ficheros.
rm(list = ls())
Vectores
ad
La estructura de datos básica es el vector. Es sobre vectores sobre los que vamos a realizar
análisis de datos. Crea los siguientes vectores desde el script. Observa cómo se van añadiendo
rr
## [1] 10 20 30
x2 <- 1:10; x2
## [1] 1 2 3 4 5 6 7 8 9 10
x3 <- seq(0, 1, 0.1); x3
## [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
x4 <- c(rep("IBERICO", 3), rep("SERRANO", 2)); x4
1.7. PRÁCTICAS 85
## [1] 1 2 3 4 5
Crea un vector introduciendo datos directamente en la consola con la función scan. Introduce
unos cuantos valores numéricos y para terminar, pulsa INTRO sin introducir ningún dato.
x <- scan() # Ejecutar en la consola
07
miFactor <- factor(1:5, labels = letters[1:5]); miFactor
## [1] a b c d e
5-
## Levels: a b c d e
factorNiveles <- gl(5, 3, labels = letters[1:5]); factorNiveles
-0
## [1] a a a b b b c c c d d d e e e
## Levels: a b c d e
vectorLogico <- 1:10 > 5; vectorLogico 19
20
## [1] FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE
Asigna nombres al vector x1 y comprueba el número de elementos que tiene.
names(x1) <- c("semana1", "semana2", "semana3")
x1
or
length(x1)
## [1] 3
rr
1:length(x1)
Bo
## [1] 1 2 3
Selección en vectores
x1[1]
## semana1
## 10
x1["semana1"]
## semana1
## 10
86 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
x1[c(1,3)]
## semana1 semana3
## 10 30
x1[-c(1)]
## semana2 semana3
## 20 30
Selección lógica
07
x1 >= 15
5-
## FALSE TRUE TRUE
x1[x1 >= 15] # Equivale a x1[c(2, 3)
-0
## semana2 semana3
## 20 30
x4[x4 != "IBERICO"]
Ordenación. Hay dos funciones relacionadas con el orden de los elementos de un vector,
con una obtenemos el vector ordenado, y con la otra obtenemos los índices que ocupan los
valores ordenados, es decir, el primer elemento del vector es el índice del mínimo valor, y así
ad
x6
Bo
## [1] 9 5 4 8 4 5 3 1 6 5
sort(x6)
## [1] 1 3 4 4 5 5 5 6 8 9
rev(sort(x6))
## [1] 9 8 6 5 5 5 4 4 3 1
order(x6)
## [1] 8 7 3 5 2 6 10 9 4 1
1.7. PRÁCTICAS 87
07
x1 + 2
5-
x2
-0
## [1] 1 2 3 4 5 6 7 8 9 10
x5
## [1] 1 2 3 4 5
x2 + x5 19
20
## [1] 2 4 6 8 10 7 9 11 13 15
x1 + x3
## de uno menor
## [1] 10.0 20.1 30.2 10.3 20.4 30.5 10.6 20.7 30.8 10.9 21.0
ad
mean(x1)
## [1] 20
sqrt(x1)
rr
Matrices
Creación y acceso a matrices
miMatriz <- matrix(c(10, 20, 30, 40, 12, 26, 34, 39),
nrow = 4, ncol = 2); miMatriz
## [,1] [,2]
## [1,] 10 12
## [2,] 20 26
88 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
## [3,] 30 34
## [4,] 40 39
miMatriz[1, ]
## [1] 10 12
miMatriz[, 1]
## [1] 10 20 30 40
miMatriz[3, 2]
07
## [1] 34
5-
Podemos asignar nombres a las filas y columnas de una matriz, y realizar cálculos sobre filas
o columnas
colnames(miMatriz) <- c("variable1", "variable2")
-0
rownames(miMatriz) <- c("caso1", "caso2", "caso3", "caso4")
miMatriz
##
##
##
caso1
caso2
variable1 variable2
10
20
12
26
19
20
## caso3 30 34
## caso4 40 39
rowSums(miMatriz)
or
colMeans(miMatriz)
## variable1 variable2
## 25.00 27.75
rr
Arrays
Bo
## , , 1
##
## [,1] [,2] [,3] [,4]
## [1,] "a" "d" "g" "j"
## [2,] "b" "e" "h" "k"
## [3,] "c" "f" "i" "l"
##
## , , 2
##
1.7. PRÁCTICAS 89
Listas
Las listas se pueden crear introduciendo sus elementos, que pueden ser otros objetos ya
creados. Las listas también están indexadas y se puede acceder a sus elementos por índice o
07
por nombre. En este caso, el acceso por nombre se puede hacer mediante el operador $.
miLista <- list(matriz = miMatriz, vector1 = x1, x2); miLista
5-
## $matriz
## variable1 variable2
## caso1 10 12
-0
## caso2 20 26
## caso3 30 34
##
##
##
caso4
$vector1
40 39
19
20
## semana1 semana2 semana3
## 10 20 30
##
## [[3]]
## [1] 1 2 3 4 5 6 7 8 9 10
or
Acceso a listas
ad
miLista$vector1
miLista[[1]]
Bo
## variable1 variable2
## caso1 10 12
## caso2 20 26
## caso3 30 34
## caso4 40 39
miLista["vector1"]
## $vector1
## semana1 semana2 semana3
## 10 20 30
90 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
miLista[3]
## [[1]]
## [1] 1 2 3 4 5 6 7 8 9 10
miLista$matriz[, 2]
07
habituales para análisis estadístico, son listas a las que se acceden como hemos visto atrás.
modelo <- lm(Ozone ~ Temp, airquality)
class(modelo); typeof(modelo)
5-
## [1] "lm"
-0
## [1] "list"
names(modelo)
## [1]
## [5]
## [9]
"coefficients" "residuals"
"fitted.values" "assign"
"na.action" "xlevels"
19 "effects"
"qr"
"call"
"rank"
"df.residual"
"terms"
20
## [13] "model"
var(modelo$residuals)
## [1] 557.4773
or
La diferencia entre los corchetes simples y dobles es que los dobles devuelven el objeto original
dentro de la lista (por ejemplo, un vector), mientras que el corchete simple devuelve una lista
ad
que contiene los elementos de la selección. Vemos que también podemos acceder directamente
a un elemento del objeto que hay dentro de la lista, por ejemplo una fila de la matriz en el
primer elemento de la lista.
rr
Aunque lo normal será que importemos los datos de ficheros csv como veremos en el siguien-
te apartado, algunas veces necesitaremos crear nuestras propias tablas de datos. Podemos
obtener la estructura del conjunto de datos y el número de filas.
Crear data.frames:
misDatos <- data.frame(tipo = c("A", "A", "B", "C", "C", "C"),
peso = c(10, 20, 15, 13, 23, 8)); misDatos
## tipo peso
## 1 A 10
## 2 A 20
1.7. PRÁCTICAS 91
## 3 B 15
## 4 C 13
## 5 C 23
## 6 C 8
str(misDatos)
07
nrow(misDatos)
## [1] 6
5-
Una vez tenemos un objeto de clase data.frame, podemos acceder a sus filas y columnas de
la misma forma que una matriz, y a las columnas (variables) de la misma manera que a las
listas. Aquí vemos la aplicación de la selección mediante vectores lógicos.
-0
misDatos$peso
## [1] 10 20 15 13 23
misDatos[3, ]
8
19
20
## tipo peso
## 3 B 15
misDatos$peso < 15
or
## tipo peso
## 1 A 10
## 4 C 13
rr
## 6 C 8
Para no tener que usar el símbolo $, probamos las dos alternativas. La no recomendada:
Bo
attach(misDatos)
peso <- peso * 2.20462
# más instrucciones
detach(misDatos)
Buenas prácticas:
with(misDatos, {
peso <- peso * 2.20462
# más instrucciones
})
92 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
## tipo peso
## 1 A 10
## 4 C 13
## 6 C 8
07
aggregate(peso ~ tipo, data = misDatos, mean)
## tipo peso
## 1 A 15.00000
5-
## 2 B 15.00000
## 3 C 14.66667
-0
misDatos[order(misDatos$peso), ]
## tipo peso
##
##
##
6
1
4
C
A
C
8
10
13
19
20
## 3 B 15
## 2 A 20
## 5 C 23
or
## 1 A 10 NA
## 2 A 20 NA
Bo
## 3 B 15 NA
## 4 C 13 NA
## 5 C 23 NA
## 6 C 8 NA
misDatos$prueba <- NULL; misDatos
## tipo peso
## 1 A 10
## 2 A 20
## 3 B 15
## 4 C 13
1.7. PRÁCTICAS 93
## 5 C 23
## 6 C 8
Columnas calculadas:
misDatos$proporcion <- misDatos$peso/sum(misDatos$peso)
misDatos$suma <- misDatos$peso + misDatos$proporcion
misDatos
07
## 2 A 20 0.22471910 20.224719
## 3 B 15 0.16853933 15.168539
## 4 C 13 0.14606742 13.146067
5-
## 5 C 23 0.25842697 23.258427
## 6 C 8 0.08988764 8.089888
-0
Accede y modifica los nombres de filas y columnas del data frame y explora los resultados
en el Environment y el visualizador de datos.
colnames(misDatos)
misDatos
Valores especiales
Creamos un vector con valores perdidos y vemos qué pasa si intentamos calcular la media:
x <- c(1, 3, NA, 5, 6)
mean(x)
## [1] NA
Tenemos que especificar en la función que ignore los valores perdidos, o bien imputarles algún
valor.
94 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
## [1] 3.75
x[is.na(x)] <- 0; x
## [1] 1 3 0 5 6
mean(x)
## [1] 3
07
Otros valores especiales:
NULL
5-
## NULL
1/0
-0
## [1] Inf
sqrt(-1)
19
## Warning in sqrt(-1): Se han producido NaNs
20
## [1] NaN
1i
## [1] 0+1i
or
pi
## [1] 3.141593
ad
letters
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q"
rr
## [18] "r" "s" "t" "u" "v" "w" "x" "y" "z"
LETTERS
Bo
## [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q"
## [18] "R" "S" "T" "U" "V" "W" "X" "Y" "Z"
month.name
## [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov"
1.7. PRÁCTICAS 95
## [12] "Dec"
07
y <- as.numeric(x)
5-
y
## [1] 1 2 NA
-0
str(y)
## num [1:3] 1 2 NA
class(y) 19
20
## [1] "numeric"
is.numeric(y)
## [1] TRUE
or
Las fechas en formato texto se importan como vectores. Nótese que hemos incluido el argu-
mento stringsAsFactors = FALSE para evitar que los cree como factores. Hay que trans-
formarlas en fechas, nótese cómo afecta el tipo de datos a la ordenación.
str(vectorfechas)
07
## [11] "2011-09-30" "2011-09-30" "2011-09-30" "2011-10-03" "2011-10-04"
## [16] "2011-10-04" "2011-10-04" "2011-10-04" "2011-10-04" "2011-10-05"
Vamos a dar formato a las fechas y por ejemplo obtener una tabla de frecuencias por día de
5-
la semana.
vectornumeromes <- format(vectorfechas, "%m")
-0
vectormes <- format(vectorfechas, "%Y-%m")
vectordiasemana <- format(vectorfechas,"%A")
table(vectordiasemana)
## vectordiasemana
## jueves lunes
19
martes miércoles viernes
20
## 5 1 5 5 4
Consulta la ayuda ?strptime y explora más opciones de formato, por ejemplo para obtener
el número de semana del año.
or
Recodificación - discretización
Vamos a usar un nuevo conjunto de datos, se puede descargar así:
ad
download.file("http://emilio.lcano.com/b/adr/p/datos/ejdatos.csv",
"datos/ejdatos.csv")
rr
Lo leemos y creamos una variable nueva disc que divida la variable merma en 4 cortes
(breaks), poniendo unas etiquetas personalizadas.
Bo
include.lowest = TRUE)
summary(ejDatos$disc)
## A1 A2 A3 A4
## 30 50 19 1
07
## [1] A2 A3 A2 A3 A1 A2 A1 A2 A1 A2 A3 A1 A2 A1 A2 A2 A2 A2 A2 A2 A2 A1 A3
## [24] A2 A2 A1 A1 A1 A1 A1 A2 A2 A3 A2 A2 A2 A2 A1 A2 A3 A2 A2 A2 A3 A2 A1
## [47] A2 A2 A2 A2 A2 A3 A1 A1 A1 A2 A3 A3 A1 A3 A2 A4 A2 A2 A3 A2 A1 A3 A2
5-
## [70] A1 A2 A2 A1 A3 A2 A1 A3 A2 A3 A2 A1 A1 A2 A2 A1 A2 A1 A2 A2 A1 A2 A3
## [93] A1 A2 A3 A1 A1 A2 A3 A1
## Levels: A1 A2 A3 A4
-0
levels(ejDatos$disc)
Los factores pueden estar ordenados si los niveles tienen una relación de orden. Para ilustrar
la creación de un factor ordenado, vamos a invertir el orden del que ya tenemos. Observa en
ad
el Environment la diferencia.
ejDatos$disc2 <- ordered(ejDatos$disc,
levels = c("alto", "medio-alto", "medio-bajo", "bajo"))
rr
levels(ejDatos$disc2)
str(ejDatos$disc2)
07
El primer fichero con el que vamos a trabajar es uno llamado “ejDatos.csv”, que contiene da-
tos sobre la producción de un determinado producto de alimentación. La siguiente expresión
descarga el fichero a la carpeta “datos” de nuestro proyecto.
5-
download.file("http://emilio.lcano.com/b/adr/p/datos/ejDatos.csv",
"datos/ejDatos.csv")
-0
Abre el fichero de texto en el editor (clic en el fichero y View file) y observa cómo son los
valores. Claramente tiene encabezados, el separador es el punto y coma y el símbolo decimal
19
la coma. Si al importarlo con Import Dataset en la pestaña Environment no detectara estos
parámetros habría que especificarlos. Es importante asignar el resultado de la importación
a un objeto, si no lo hacemos los datos se mostrarán en el output, pero no se guardarán en el
20
espacio de trabajo. Este fichero en particular lo podemos importar también mediante código
utilizando cualquiera de las siguientes expresiones:
ejDatos <- read.csv2("datos/ejDatos.csv")
ejDatos <- read.table("datos/ejDatos.csv",
or
Al hacerlo con el paquete readr (que es lo que realmente utiliza el Import Dataset), hay que
ad
que produce el mismo resultado que los anteriores, informando en el output del tipo de datos
que ha asignado a cada columna.
07
destfile = "datos/RRHH.xlsx",
mode = "wb")
5-
ninguna opción ya que es un fichero bien estructurado de Excel. Tras la importación debemos
tener el siguiente código:
-0
library(readxl)
RRHH <- read_excel("datos/RRHH.xlsx")
¿Notas alguna diferencia? Observa cómo se importan también algunos metadatos del formato
original:
rr
El fichero Stata, la clase del objeto creado y una muestra de los datos:
library(haven)
Bo
## # A tibble: 6 x 5
## state educspnd income prop18 propurb
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 ME 189 2824 351. 508
## 2 NH 169 3259 346. 564
100 CAPÍTULO 1. INTRODUCCIÓN AL ANÁLISIS DE DATOS CON R
07
## Min. : 14.00 Min. : 17.0 Min. :1.800 Min. :1.300
## 1st Qu.: 54.00 1st Qu.: 53.0 1st Qu.:3.150 1st Qu.:2.900
## Median : 64.00 Median : 62.0 Median :3.600 Median :3.200
5-
## Mean : 64.82 Mean : 62.6 Mean :3.723 Mean :3.185
## 3rd Qu.: 77.00 3rd Qu.: 73.0 3rd Qu.:4.100 3rd Qu.:3.400
## Max. :113.00 Max. :104.0 Max. :7.400 Max. :8.900
-0
## DAYS LACTATIO I79
## Min. : 21.0 Min. :1.000 Min. :0.0000
##
##
##
1st Qu.:105.0
Median :149.0
Mean :155.1 Mean
19
1st Qu.:1.000
Median :2.000
:2.236
1st Qu.:1.0000
Median :1.0000
Mean :0.8492
20
## 3rd Qu.:208.5 3rd Qu.:3.000 3rd Qu.:1.0000
## Max. :301.0 Max. :8.000 Max. :1.0000
El fichero SAS y sus variables:
pulmon <- read_sas("datos/lung.sas7bdat")
or
names(pulmon)
ad
Ficheros RData
Vamos a exportar algunos datos al formato de datos de R:
merma <- ejDatos[, 2:3]
save(merma, file = "datos/merma.RData")
07
Exportación
5-
Vamos ahora a exportar los datos que importamos desde Excel a formato csv. Ya deberiamos
tener el objeto RRHH en el espacio de trabajo, si no es así, lo volvemos a importar:
-0
library(readxl)
RRHH <- read_excel("datos/RRHH.xlsx")
plantilla.
Examina el texto y el código del fichero creado.
Genera el informe en formato HTML con el botón Knit.
Abre el fichero de ejemplo de esta práctica. Observa qué se hace en cada chunk.
Genera el informe en HTML sin hacer ningún cambio
Cambia opciones de los chunks y vuelve a generarlo, observa los diferentes resultados.
Realiza algún análisis con esos datos, ve cambiando cosas para ver cómo se actualiza
el informe automáticamente.
07
HTML, porque si lo hacemos siempre en Word hay que estar cerrando el fichero y abriéndolo.
Genera el informe en Word.
5-
-0
19
20
or
ad
rr
Bo
Capítulo 2
07
Análisis exploratorio de datos con R
5-
Independientemente de los datos que tengamos y de las técnicas estadísticas que sean más
-0
apropiadas para el análisis, siempre empezaremos por un análisis descriptivo que nos permita
conocer los datos e identificar posibles problemas. Con el análisis exploratorio de datos
podremos identificar cuáles van a ser esas técnicas más apropiadas, limpiar los datos, y
19
organizarlos de una forma estructurada para aplicar las técnicas.
20
2.1. Estructuras de datos y tipos de variables
Para realizar análisis de datos, necesitamos que estos estén estructurados de forma adecua-
da. Algunas fuentes de información contienen datos no estructurados, como por ejemplo la
or
información de texto, imágenes y videos disponible en Internet (vídeos, imágenes, redes so-
ciales, contenidos, etc.). Otro tipo de datos no estructurados (aunque lo parezcan) son las
hojas de cálculo que de forma más o menos anárquica se van elaborando en las empresas con
ad
los datos que se producen en distintos departamentos o áreas. Este tipo de información no
estructurada se debe tratar convenientemente de forma que tenga el formato adecuado para
el análisis de datos.
rr
103
104 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
de observaciones, son datos multivariantes, frente a los datos univariantes cuando tenemos
una sola característica. Generalmente tenemos datos multivariantes con los que podremos
hacer análisis estadístico univariante de cada una de las características observadas y análisis
estadístico multivariante utilizando conjuntamente varias variables.
07
En el análisis univariante, trabajaremos con vectores de datos con los que podemos
hacer cálculos con todos los elementos, o con cada uno de ellos.
5-
En al análisis multivariante será igual, pero trabajando con cálculo matricial.
Nótese que cuando estamos observando características no numéricas (por ejemplo, la ocupa-
-0
ción en una serie de individuos), el vector que representa la variable no contiene números,
sino atributos. Esto difiere del concepto matemático de vector y matriz, donde los componen-
19
tes son siempre números. Estas variables tendrán un tratamiento distinto según los objetivos
del análisis, que a lo largo del texto se irán describiendo, así como su posible tratamiento en
el análisis de datos.
20
2.1.2. Tipos de variables y escalas
Las características a observar pueden dar lugar a diferentes tipos de datos o variables. Antes
or
de realizar ningún tipo de análisis, lo primero que tenemos que tener en cuenta es qué
tipos de variables tenemos. Dependiendo del tipo de variable, tanto el tratamiento de esos
datos como los modelos a aplicar para la toma de decisiones puede ser distinto. Veamos
ad
los distintos tipos de variables que nos podemos encontrar. La primera clasificación posible
es si las variables son numéricas o nominales. Una variable numérica o cuantitativa es
aquella cuya característica a observar se puede expresar como un número. Las variables
rr
categóricas o cualitativas son aquellas que no se pueden expresar como un número (con
sentido numérico), sino que indican una cualidad o atributo que tiene el elemento. A su
vez, las variables cuantitativas puden ser de dos tipos: variables continuas cuando pueden
Bo
tomar cualquier valor en un intervalo dado (es decir, infinitos), y variables discretas,
cuando podemos contar el número de valores que puede tomar la variable (pueden ser finitos
o infinito numerable). Por su parte las variables cualitativas pueden tener varios niveles o solo
dos (dicotómicas). Si en una variable categórica podemos ordenar las categorías, entonces
tenemos variables ordinales, a las que podremos asignar un número de orden y aplicar
algunos cálculos de las variables numéricas1 .
Relacionado con estos tipos de variables, a menudo se habla de Escalas de medida. Cada
variable está referida e una escala de medida, que puede ser:
1
Pero con cuidado, porque realmente no son variables cuantitativas.
2.1. ESTRUCTURAS DE DATOS Y TIPOS DE VARIABLES 105
Escala nominal. Los valores que toma la variable son etiquetas que diferencian a los
individuos en grupos.
Escala ordinal: Los valores que toma el atributo indican un orden de precedencia entre
los individuos, pero no la distancia entre ellos.
Escala métrica: Permiten medir diferencias entre individuos, puesto que cuantifica el
grado en que se da la característica en el individuo.
Nótese que a nivel de estructura de datos, podemos almacenar los atributos como números
07
(por ejemplo, 1=hombre, 2=mujer), pero lo importante es la naturaleza de la característica
que estamos midiendo y su escala.
En el apartado 2.3 volveremos sobre estos conceptos cuando hablemos de conjuntos de datos
5-
multivariantes.
-0
La variable tiempo cuando se refiere al momento en que se realiza la medición, por ejemplo la
fecha y hora, es un tipo especial de datos que algunas veces tratamos como variable nominal
para estudiar datos en distintos momentos del tiempo, realizando las agrupaciones oportunas.
19
Agrupados o sin agrupar, uno de los principales usos de la variable tiempo es el de ordenar los
datos y comparar en periodos de tiempo distintos, o estudiar la evolución. En otras técnicas
puede ser tratada como una variable en escala métrica.
20
Téngase en cuenta que las variables continuas se pueden discretizar, simplemente creando
intervalos que representen un atributo creado de forma arbitraria. Por ejemplo, si tenemos
una variable que sea el sueldo de los empleados de una empresa (numérica continua), podemos
crear una variable cualitativa que sea nivel de ingresos con las categorías bajo, medio, y alto
or
el número de clientes que visitan una página web hasta que se materializa una compra,
el número de piezas producidas de un determinado artículo, el número de pasas en una
cucharada de cereales, etc.
Ejemplos de variables categóricas es cualquier atributo que se pueda observar en un deter-
minado elemento. Por ejemplo, si una pieza es defectuosa o no, la especie de los animales
en una granja, el tipo de música o cine preferido, el tipo de queso en una fábrica de quesos,
etc. La estación del año, el día de la semana, o el mes, son ejemplos de variables categóricas
relacionadas con la variable tiempo (que por naturaleza es continua). Las mediciones en una
escala de preferencias como por ejemplo del 1 al 5 donde 1 es nada satisfecho y 5 es muy
satisfecho, son del tipo nominal ordinal.
106 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
Probabilidad
Población Estadística
Descriptiva
Muestra
07
5-
Inferencia Estadística
Figura 2.1: Relación entre la Estadística Descriptiva, el Cálculo de Probabilidades y la Es-
-0
tadística Inferencial
Otras técnicas nos servirán para realizar inferencia sobre la población, es decir, obtener
estimaciones, predicciones, extraer conclusiones o tomar decisiones para toda la población a
partir de la evidencia que muestran los datos de la muestra.
ad
El muestreo y sus técnicas no se trata en este texto, pero debe tenerse en cuenta que la
adecuada selección de la muestra es un tema de vital importancia para el análisis de datos
en general.
rr
Bo
07
desviación. Se suele atribuir a una de las siguientes causas:
1. Error de medida o de registro. Esto puede ser debido a la observación del dato o al
propio registro.
5-
2. Contaminación. Los datos provienen de más de una distribución. Por ejemplo, por
estar mezclando datos de grupos que tienen distintas medias. Entonces, los valores
-0
de la distribución contaninante aparecerán como valores atípicos en la distribución de
interés.
19
3. Suposición incorrecta sobre la distribución. La característica en estudio de la pobla-
ción se supone que sigue una determinada distribución (por ejemplo normal) pero en
realidad sigue otra (por ejemnplo exponencial). Entonces los valores que parecen atí-
20
picos para la distribución normal, son perfectamente compatibles con la distribución
verdadera.
4. Observaciones excepcionales. Estos no son verdaderos valores atípicos, simplemente
or
por grupos, separando las distribuciones. Si son solo unos pocos datos los que por error
han contaminado la muestra, se pueden eliminar o dar por perdidos. En el tercer caso, se
modifican las asunciones sobre el modelo de distribución subyacente en la población. En el
rr
último caso los valores deberían permanecer en la muestra, aunque generalmente se etiquetan
erróneamente como valores atípicos por su excepcionalidad.
Bo
El análisis de los valores atípicos es importante por varios motivos. Por una parte, puede dar
lugar a descubrimientos interesantes al investigar por qué han ocurrido (por ejemplo, se ha
hecho algo diferente y un proceso ha mejorado). Por otra parte, muchas medidas y métodos
estadísticos son muy sensibles a observaciones atípicas, y entonces es posible que haya que
usar alternativas robustas. Y en todo caso, nos ayuda a determinar la adecuada distribución
de probabilidad.
La observación de los datos con métodos gráficos a menudo proporciona suficiente informa-
ción para identificar valores candidatos a ser atípicos. En contreto, el gráfico de cajas diseñado
por John W. Tukey (Tukey, 1977) y recogido en la norma UNE-ISO 16269 (ISO, 2010) marca
estos valores de forma clara (véase el apartado 2.2.2 para una completa explicación de su
108 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
construcción e interpretación).
Aparte de los métodos gráficos, existen diversos contrastes de hipótesis para determinar si
existen valores atípicos en una muestra de datos dada una distribución de probabilidad. La
norma UNE-ISO 16269 (ISO, 2010) recoge métodos para la distribución normal y también
para otros modelos de distribución, así como un método general para distribuciones descono-
cidas y el test de Cochran para varianza atípica. El paquete outliers de R contiene varias
funciones para realizar contrastes de hipótesis sobre valores atípicos a un conjunto de datos,
incluidos el test de Grubbs y el test de Cochran.
En cuanto al tratamiento de datos que contienen valores candidatos a ser atípicos pero de
07
los que no se ha podido identificar una causa válida para eliminarlos, deberíamos recurrir al
análisis de datos robusto, de forma que las observaciones atípicas no influyan demasiado
en los resultados, pero sin eliminarlas. Otra alternativa es realizar el análisis con y sin valores
5-
candidatos a ser atípicos y comprobar cómo varía ese resultado.
Entre las medidas de centralización robustas se encuentran la mediana y la media recortada
-0
(véase 2.2.1.2), aunque hay otras. También para la estimación de la dispersión se encuentran
estimadores robustos como la Mediana de las medianas de las desviaciones absolutas de los
pares (ISO, 2010).
19
Lo dicho hasta ahora sirve para detectar atípicos para una característica. En conjuntos
multivariantes, se pueden observar valores atípicos con respecto a más de una variable. En
20
particular, en modelos de regresión puede haber observaciones influyentes (que posiblemente
no son atípicas en la variable aislada) que influyen en la estimación de los parámetros de forma
que el resultado no es representativo del conjunto de datos. Los gráficos de diagnóstico de
R para los modelos lineales proporcionan un gráfico señalando las observaciones influyentes
or
según la distancia de Cook. También el paquete car contiene una función (outlierTest)
con la que podemos obtener la observación más extrema para la regresión.
Por último, podemos detectar observaciones atípicas con respecto a todo un conjunto multi-
ad
variante de datos en escala métrica. Para ello, lo que se hace es reducir este conjunto multiva-
riate en univariante, obteniendo unas distancias de las observaciones a la media muestral del
conjunto de datos, estandarizada mediante la matriz de varianzas-covarianzas de la muestra.
rr
Entonces aquellas observaciones muy alejadas de esos valores centrales pueden estudiarse
como candidatos a ser valores atípicos multivariantes. En ISO (2010) se proporciona un con-
traste de hipótesis y un método gráfico para identificar estos valores atípicos. En el apartado
Bo
07
dos variables2 .
El segundo camino es más complicado y requiere a su vez elegir el método de imputación
del valor perdido. La imputación más sencilla es simplemente asignar la media o la mediana
5-
como valor representativo de toda la variable. Pero cuando tenemos conjuntos multivariantes,
puede ser más adecuado hacer una imputación en función de la información disponible en
otras variables. Por ejemplo, si tenemos una variable de tipo atributo, la media del grupo al
-0
que pertenece la observación será generalmente más adecuada que la media global.
En R tenemos varias alternativas para la imputación de valores perdidos. La función impute
19
del paquete Hmisc realiza imputaciones sencillas (por defecto la mediana). El paquete mice
realiza imputaciones utilizando datos multivariantes con un buen número de opciones.
20
La investigación de los valores perdidos y su tratamiento adecuado debe ser siempre una
fase importante del proyecto de análisis de datos. Además, este análisis se puede solapar con
el análisis de los valores atípicos, por ejemplo cuando un valor atípico se determina que es
un dato erróneo pero no podemos asegurar cuál es el valor verdadero, entonces tenemos que
considerarlo como perdido y aplicar lo aquí visto.
or
Aparte de los errores en los datos que ya se han tratado, hay que evitar algunos errores
demasiado comunes a la hora de abordar el análisis de datos, y especialmente la interpretación
de resultados. En este apartado se mencionan algunos de los más importantes.
rr
el fenómeno a estudiar, frente a modelos más complejos (con muchas variables) con una
mínima o nula ganancia de poder predictivo. En modelos de regresión múltiple, por ejemplo,
ninguna variable cuyo coeficiente no sea significativo se debería incluir en el modelo final al
que llega la investigación.
Este error común viene explicado por la paradoja de Simpson (Wikipedia, 2019). Esta
paradoja aparece cuando hay un atributo oculto que no se tiene en cuenta a la hora de
interpretar porcentajes, pudiendo darse el caso de que otro atributo presenta un porcentaje
07
mayor en una categoría, pero si se analizan por separado los porcentajes para las categorías
del atributo oculto, resulta que el porcentaje de la categoría que era mayor globalmente, es
menor en TODOS los grupos del atributo oculto.
5-
3. Informar los valores medios pero no la dispersión.
La media por sí sola no debería llevar a conclusión alguna. Siempre se debe analizar conjun-
-0
tamente la centralidad y dispersión de los datos, ya que un valor medio puede estar calculado
con valores muy extremos y ocultar mucha información.
19
4. Pasar por alto las hipótesis del modelo.
Muchos modelos estadísticos requieren, para ser válidos, que se cumplan ciertas condiciones.
20
Si utilizamos un método que requiere normalidad, debemos comprobar que los datos pro-
vienen de una distribución normal. Ante la duda, debemos comprobar que un método no
paramétrico conduce a resultados similares.
5. Sobreajuste (overfitting).
or
En Machine Learning es muy fácil conseguir un modelo perfecto para los datos utilizados,
pero pésimo para nuevos casos. El paradigma de entrenamiento y validación consigue evitar
el sobreajuste.
rr
Los métodos probabilísticos de uno u otro modo se basan en que los datos provienen de
muestras aleatorias. A pesar de que en muchas situaciones de análisis de datos esto no lo
podamos ni siquiera soñar, es importante tenerlo en mente para, a la hora de interpretar re-
sultados y llegar a conclusiones, hacer una reflexión sobre cuánto nos estamos alejando de esa
aleatoriedad. Por ejemplo, si estoy haciendo un estudio de los clientes de una empresa y solo
analizo las transacciones de la primera semana del mes, tengo una muestra sesgada porque
no tengo representado el resto del mes (posiblemente con un comportamiento diferente).
Realice la práctica 2.1 cuyo guión se encuentra en el apartado 2.5 para identificar
problemas y limpiar un conjunto de datos.
2.2. ANÁLISIS UNIVARIANTE 111
07
2.2. Análisis univariante
En un conjunto de datos, podemos analizar una única variable de forma independiente,
5-
ya sea de un tipo u otro. Tenemos un vector de datos con los valores de la variable. En
el siguiente apartado hablaremos del análisis multivariante, pero tengamos en cuenta que
-0
siempre podemos extraer una variable del conjunto de datos multivariante para analizarla
por separado. De hecho, esto será parte del análisis exploratorio de datos multivariantes.
19
Ejemplo numérico. La tabla 2.1 muestra las primeras filas de un conjunto de datos
de 100 observaciones. Cada una contiene la medición de una característica en un producto,
20
supongamos que está relacionada con la merma en gramos. Las variables merma1y merma2son
numéricas continuas, ya que puede tomar cualquier valor en un intervalo. La variable maquina
es cualitativa, ya que no se puede cuantificar. La variable manchas representa el número de
manchas detectadas en cada unidad en una inspección visual. Esta es una variable numé-
rica discreta. La variable defecto inicialmente la podemos considerar categórica (toma los
or
valores sí/no), pero también la podemos considerar ordinal (defecto2), y asignando un va-
lor numérico ordenado podemos hacer cálculos. Comprobamos que los tipos de datos en el
espacio de trabajo se corresponden con los tipos de variables que tenemos.
ad
str(ejDatos)
rr
estudiar los datos en su conjunto mediante tablas, medidas y representaciones gráficas que
07
resumen la información.
5-
2.2.1.1. Tablas de frecuencias
Los datos se pueden resumir en forma de tablas. Esta información nos aportará más infor-
mación que un solo número de resumen, y es útil para incluir en informes o análisis previos.
-0
Las tablas más utilizadas son las tablas de frecuencias, que contienen el número de ob-
servaciones para cada posible valor de la variables. Para variables discretas y categóricas,
19
la tabla de frecuencias representa el número de observaciones para el cual la variable toma
cada uno de los valores o atributos.
20
La tabla 2.2 muestra la tabla de frecuencias de la variable defecto en el conjunto de
datos de ejemplo, y la tabla 2.3 muestra la tabla de frecuencias de la variable manchas.
En el caso de las variables continuas, las observaciones se cuentan por intervalos. Estos
or
intervalos se pueden calcular utilizando diferentes métodos. Una posible regla sería el método
de Sturges, que es el que utiliza por defecto R. Esta regla establece que el número de intervalos
k en el que se deben dividir los datos es:
ad
log n
k = 1 + log2 n = 1 +
log 2
rr
redondeado por arriba, es decir, el menor entero mayor que el cálculo anterior. Una vez
Bo
decidido el número de intervalos, la amplitud de los mismos será el rango (máximo menos
mínimo) dividido por el número de intervalos, que normalmente se redondea o trunca para
facilitar la presentación e interpretación. Al valor central de cada intervalo se le denomina
marca de clase.
07
6.50 - 7.00 5
7.00 - 7.50 1
7.50 - 8.00 6
5-
frecuencias así calculada sería la que se muestra en la tabla 2.4, con 10 intervalos de amplitud
-0
0,5.
19
La importancia de esta tabla de frecuencias radica en que es la base para dibujar histogramas,
que es una de las herramientas gráficas más importantes en el análisis exploratorio de datos.
20
2.2.1.2. Medidas de centralización
La información en tablas de frecuencias está bien, pero para realizar cálculos necesitamos me-
didas numéricas que resuman alguna característica de los datos mediante un número. Cuando
or
estas medidas resumen se calculan sobre los datos de una muestra, se llaman estadísticos.
El valor teórico de una medida resumen referido al conjunto de la población, generalmente
desconocido, se llama parámetro. Las principales medidas numéricas se agrupan en dos
ad
grandes bloques:
Medidas de centralización. Recogen valores entorno a los cuales varían los datos.
Medidas de dispersión. Describen cómo es esa variación.
rr
Llegados a este punto, se hace necesario recordar algunos símbolos y nomenclatura que
aparecen durante el texto.
X, Y, Xj , . . .: Variables
i: Identificador o índice para cada observación
xi : Valor que toma la variable X en la observación i4 .
n: Número total de observaciones en la muestra. Si hay muestras de distinto tamaño,
pueden representarse como nj
N : Número total de observaciones en la población
4
En datos agrupados, xi representa la marca de clase de los intervalos.
114 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
∑
n
: Representa la suma de los elementos que contiene en su interior para cada obser-
i=1
vación
x̄: Media muestral de la variable X
s2 : Varianza muestral de la variable X
s: Desviación típica muestral de la variable X
µ: Media poblacional
σ 2 : Varianza poblacional
σ: Desviación típica poblacional
ˆ Simboliza un estimador de [·]. Por ejemplo, s = σ̂ quiere decir que la desviación
[·]:
07
típica muestral s es un estimador de la desviación típica poblacional σ.
Las medidas de centralización resumen los datos mediante valores medios, entorno a los cuales
varían los datos. Las más importantes son la media aritmética, la mediana y la moda. Hay
5-
otras medias como la media geométrica, la armónica y la cuadrática. La media aritmética
es la suma de todos los valores de la variable dividido por el número de observaciones.
-0
∑
n
xi
19 x̄ = i=1
n
∑
n
x̄ = xi · f i ,
i=1
ad
mean(ejDatos$merma1)
## [1] 5.06671
5
En realidad, podemos utilizar otras ponderaciones por conveniencia, por ejemplo en estadística espacial
es habitual ponderar por la distancia inversa al cuadrado.
2.2. ANÁLISIS UNIVARIANTE 115
## [1] 5.071167
weighted.mean(x = df[, 1], w = df[, 2])
## [1] 4.64
La media representa el centro de gravedad de los datos. Es una buena medida resumen para
distribuciones simétricas y que no tengan valores muy extremos. Sus buenas propiedades
07
matemáticas la hacen imprescindible para realizar otros cálculos. Una propiedad importante
de la media es que la suma de las diferencias de la variable a su media es cero:
5-
∑
n
(xi − x̄) = 0 (2.1)
i=1
-0
La mediana es el valor central de los datos, es decir, aquél que divide los datos en dos mitades:
uno con las observaciones cuyo valor es inferior a la mediana, y otro con las observaciones
19
cuyo valor es mayor que la mediana. Esta medida de centralización no se ve afectada por
valores atípicos, ya que es una medida de orden. Para calcularla, ordenamos las observaciones.
Si el número de observaciones es impar, la mediana es exactamente el valor que queda en
20
medio. Por ejemplo, si tenemos 25 mediciones, la número 13 en orden ascendente deja por
debajo y por arriba 12 observaciones, por lo tanto el valor que tome en la decimotercera
observación ordenada, es la mediana. Si el número de observaciones es par, se toman los dos
valores centrales y la mediana se calcula como la media aritmética de esos dos valores.
or
la variable merma1:
median(ejDatos$merma1)
rr
## [1] 5.0745
La moda es el valor central de los datos en el sentido de ser el más frecuente. En variables
Bo
categóricas, será la clase que más observaciones tiene. En variables numéricas discretas,
contamos el número de observaciones para cada posible valor, y la moda será aquél valor
que se produce en mayor número de observaciones. En variables continuas, tendremos un
intervalo modal que es el que más observaciones contiene (ver más adelante el histograma).
Mientras que la mediana y la media son únicas, es posible que un conjunto de datos tenga
dos modas. Esto, muy probablemente, nos estará indicando que estamos analizando datos
mezclados de dos grupos distintos y quizás deberíamos separarlos (análisis estratificado).
No hay una función en R para calcular la moda, aunque podemos obtenerla buscando en la
tabla de frecuencias cuál es el valor más frecuente.
116 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
Por ejemplo para la variable manchas del ejemplo se calcularía con el siguiente código,
siendo 7 manchas el valor más frecuente, y por tanto la moda.
## [1] 7
07
2.2.1.3. Medidas de posición
Del mismo modo que definimos la mediana para separar los datos en dos mitades, definimos el
5-
percentil Xp como el valor tal que el p % de las observaciones tienen un valor de la variable
menor o igual que Xp . Podemos calcular cualquier percentil, siendo los más importantes,
además de la mediana, el primer y tercer cuartil (Q1 y Q3 respectivamente), que dejan entre
-0
ambos el 50 % de las observaciones entorno a la mediana.
Los percentiles se suelen expresar como porcentajes (por ejemplo, percentil 10). A menudo
19
se les nombra también como cuantiles, pero en este caso se expresan en forma de tanto por
uno, por ejemplo, cuantil 0,1.
20
La figura 2.2 muestra gráficamente la distribución de las observaciones con relación a
la mediana y los cuartiles de la variable merma1 del conjunto de datos de ejemplo. Podemos
ver fácilmente cómo la mediana es robusta a los valores atípicos. Por ejemplo, si el mayor
valor se hubiera almacenado sin el punto decimal, la media sería un valor muy alto y no
or
representativa de los datos, mientras que la mediana seguiría teniendo el mismo valor y
representaría mucho mejor los datos. En R podemos utilizar la función quantile para obtener
cualquier percentil. La función summary sobre un vector numérico nos proporciona el mínimo,
ad
el máximo, el primer cuartil, la mediana, el tercer cuartil y el máximo. Además, esta función
nos informa de si existen valores perdidos. Véase el siguiente código.
rr
## 10% 90%
Bo
## 4.4019 5.7959
summary(ejDatos$merma1)
Q1 Mediana Q3
07
5-
3.728 4.728 5.0745 5.386 6.167
-0
R = máx xi − mı́n xi .
19 i i
(véase la figura 2.3). Pero por la propiedad vista en la ecuación (2.1), ese promedio es cero.
La medida más utilizada para medir la dispersión de los datos es la desviación típica,
ad
∑
N
(xi − µ)2
2 i=1
σ =
Bo
N
La mayoría de las veces trabajamos con muestras, y por tanto no podemos calcular σ 2 , sino
su estimador s2 :
∑
n
(xi − x̄)2
2 i=1
s =
n−1
Se utiliza n − 1 en el denominador en vez de n debido a que es el mejor estimador de la
varianza al trabajar con muestras. Nótese que las unidades de la varianza no son las mismas
que las de la variable, y es por eso que se utiliza la desviación típica s:
118 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
07
Merma máquina proceso 1
x11 = 6.075
5-
6.0
-0
5.5
19
Peso
5.0 x = 4.97
20
4.5
or
4.0
ad
0 10 20 30 40 50
rr
Pieza
√
s= s2 .
Al igual que la media, la desviación típica es muy sensible a observaciones atípicas. Una
propiedad interesante de la desviación típica es que, sea cual sea la distribución de los
datos,
( entre
) la media y un número de desviaciones típicas k se encuentran, al menos, el
1 − k12 × 100 %. Por ejemplo, para cualquier distribución de datos, entre la media y dos
desviaciones típicas (k = 2) se encuentran al menos el 75 % de las observaciones, y entre
la media y tres desviaciones típicas (k = 3), al menos el 89 % de las observaciones. Estos
07
límites aumentan dependiendo de la distribución específica que siguen los datos (el modelo).
Las funciones var y sd de R calculan la varianza y la desviación típica respectivamente de
un vector de datos.
5-
A veces se utiliza una medida relativa de la variabilidad, como es el coeficiente de variación.
Es especialmente útil para comparar variables que están en distintas unidades:
-0
s
CV = .
x
19
La instalación base de R no tienen una función para calcular el coeficiente de variación,
aunque es trivial calcularlo como sd(x)/mean(x).
20
En general, un coeficiente de variación inferior a 0,1 indicará que la media es representativa
de los datos, mientras que con valores mayores debemos cuestionarnos esa representatividad.
Para evitar los problemas que plantea la desviación típica, se puede utilizar como medida
de la variabilidad el rango intercuartílico, que es la diferencia entre el tercer y el primer
or
cuartil, que al igual que la mediana no está afectada excesivamente por los valores atípicos.
Representa la diferencia entre los valores centrales que incluyen el 50 % de los datos, es decir,
entre el primer y el tercer cuartil. La dispersión se puede medir también entorno a la mediana,
ad
por ejemplo con la desviación absoluta a la mediana, que es la mediana de las desviaciones
absolutas a la mediana. Las funciones IQR y mad de R realizan estos cálculos.
rr
range(ejDatos$merma1)
## [1] 2.439
var(ejDatos$merma1)
## [1] 0.2748028
120 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
sd(ejDatos$merma1)
## [1] 0.5242164
sd(ejDatos$merma1)/mean(ejDatos$merma1)
## [1] 0.1034629
IQR(ejDatos$merma1)
## [1] 0.645
07
mad(ejDatos$merma1)
## [1] 0.4766559
5-
Recordemos que si hay valores faltantes en los datos no podemos hacer cálculos a menos que
indiquemos que no se tengan en cuenta esas observaciones con el argumento na.rm = TRUE
-0
en las funciones utilizadas.
Estas medidas son útiles cuando los métodos gráficos no son suficientemente claros acerca
de la forma de la distribución, para establecer los modelos que tenemos que aplicar. Así,
los histogramas de los datos recogidos en dos líneas de producción pueden ser muy pare-
ad
cidos visualmente, pero puede haber cálculos numéricos que nos aporten más información.
Los paquetes moments (Komsta and Novomestky, 2015) y psych (Revelle, 2019) contienen
funciones para obtener estas y otras medidas.
rr
Otro tipo de análisis univariante que se puede realizar y que no se trata en este texto es
el análisis de series temporales. Cuando cada observación de una variable se refiere a un
Bo
Piezas defectuosas
No
07
Sí
5-
Figura 2.4: Gráfico de sectores de las piezas defectuosas. Se debe acompañar siempre de los
-0
datos (en el propio gráfico o fuera de él)
19
gráficos. En un capítulo posterior se trata en detalle la elaboración de gráficos, por lo que
estas opciones no se explican aquí. El lector puede consultar la ayuda de cada función para
saber más sobre sus opciones.
20
Para variables cualitativas, resumidas en tablas de frecuencias, podemos utilizar gráficos de
sectores y gráficos de barras. Los primeros no son en general recomendables6 , a menos que
se incluyan los valores numéricos claramente. Los gráficos de barras son ideales para tablas
de frecuencias, tanto de variables cualitativas como cuantitativas discretas.
or
Las figuras 2.4 y 2.5 son ejemplos de visualizaciones de las tablas de frecuencias 2.2
ad
barplot(table(ejDatos$manchas))
Bo
En cuanto a las variables cuantitativas continuas, la representación más simple que podemos
obtener es un gráfico de puntos en el que el eje vertical representa el valor de la variable, y el
eje horizontal un identificador del dato, secuencialmente a como se han obtenidos los datos.
Cuando el orden de las observaciones tiene un sentido, por ejemplo una serie temporal, es
adecuado unir los puntos con líneas.
6
Véase la nota en la ayuda de la función con ?pie.
122 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
15
10
5
07
5-
0
3 4 5 6 7 8 9 10 11
-0
Figura 2.5: Gráfico de barras del número de manchas
19
opciones gráficas. Nótese cómo una expresión muy sencilla, con un único argumento, produce
un resultado, y cómo se puede mejorar añadiendo algunas opciones. Para saber más sobre
20
las opciones gráficas, véase la ayuda de ?gpar.
plot(ejDatos$merma2)
barra y otra, significa que en ese intervalo hay cero observaciones. Con el histograma vemos
de un vistazo la distribución de los datos, por ejemplo si hay valores extremos, si es simétrica,
o cuáles son los valores más frecuentes. El histograma, como resumen gráfico que es, oculta
Bo
hist(ejDatos$merma2)
2.2. ANÁLISIS UNIVARIANTE 123
8
7
ejDatos$merma2
6
5
07
4
5-
-0
0 20 40 60 80 100
Index
19
Figura 2.6: Gráfico de puntos básico de una variable numérica
20
Valores de una variable numérica
8
or
7
ad
6
Peso
rr
5
Bo
0 20 40 60 80 100
Identificador
Figura 2.7: Gráfico de puntos y líneas de una variable numérica, con algunas opciones gráficas
124 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
Histogram of ejDatos$merma2
20
15
Frequency
10
07
5
5-
0
-0
3 4 5 6 7 8
19 ejDatos$merma2
conocido como “de cajas y bigotes” (box-and-whisker plot). Consiste en la representación del
conocido como “Resumen de cinco números”, que son el mínimo, el máximo, la mediana y
las bisagras (hinges) de Tukey. Estas bisagras son una versión del primer y tercer cuartil,
Bo
aunque calculados de forma ligeramente diferente7 . La función fivenum nos devuelve estos
números.
Las siguientes expresiones muestran los cuartiles y las bisagras de la variable merma2
del conjunto de datos de ejemplo. Nótese cómo la bisagra superior no es exactamente el
tercer cuartil, aunque están muy próximos.
7
Véase la ayuda de ?boxplot.stats en R. El cálculo también está especificado en la norma UNE-ISO
16269:4.
2.2. ANÁLISIS UNIVARIANTE 125
20
15
Frecuencias
10
07
5
5-
0
-0
3 4 5 6 7 8
19 Peso
cuartil) respectivamente. Los extremos de las líneas que salen de los bordes superior (inferior)
de la caja llegan hasta el valor más cercano a la caja de entre los siguientes:
Bo
El máximo (mínimo)
Una distancia k veces el rango intercuartílico desde el borde superior (inferior) de la
caja. Por defecto se toma k = 1,5 Todos los valores que van más allá de los bigotes se
representan como puntos, y se consideran candidatos a ser valores atípicos (outiliers).
Valores fuera de los límites calculado con k = 3 deben ser seriamente considerados como
atípicos e investigar su causa.
8
7
6
5
07
4
5-
Figura 2.10: Ejemplo de gráfico de cajas con un valor atípico
-0
candidato a ser un valor atípico ya que es mayor que el límite marcado por la bisagra
fivenum(ejDatos$merma2)[4] + 1.5*IQR(ejDatos$merma2)
20
## [1] 7.735125
max(ejDatos$merma2)
or
## [1] 7.869
boxplot(ejDatos$merma2)
ad
una variable aleatoria que sigue un modelo teórico representado por la función de densidad
de probabilidad (línea suave superpuesta al histograma), generalmente desconocido y con
el que queremos realizar inferencia estadística para tomar decisiones. Para ello necesitamos
datos, y obtenemos muestras. Los datos que obtenemos, representados en el histograma, nos
sirven para describir la población a través de la muestra y caracterizar el modelo teórico
(distribución de probabilidad, parámetros, etc.)
A los efectos de esta obra, simplemente vamos a recordar la definición de probabilidad como
frecuencia relativa en el límite. Si pudiéramos obtener muestras indefinidamente de nuestra
variable, el histograma se parecería cada vez más al modelo teórico. La probabilidad de que
la variable aleatoria tome valores en cada un intervalo cualquiera es igual al área debajo de
2.2. ANÁLISIS UNIVARIANTE 127
8
7.869
Límite superior: 7.735
Máximo no atípico: 7.716
07
7
5-
-0
6 19 Hinge: 5.847
20
Peso
Mediana: 5.269
or
5
ad
Hinge: 4.598
rr
4
Bo
Mínimo: 3.2
3
0.75
0.50
07
5-
0.25
-0
0.00
4.0 4.5
19 5.0
Volumen (cl)
5.5 6.0
20
Figura 2.12: Histograma y densidad de probabilidad
la curva, y se puede aproximar sumando las frecuencias relativas de los intervalos correspon-
dientes en la muestra. La explicación dada aquí se extiende fácilmente a variables discretas
or
## method from
## [.quosures rlang
## c.quosures rlang
rr
## print.quosures rlang
La variable aleatoria que describe la característica en estudio en la población puede estar ca-
Bo
racterizada por cualquier función de densidad que cumpla ciertos requisitos (véase el capítulo
8 de López Cano (2018). En la práctica, se utilizan un subconjunto reducido de modelos de
distribución de probabilidad que quedan caracterizadas por unos pocos parámetros. El más
importante de estos modelos es la llamada distribución normal, que queda caracterizada
por la media µ y varianza σ 2 , siendo la expresión de su función de densidad:
1 (x−µ)2
f (x) = √ e− 2σ2 .
2πσ 2
Denotamos que una variable aleatoria sigue una distribución normal como:
2.2. ANÁLISIS UNIVARIANTE 129
07
5-
µ − 3σ µ − 2σ µ−σ µ µ+σ µ + 2σ µ + 3σ
-0
Figura 2.13: Distribución normal estandarizada
19
X ∼ N (µ, σ).
20
La distribución normal es simétrica, toma valores −∞ < x < ∞, y se cumple que:
Entre la media y tres desviaciones típicas tenemos una probabilidad de 0.997
Entre la media y dos desviaciones típicas tenemos una probabilidad de 0.955
or
muestra. O al menos, identificar si los datos provienen de una distribución normal o no, ya
que muchos métodos estadísticos se basan en la hipótesis de que los datos provienen de una
distribución normal. Un simple examen visual del histograma de la variable nos puede dar
Bo
una idea para aceptar este hecho o no. Otra herramienta gráfica para este cometido es el
gráfico cuantil-cuantil, que representa los cuantiles teóricos de la distribución frente a los ob-
servados en la muestra. Los puntos así representados deberían caer aproximadamente sobre
una línea recta si los datos provienen de una distribución normal8 . La función qqnorm de
R produce este gráfico para un vector de datos. Si los métodos gráficos no fueran suficien-
tes, podemos comprobar numéricamente si los datos nos proporcionan evidencias suficientes
para rechazar que los datos provienen de una distribución normal, mediante un contraste
de hipótesis. La función shapiro.test contrasta la hipótesis nula de que los datos provie-
nen de una distribución normal frente a la alternativa de que no mediante el estadístico de
8
Se puede utilizar el método para otras distribuciones de probabilidad
130 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
8
7
Sample Quantiles
07
5
5-
4
-0
−2 −1 0 1 2
19 Theoretical Quantiles
cuantil-cuantil de los datos, donde vemos que los puntos caen aproximadamente sobre una
línea recta. En la prueba de Shapiro-Wilk, obtenemos un p-valor de 0,09911, suficientemente
grande como para no rechazar la hipótesis de normalidad a un nivel de significación del 5 %.
rr
qqnorm(ejDatos$merma2)
Bo
shapiro.test(ejDatos$merma2)
##
## Shapiro-Wilk normality test
##
## data: ejDatos$merma2
## W = 0.97837, p-value = 0.09911
Una vez determinada la distribución de probabilidad de una variable aleatoria, podemos
calcular probabilidades de que dicha variable tome ciertos valores (intervalos en el caso de
2.2. ANÁLISIS UNIVARIANTE 131
07
p, el cuantil q para el cual P [X < q] = p.
r*: Estas funciones generan números aleatorios para una distribución de probabilidad,
dados sus parámetros.
5-
A continuación de cada una de estas letras, vendría el nombre de la distribución, por ejemplo
para la distribución normal, pnorm, y como argumentos hay que añadir los parámetros de la
-0
distribución. Las funciones p* y q* hacen referencia a la cola inferior, por lo que si queremos
la probabilidad o el cuantil referidos a la cola superior, tenemos que añadir el argumento
lower.tail = FALSE.
19
Supongamos que sabemos que la variable merma1 del conjunto de datos de ejemplo
20
proviene de una distribución normal con media 5 y desviación típica 0,5. Con las dos primeras
expresiones a continuación respondemos a las siguiente preguntas:
¿Cuál es la probabilidad de que la variable valga menos de 6?
¿Cuál el es valor por encima del cuál solo queda el 5 % de probabilidad?
or
La última de las expresiones devuelve la probabilidad de que una variable aleatoria de Poisson
de parámetro λ = 5 sea igual a 2.
## [1] 0.9772499
Bo
## [1] 5.822427
set.seed(1)
rnorm(10, mean = 5, sd = 0.5)
## [1] 0.08422434
2.2.4.1. Tipificación
La tipificación o escalado de datos consiste en convertir cualquier conjunto de datos en otro
07
cuya media es igual a cero y desviación típica es igual a 1. Por las propiedades de la media
y la varianza, cualquier conjunto de datos X se tipifica restando su media y dividiendo por
su desviación típica:
5-
x − x̄
-0
Z=
s
19
La siguiente expresión tipifica la variable merma1 del conjunto de datos de ejemplo.
Podemos comprobar la media y desviación típica del nuevo conjunto de datos. Nótese cómo
por efectos de precisión de los cálculos con ordenador, no obtenemos exactamente cero, sino
20
un número infinitesimal (que es prácticamente cero).
z <- scale(ejDatos$merma1)
mean(z)
or
## [1] 7.917289e-16
sd(z)
ad
## [1] 1
Se puede transformar un conjunto de datos solamente centrándolo, fijando el argumento
rr
scale = FALSE dentro de la función scale. La tipificación de datos tiene muchas aplicacio-
nes. En el siguiente apartado veremos su utilidad en el análisis multivariante.
Bo
xλ −1 λ ̸= 0
x(λ) = λ
.
log(X) λ=0
Para algún valor de λ, los datos transformados suelen ser normales. Si la variable toma
valores iguales o menores que cero, entonces se transforma previamente x añadiendo una
constante α y se hace la transformación a los datos x + α. El paquete car contiene funciones
para encontrar el mejor valor de λ y transformar la variable.
07
La variable Volume del conjunto de datos trees que se encuentra en el paquete
datasets de R es claramente no normal, como demuestra la prueba de Shapiro-Wilk reali-
zada en la primera expresión del siguiente código de ejemplo. La función powerTransform
5-
del paquete car obtiene el valor óptimo de λ para acercarse a la distribución normal. La
función summary sobre el objeto creado con esta función nos da más información: además
del valor óptimo (Est Power), nos da un valor redondeado y un intervalo de confianza. Tam-
-0
bién proporciona dos pruebas muy útiles: la primera para comprobar si λ = 0, en cuyo caso
la transformación logarítmica es la adecuada y facilita la interpretación; la segunda com-
19
prueba si no es necesaria transformación. En este ejemplo concreto, la mejor transformación
es λ = 0. En general, se prefieren valores redondeados para facilitar la interpretación. Por
ejemplo, λ = −1 se corresponde con la inversa, λ = 0,5 con la raíz cuadrada, etc. Una vez
20
elegido λ, la variable transformada se puede obtener directamente con la función bcPower,
y comprobar la normalidad de los datos transformados, véase la figura 2.15.
shapiro.test(trees$Volume)
or
##
## Shapiro-Wilk normality test
##
ad
## data: trees$Volume
## W = 0.88757, p-value = 0.003579
library(car)
rr
Frequency
8
8
4
4
0
07
10 30 50 70 2.0 2.5 3.0 3.5 4.0 4.5
trees$Volume xt
5-
Figura 2.15: Histogramas de la variable Volume original (izquierda) y transformada (derecha)
-0
##
## Likelihood ratio test that no transformation is needed
## LRT df pval
## LR test, lambda = (1) 10.5197 1 0.0011811
xt <- bcPower(trees$Volume, bctrees$roundlam)
19
20
shapiro.test(xt)
##
## Shapiro-Wilk normality test
##
or
## data: xt
## W = 0.96427, p-value = 0.3766
ad
par(mfrow=c(1,2))
hist(trees$Volume)
hist(xt)
rr
Realice la práctica 2.2 cuyo guión se encuentra en el apartado 2.5 para realizar análisis
Bo
exploratorio univariante.
ellas como se ha visto anteriormente. Además, podemos estudiar las variables conjuntamente.
Dependiendo de la pregunta que queramos responder con la técnica estadística y del tipo
de variables de que disponemos y sus escalas, se utilizarán unas técnicas u otras. Antes de
pasar a las técnicas, vamos a ver algunas medidas conjuntas para varias variables.
07
2.3.1. Frecuencias conjuntas
5-
Cuando tenemos variables de tipo cualitativo o discreto, podemos construir tablas de contin-
gencia con las frecuencias conjuntas de dos o más variables. El caso más común es la tabla de
-0
doble entrada para dos variables, en la que tenemos los niveles o valores de una variable en
filas, y los valores o niveles de la otra en columnas. Las celdas de la tabla son las frecuencias
absolutas conjuntas. Si lo queremos hacer para más de dos variables, entonces obtendremos
19
una tabla de doble entrada para cada valor de la tercera y sucesivas variables.
20
De forma similar a una variable, la función table de R produce tablas de contingencia
cuando se le pasa más de una variable. La función xtabs es otra opción utilizando un interfaz
de fórmula. Las siguientes expresiones producen la tabla de contingencias representada en la
tabla 2.5.
or
table(ejDatos$defecto, ejDatos$manchas)
xtabs(~ defecto + manchas, ejDatos)
ad
realizar cálculo de las variables dos a dos. Vamos a revisar las más importantes en análisis
multivariante.
Bo
Para cada par de variables, podemos obtener la covarianza sxy y el coeficiente de corre-
lación lineal rxy .
∑
(xi − x)(yi − y)
sxy = ,
n−1
sxy
rxy = .
sx sy
En las técnicas multivariantes en las que intervienen variables en escala métrica, podemos
tener variables de magnitudes muy distintas. En algunas técnicas una práctica habitual es
136 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
tipificar o estandarizar todas las variables como se vio en el apartado anterior. Una propiedad
importante de la tipificación es que, aunque cambiemos la escala, no se mofifica la estructura
de correlación entre las variables. Esto implica que la covarianza de dos variables tipificadas
es igual a su coeficiente de correlación, que es el mismo que para las variables originales:
x − x̄ y − ȳ
zx = ; zy = =⇒ Cov(zx ; zy ) = rzx ,zy = rx,y .
sx sy
Cuando tenemos más de dos variables, representamos la estructura de correlación del con-
07
junto de datos multivariantes con la matriz de varianzas-covarianzas S. La posición central
del conjunto de datos se resume con la matriz de medias x. Así, para un conjunto de xk
variables k = 1, . . . , m, tendríamos:
5-
x̄1
x̄2
-0
...
x=
x̄k
s21
19 ...
x̄m
20
s12 . . . s1k . . . s1m
s21 s22 . . . s2k . . . s2m
.. .. .. .. .. ..
. . . . . .
S=
sk1 sk2 . . . s2k . . . skm
.. .. .. .. .. ..
or
.
. . . . .
sm1 sm2 . . . smk . . . s2m
ad
Bo
mos las matrices y medidas explicadas. El argumento select de la función subset permite
seleccionar columnas por nombre.
07
## merma1 merma2 manchas temp
## merma1 0.27480279 -0.08238823 0.07961172 0.85817228
## merma2 -0.08238823 1.06823134 0.17175152 -0.24638949
5-
## manchas 0.07961172 0.17175152 4.35393939 0.04145455
## temp 0.85817228 -0.24638949 0.04145455 3.47828687
-0
r <- cor(ejMetricas); r
de forma conjunta. Hay varias formas de calcular esta distancia entre observaciones, siendo
las más importantes:
Distancia euclídea
rr
v
u∑
um
Bo
En ocasiones se utiliza la distancia euclídea al cuadrado, para quitar la raíz y reducir el coste
computacional.
Distancia de Manhattan
∑
m
d ii′ = |xij − xi′ j |.
j=1
m
dii′ = máx |xij − xi′ j |.
j=1
Distancia Mínima
m
dii′ = mı́n |xij − xi′ j |.
j=1
Distancia de Minkowski
07
1
∑
m p
d2ii′ = p
|xij − xi′ j | .
j=1
5-
Los valores más habituales de p son 1 y 2, que se corresponden con la distancia de Manhattan
y la distancia euclidea respectivamente. Además, cuando p tiende a infinito o a menos infinito,
-0
la distancia de Minkowski se corresponde, respectivamente, con la distancia máxima (o de
Chebyshev) y mínima.
Distancia de Mahalanobis
19
Las medidas anteriores no tienen en cuenta la estructura de correlación del conjunto de datos
multivariante. Una medida más completa es la distancia de Mahalanobis (D):
20
√
Dii′ = xi − x i′ )T S −1 (x
(x xi − x i′ ),
para todas las observaciones del conjunto de datos dos a dos. Será una matriz simétrica con
ceros en la diagonal, normalmente muy grande para ser mostrada en su totalidad, pero que
se utilizará en algunas técnicas multivariantes. La función dist de R calcula distancias en
matrices de datos10 .
rr
Bo
## 1 2 3 4 5
## 1 0.000000 5.133827 3.249346 5.766106 6.518078
10
Por defecto la distancia euclídea, pero se pueden seleccionar otros métodos.
2.3. ANÁLISIS MULTIVARIANTE 139
Recordemos la forma que teníamos en conjuntos de datos univariantes para detectar valores
extremos, candidatos a ser valores atípicos o outliers. Mirábamos el gráfico de cajas, y los
valores que aparecían demasiado alejados del resto se representaban como valores atípicos.
Pues bien, en conjuntos de datos multivariantes vamos a utilizar la distancia entre obser-
vaciones definida anteriormente para detectar aquellas observaciones que estén demasiado
07
alejadas del resto como para ser considerada atípica en relación al conjunto de datos y su
estructura de correlación. En particular, el método más comúnmente aceptado es el de la
distancia de Mahalanobis. La idea es calcular esta distancia con respecto al vector de medias
5-
del conjunto de datos. Así, aquellas observaciones que más se alejen de este vector de medias
deberían ser investigadas. Un simple gráfico de estas distancias etiquetando las observaciones
más alejadas puede ser suficiente en análisis exploratorio de datos. Existen métodos más so-
-0
fisticados aprovechando que la distancia de Mahalanobis sigue una distribución chi-cuadrado
pero no los tratamos aquí.
19
La función mahalanobis calcula la distancia de Mahalanobis de un conjunto de datos
a un determinado vector. Aprovechando que ya teníamos guardadas la matriz de varianzas-
20
covarianzas y el vector de medias para proporcionárselo a la función. El resultado es un
vector con las 100 distancias al centro. la figura 2.16 identifica los números de fila de todas
las distancias, parece que las observaciones 53 y 64 están más alejadas del resto, aunque no
demasiado.
or
dm <- mahalanobis(ejMetricas, M, S)
plot(dm, type = "n")
ad
text(dm)
Realice la práctica 2.3 cuyo guión se encuentra en el apartado 2.5 para realizar cálculos
rr
12
53
64
10
8 37 66
42
33 40 70 78
1 1114 26 32 51 56 90
dm
79 74
72
6
5 12 30 38 55 59 71 83
97
23 28 54 61 95
4 8 15 2225 76 88 93
65 69 73 81 96
4
2 6 52
07
18 2427 34 77
16 44 48
43 5860 848689
21 35 46 68 75 91
3 17 29 92 98
2
13 39 50 63 99
100
10 20 36 49 57 82 85
19 31 41 47 67 80
79 87 94
5-
45 62
0 20 40 60 80 100
-0
Index
19
Figura 2.16: Distancias de Mahalanobis del conjunto de datos de ejemplo
X y el eje vertical Y. Estos dos ejes generalmente pueden representar dos variables. Para
20
visualizar más variables, se añaden características gráficas que identifiquen otras variables,
como colores, tamaño de punto, grosor de linea, tipo de línea o símbolo, o etiqueta de texto.
Los distintos gráficos que podemos realizar, se pueden organizar a su vez en facetas (facets) o
rejillas (grids, lattice). En definitiva, matrices de gráficos que organizamos en filas y columnas,
or
donde a su vez estas filas y columnas pueden representar alguna variable cualitativa.
Los gráficos de mosaico son especialmente útiles para explorar muchas variables cualitativas
ad
La figura 2.17 que se genera con el código a continuación representa las frecuencias
rr
de los distintos grupos de las variables maquina y defecto del conjunto de datos de ejemplo.
Bo
mosaicplot(table(ejDatos$maquina, ejDatos$defecto),
main = "Frecuencias por niveles de factores",
xlab = "Máquina", ylab = "Defectuoso")
Para visualizar dos variables en escala métrica, la visualización más adecuada es el gráfico de
dispersión, en el que los ejes representan la escala de las variables y los datos se representan
como puntos. Se puede añadir una línea de regresión para comprobar de un vistazo el tipo
de relación.
Vamos a comprobar gráficamente si hay algún tipo de relación entre las variables
2.3. ANÁLISIS MULTIVARIANTE 141
maquina1 maquina2
Defectuoso
No
07
5-
Sí
-0
Máquina
19
Figura 2.17: Gráfico de mosaico para dos variables con dos categorías cada una
20
merma1 y temp del conjunto de datos de ejemplo. La primera de las siguientes expresiones crea
el gráfico sencillo de puntos de la figura 2.18. La siguiente expresión que aparece comentada
produciría al mismo resultado, utilizando los vectores de datos como argumentos en vez de
un objeto fórmula. La tercera expresión produce un gráfico más elaborado (figura 2.19), con
or
# plot(ejDatos$temp, ejDatos$merma1)
library(ggplot2)
rr
Cuando una de las variables está en escala métrica y la otra en escala de atributo, la re-
presentación más efectiva son los gráficos en los cuales en el eje horizontal se presentan los
niveles del atributo y en el eje vertical la escala de la variable métrica. Bajo esta idea general,
lo que cambia es la representación que se hace dentro del gráfico. Para identificar diferencias
entre grupos, podemos representar gráficos de cajas para cada grupo. Si hay pocos datos de
cada grupo, puede ser más adecuado representar cada dato como un punto y las medias de
cada grupo, posiblemente unidas con líneas.
142 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
6.0
5.5
merma1
5.0
07
4.5
5-
4.0
-0
12 14 16 18
19 temp
aunque el valor más alto está en la máquina 2, los valores centrales están menos dispersos.
La máquina 1 presenta mucha más variabilidad, aunque la mediana es más baja. La máquina
2 además presenta un posible valor atípico por debajo. Nótese cómo la expresión utlizada
para producir este gráfico (la primera de las siguientes) es idéntica que la utilizada para el
rr
gráfico de dispersión. R decide en función del tipo de datos almacenado qué gráfico debe
generar. Para ilustrar el gráfico de puntos, creamos un subconjunto solo con las filas que
Bo
toman el valor “Sí” en la variable defecto. Las siguientes expresiones crean un gráfico de
puntos con las medias unidas con líneas de este subconjunto de datos como el que se ve en
la figura 2.21.
07
Gráfico de dispersión con ggplot2
5-
6.0
-0
5.5
19
Merma
5.0
20
4.5
or
ad
4.0
rr
12 14 16 18
Temperatura
Bo
6.0
5.5
merma1
5.0
07
4.5
5-
4.0
-0
maquina1 maquina2
19 maquina
Para representar más variables, como se ha indicado anteriormente se puede dotar a los
puntos, líneas, etc. de características gráficas distintas para diferenciar unos grupos de otros,
escalas de color para variables en escala métrica, o crear matrices de gráficos. Estas matri-
ad
ces de gráficos se pueden realizar con los paquetes lattice y ggplot. En este último, se
organizan los gráficos en “facetas”, indicando por qué grupos se hace cada gráfico.
rr
La siguiente expresión crea un gráfico representando todas las variables mediante una
matriz de gráficos con el atributo maquina en columnas y el atributo defecto en filas. Se ha
Bo
añadido una escala de color para los valores de la variable merma2. El resultado se muestra
en la figura 2.22.
Por último, es habitual representar todos los pares de variables en una matriz de gráficos en
los que filas y columnas son las distintas variables. La función ggpairs del paquete GGally
(Schloerke et al., 2018) realiza gráficos adecuados para cada par de variables de forma que
se tiene una visión de conjunto de todos los datos.
2.3. ANÁLISIS MULTIVARIANTE 145
07
6.15
5-
-0
6.10
19
merma1
20
6.05
or
ad
6.00
rr
maquina1 maquina2
maquina
Bo
07
maquina1 maquina2
5-
18
-0
16
No
merma2
14
12
19 7
temp
6
20
5
18 4
16
or
Sí
14
ad
12
4.0 4.5 5.0 5.5 6.0 4.0 4.5 5.0 5.5 6.0
rr
merma1
maquina
40
30
20
10
0
6.0 Cor : −0.152Cor : 0.0728 Cor : 0.478 Cor : 0.878
merma1
5.5
5.0 maquina1: −0.0786
maquina1: 0.26 maquina1: maquina1:
0.56 0.905
4.5
4.0 maquina2: −0.258
maquina2: −0.152 maquina2: 0.414
maquina2: 0.847
8
Cor : 0.0796 Cor : −0.227Cor : −0.128
merma2
7
6 maquina1: 0.155 maquina1: −0.281
maquina1: 0.0232
5
07
4 maquina2: 0.0165 maquina2: −0.173
maquina2: −0.28
3
Cor : −0.0779Cor : 0.0107
manchas
10.0
7.5 maquina1: 0.0156
maquina1: 0.266
5-
5.0 maquina2: maquina2:
−0.21 −0.266
2.5
50
40
30
defecto
20
10
0
-0
50
40
30
20
10
0
1.00 Cor : 0.413
defecto2
0.75
0.50
0.25
0.00
20
18
19 maquina1: 0.463
maquina2: 0.379
20
temp
16
14
12
012345012345 4.04.55.05.56.0 3 4 5 6 7 8 5.0 7.510.0 0 2 4 6 0 2 4 6 0.00
0.25
0.50
0.75
1.0012 14 16 18
El siguiente código realiza un análisis gráfico completo de las variables por pares del
conjunto de datos de ejemplo. Además de los gráficos, se muestran las correlaciones, y se
rr
identifican los grupos según se indica, en este caso por la variable máquina. El resultado es
el que se muestra en la figura 2.23.
Bo
library(GGally)
ggpairs(ejDatos, aes(col = maquina, pch = defecto), progress = FALSE)
Para variables ordinales en escala Likert, una representación visual muy completa es la
que proporciona el paquete likert (Bryer and Speerschneider, 2016) de R, en el que se
representan los porcentajes para cada item en forma de barras como el de la figura 2.24 que
se crea con el siguiente código utilizando datos de ejemplo del propio paquete likert. Véase
la ayuda de la función (?plot.likert) para ver más opciones de visualización.
library(likert)
data(pisaitems)
148 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
07
No ficción 61% 20% 19%
100 50 0 50 100
5-
Percentage
Response Never or almost never A few times a year About once a month Several times a month Several times a week
-0
Figura 2.24: Ejemplo de visualización de variable categórica ordinal
19
items29 <- pisaitems[,substr(names(pisaitems), 1,5) == 'ST25Q']
names(items29) <- c("Revistas", "Comics", "Ficción",
20
"No ficción", "Periódicos")
l29 <- likert(items29)
plot(l29)
or
tenemos un vector aleatorio X con m variables aleatorias X1 , . . . , Xm . Cada una de estas va-
riables aleatorias sigue una distribución de probabilidad, y la variable aleatoria multivariante
queda determinada por la de sus componentes.
Bo
X ∼ Np (µ
µ, Σ)
Σ),
1.0
0.8
0.02
0.06
0.6
0.1
0.16
07
Z
14
0.
0.12
0.4
0.08
0.04
5-
Y
ou
t 0.2
-0
0.0
2
con −∞ < Xj < ∞ para todo j.
ad
La distribución normal multivariante tiene algunas propiedades importantes, entre las que
destacamos:
Las combinaciones lineales de sus componentes son también normales.
rr
Realice la práctica 2.4 cuyo guión se encuentra en el apartado 2.5 para realizar análisis
150 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
exploratorio multivariante.
07
fundamentales:
Los fenómenos que caracterizan a una sociedad cada vez más compleja son, por tanto,
más complejos, integrando múltiples relaciones entre variables.
5-
Al incremento en la capacidad del hardware y el software, que hacen posible el proce-
samiento de grandes masas de información.
-0
Las técnicas a aplicar dependerán de cómo se midan las características (variables o atributos)
que componen los conjuntos de datos multivariantes, según se vio en el apartado anterior.
en el que tenemos una variable respuesta (dependiente) continua y una variable predictiva
(independiente) continua:
ad
Y = β0 + β1 X.
Las técnicas de interdependencia buscan encontrar cómo se relacionan las variables entre
rr
sí, pero sin que necesariamente unas expliquen a otras. Podríamos decir que, en cierto sentido,
las primeras son técnicas predictivas, y las segundas son técnicas descriptivas.
Bo
Una vez sabemos el tipo de técnica a aplicar, la técnica concreta a utilizar va a depender
del tipo de datos de las variables y, en el caso de las técnicas de dependencia, el número
de variables independientes. Así, una clasificación de las técnicas multivariantes tratadas en
este texto sería la siguiente:
Técnicas de interdependencia
• Variables cuantitativas
◦ Análisis de Componentes Principales (PCA, Principal Component Analysis)
◦ Análisis de Conglomerados (Cluster Analysis)
• Variables cualitativas
◦ Análisis de Correspondencias
2.4. TÉCNICAS DE ANÁLISIS MULTIVARIANTE 151
Técnicas de dependencia
• Una variable respuesta cuantitativa
◦ Análisis de la varianza (ANOVA)
• Varias variables respuesta cuantitativas
◦ Análisis de la varianza múltiple (MANOVA)
A continuación se incluye una breve descripción de la pregunta a la que da respuesta cada
técnica, así como un breve ejemplo.
07
Análisis de la varianza
El objetivo de esta técnica es determinar cómo influyen una serie de atributos o variables
5-
cualitativas independientes no métricos (factores) sobre variables dependientes métricas.
Ejemplo: ¿afecta de distinta manera a la productividad de una plantación agrícola el
-0
uso de fertilizantes químicos o biológicos? La Variable dependiente sería la productividad
(EUR/m2 ), y la variable independiente (o factor) el tipo de fertilizante (químico o biológico).
19
Cada posible valor del factor es un nivel de éste.
son métricas.
Ejemplo: agrupar items de una encuesta.
ad
Análisis Cluster
Objetivo: agrupar observaciones o individuos de manera que cada grupo esté constituido por
rr
individuos con valores para ciertas variables muy parecidos; y que los individuos de distintos
grupos presenten valores observados para dichas variables muy diferentes entre sí. Es decir,
Bo
Análisis de Correspondencias
Objetivo: es una técnica que permite representar en un espacio multidimensional reducido
(usualmente bidimensional) la relación existente entre las categorías o niveles de dos atributos
o variables no-métricas.
Este análisis mostrará las distancias entre los diferentes niveles de dos atributos, por lo que
sirve para visualizar tablas de contingencia.
152 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
07
recogida de datos correctos. Las escalas deben ser las adecuadas para la Técnica de Análisis
Multivariante (TAM) elegida.
Paso 3. Cumplimiento de hipótesis básicas.
5-
La aplicación de ciertas TAM está sujeta al cumplimiento de una serie de hipótesis básicas,
tales como cumplimiento de normalidad, homoscedasticidad en los errores de los modelos,
-0
linealidad, etc. Para ello conviene someter a los datos a un análisis exploratorio previo, así
como efectuar una serie de contrastes o test sobre el cumplimiento de las hipótesis.
Paso 4. Aplicación de la TAM
19
Tras aplicarse la TAM, debe comprobarse que la bondad del ajuste del modelo es suficiente
como para garantizar que las conclusiones son sólidas. Además, en los resultados suelen
20
incluirse test y contrastes para verificar que la aplicación de la técnica ha sido correcta.
Paso 5. Análisis de los resultados.
Interpretación de éstos desde el punto de vista económico, y con la óptica de los objetivos
or
que se plantearon en el paso 1. Esta es la fase más importante del proceso: extracción de
conclusiones. Debe valorarse más este paso que el simple procedimiento técnico de utilización
de una TAM determinada.
ad
En este apartado se proporciona una breve descripción de cómo ajustar modelos multivarian-
tes con R.
Bo
+ aditivo
: Interacción
* aditivo + interacción
| (Alt Gr + 1) para modelos mixtos
1 Término independiente
. Puede indicar “todas”
… Otros, depende de las funciones
En el lado de las variables dependientes, se pueden incluir con operadores, o en forma de
matriz. En técnicas donde no hay una variable dependiente, puede estar vacío.
07
En la mayoría de técnicas, se especifican los nombres de las variables en el argumento formula
y el conjunto de datos en el argumento data. Los objetos de clase formula se utilizan también
en gráficos, como ya se ha visto.
5-
2.4.4.2. Ajuste de un modelo lineal
-0
A modo de ejemplo, la función lm ajusta modelos lineales, y su estructura es la siguiente:
str(lm)
##
19
## function (formula, data, subset, weights, na.action, method = "qr",
model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
20
## contrasts = NULL, offset, ...)
A continuación se presenta un ejemplo para entender la mecánica, aunque no se explican los
resultados. En los siguientes capítulos se darán más detalles.
or
names(modelo)
resumen.modelo
##
## Call:
## lm(formula = dist ~ speed, data = cars)
##
## Residuals:
## Min 1Q Median 3Q Max
## -29.069 -9.525 -2.272 9.215 43.201
07
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
5-
## (Intercept) -17.5791 6.7584 -2.601 0.0123 *
## speed 3.9324 0.4155 9.464 1.49e-12 ***
-0
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
##
##
19
Residual standard error: 15.38 on 48 degrees of freedom
Multiple R-squared: 0.6511, Adjusted R-squared: 0.6438
F-statistic: 89.57 on 1 and 48 DF, p-value: 1.49e-12
20
resumen.modelo$r.squared
## [1] 0.6510794
or
Realice la práctica 2.5 cuyo guión se encuentra en el apartado 2.5 para ajustar un
ad
2.5. Prácticas
Bo
En este apartado se presentan las prácticas a las que se han hecho referencia durante el
capítulo. La reproducibilidad del código ha sido comprobada con la sesión de R que se
detalla en el Prefacio. El lector puede teclear el código o copiarlo y pegarlo en la consola
o el editor. También se puede descargar el script con el código de todas las prácticas con
la siguiente expresión (asumiendo que tenemos una carpeta llamada “practicas” en nuestro
directorio de trabajo):
download.file("http://emilio.lcano.com/b/adr/practicas/02-aed.R",
destfile = "practicas/02-aed.R")
2.5. PRÁCTICAS 155
07
pestaña Environment, o ejecutar la siguiente expresión:
rm(list = ls())
5-
Datos
-0
El siguiente fichero contiene datos con varios problemas que debemos identificar y resolver.
Debemos tener una carpeta llamada “datos” en el directorio de trabajo actual (se recomienda
trabajar en un proyecto de RStudio).
19
download.file("http://emilio.lcano.com/b/adr/datos/ejdatos_sucios.csv",
"datos/ejdatos_sucios.csv")
20
Lo importamos al espacio de trabajo. Para los efectos de esta práctica, nos interesa importar
las variables de texto como carácter, y no como factores. El argumento fileEncoding es
necesario en este caso para que la expresión importe bien el texto en cualquier sistema
operativo.
or
fileEncoding = "utf8")
Exploración de datos
Bo
Una vez importados los datos, ya están en el espacio de trabajo y podemos trabajar directa-
mente con ellos. Vamos a obtener un resumen de todas las variables.
summary(ejDatosSucios)
## NA's :1
## defecto2 temp
## Min. :0.00 Length:100
## 1st Qu.:0.00 Class :character
## Median :1.00 Mode :character
## Mean :0.52
## 3rd Qu.:1.00
## Max. :1.00
##
07
y un gráfico de las variables por pares de las variables numéricas:
ejDatosSuciosNum <- subset(ejDatosSucios, select = c(merma, manchas, defecto2, temp))
lattice::splom(ejDatosSuciosNum)
5-
23.88
23.88
-0
temp
10.16
10.16
1.0
19
0.8 0.6 1.0
0.6
defecto2
20
0.4
0.0 0.4 0.2
0.0
30
25 20 30
or
20
manchas
15
10
5 10 5
ad
7 6 7
6
merma
5
rr
4 5 4
tenemos dos opciones: ir al fichero original, modificar el dato erróneo y volver a importarlo;
o modificar el conjunto de datos en R, y guardar el fichero CSV corregido. De esta forma
queda registrado todo lo que se ha hecho. Debemos documentar el código con lo que hacemos
para futura referencia. En primer lugar hacemos una copia en el espacio de trabajo para ir
arreglando los errores y no tocar los datos originales.
## Crear una copia de los datos a modificar
ejDatosLimpios <- ejDatosSucios
Tipo de datos
07
La variable temp debería ser numérica, pero es de tipo carácter. Esto nos va a impedir aplicar
técnicas que requieran hacer cálculos, por ejemplo si intentamos hacer una media:
5-
mean(ejDatosLimpios$temp)
-0
## logical: returning NA
## [1] NA
19
Obtenemos NA y un warning indicando que los datos no son del tipo que se esperaba para
hacer una media. Aquí podemos pensar que obtenemos NA porque hay valores perdidos,
20
pero si añadimos el argumento para no tener en cuenta dichos valores, obtenemos el mismo
resultado:
mean(ejDatosLimpios$temp, na.rm = TRUE)
or
## [1] NA
¿Qué puede haber pasado? ¡Porque aparentemente son números!:
ejDatosLimpios$temp
rr
07
## [34] 15.67 14.19 16.05 18.19 12.74 14.60 18.08 17.87 13.13 15.64 19.10
## [45] 16.11 13.33 14.08 14.77 16.61 17.63 15.14 17.03 11.97 12.81 12.05
## [56] 13.86 16.75 17.37 11.72 19.05 16.47 23.88 14.85 15.72 18.79 14.46
## [67] 10.54 18.57 16.28 10.78 13.98 15.27 11.47 18.43 15.86 13.66 17.36
5-
## [78] 15.99 18.76 14.28 11.15 10.25 15.84 16.00 11.72 15.58 10.18 14.12
## [89] 15.68 12.04 14.62 15.98 12.05 16.48 17.71 10.84 11.90 17.47 17.86
-0
## [100] 13.51
Nótese la diferencia con el output anterior: antes estaban entre comillas porque el vector era
19
de tipo carácter. Ahora no salen comillas porque es de tipo numérico.
Y vemos que ha devuelto un valor NA porque no era un número. En particular, el elemento
número 16 del vector es “16,34”, con la coma decimal. El resto de números usa el punto
20
decimal, como tiene que ser para la función read.csv. Por tanto, para corregir este error
podemos sustituir todas las comas por puntos (podría haber más de un valor) y después
convertir a numérico11 :
ejDatosLimpios$temp <- gsub(",", ".", ejDatosLimpios$temp)
or
summary(ejDatosLimpios$temp)
Valores atípicos
La variable manchas parece que tiene un punto muy alejado del resto. En el resumen también
se ve que el máximo está lejos de los valores centrales. Lo podemos comprobar numérica y
gráficamente con el gráfico de cajas:
summary(ejDatosLimpios$manchas)
boxplot(ejDatosLimpios$manchas)
30
25
20
15
07
10
5-
5
-0
En ete caso hay que actuar con mucha cautela, efectivamente el máximo de 30 es un candidato
19
a ser un valor atípico. Habría que investigar si ha sido un error y ver si hay que cambiar
por otro, o eliminar la observación para los futuros análisis. Podemos utilizar el resultado
del gráfico de cajas para examinar y filtrar los datos atípicos. Al guardar el resultado de la
20
función boxplot en un objeto:
bp <- boxplot(ejDatosLimpios$manchas)
podemos acceder a los valores de las observaciones atípicas, que se guardan en el elemento
or
## [1] 14 30 14
rr
y filtrar el conjunto de datos para ver cuáles son esas observaciones. Con la función which
podemos averiguar los índices de las observaciones candidatas a ser valores atípicos:
Bo
Valores perdidos
Según vimos en el resumen, tenemos un valor perdido (NA) en la variable merma.
summary(ejDatosLimpios$merma)
07
## [1] NA
A menos que indiquemos expresamente que los obvie:
5-
mean(ejDatosLimpios$merma, na.rm = TRUE)
-0
## [1] 4.943303
Supongamos que el dato perdido en cuestión existe, pero por alguna razón no ha llegado al
19
fichero de datos. Primero querremos ver a qué observación se refiere ese valor perdido. Lo
podemos hacer seleccionando las filas del data frame para las que la variable merma es NA:
ejDatosLimpios[is.na(ejDatosLimpios$merma), ]
20
## maquina merma manchas defecto defecto2 temp
## 4 maquina1 NA 8 Sí 1 18.03
or
Es la observación 4. Imaginemos que al investigar qué paso encontramos que nos saltamos
el dato de la observación número 4 al meterlo en la hoja de cálculo (supongamos que el dato
es 0.188).
ad
summary(ejDatosLimpios$merma)
## [1] 4.89575
Exportación final
Por último, guardamos el fichero arreglado, que es el que se debe utilizar en sucesivos análisis.
2.5. PRÁCTICAS 161
07
Limpiar el espacio de trabajo
Crea un script para esta práctica (o abre el script descargado de la web de material del
curso). Antes de empezar a explorar datos, vamos a limpiar el espacio de trabajo para que
5-
podamos ir viendo cómo se van añadiendo los datos de forma clara. Puedes utilizar el icono
de la escoba en la pestaña Environment, o ejecutar la siguiente expresión:
-0
rm(list = ls())
Datos
19
Vamos a trabajar con el conjunto de datos ejdatos. Lo podemos descargar con la siguiente
expresión. Debemos tener una carpeta llamada “datos” en el directorio de trabajo actual (se
20
recomienda trabajar en un proyecto de RStudio).
download.file("http://emilio.lcano.com/b/adr/p/datos/ejdatos.csv", "datos/ejdatos.csv")
fileEncoding = "utf8")
str(ejDatos)
07
## 98 maquina2 5.136236 7 Sí 1 17.46687
## 99 maquina2 5.702205 5 Sí 1 17.85712
## 100 maquina2 3.896857 9 No 0 13.51478
5-
-0
Tablas de frecuencias
19
20
Tabla de frecuencias de una variable:
table(ejDatos$defecto)
or
##
## No Sí
ad
## 48 52
table(ejDatos$defecto, ejDatos$maquina)
Bo
##
## maquina1 maquina2
## No 25 23
## Sí 25 27
Representación gráfica
barplot(table(ejDatos$manchas))
2.5. PRÁCTICAS 163
25
20
15
10
07
5
5-
0
2 3 4 5 6 7 8 9 10 11 14
-0
pie(table(ejDatos$defecto))
19
20
or
ad
rr
No
Bo
Sí
datoshist <- hist(ejDatos$merma)
164 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
Histogram of ejDatos$merma
30
25
20
Frequency
15
07
10
5-
5
0
-0
3 4 5 6 7 8
cbind(datoshist$mids, datoshist$counts)
19
ejDatos$merma
20
## [,1] [,2]
## [1,] 3.25 1
## [2,] 3.75 11
or
## [3,] 4.25 18
## [4,] 4.75 18
## [5,] 5.25 32
ad
## [6,] 5.75 10
## [7,] 6.25 8
## [8,] 6.75 1
## [9,] 7.25 0
rr
## [10,] 7.75 1
Bo
Medidas de posición
summary(ejDatos$merma)
## [1] 5.04131
Representación gráfica
2.5. PRÁCTICAS 165
07
5
5-
4
-0
maquina1 maquina2
19 maquina
20
Varianza y desviación típica
var(ejDatos$merma)
## [1] 0.6008204
or
sd(ejDatos$merma)
ad
## [1] 0.775126
Introducción
Comenzamos como siempre limpiando el espacio de trabajo para que podamos ir viendo
Bo
cómo se van añadiendo los datos de forma clara. Puedes utilizar el icono de la escoba en la
pestaña Environment, o ejecutar la siguiente expresión:
rm(list = ls())
## $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
## $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
## $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
head(iris)
07
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
5-
Seleccionamos las columnas numéricas solamente, ya que lo que nos interesa es realizar
operaciones matemáticas con las matrices.
-0
matriz <- as.matrix(iris[, 1:4])
head(matriz)
##
##
##
[1,]
[2,]
5.1
4.9
3.5
3.0
19
Sepal.Length Sepal.Width Petal.Length Petal.Width
1.4
1.4
0.2
0.2
20
## [3,] 4.7 3.2 1.3 0.2
## [4,] 4.6 3.1 1.5 0.2
## [5,] 5.0 3.6 1.4 0.2
## [6,] 5.4 3.9 1.7 0.4
or
Trasponer matriz
ad
Matriz de varianzas-covarianzas
07
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Sepal.Length 0.6856935 -0.0424340 1.2743154 0.5162707
## Sepal.Width -0.0424340 0.1899794 -0.3296564 -0.1216394
5-
## Petal.Length 1.2743154 -0.3296564 3.1162779 1.2956094
## Petal.Width 0.5162707 -0.1216394 1.2956094 0.5810063
-0
Matriz de correlaciones
Invertir matriz
varcovar%*%matrizinversa
07
Determinante de una matriz
det(varcovar)
5-
## [1] 0.00191273
-0
det(matrizinversa)
## [1] 522.813
det(varcovar%*%matrizinversa)
## [1] 1
19
20
2.5.0.1. Diagonal de una matriz
diag(varcovar)
or
Se puee utilizar para crear matrices identidad, con ceros salvo la diagonal:
diag(5)
## [1] 4.572957
07
Autovalores y autovectores de una matriz
5-
eigen(varcovar)
## eigen() decomposition
-0
## $values
## [1] 4.22824171 0.24267075 0.07820950 0.02383509
##
##
##
##
$vectors
[1,]
[,1] [,2]
19 [,3] [,4]
0.36138659 -0.65658877 -0.58202985 0.3154872
20
## [2,] -0.08452251 -0.73016143 0.59791083 -0.3197231
## [3,] 0.85667061 0.17337266 0.07623608 -0.4798390
## [4,] 0.35828920 0.07548102 0.54583143 0.7536574
or
Matriz de distancias
ad
d <-dist(matriz)
as.matrix(d)[1:5, 1:5]
## 1 2 3 4 5
rr
rm(list = ls())
Datos
Vamos a trabajar con el conjunto de datos ejdatos
download.file("http://emilio.lcano.com/b/adr/p/datos/ejdatos.csv", "datos/ejdatos.csv")
07
Exploremos el conjunto de datos:
str(ejDatos)
5-
## 'data.frame': 100 obs. of 6 variables:
## $ maquina : Factor w/ 2 levels "maquina1","maquina2": 1 1 1 1 1 1 1 1 1 1 ...
## $ merma : num 5.38 6.01 4.82 6.01 3.89 ...
-0
## $ manchas : int 4 8 8 8 10 8 2 5 8 7 ...
## $ defecto : Factor w/ 2 levels "No","Sí": 2 2 1 2 1 2 1 1 1 1 ...
## $ defecto2: int 1 1 0 1 0 1 0 0 0 0 ...
## $ temp
head(ejDatos)
19
: num 14.7 18.6 13.4 18 10.7 ...
20
## maquina merma manchas defecto defecto2 temp
## 1 maquina1 5.376656 4 Sí 1 14.68176
## 2 maquina1 6.007177 8 Sí 1 18.59629
## 3 maquina1 4.822433 8 No 0 13.44364
or
tail(ejDatos)
Correlación
cov(ejDatos[, c(2,3,6)])
07
## temp 0.92321616 -0.01210713 1.00000000
Representación gráfica
5-
library(corrplot)
-0
## corrplot 0.84 loaded
corrplot(micor, method = "ellipse")
19
20
manchas
merma
temp
1
or
0.8
merma
ad
0.6
0.4
rr
0.2
manchas 0
Bo
−0.2
−0.4
−0.6
temp
−0.8
−1
7
6
merma
07
4
5-
10 12 14 16 18 20 22 24
-0
temp
Gráficos multivariantes
Utilizando el paquete lattice:
19
20
library(lattice)
xyplot(merma ~ temp | maquina, data = ejDatos)
10 15 20
or
maquina1 maquina2
ad
7
rr
6
merma
Bo
10 15 20
temp
2.5. PRÁCTICAS 173
No Sí
07
7
maquina1
6
5-
5
-0
4
merma
7
19
maquina2
20
6
4
or
10 15 20 10 15 20
temp
ad
Objetivo
Bo
Crea un script para esta práctica (o abre el script descargado de la web de material del
curso). Antes de empezar a crear estructuras de datos, vamos a limpiar el espacio de trabajo
para que podamos ir viendo cómo se van añadiendo los datos de forma clara. Puedes utilizar
el icono de la escoba en la pestaña Environment, o ejecutar la siguiente expresión:
rm(list = ls())
174 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
Datos
Vamos a trabajar con el conjunto de datos de recursos humanos.
library(readxl)
RRHH <- read_excel("datos/RRHH.xlsx")
07
## $ nivel_satisfaccion : num 0.22 0.89 0.63 0.8 0.42 0.77 0.51 0.15 0.98 0.19 ..
## $ ultima_evaluacion : num 0.98 0.65 0.76 0.96 0.48 0.82 0.5 0.75 0.99 1 ...
## $ numero_proyectos : num 4 5 4 3 2 4 5 3 3 4 ...
5-
## $ promedio_horas_mensuales: num 185 195 245 161 155 217 176 259 235 192 ...
## $ antiguedad : num 3 6 3 3 3 5 5 8 3 4 ...
## $ accidente : chr "No" "No" "No" "No" ...
-0
## $ abandona : chr "No" "Sí" "No" "No" ...
## $ promocionado : chr "No" "No" "No" "No" ...
## $ departamento
## $ salario
head(RRHH)
19
: chr "soporte" "soporte" "otro" "ingeniería" ...
: chr "bajo" "bajo" "bajo" "bajo" ...
20
## # A tibble: 6 x 10
## nivel_satisfacc~ ultima_evaluaci~ numero_proyectos promedio_horas_~
## <dbl> <dbl> <dbl> <dbl>
## 1 0.22 0.98 4 185
or
summary(modelo)
##
## Call:
## lm(formula = nivel_satisfaccion ~ ultima_evaluacion + numero_proyectos +
## promedio_horas_mensuales, data = RRHH)
2.5. PRÁCTICAS 175
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.51849 -0.16055 0.01814 0.19965 0.43562
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.4635894 0.1250164 3.708 0.000349 ***
## ultima_evaluacion 0.0988790 0.1664402 0.594 0.553855
## numero_proyectos -0.0565945 0.0241336 -2.345 0.021084 *
07
## promedio_horas_mensuales 0.0011603 0.0005949 1.950 0.054055 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
5-
##
## Residual standard error: 0.2515 on 96 degrees of freedom
## Multiple R-squared: 0.06981, Adjusted R-squared: 0.04074
-0
## F-statistic: 2.401 on 3 and 96 DF, p-value: 0.07245
selección automática de variables
modelo2 <- step(modelo)
## Start: AIC=-272.12
19
20
## nivel_satisfaccion ~ ultima_evaluacion + numero_proyectos + promedio_horas_mensuales
##
## Df Sum of Sq RSS AIC
## - ultima_evaluacion 1 0.02233 6.0962 -273.75
or
##
## Step: AIC=-273.75
## nivel_satisfaccion ~ numero_proyectos + promedio_horas_mensuales
rr
##
## Df Sum of Sq RSS AIC
Bo
##
## Call:
## lm(formula = nivel_satisfaccion ~ numero_proyectos + promedio_horas_mensuales,
## data = RRHH)
##
## Residuals:
176 CAPÍTULO 2. ANÁLISIS EXPLORATORIO DE DATOS CON R
07
##
## Residual standard error: 0.2507 on 97 degrees of freedom
## Multiple R-squared: 0.06639, Adjusted R-squared: 0.04714
5-
## F-statistic: 3.449 on 2 and 97 DF, p-value: 0.03573
-0
19
20
Representación gráfica - validación
plot(nivel_satisfaccion ~ numero_proyectos + promedio_horas_mensuales,
data = RRHH)
or
1.0
ad
0.8
nivel_satisfaccion
rr
0.6
Bo 0.4
0.2
2 3 4 5 6
numero_proyectos
2.5. PRÁCTICAS 177
1.0
0.8
nivel_satisfaccion
0.6
0.4
07
0.2
5-
100 150 200 250
-0
promedio_horas_mensuales
par(mfrow=c(2,2))
plot(modelo2) 19
20 Standardized residuals
or
−0.6 0.0
ad
0
−2
61 8 76 861
76
Standardized residuals
61 29
1.0
Cook's distance
−2
0.0
8 76
Predicción
07
## fit lwr upr
## 1 0.6987388 0.5609063 0.8365714
5-
-0
19
20
or
ad
rr
Bo
07
5-
Parte II
-0
19
Técnicas multivariantes
20
or
ad
rr
Bo
179
Bo
rr
ad
or
20
19
-0
5-
07
Capítulo 3
07
Análisis de la varianza con R
5-
3.1. Introducción
-0
El análisis de la varianza es una técnica estadística de análisis de dependencias, donde se bus-
ca explicar una o varias variables cuantitativas a partir de una o varias variables cualitativas
19
o factores. Es decir, buscamos un modelo del tipo:
20
X) + ε
Y = f (X (3.1)
X . En los apartados siguientes se irán detallando los distintos modelos desde el más sencillo
al más complejo. A medida que se avance en los modelos, se presentan más ejemplos y menos
teoría, ya que el fundamento es muy similar y se puede consultar en la bibliografía citada.
rr
La técnica del análisis de la varianza se puede abordar desde dos perspectivas: explicativa
y predictiva. Desde una perspectiva explicativa, se puede aplicar la técnica para realizar es-
Bo
181
182 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
07
calida 5.711
calida 27.511
calida 56.797
5-
calida 15.230
calida 40.784
calida_intensa 2.416
-0
calida_intensa 6.442
calida_intensa 6.833
19
calida_intensa 27.010
calida_intensa
calida_intensa
6.180
8.853
20
posibles niveles, podemos utilizar simplemente contrastes de hipótesis para la comparación
de poblaciones mediante test paramétricos como el de la t de Student, o no paramétricos
or
Una empresa de comercio minorista quiere estudiar el efecto que tiene el tipo de
iluminación en sus tiendas en el tiempo que pasan los clientes en la misma. Para ello diseña
rr
un experimento en el que selecciona a doce clientes de tres tiendas distintas (suponemos que
un cliente siempre compra en la misma tienda). Se asigna aleatoriamente a cada tienda un
tipo de iluminación de entre las siguientes: fría, cálida suave, cálida intensa. El tiempo que
Bo
pasa cada cliente en la tienda se recoge en la tabla 3.1, que están guardados en el data frame
danova1 . Vamos a utilizar este ejemplo a lo largo de este capítulo. El primer paso en toda
técnica estadística es hacer un análisis exploratorio. Como son muy pocos puntos por cada
grupo, vamos a obtener un resumen numérico y a representarlos todos con un gráfico de
puntos (figura 3.1).
A la vista de las medias parece que el tiempo con luz cálida intensa es menor. En los otros
dos no está tan claro que haya diferencia. Por otra parte parece que hay menos variabilidad
con luz cálida intensa. Una vez ajustado el modelo lo comprobaremos numéricamente.
80
60
tiempo
40
07
5-
20
-0
0
calida
19 calida_intensa
##
## $calida_intensa
## Min. 1st Qu. Median Mean 3rd Qu. Max.
ad
3.2.1. Modelo
Tenemos una variable Y que toma valores reales y una variable cualitativa o factor X con
niveles 1, 2, . . . , i, . . . , k. La variable Y toma valores yij , j = 1, . . . , ni en el nivel i del factor X,
siendo ni el número de observaciones en el nivel i del factor X. Cuando todos los niveles tienen
el mismo número de observaciones, ni = ni′ ∀i, i′ , decimos que el diseño está balanceado o
equilibrado. El modelo puede escribirse de dos formas:
184 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
07
αi = µi − µ,
5-
y el término de error, que representa toda la variabilidad que no explica el modelo, es:
-0
εij = yij − µi .
Se cumple que:
∑ 19
αi = 0; εij ∼ N (0, σ 2 )
20
i
tiempo = µ + αtipo + ε,
o:
ad
tiempo = µtipo + ε.
El modelo ANOVA se ajusta en R con la función aov. El siguiente código ajusta el modelo
de nuestro ejemplo, pero de momento solo lo guardamos, veremos en los siguientes apartados
rr
∑
ni
yij
j=1
µ̂i = y i· = ,
ni
3.2. ANÁLISIS DE LA VARIANZA DE UN FACTOR 185
∑
k ∑
k ∑
ni
yi· yij
i=1 i=1 j=1
µ̂ = y ·· = = ,
k n
es decir, las medias dentro de cada nivel del factor, y la media total. Con estos estimadores
de los parámetros, la estimación de valores de Y vendrá dada por:
07
ŷij = µ̂i = µ̂ + α̂i ,
y por tanto los residuos del modelo son:
5-
eij = yij − ŷij
-0
Nótese que, si tenemos k niveles solo tenemos que estimar k − 1, ya que:
19 ∑
αi = 0.
20
i
Esta última restricción hace que no se puedan estimar los efectos con la representación
matricial:
or
y = Xβ + ε
ad
y11 1 1 0 ··· 0 ε11
. . .. .. . . ..
.. .. . . . 0 .
rr
y1n1
1 1 0 ··· 0
ε1n1
y21 1 0 1 ··· 0 µ ε21
.. .. .. .. . . α ..
Bo
. . . . . 0 1 .
α
= 2 +
y2n2
1 0 1 ··· 0
... ε2n2
.. .. .. .. . . .. ..
. . . . . . .
α
yk1
εk1
k
1 0 0 ··· 1
.. .. ..
.. . . .. ..
. . . . . . .
yknk 1 0 0 ··· 1 εknk
µ̂ + α̂1
β̂ = α̂2 − α̂1
α̂3 − α̂1
Sobre el objeto modelo.aov que guardamos antes, podemos aplicar funciones genéricas
07
que devuelvan ciertos resultados. Por ejemplo, la función coef nos devuelve los estimadores
de los coeficientes, teniendo en cuenta que toma calida como nivel de referencia del factor
tipo. Podemos comprobar cómo se corresponden los coeficientes con los efectos estimados.
5-
La función confint nos devuelve un intervalo de confianza para los parámetros. Vemos que,
con respecto al nivel base calida, el tiempo de visita se reduce en 15 minutos cuando la luz
es calida_intensa y aumenta 17 cuando la luz es fria. Se pueden visualizar los efectos con
-0
el paquete effect, como se muestra en la figura 3.2.
## [1] "calida"
19
"calida_intensa" "fria"
20
## Estimación de los coeficientes
coef(modelo.aov)
## (Intercept)
## -0.7836667
rr
## Coeficiente nivel 2
a2 <- coef(modelo.aov)[2] + a1; a2
Bo
## tipocalida_intensa
## -16.38583
## Coeficiente nivel 3
a3 <- coef(modelo.aov)[3] + a1; a3
## tipofria
## 17.1695
## Comprobación
aggregate(tiempo ~ tipo, danova, mean)$tiempo - mean(danova$tiempo)
3.2. ANÁLISIS DE LA VARIANZA DE UN FACTOR 187
60
50
40
07
tiempo
30
20
5-
10
-0
0
−10
calida 19calida_intensa
tipo
fria
20
Figura 3.2: Visualización de los efectos
or
## 2.5 % 97.5 %
## (Intercept) 6.948564 43.50044
## tipocalida_intensa -41.448244 10.24391
Bo
3.2.3. Contrastes
En el análisis de la varianza de un factor, lo que nos interesa demostrar es que hay diferencias
entre los niveles del factor (la X explica la Y ). Si no hubiera diferencias entre los niveles,
entonces las medias µi serían iguales, o lo que es lo mismo, los efectos αi serían nulos. Por
tanto, la hipótesis nula del modelo ANOVA de un factor es:
H0 : µ1 = µ2 = · · · = µk ,
o equivalentemente:
07
H0 : αi = 0 ∀i.
5-
Nótese que la hipótes alternativa es que hay diferencia entre los niveles, pero eso no significa
que todos los niveles sean diferentes. Es decir, si rechazamos la hipótesis nula, y por tanto
-0
tenemos evidencia para aceptar la alternativa:
19
H1 : αi ̸= 0 para algún i,
Para contrastar la hipótesis nula, dividimos la variabilidad total de los datos entre la variabi-
20
lidad que existe “dentro” de los grupos y la variabilidad que existe “entre” los grupos. Esta
variabilidad la representamos por las sumas de cuadrados, de manera que la suma de cua-
drados total (SCT ) la podemos descomponer en la suma de cuadrados entre grupos (SCE)
más la suma de cuadrados dentro de grupos (SCD):
or
∑ ∑ ∑
(yij − y ·· )2 = ni (y i· − y ·· )2 + (yij − yi· )2 ,
ad
ij i ij
∑
(yij − y ·· )2
ij
CM T = ,
n−1
∑
ni (y i· − y ·· )2
i
CM E = ,
k−1
∑
ni (y i· − y ·· )2
i
CM D = ,
n−k
3.2. ANÁLISIS DE LA VARIANZA DE UN FACTOR 189
Entonces, si se cumplen las condiciones para aplicar el modelo y la hipótesis nula es cierta,
el estadístico:
07
CM E
F =
CM D
sigue una distribución F con k − 1 y n − k grados de libertad, y podemos bien realizar el
5-
contraste de hipótesis para un nivel de confianza determinado, bien interpretar el p-valor,
para llegar a una conclusión o decisión. En Análisis de la Varianza aquí descrito se resume
normalmente en la llamada tabla ANOVA (ver tabla 3.2), que incluye las sumas de cuadrados,
-0
cuadrados medios, estadístico F y el p-valor.
19
La función genérica summary aplicada a un modelo ANOVA devuelve precisamente la
tabla ANOVA. En nuestro ejemplo, el p-valor es pequeño, menor de 0.05 (aunque por poco).
Luego para un nivel de significación del 5 % podemos rechazar la hipótesis nula y aceptamos
20
que hay diferencias en las medias2 .
summary(modelo.aov)
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Como se ha indicado anteriormente, al rechazar la hipótesis nula aceptamos que no todos
rr
los niveles del factor producen una misma respuesta en la variable Y . Una vez rechazada
la hipótesis nula, tendremos que comprobar qué niveles son realmente distintos para, en
última instancia, sacar conclusiones o tomar decisiones. Un enfoque erróneo sería realizar
Bo
comparaciones con el test de la t de Student para cada par de niveles del factor. En su lugar,
utilizamos el método HSD3 de Tukey, que utiliza el estadístico de los rangos estudentizados,
R/σ̂ para realizar todos los contrastes siguientes:
H0 : µi = µj ∀i ̸= j.
La función TukeyHSD realiza los contrastes dos a dos de un modelo ANOVA, con
3
Honestly Significance Difference
190 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
fria−calida_intensa fria−calida
07
5-
-0
−40 −20 0 20 40 60
19
Differences in mean levels of tipo
20
Figura 3.3: Visualización de las diferencias por pares
en el siguiente ejemplo. La salida proporciona las diferencias entre cada par de niveles, un
intervalo de confianza y el p-valor del contraste. Vemos que hay diferencias significativas
or
entre la luz fria y la calida intensa, pero no en el resto de comparaciones. Estas diferencias
se pueden visualizar utilizando la función plot, que produce la figura @fig(fig:tukeytipo).
ad
TukeyHSD(modelo.aov)
del factor sobre la variable, el ANOVA de un factor debe realizarse a partir de un experimento
diseñado correctamente, véase 3.6.
07
Las hipótesis del test de la F y de los tests HSD de Tukey son la igualdad de varianzas
entre grupos, y la normalidad de los residuos. La igualdad de varianzas se pueden comprobar
fácilmente con el test de Bartlett4 . La normalidad de los residuos se puede verificar con
5-
alguno de los múltiples tests de normalidad existentes, como por ejemplo el de Kolmogorov-
Smirnoff, el de Shapiro-Wilk o el de Anderson-Darling. La función genérica plot de R sobre
un modelo ANOVA guardado produce una serie de gráficos de diagnóstico que nos dan una
-0
idea a veces suficiente del cumplimiento de las hipótesis.
19
La función genérica residuals sobre el objeto modelo.aov devuelve los residuos del
modelo. Podemos entonces hacer un contraste de normalidad. El p-valor es grande, mucho
mayor de 0,05, por lo que no podemos rechazar que los residuos sean normales. La función
20
bartlett.test contrasta la hipótesis de homogeneidad de varianzas. El p-valor de este
contraste es grande, mayor de 0.05 (aunque no mucho mayor). Podemos aceptar la igualdad
de varianzas y por tanto las conclusiones de las pruebas de Fisher y de Tukey son válidas.
or
La figura 3.4 muestra los gráficos de diagnóstico generados con la función plot. Nótese que
para mostrar los cuatro gráficos en un mismo panel hemos dividido el espacio gráfico en 2
filas y 2 columnas (función par, véase la ayuda de esta función). El gráfico superior izquierdo
ad
deberia mostrar una línea recta si el modelo lineal se ajusta, y también se aprecia la homoge-
neidad de varianzas. A menudo cuando no se cumple esta hipótesis el gráfico muestra forma
de embudo. El gráfico inferior izquierdo muestra la misma información pero a otra escala,
donde tampoco se aprecian varianzas distintas. El gráfico superior derecho es un gráfico
rr
cuantil-cuantil para comprobar la normalidad de los residuos, en este caso se ajusta bastante
bien. El gráfico inferior derecho sirve para detectar observaciones con gran influencia en el
Bo
shapiro.test(residuals(modelo.aov))
##
## Shapiro-Wilk normality test
##
## data: residuals(modelo.aov)
## W = 0.92539, p-value = 0.161
4
Hay otras alternativas, como el test de Levene en la función levene.test del paquete car.
192 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
Standardized residuals
Residuals vs Fitted Normal Q−Q
5
2 10 2 5
Residuals
10
20
1
−20
−1
10 15 20 25 30 35 40 −2 −1 0 1 2
07
Constant Leverage:
Standardized residuals
Standardized residuals
Scale−Location Residuals vs Factor Levels
5-
10 5
2 5
10 2
1
0.8
-0
−1
0.0
tipo :
10 15 20 25 30 35 40 calida fria
Fitted values 19
Figura 3.4: Gráficos de diagnóstico modelo ANOVA
Factor Level Combinations
20
bartlett.test(tiempo ~ tipo, data = danova)
or
##
## Bartlett test of homogeneity of variances
ad
##
## data: tiempo by tipo
## Bartlett's K-squared = 5.3399, df = 2, p-value = 0.06926
rr
par(mfrow = c(2,2))
plot(modelo.aov)
Bo
par(mfrow = c(1,1))
Otra alternativa es transformar los datos originales para conseguir normalidad y/o homoge-
neidad de varianzas y realizar el análisis con los datos transformados.
3.2. ANÁLISIS DE LA VARIANZA DE UN FACTOR 193
07
podemos rechazar que los datos vengan de la misma población, y por tanto llegamos a
la conclusión de que no hay diferencias. Aunque en este caso no sería necesario seguir,
por completitud del ejemplo vamos a realizar las comparaciones por pares utilizando la
5-
función kruskalmc del paquete pgirmess. Obtenemos en este caso la siferencias observadas
y críticas (para un determinado nivel de significación) y un indicador (TRUE/FALSE) de
diferencia significativa. Como era de esperar, no se encuentra ningún par de niveles con
-0
diferencias significativas.
##
19
Df Sum Sq Mean Sq F value Pr(>F)
20
## temperatura 2 43 21.6 0.033 0.968
## Residuals 15 9957 663.8
shapiro.test(residuals(modelo.aov2))
or
##
## Shapiro-Wilk normality test
ad
##
## data: residuals(modelo.aov2)
## W = 0.84498, p-value = 0.007066
rr
##
Bo
##
## Kruskal-Wallis rank sum test
##
## data: tiempo by temperatura
194 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
07
baja 5.711
media 27.511
alta 56.797
5-
baja 15.230
alta 40.784
baja 2.416
-0
alta 6.442
baja 6.833
alta
baja
19
media 27.010
6.180
8.853
20
## Kruskal-Wallis chi-squared = 0.5653, df = 2, p-value = 0.7538
pgirmess::kruskalmc(tiempo ~ temperatura, data = danova)
or
## Comparisons
## obs.dif critical.dif difference
## alta-baja 1.9444444 6.735838 FALSE
## alta-media 0.1666667 9.037076 FALSE
rr
Realice la práctica 3.1 cuyo guión se encuentra en el apartado 3.7 para realizar análisis
de la varianza de un factor.
07
Y = µ + αi + βj + (αβ)ij + ε,
5-
interpretación que en el ANOVA de un factor (o one-way anova). En la tabla ANOVA se
añaden nuevas filas y contrastes para los efectos principales y las interacciones. Las hipótesis
-0
del modelo son las mismas, luego comprobamos normalidad de los residuos y homogeneidad
de variazas. Para este último caso, utilizamos mejor el test de Levene que permite incluir el
término de la interacción.
19
En el ajuste del modelo y estimación de efectos, se toma como base el primer nivel de todos
los factores.
20
Para especificar modelos con más de un factor e interacción en R, ampliamos el lado derecho
de la fórmula del modelo. Los nuevos efectos se añaden “sumando”. La interacción se expresa
separando los factores con dos puntos. Si utilizamos el símbolo asterisco, entonces el modelo
incluye todos los efectos principales y las interacciones. Por ejemplo, para dos factores a y b,
or
En el apartado anterior hemos analizado por separado el tiempo frente a los factores
iluminación y temperatura. Pero deberíamos analizarlos en un modelo multifactorial como
el generado con el siguiente código.
rr
luz fría y temperatura media, lo que sería una pésima decisión ya que esta interacción baja
drásticamente el tiempo de permanencia en la tienda.
07
## Residuals 9 1578 175.3
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
5-
shapiro.test(residuals(modelo.aov3))
-0
##
## Shapiro-Wilk normality test
##
## data: residuals(modelo.aov3)
## W = 0.90973, p-value = 0.08508 19
car::leveneTest(tiempo ~ tipo*temperatura, danova)
20
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 8 0.5545 0.7908
or
## 9
coef(modelo.aov3)
ad
## (Intercept) tipocalida_intensa
## 48.79050 -42.47950
## tipofria temperaturabaja
rr
## -22.18850 -40.03883
## temperaturamedia tipocalida_intensa:temperaturabaja
Bo
## -21.27950 39.76183
## tipofria:temperaturabaja tipocalida_intensa:temperaturamedia
## 77.55783 41.97850
## tipofria:temperaturamedia
## 8.17650
effects::allEffects(modelo.aov3)
60 temperatura
baja
50 alta
media
mean of tiempo
40
30
07
20
5-
10
-0
calida calida_intensa fria
19 tipo
interaction.plot(x.factor = tipo,
trace.factor = temperatura,
response = tiempo,
rr
las = 1))
Bo
El caso de dos factores con interacción se extiende fácilmente a más de dos factores aña-
diento términos a la fórmula. No obstante, las interacciones de más de dos factores se suele
despreciar. En el modelo resultante final se deberian eliminar los efectos no significativos,
aunque manteniendo aquellos efectos principales que intervengan en alguna interacción.
Realice la práctica 3.2 cuyo guión se encuentra en el apartado 3.7 para realizar análisis
de la varianza multifactorial.
07
individuos se han asignado aleatoriamente a los distintos niveles. Incluso en estudios obser-
vacionales, podemos asumir que esta asignación se ha hecho de forma aleatoria y controlada,
y son efectos fijos.
5-
Pero esto no siempre se puede asumir, o directamente la naturaleza del propio factor es
aleatoria, y el tratamiento que le tenemos que dar a los factores es distinto. En particular, los
-0
efectos de estos factores no son una constante que queramos estimar, sino variables aleatorias
de las cuales queremos estudiar su varianza en el modelo. El modelo para un factor fijo α y
otro aleatorio β sería el siguiente:
19
Y = µ + αi + βj + ε,
20
donde el efecto aleatorio β ∼ N (0, σβ2 ). No tiene por tanto sentido estimar el efecto, cuya
media es cero, sino la variabilidad, y ver si es importante con respecto al resto de factores.
or
En este caso tendríamos que ajustar un modelo mixto. En este ejemplo vemos que el factor
temperatura afecta poco o nada a la variable respuesta, ya que la varianza es prácticamente
nula6 . Podemos obtener una estimación de los efectos con la función ranef del paquete lme4.
rr
library(lme4)
Bo
07
## Number of obs: 18, groups: temperatura, 3
##
## Fixed effects:
5-
## Estimate Std. Error t value
## (Intercept) 25.225 8.574 2.942
## tipocalida_intensa -15.602 12.126 -1.287
-0
## tipofria 17.953 12.126 1.481
##
##
##
##
Correlation of Fixed Effects:
(Intr) tpcld_
tipcld_ntns -0.707
19
20
## tipofria -0.707 0.500
## convergence code: 0
## boundary (singular) fit: see ?isSingular
ranef(modelo.mixto)
or
## $temperatura
## (Intercept)
ad
## alta 0
## baja 0
## media 0
rr
##
## with conditional variances for "temperatura"
Bo
Los modelos mixtos (o incluso aleatorios puros) tienen muchas aplicaciones tanto en modelos
económicos como en cualquier otro ámbito. Algunos ejemplos son:
Efectos aleatorios puros, como el que se ha mostrado en el ejemplo.
Modelos de panel, donde tenemos mediciones en diferentes periodos, y la unidad ob-
servable dentro del tiempo forman el factor aleatorio
Medidas repetidas, donde el individuo es el factor aleatorio
Modelos anidados y jerarquizados, donde unos niveles están dentro de otros
Como se ha podido comprobar, el análisis de modelos mixtos no es tan sencillo como el de
200 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
efectos fijos. Para una revisión más completa se recomienda consultar el libro de Faraway
(2016).
07
variables en el vector de variables independientes X . El método calcula una matriz de errores
y una matriz de hipótesis7 , y mediante el cálculo de un estadístico (por defecto Pillai8 ) se
contrasta la hipótesis.
5-
En el conjunto de datos de ejemplo tenemos otra variable en escala métrica que es el
-0
gasto realizado por cada cliente durante la compra. El siguiente ejemplo realiza el análisis
multivariante de la varianza para estas dos variables agrupadas en una matriz. El modelo se
puede ajustar con la función aov, o bien con la función maov, que es realmente un wrapper de
19
la anterior. Los contrastes multivariantes se obtienen con la función summary.manova, si no
le añadimos .manova tenemos los contrastes univariantes para cada componente del vector
aleatorio Y . El resultado que obtenemos en este caso es muy similar al obtenido en el ejemplo
20
univariante. En ocasiones puede suceder que los contrastes univariantes no son significativos
pero sí lo es el contraste multivariante.
## Residuals 9
## ---
Bo
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
summary(modelo.manova)
## Response tiempo :
## Df Sum Sq Mean Sq F value Pr(>F)
## tipo 2 3383.4 1691.70 9.6499 0.005768 **
## temperatura 2 43.2 21.58 0.1231 0.885628
## tipo:temperatura 4 4995.9 1248.98 7.1245 0.007186 **
7
Ver: https://rpubs.com/aaronsc32/manova-test-statistics
8
ver una descripción de las alternativas en https://rpubs.com/aaronsc32/manova-test-statistics.
3.6. INTRODUCCIÓN AL DISEÑO DE EXPERIMENTOS 201
07
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
5-
Realice la práctica 3.3 cuyo guión se encuentra en el apartado 3.7 para realizar análisis
multivariante de la varianza.
-0
3.6. Introducción al diseño de experimentos
3.6.1. Introducción
19
20
El Diseño y Análisis de Experimentos (que abreviaremos como DoE), como cualquier otra
técnica estadística, se basa en el estudio de la variabilidad. DoE es la herramienta más
potente para la mejora, lo que ha llevado a algunos autores a llamarlo “the jewel of quality
engineering” (Ver por ejemplo Allen (2010)).
or
En apartados anteriores del libro hemos aprendido las herramientas básicas para analizar
la variabilidad de los datos. En este apartado vamos a revisar las técnicas de Diseño de
ad
datos.
El objetivo del diseño de experimentos es encontrar los niveles de ciertos factores que opti-
mizan una determinada característica medible. Esto se consigue con un método sistemático9
que evita salidas en falso y respuestas incompletas. Mediante la reducción del error experi-
mental se consigue evitar la confusión de los efectos y anular los efectos sin interés para el
estudio.
Para empezar, lo primero que necesitamos es definir los datos del problema objeto de estudio
y disponer de una forma de obtenerlos adecuadamente, en particular:
07
Una variable respuesta en escala métrica
Factores controlables
Posiblemente, otros factores aleatorios
5-
Esta recogida de datos se debe realizar de forma sistemática y teniendo en cuenta los tres
pilares del DoE: aleatorización, bloqueo y replicación.
-0
3.6.3. Importancia del diseño
19
Con la experimentación básicamente controlamos los niveles a los que operan ciertos factores
controlables, a la vez que se asignan dichos niveles (configuraciones, tratamientos, etc.) a las
unidades experimentales. Esto permite, unido a las apropiadas estrategias de aleatorización,
20
bloqueo y replicación, realizar predicciones acerca del desempeño de un determinado proceso.
Estas predicciones así establecidas serán el resultado de la identificación de una relación
causa-efecto, que no se puede conseguir simplemente analizando datos recogidos sin diseño.
En los estudios observacionales:
or
Recogemos información
No controlamos factores
Análisis descriptivos
ad
Descubrir relaciones
Mientras que con experimentos diseñados:
rr
El análisis de datos, por muy sofisticado que sea, no puede nunca arreglar un experi-
mento mal diseñado (chapucero, según Lawson)
Sometimes the only thing you can do with a poorly designed experiment is to
try to find out what it died of
R.A. Fisher
As we know from Murphy’s Law, if anything can go wrong it will, and analysis
of data can never compensate for botched experiments
07
John Lawson Lawson (2015)
5-
Sin Diseño de Experimentos, los datos pueden ser inconsistentes o incompletos, al no incluir
factores de ruido o Factores latentes. Si tenemos variables correlacionadas, y alguna de ellas
no se mide, su efecto puede quedar enmascarado por las otras, como en el ejemplo de la figura
-0
3.6, donde si miramos solo la relación de la variable respuesta con el factor 1 (gráfico de la
izquierda), podemos llegar a la conclusión errónea de que el factor 1 es determinante. Pero
19
podría ser que la causa real sea el factor 2, que no ha sido medido y está muy correlacionado
con el factor 1. En el gráfico de la derecha vemos que la variable respuesta crece en el mismo
sentido que los factores 1 y 2, pero podría ser que el factor 2, no medido al principio, sea la
20
causa, y no el que realmente se ha medido.
Por otra parte, el rango de valores de la variable respuesta está limitado por su rango normal
de operación, que puede ocultar relaciones más amplias. En la figura 3.7, el gráfico de la
derecha se corresponde con el rango de variación normal de los factores de un proceso. En el
or
cimientos, lleva a una mayor capacidad de mejora. Estas ideas, originarias de Deming, se
recogen en Moen et al. (2012). Algunas capacidades necesarias fruto de esta combinación
son:
Entender las interdependencias entre los sistemas donde se lleva a cabo la experimen-
tación;
Entender la relación entre las predicciones y el conocimiento del sistema que se quiere
cambiar;
Entender el efecto temporal de los cambios;
Entender la importancia de la estabilidad del proceso;
Entender la extrapolación de los resultados de las pruebas para mejorar el sistema.
204 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
07
138
28.0
5-
136 27.5
-0
response
19 27.0
response
134 130
factor2
132
20
134
26.5
136
132
or
26.0
ad
130
25.5
rr
78 79 80 81 82 78 79 80 81 82
factor1 factor1
Bo
14
10 11 12 13
12
Y
y
9 10
07
8
8
5-
7
7
8 9 10 11 12 9.0 9.5 10.0 10.5 11.0
-0
X x
19
Figura 3.7: Efecto de la limitación del rango de valores
Datos
07
Inducción Inducción
5-
-0
Idea (modelo, hipótesis, ...)
19
Figura 3.8: Método iterativo de aprendizaje
20
or
Act Plan
ad
rr
Bo
Study Do
07
Six Sigma Cause−and−effect Diagram
5-
-0
Operator Environment Tools
operator #1 height scissors
operator #2
operator #3
19
cleaning tape
20
Flight Time
paperclip
or
Hasta ahora, hemos ido mencionando algunos conceptos básicos del diseño de experimentos.
Ahora vamos a definirlos un poco más formalmente.
variable respuesta: La variable de interés que pretendemos mejorar. Será una cuan-
tificación de alguna característica de calidad, en sentido amplio.
factor: Variable independiente que puede ser causa de la respuesta. La inferencia que
haremos con DoE será confirmar o rechazar esta hipótesis.
07
variable de bloque: Variable que no tiene interés en la investigación, pero puede
influir en la respuesta. Mediante la formación de bloques confundimos su efecto con
los factores que realmente nos interesan.
variable ruido: Variable que puede influir en la respuesta, pero de la que no tenemos
5-
control.
nivel: Valor que fijamos de un factor. En variables cualitativas, una categoría. En
-0
variables cuantitativas, un valor numérico determinado fijado con antelación. A menudo
se le llama también tratamiento.
unidad experimental: La división más pequeña posible de unidades de un expe-
factores y niveles. 19
rimento tal que a dos cualesquiera se les pueden aplicar distintas combinaciones de
unidad observable: Cada uno de los elementos que forman la unidad experimental.
20
A veces, un tratamiento no se puede aplicar a un solo elemento, sino a varios a la vez.
bloque: Grupos de unidades experimentales que son tratados de forma similar en el
experimento.
efecto: El principal resultado de interés del experimento: qué pasa con la variable
or
respuesta.
réplica: Repetición de un experimento sobre una misma combinación de factores y
niveles, a diferentes unidades experimentales.
ad
aleatoria
Al utilizar un modelo para simplificar una realidad, estamos cometiendo un error. El error
Bo
experimental es aquel que se debe exclusivamente a las réplicas de las mismas condiciones
experimentales. En cada diseño el error experimental se calcula de una forma distinta, de
forma que se separa de la variabilidad total para ver cuánta variaación se debe al modelo y
poder así tomar decisiones.
Aleatorización. Los tratamientos deben ser asignados de forma aleatoria a las unida-
des experimentales. Esto incluye bloques, factores controlables, anidamientos, etc.
07
7. Elegir el diseño experimental
8. Determinar el número de réplicas necesarias
9. Aleatorizar las condiciones experimentales a las unidades experimentales
5-
10. Definir método de análisis de datos
11. Calendario y presupuesto para la ejecución
-0
3.6.5. Tipos de diseños de experimentos
3.6.5.1. Experimentos con un factor
19
Podemos comparar una variable a distintos niveles de un solo factor. El contraste de la t de
Student es la técnica utilizada para dos niveles. Para más niveles, utilizamos el análisis de la
20
varianza de un factor (véase sec:anova1). Cuando hay algún factor más que no es de interés,
pero puede afectar a la variable resupesta, se debe introducir como variable de bloque. Los
diseños de cuadrados latinos y cuadrados greco-latinos se utilizan para introducir dos o tres
factores de bloque respectivamente.
or
1. Se quiere estudiar el efecto de un solo factor sobre una población. No hay otros factores
controlables que puedan influir.
2. Se realiza el plan de recogida de datos, posiblemente con prueba piloto.
rr
07
3.6.5.3. Diseños factoriales a dos niveles 2k
Un tipo especial de diseño multifactorial es aquél en el que todos los factores tienen solamente
5-
dos niveles. El número de experimentos necesarios para probar todas las combinaciones de
niveles para k factores es 2k , de ahi su nombre.
-0
Diseño factorial 22
Modelo:
19
yijk = αi + βj + αβij + εijk
20
Datos:
Aleatorizar tratamientos
Realizar k réplicas
or
Número de experimentos: k × 22
Análisis: - Efectos principales - Interacción
ad
library(xtable)
library(DoE.base)
rr
07
## lengths
library(effects)
5-
## Use the command
## lattice::trellis.par.set(effectsTheme())
## to customize lattice options for effects plots.
-0
## See ?effectsTheme for details.
library(reshape2)
datosf22 <- scan(text = "
-
-
-
-
28
25
19
20
- - 27
+ - 36
+ - 32
+ - 32
or
- + 18
- + 19
- + 23
ad
+ + 31
+ + 30
+ + 29
",
rr
A B 1 2 3
- - 28 25 27
- + 18 19 23
+ - 36 32 32
+ + 31 30 29
212 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
07
## B 1 75.000 75.000 19.1489 0.002362 **
## A:B 1 8.333 8.333 2.1277 0.182776
## Residuals 8 31.333 3.917
5-
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
-0
Gráficos de los efectos
library(lattice)
trellis.par.set(background = list(col = "white"))
plot(effect(term = "A", mod = modelof22))
19
## NOTE: A is not a high-order term in the model
20
A effect plot
or
32
ad
30
respuesta
rr
28
Bo
26
24
22
− +
A
3.6. INTRODUCCIÓN AL DISEÑO DE EXPERIMENTOS 213
07
## NOTE: B is not a high-order term in the model
5-
-0
19
20
B effect plot
32
or
30
ad
respuesta
28
rr
Bo
26
24
− +
B
plot(effect(term = "A:B", mod = modelof22))
214 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
30
07
respuesta
25
5-
-0
20
− 19 +
A
20
modelof22 <- lm(respuesta ~ A + B, data = datosf22)
anova(modelof22)
or
ad
rr
Bo
A effect plot
32
30
respuesta
07
28
26
5-
24
-0
22
− 19 A
+
20
plot(effect(term = "B", mod = modelof22))
B effect plot
or
32
ad
30
rr
respuesta
28
Bo
26
24
− +
B
216 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
Diseño factorial 23
Modelo:
07
Efectos principales
Interacciones (más de dos difícil de ver)
Eliminar no significativas para aumentar precisión
5-
Ejemplo:
datosf23 <- scan(text = "
-0
- - - 60
+ - - 72
- + - 54
+
-
+
+
-
-
-
+
+
68
52
83
19
20
- + + 45
+ + + 80
",
what = list(character(), character(), character(), numeric()),
or
sep = "\t")
datosf23 <- as.data.frame(datosf23)
colnames(datosf23) <- c("T", "C", "K", "rendimiento")
ad
T C K .
- - - 60
rr
- - + 52
- + - 54
Bo
- + + 45
+ - - 72
+ - + 83
+ + - 68
+ + + 80
modelof23 <- lm(rendimiento ~ T + C + K + T*C + T*K + C*K, data = datosf23)
anova(modelof23)
07
Gráfico de efectos e interacciones:
5-
plot(effect(term = "T", mod = modelof23))
-0
## NOTE: T is not a high-order term in the model
19
T effect plot
20
80
75
or
70
rendimiento
ad
65
60
rr
55
Bo
50
− +
T
plot(effect(term = "C", mod = modelof23))
C effect plot
70
68
rendimiento
66
07
64
5-
62
60
-0
58
− 19 C
+
20
plot(effect(term = "K", mod = modelof23))
or
ad
rr
Bo
K effect plot
68
66
rendimiento
07
64
5-
62
-0
60
− 19 K
+
20
plot(effect(term = "T:C", mod = modelof23))
− +
C=− C=+
ad
80
rr
70
rendimiento
Bo
60
50
− +
T
220 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
07
5-
-0
19
20
T*K effect plot
− +
or
K=− K=+
ad
80
rendimiento
rr
70
Bo
60
50
− +
T
plot(effect(term = "C:K", mod = modelof23))
3.6. INTRODUCCIÓN AL DISEÑO DE EXPERIMENTOS 221
70
rendimiento
07
65
5-
60
-0
55
− 19 +
C
20
Diseño factorial 2k
3.7. Prácticas
En este apartado se presentan las prácticas a las que se han hecho referencia durante el
capítulo. La reproducibilidad del código ha sido comprobada con la sesión de R que se
detalla en el Prefacio. El lector puede teclear el código o copiarlo y pegarlo en la consola o
el editor. También se puede descargar el script con el código de todas las prácticas con la
siguiente expresión:
download.file("http://emilio.lcano.com/b/adr/practicas/03-anova.R",
destfile = "practicas/03-anova.R")
07
Práctica 3.1: ANOVA de un factor
5-
Ejemplo 1
El primer ejemplo de ANOVA trata de verificar si la variable dependiente “Rendimiento por
-0
árbol” depende, en media, del factor “Tipo de fertilizante utilizado”. Dicho factor tiene tres
niveles: (1) fertilizante de tipo químico y (2) fertilizante de tipo orgánico y (3) fertilizante
tipo cuántico.
19
Las expresiones utilizadas se encuentran en el script de las prácticas del capítulo. Para tu
comodidad, puedes descargarlo a una carpeta dentro de tu proyecto de RStudio, por ejemplo,
“prácticas”, o cualquier otro nombre de tu elección. En lo sucesivo, vamos a suponer que
20
estamos trabajando en un proyecto que contiene una carpeta llamada “datos” donde se
encuentran los ficheros de datos.
Opcionalmente, podemos en primer lugar limpiar el espacio de trabajo eliminando todos los
or
objetos existentes:
rm(list = ls())
ad
ducimos las variables para 6 casos (plantaciones) mediante dos vectores, uno numérico para
la variable “Rendimiento” y otro de tipo factor para la variable “(Tipo de) Fertilizante”,
Bo
que puede ser Q(uímico), O(rgánico) o C(uántico). Luego formamos la hoja de trabajo o
data.frame uniendo ambos vectores, y calculamos los principales estadísticos de la variable
y el factor con la función summary. Esta función nos devuelve, para variables numéricas, el
resumen de cinco números más la media, y para factores, una tabla de frecuencias.
Rendimiento <- c(1, 2, 5, 3, 7, 8, 8, 8.5, 10)
Fertilizante <- factor(c("Q", "Q", "Q", "O", "O", "O", "C", "C", "C"))
Datos <- data.frame(Rendimiento, Fertilizante)
summary(Datos)
## Rendimiento Fertilizante
## Min. : 1.000 C:3
3.7. PRÁCTICAS 223
07
La función tapply ofrece la información sobre la primera variable para cada uno de los
grupos formados por los diferentes niveles del factor que se pasa como segunda variable. En
5-
nuestro caso, nos interesa estudiar el rendimiento para cada fertilizante. Esta información
puede ser un summary o cualquier otra función.
-0
tapply(Rendimiento, Fertilizante, summary)
19
20
## $C
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 8.000 8.250 8.500 8.833 9.250 10.000
or
##
## $O
## Min. 1st Qu. Median Mean 3rd Qu. Max.
ad
10
8
Rendimiento
07
4
5-
2
-0
C O Q
19 Fertilizante
Los gráficos “boxplot” ya nos indican cómo todo hace pensar que entre los grupos de distinto
20
tipo de fertilizante va a haber apreciables diferencias en la media. Interpretación del gráfico:
La caja contiene una banda que es la mediana. La caja contiene el 50 % de los casos centrales.
Por arriba sale una línea que llega al valor más grande que no llega a ser atípico; y por debajo
de la caja lo mismo pero mínimo. Un valor atípico es el que se aleja más de 1.5 longitudes de
or
caja del percentil 75, por arriba; o del 25, por debajo. Si hubiera, saldrían dibujos de círculos.
Valores extremos son aquellos que se alejan más de 3 longitudes de caja del percentil 75, por
arriba; o del 25, por debajo.
ad
Rendimiento = µ + F ertilizantei + ε,
07
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
5-
El valor del estadístico F es de 6.906, con un p-value de 0.0278. Como el p-value es menor
-0
que 0.05, se rechaza la hipótesis nula de medias iguales para un nivel de confianza del 95 %;
por lo que podremos decir que el tipo de fertilizante explica, en media, el rendimiento de la
explotación.
19
20
or
Sabemos que las conclusiones a las que lleguemos con el análisis de la varianza (ANOVA)
rr
serán válidas en la medida en que se cumplan las hipótesis de normalidad de los residuos y
homogeneidad en las varianzas de la variable dependiente (“Rendimiento”) en los grupos en
que queda dividida la muestra por los niveles o categorías del factor (“Fertilizante”). Hemos
Bo
Ahora que tenemos el modelo, vamos a validar la hipótesis de normalidad. La función plot
sobre el modelo ajustado del análisis de la varianza nos proporciona varios gráficos de diag-
nóstico. Para verlos todos juntos, utilizamos la función par para crear una matriz de 2 × 2
gráficos.
par(mfrow = c(2, 2))
plot(Datos.aov)
226 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
Standardized residuals
Residuals vs Fitted Normal Q−Q
3 3
Residuals
2 6 6
0.5
0
−1.5
−3
4 4
07
Constant Leverage:
Standardized residuals
Standardized residuals
Scale−Location Residuals vs Factor Levels
5-
4 3
3 6 6
0.8
-0
0.0
−2
4
Fertilizante :
3 4 5 6 7 8 9 C O Q
par(mfrow = c(1,1))
Fitted values 19 Factor Level Combinations
20
El gráfico de los residuos frente a los valores estimados (fitted) sirve para comprobar la
homogeneidad de varianzas. Una forma de embudo de la nube de puntos significaría un
problema en este sentido. El gráfico QQ debería mostrar los puntos aproximadamente sobre
or
la línea recta para confirmar la normalidad de los residuos. Los gráficos inferiores pueden
ser útiles para identificar dónde puede estar el problema concreto si los gráficos superiores
muestran alguna violación de las hipótesis.
ad
Podemos utilizar contrastes de hipótesis si los métodos gráficos no son suficientemente claros.
Para contrastar la homogeneidad en las varianzas (varianzas constantes entre los grupos),
podemos proceder a un análisis de la dispersión mediante la prueba de Bartlett.
rr
##
## Bartlett test of homogeneity of variances
##
## data: Rendimiento by Fertilizante
## Bartlett's K-squared = 1.2584, df = 2, p-value = 0.533
Para contrastar la hipótesis de normalidad de los residuos, podemos utilizar el test de Shapiro-
3.7. PRÁCTICAS 227
Wilk. Los residuos los podemos obtener directamente con la función residuals aplicada al
modelo,
shapiro.test(residuals(Datos.aov))
##
## Shapiro-Wilk normality test
##
## data: residuals(Datos.aov)
## W = 0.96032, p-value = 0.8016
07
El p-valor es muy grande, por lo que no tenemos evidencia para rechazar la hipótesis de
normalidad, y por tanto consideramos válido el resultado del contraste de la F .
5-
3.7.0.0.0.4. Análisis del modelo
-0
El análisis no ha terminado, hay que proceder al análisis de “comparaciones múltiples”. Este
análisis indica qué grupos concretos difieren significativamente entre sí en la media de la
19
variable dependiente (test HSD de Tukey).
TukeyHSD(Datos.aov, conf.level = 0.95)
20
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov.default(formula = Rendimiento ~ Fertilizante, data = Datos)
or
##
## $Fertilizante
## diff lwr upr p adj
ad
La tabla nos proporciona las diferencias reales entre cada grupo, un intervalo de confianza
(lwr límite inferior, upr límite superior) al 95 % (por defecto, pero se puede cambiar), y
Bo
un p-valor con el contraste de Tukey para comparaciones múltiples. Vemos cómo solo hay
diferencias significativas entre el fertilizante cuántico y el químico, ya que el intervalo de
confianza no contiene al cero. A partir de aquí, el analista deberá combinar otra información,
como el coste de los fertilizantes y otras consideraciones para tomar una decisión sobre cuál
utilizar.
Aunque en este caso no habría que hacerlo, si no se hubieran cumplido las hipótesis de
normalidad y/o homogeneidad en las varianzas, existen varias pruebas robustas para saber
si, en media, el factor influye sobre el valor de la variable dependiente. Aquí mostramos la
prueba de Kruskal-Wallis. En este caso, para un nivel de confianza del 95 % se rechaza la
hipótesis nula de igualdad en las medias, aunque por poco.
228 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
##
## Kruskal-Wallis rank sum test
##
## data: Rendimiento by Fertilizante
## Kruskal-Wallis chi-squared = 6.1176, df = 2, p-value = 0.04694
Para las comparaciones múltiples, en este caso también existe una prueba de Kruskal; pero
para poder ejecutarla hay que cargar en el espacio de trabajo el paquete “pgirmess”. La
07
instalación desde RStudio es trivial a través de la pestaña “Packages” del panel inferior
derecho. Una vez el paquete está instalado, hay que cargarlo con la función library para
que sus funciones estén disponibles.
5-
library("pgirmess")
-0
La prueba, una vez cargado el paquete anterior, se ejecuta con la función “kruskalmc”:
kruskalmc(Rendimiento ~ Fertilizante, data = Datos)
##
##
##
p.value: 0.05
Comparisons
19
Multiple comparison test after Kruskal-Wallis
20
## obs.dif critical.dif difference
## C-O 3.0 5.353102 FALSE
## C-Q 5.5 5.353102 TRUE
## O-Q 2.5 5.353102 FALSE
or
Para cada posible diferencia se da la diferencia observada en los rangos medios, el valor
crítico, y la conclusión (si es verdadera o falsa la relevancia de la diferencia). En este caso,
se llega a la misma conclusión que con el test paramétrico.
ad
Ejemplo 2
rr
En este ejemplo vamos a intentar verificar la influencia del nivel de renta per cápita provin-
cial (factorizado mediante la variable NIV_RENT_04 en tres niveles de renta, “Alta” para
provincias con renta superior a 20000 euros / habitante; “Media” para provincias con rentas
Bo
entre 20000 y 15000, y “Baja” para provincias con renta inferior a 15000)) sobre la tasa
de paro (variable TASA_PARO_05). Los datos se encuentran en el archivo de texto con
separación mediante tabulaciones “rentas_paro.txt”.
Las expresiones utilizadas se encuentran en el script de las prácticas del capítulo. En lo
sucesivo, vamos a suponer que estamos trabajando en un proyecto que contiene una carpeta
llamada “datos” donde se encuentran los ficheros de datos. El fichero se puede descargar a
la carpeta de datos del proyecto con la siguiente expresión:
download.file("http://emilio.lcano.com/b/adr/datos/rentas_paro.txt",
"datos/rentas_paro.txt")
3.7. PRÁCTICAS 229
Opcionalmente, podemos en primer lugar limpiar el espacio de trabajo eliminando todos los
objetos existentes:
rm(list = ls())
07
Para cargar los datos correctamente ejecutaremos la siguiente expresión:
Datos <- read.table("datos/rentas_paro.txt",
header = TRUE, sep = "\t", dec = ",",
5-
na.strings = "NA", row.names = 1,
encoding = "latin1")
-0
Datos
## A Coruña 9.859223 1 2
## Alicante 9.611898 1 2
ad
## Almería 9.162806 1 2
## Asturias 10.240363 1 2
## Ávila 8.844508 0 2
## Cádiz 17.652023 1 2
rr
## Cantabria 8.502295 1 2
## Ciudad Real 10.580164 0 2
Bo
## Cuenca 6.478210 0 2
## Guadalajara 7.050285 0 2
## Huelva 15.876516 1 2
## Las Palmas 12.830075 1 2
## León 10.819949 0 2
## Málaga 11.657573 1 2
## Murcia 8.009366 1 2
## Palencia 7.474227 0 2
## Pontevedra 11.021749 1 2
## Salamanca 9.088000 0 2
## Santa Cruz de Tenerife 10.492766 1 2
230 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
## Segovia 6.816655 0 2
## Sevilla 13.857495 0 2
## Soria 5.118602 0 2
## Teruel 4.662379 0 2
## Toledo 9.117195 0 2
## Valencia 8.586980 1 2
## Zamora 9.996733 0 2
## Álava 7.088059 0 3
## Baleares 7.215780 1 3
## Barcelona 6.965572 1 3
07
## Burgos 6.730066 0 3
## Castellón 7.315701 1 3
## Girona 7.331990 1 3
5-
## Guipúzcoa 5.648889 1 3
## Huesca 6.886841 0 3
## Lleida 5.885396 0 3
-0
## Madrid 6.804290 0 3
## Navarra 5.647241 0 3
##
##
##
Rioja
Tarragona
Valladolid
19
6.180243
7.062623
9.229526
0
1
0
3
3
3
20
## Vizcaya 8.451806 1 3
## Zaragoza 5.761757 0 3
El argumento “encoding” nos asegura la correcta importación de los caracteres no ASCII
(acentos, eñes, etc.). Por ejemplo, el fichero fue creado con Windows en la codificación “la-
or
tin1”, si no ponemos esta opción en Mac o Linux, los textos no se verían correctamente.
El resto de argumentos indican que la primera fila en dicho archivo es el nombre de las
ad
variables, éstas están separadas por tabulaciones (\t), los decimales se expresan con comas,
si faltara algún dato (que no es el caso) en el archivo vendría expresado como “NA”. Con
el argumento row.names = 1 se informa de que la primera columna de datos del archivo
no es una variable, sino que se considera como la columna que informa del nombre de cada
rr
observación (provincia). Los datos son asignados a un data.frame llamado “Datos”. Pode-
mos comprobar cómo la columna “NIV_RENT_04”, al contener números, se ha importado
Bo
## [1] FALSE
table(Datos$NIV_RENT_04)
##
## 1 2 3
## 8 26 16
Vamos a convertir esta variable numérica en un factor, asignando a los valores 1, 2, 3 los
3.7. PRÁCTICAS 231
07
(PROV_COSTERA) que no se utiliza en este ejemplo.
summary (Datos)
5-
## TASA_PARO_05 PROV_COSTERA NIV_RENT_04
## Min. : 4.662 Min. :0.00 Bajo : 8
-0
## 1st Qu.: 6.907 1st Qu.:0.00 Medio:26
## Median : 8.716 Median :0.00 Alto :16
## Mean : 9.297 Mean :0.44
##
##
3rd Qu.:10.558
Max. :17.652 Max. 19
3rd Qu.:1.00
:1.00
La instrucción tapply ofrece la información sobre la primera variable (TASA_PARO_05)
20
para cada uno de los grupos formados por los diferentes niveles del factor (NIV_RENT_04):
with(Datos,
tapply(TASA_PARO_05, NIV_RENT_04, summary)
)
or
## $Bajo
## Min. 1st Qu. Median Mean 3rd Qu. Max.
ad
##
## $Alto
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 5.647 6.107 6.926 6.888 7.241 9.230
A continuación generamos unos gráficos de caja o boxplot de la variable 2 para cada uno de
los grupos formados por el factor “NIV_RENT_04”:
boxplot(TASA_PARO_05 ~ NIV_RENT_04,
main = "Boxplot de la Tasa de Paro por nivel de Renta.",
col = "steelblue",
data = Datos,
232 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
las = 1)
18
16
TASA_PARO_05
14
07
12
10
5-
8
-0
6
summary(Datos.aov)
Como el p-value es muy pequeño, incluso mucho menor que 0.05, se rechazaría la hipótesis
nula de medias iguales; por lo que podríamos decir que el nivel de renta está relacionado, en
media, con la tasa de paro de las provincias.
3.7. PRÁCTICAS 233
07
par(mfrow = c(2,2))
plot(Datos.aov)
Standardized residuals
5-
Residuals vs Fitted Normal Q−Q
Cádiz Cádiz
3
Residuals
Huelva Huelva
5
-0
1
−5
−2
Lugo Lugo
7 8 9 10
Fitted values
11 12
19 −2 −1 0
Theoretical Quantiles
1 2
20
Standardized residuals
Standardized residuals
Cádiz Cádiz
Huelva Lugo 0.5
Badajoz
0 2
1.0
Cook's distance
ad
0.0
−3
Lugo
par(mfrow = c(1,1))
Bo
##
## Shapiro-Wilk normality test
##
## data: residuals(Datos.aov)
## W = 0.95283, p-value = 0.04465
Para un nivel de confianza del 95 %, los rechazaríamos la hipótesis nula de normalidad de
234 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
los residuos. En cuanto a la homogeneidad en las varianzas (varianzas constantes entre los
grupos), procedemos a un análisis de la dispersión mediante la pruebas de Bartlett.
bartlett.test(TASA_PARO_05 ~ NIV_RENT_04,
data = Datos)
##
## Bartlett test of homogeneity of variances
##
## data: TASA_PARO_05 by NIV_RENT_04
## Bartlett's K-squared = 18.279, df = 2, p-value = 0.0001073
07
La igualdad de varianzas tampoco se cumple, y la normalidad de los residuos está muy
dudosa, ya que aunque se rechazaria la hipótesis de normalidad para un nivel de confianza
5-
del 95 %, el p-valor es muy próximo a 0.05.
-0
Hagamos el análisis de “comparaciones múltiples”. Este análisis indica qué grupos concretos
difieren significativamente entre sí en la media de la variable dependiente (test HSD de
Tukey):
TukeyHSD(Datos.aov, conf.level = 0.95)
19
20
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov.default(formula = TASA_PARO_05 ~ NIV_RENT_04, data = Datos)
or
##
## $NIV_RENT_04
## diff lwr upr p adj
ad
Vemos cómo entre cada dos grupos de renta el intervalo de valores definido por los extremos
(lwr) y (upr) no contienen al 0. Esto indicaría que las diferencias entre los distintos grupos,
Bo
##
3.7. PRÁCTICAS 235
07
pero para poder ejecutarla hay que cargar en memoria el paquete “pgirmess” como vimos
en el primer ejemplo.
library ("pgirmess")
5-
La prueba, una vez cargado el paquete anterior, se ejecuta con la instrucción “kruskalmc”:
-0
kruskalmc(TASA_PARO_05 ~ NIV_RENT_04,
data = Datos)
##
##
##
p.value: 0.05
Comparisons
19
Multiple comparison test after Kruskal-Wallis
20
## obs.dif critical.dif difference
## Bajo-Medio 9.778846 14.10937 FALSE
## Bajo-Alto 25.125000 15.11126 TRUE
## Medio-Alto 15.346154 11.08863 TRUE
or
Esta prueba nos informa de que las diferencias en la tasa de paro media entre los grupos de
renta “alta” y “media”; y “alta” y “baja” son relevantes; no así entre los grupos de renta
“media” y “baja”.
ad
En el segundo ejemplo de la práctica 3.1 teníamos una variable que en principio no hemos
utilizado, pero que ahora vamos a analizar para realizar un ANOVA con dos factores. Esta
variable llamada “PROV_COSTERA” tiene un 0 si la provincia es de interior, y un 1 si
la provincia es de costa. Como hemos borrado el espacio de trabajo para empezar de cero,
vamos a importar el conjunto de datos de nuevo:
Datos <- read.table("datos/rentas_paro.txt",
header = TRUE, sep = "\t", dec = ",",
na.strings = "NA", row.names = 1,
encoding = "latin1")
236 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
Vamos a recodificar las variables cualitativas TIPO_PROV y NIV_RENTA_04 como factores para
una aplicación correcta del método, y a la vez facilitar la interpretación:
Datos$TIPO_PROV <- factor(Datos$PROV_COSTERA, labels = c("Interior", "Costa"))
Datos$NIV_RENT_04 <- factor(Datos$NIV_RENT_04,
labels = c("Bajo", "Medio", "Alto"))
Como ahora tenemos dos factores, el modelo que queremos ajustar es:
07
5-
Y = µ + αi + βj + (αβ)ij + ε
-0
siendo Y la variable TASA_PARO_05, A el factor NIV_RENTA_04 y B el factor TI-
PO_PROV. Para especificar este modelo con interacción podemos utilizar en la parte dere-
19
cha de la fórmula la forma a*b, que indica todos los efectos principales y sus interacciones, o
equivalentemente a + b + a:b, que incluye explícitamente cada término. Así, para nuestro
ejemplo:
20
Datos.aov2 <- aov(TASA_PARO_05 ~ NIV_RENT_04*TIPO_PROV, data = Datos)
summary(Datos.aov2)
or
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Bo
Lo que nos indica que, si bien el efecto principal del tipo de provincia no es significativo
de por sí, sí que lo es la interacción entre el nivel de renta y el tipo de provincia. Esto lo
podemos visualizar claramente en los siguientes gráficos de los efectos:
with(Datos,
interaction.plot(NIV_RENT_04, TIPO_PROV, TASA_PARO_05,
las = 1, ylab = "Tasa de Paro", xlab = "Nivel de Renta",
lwd = 2, col = "steelblue")
)
3.7. PRÁCTICAS 237
TIPO_PROV
13
Costa
12 Interior
Tasa de Paro
11
10
07
8
5-
Bajo Medio Alto
-0
Nivel de Renta
diferencia: 19
Sin embargo comparando el tipo de provincia por separado no hubiéramos observado ninguna
16
or
TASA_PARO_05
14
ad
12
10
rr
8
Bo
Interior Costa
Tasa de paro
Conclusión: Asegúrate siempre de medir todas las variables que puedas. Si te dejas
algunas, información relevante puede quedar oculta.
Comprobamos finalmente que las hipótesis del modelo para asegurarnos de que las conclusio-
238 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
nes son válidas. Para la homogeneidad de varianzas utilizamos el test de Levene, que permite
incluir el término de interacción.
shapiro.test(residuals(Datos.aov2))
##
## Shapiro-Wilk normality test
##
## data: residuals(Datos.aov2)
## W = 0.95677, p-value = 0.06508
07
car::leveneTest(TASA_PARO_05 ~ NIV_RENT_04*TIPO_PROV, data = Datos)
5-
## Df F value Pr(>F)
## group 5 2.4295 0.0498 *
## 44
-0
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
19
Para un nivel de confianza del 95 % no rechazamos la normalidad de los residuos. Sí recha-
zaríamos la homogeneidad de la varianza, pero por muy poquito. Sería aceptable dar por
bueno el modelo, informando de este resultado ajustado para la igualdad de varianzas.
20
Práctica 3.3: Análisis de un experimento con efectos aleatorios
Limpiamos el espacio de trabajo:
or
rm(list = ls())
en preparación
ad
rm(list = ls())
Bo
Para el caso en el que tengamos más de una variable respuesta que puedan estar afectadas
por los niveles de un factor conjuntamente, la función que utilizaremos en R es manova. En
este caso, en la especificación del modelo tenemos que indicar en el lado izquierdo de la
fórmula una matriz con las variables respuesta.
Vamos a ilustrar el MANOVA con un conjunto de datos de ejemplo disponible en R llamado
iris. Este conjunto de datos contiene las dimensiones del pétalo y el sépalo de una serie de
flores de tres especies distintas:
summary(iris)
07
##
##
##
5-
Podemos estudiar si los vectores de estas mediciones son significativamente diferentes para
cada especie así:
-0
X <- iris$Species
Y <- as.matrix(iris[, 1:4])
modelo <- manova(Y ~ X)
summary(modelo)
##
19
Df Pillai approx F num Df den Df Pr(>F)
20
## X 2 1.1919 53.466 8 290 < 2.2e-16 ***
## Residuals 147
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
or
El contraste de hipótesis nos indica que sí hay diferencias, que podríamos ir buscando en
cada una de las variables con los métodos vistos anteriormente.
ad
Como ejercicio, prueba a realizar el MANOVA con grupos de dos variables (las referidas al
sépalo y al pétalo), en vez de las cuatro en conjunto.
rr
Bo
240 CAPÍTULO 3. ANÁLISIS DE LA VARIANZA CON R
07
5-
-0
19
20
or
ad
rr
Bo
Capítulo 4
07
Análisis de componentes principales
con R
5-
-0
4.1. Introducción
19
El análisis de componentes principales (ACP) es una técnica multivariante de análisis de
interdependencias. Esto quiere decir que no tenemos una variable dependiente que queramos
predecir o explicar, sino que lo que nos interesa es explicar el conjunto de las variables,
20
reduciendo la dimensión para una fácil interpretación o posterior uso. Forma parte de un
conjunto de técnicas llamadas genéricamente análisis factorial que no veremos en este texto.
Los métodos matemáticos difieren, la interpretación es similar pero se utilizan para distintos
propósitos.
or
1. Reducir la dimensión para utilizar en otras técnicas. Por ejemplo, en regresión múltiple,
donde es necesario que las variables independientes estén incorreladas, y que sean pocas
en relación al número de observaciones.
rr
2. Explicar las relaciones entre las variables. Por ejemplo para agrupar características de
productos, servicios, etc., o detectar variables latentes.
Bo
241
242 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
x11 x12 · · · x1j · · · x1p u11 ··· u1k · · · u1r
x21 x22 · · · x2j · · · x2p u21 ··· u2k · · · u2r
−→
r < p,
··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ···
xn1 xn2 · · · xnj · · · xnp un1 ··· unk · · · unr
de forma que uik = β1k xi1 + · · · + βpk xip , y el problema por tanto es encontrar los vectores
β⃗k que expliquen la máxima cantidad de variabilidad de X .
07
4.2. Obtención de las componentes principales
5-
Aunque el análisis de componentes principales se puede realizar sobre las variables originales
Xj , es aconsejable hacerlo con las variables tipificadas a las que llamaremos Zj . De esta
-0
forma, evitaremos que variables en una escala mayor tengan más influencia en las variables
transformadas Uk por el mero hecho de estar expresadas en una escala mayor, y no por la
19
propia variabilidad de los datos, que es lo que nos interesa. Recordemos que una variable
tipificada se obtiene restando la media y dividiendo por la desviación típica:
X j − µj
20
Zj = .
σj
xij − xj
zij = .
sj
ad
y seis observaciones (n = 6). Las tres variables están en escala métrica. Vamos a utilizar el
conjunto de datos a lo largo del capítulo para ilustrar la técnica. El código siguiente crea el
Bo
conjunto de datos en forma de matriz en R y tipifica las variables con la función scale. Los
valores ya tifificados se muestran en la tabla 4.2.
07
Tabla 4.2: Datos tificados ejemplo ilustrativo
variable1 variable2 variable3
caso1 -1.035 -1.011 0.664
5-
caso2 -0.354 -0.328 -0.664
caso3 -0.950 -0.926 -1.107
-0
caso4 -0.014 -0.157 -0.664
caso5 1.432 1.381 1.550
caso6 0.922 1.040 0.221
19
Antes de empezar a aplicar la técnica, debemos comprobar que los datos cumplen con las
20
condiciones mínimas para aplicar la técnica. Recordemos que las variables tienen que estar en
escala métrica, y debe existir cierta correlación entre ellas para que tenga sentido reducir la
dimensión del conjunto con la mínima pérdida de información. La función cor de R nos ofrece
la matriz de correlaciones. Es indiferente calcularlas sobre las variables originales o sobre las
tipificadas, ya que la estructura de correlación se mantiene. La matriz de correlaciones es
or
una matriz cuadrada simétrica, en las diagonales tenemos unos y fuera de las diagonales, las
correlaciones de cada par de variables fila-columna.
ad
Debemos comprobar que las variables tienen clase num o int para poder aplicar la
técnica, por ejemplo con la función str o simplemente explorando el objeto en la pestaña
rr
Environment de R Studio. La matriz de correlaciones indica una alta correlación entre las
tres variables, especialmente entre la primera y la segunda.
Bo
str(ejacp)
07
En forma matricial:
5-
Uk = X β k , (4.1)
-0
donde βk es el vector de coeficientes de la componente principal k, que nos disponemos a
calcular1 . Esto se hace de forma iterativa, encontranto primero la componente (combinación
lineal) que explique el máximo de varianza posible de X . Es decir, para U1 Buscamos los
19
coeficientes β1 que hagan máxima la varianza de U1 , operando matricialmente:
20
V (U1 ) = E[β1′ X ′ Xβ1 ] = β1′ E[X ′ X]β1 = β1′ Σβ1 ,
lo que quiere decir que los coeficientes al cuadrado sumen 1, ya que si no podríamos aumentar
la varianza sin más que aumentar los coeficientes. Así pues, el problema de maximización es:
ad
Se demuestra que la solución a este problema viene dada por el autovector de la matriz Σ
correspondiente a la primera componente, es decir λ∗1 = máx{λ1 , . . . , λp }. Los coeficientes de
Bo
(Σ − λ∗1 I)β1 = 0.
07
Volviendo a los datos tipificados del ejemplo anterior, podemos obtener la matriz
5-
de varianzas-covarianzas con la función cov sobre el conjunto de datos. A continuación, es
trivial obtener los autovalores y autovectores con la función eigen.
-0
S <- cov(ejacpt)
S
## variable1 variable2
## variable1 1.0000000 0.9961326
## variable2 0.9961326 1.0000000
19variable3
0.6065117
0.6091628
20
## variable3 0.6065117 0.6091628 1.0000000
auto <- eigen(S)
auto
or
## eigen() decomposition
## $values
## [1] 2.491546458 0.504591729 0.003861813
ad
##
## $vectors
## [,1] [,2] [,3]
rr
vectors: una matriz cuyas columnas son los autovectores asociados a cada autovalor.
Es decir, los coeficientes factoriales.
Las siguientes matrices representan los coeficientes calculados para nuestro ejemplo.
0,612 −0,355 0,706
β1 = 0,613 ; β2 = −0,351 ; β3 = −0,708
07
0,499 0,866 0,003
Una vez tenemos los coeficientes podemos calcular los valores de las nuevas variables para
5-
cada individuo. Estos valores se denominan puntuaciones o scores, y es necesario calcularlas
cuando vamos a utilizar las nuevas variables en otras aplicaciones, como regresión o clasifi-
cación mediante la operación matricial de la ecuación (4.1).
-0
Las siguientes operaciones matriciales obtienen los scores para todas las componentes
19
y solo para la primera componente respectivamente. Por ejemplo, la puntuación del primer
individuo en la primera componente de nuestro ejemplo se calcula como se indica en la
ecuación (4.5).
20
factores <- ejacpt %*% auto$vectors
factores
or
##
## casos [,1] [,2] [,3]
## caso1 -0.9219151 1.2979978 -0.01307735
ad
##
## casos [,1]
## caso1 -0.9219151
## caso2 -0.7494908
## caso3 -1.7018787
## caso4 -0.4363583
## caso5 2.4975183
## caso6 1.3121246
4.3. SELECCIÓN E INTERPRETACIÓN DE COMPONENTES 247
u11 = β11 z11 + β21 z12 + β31 z13 = 0,612 · (−1,035) + 0,613 · (−1,011) + 0,499 · 0,664 = −0,922.
(4.5)
Podemos comprobar cómo los coeficientes y las componentes cumplen con los requisi-
tos que se impusieron para su cálculo. En primer lugar, la condición de normalización de los
coeficientes βk′ βk = 1. En segundo lugar, las correlaciones entre los nuevos factores Ui son
cero.
07
t(auto$vectors[, 1]) %*% auto$vectors[, 1]
## [,1]
5-
## [1,] 1
t(auto$vectors[, 2]) %*% auto$vectors[, 2]
-0
## [,1]
## [1,] 1
## [,1]
19
t(auto$vectors[, 3]) %*% auto$vectors[, 3]
20
## [1,] 1
cor(factores)
λ1 0 · · · 0
..
. λ2 · · · 0
Λ= .. .. . . .
. . . ..
0 0 · · · λp
## [1] 3
sum(diag(cov(factores)))
## [1] 3
sum(auto$values)
07
## [1] 3
Otra forma de verlo es calculando la varianza de los factores, que se corresponde con los
5-
autovalores como podemos comprobar en nuestro ejemplo:
apply(factores, 2, var)
-0
## [1] 2.491546458 0.504591729 0.003861813
auto$values
λ1 λ1
∑
p × 100 = × 100.
λj p
j=1
ad
reteniendo componentes principales, por lo que es fácil reducir la dimensión descartando las
últimas. Existen varios criterios para decidir cuántas componentes retener el la matriz de
datos U final. Un criterio muy extendido es quedarse con las componentes Uk cuya varianza,
o lo que es lo mismo, su autovalor asociado, sea mayor que la media de todos los autovalores:
Uk : λk > λ.
Si se han tipificado las variables originales como es habitual, esto equivale a aquellos auto-
valores mayores de 1:
07
Uk : λk > 1.
Un criterio gráfico es utilizar el llamado gráfico de sedimentación (scree plot). En este gráfico
5-
se representan en el eje vertical los autovalores, y en el eje horizontal el número de orden del
autovalor de las componentes. Así, tenemos un gráfico decreciente con forma de ladera de
-0
montaña, y el criterio sería quedarse con las componentes antes de llegar a la meseta.
19
El gráfico 4.1 muestra el gráfico de sedimentación de nuestro ejemplo, que se puede
generar con el código a continuación. Por otra parte, el criterio del autovalor mayor de uno
nos estaría indicando que una componente es suficiente. Se puede incorporar esta información
20
al gráfico como una línea horizontal.
plot(auto$values,
main = "Gráfico de sedimentación",
type = "b", pch = 16,
or
axes = FALSE,
xlab = "Número de componente",
ylab = "Autovalor")
ad
axis(1, at = 1:3)
axis(2, las = 1)
abline(h = 1, col = "blue", lty = 2)
rr
box()
Estos criterios deben servir de guía, pero el analista puede decidir tomar más o menos
Bo
componentes si esto favorece a los objetivos del análisis. Por ejemplo, para una más fácil
comprensión de los resultados, especialmente el análisis gráfico que se verá en el apartado
siguiente, lo ideal es tener dos componentes, ya que la representación en dos dimensiones de
las componentes facilita la interpretación. Por otra parte, si el criterio indica utilizar una
sola componente como en el ejemplo, utilizar dos puede enriquecer igualmente el análisis e
interpretación. En todo caso, es importante tener en cuenta que mantener menos componen-
tes de las necesarias explicarán peor el conjunto total mientras que quedarse con más de las
necesarias explicarán mejor el modelo, pero complicarán su interpretación y uso.
Una vez seleccionados los factores, vamos a intentar interpretarlos en relación a las variables
originales. Esto no siempre es sencillo, y depende principalmente de la estructura de correla-
250 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
Gráfico de sedimentación
2.5
2.0
Autovalor
1.5
07
1.0
0.5
5-
0.0
-0
1 2 3
19
Número de componente
√
ad
rjk = βjk λk .
qué variables Xj están más correlacionadas. La situación ideal es cuando cada componente
está altamente correlacionada con un grupo distinto de variables, y poco con el resto. Las
Bo
componentes principales heredarán el significado de las variables X con las que comparte
una mayor carga factorial o saturación.
Para el ejemplo de las tres variables que estamos utilizando, el siguiente código calcula
las saturaciones de los dos primeros componentes
auto$vectors[,1]*sqrt(auto$values[1])
auto$vectors[,2]*sqrt(auto$values[2])
07
## [2,] -0.2524384 -0.2491799 0.6154478
5-
cor(ejacp[, 1], factores[, 1])
## [1] 0.9666173
-0
La primera componente está más correlacionada con las variables X1 y X2 , y la segunda
componente está más correlacionada con la variable X3 . En este ejemplo de variables ge-
19
néricas no podemos decir mucho más, pero cuando las variables tienen un significado las
conclusiones pueden ser muy interesantes.
20
4.4. Análisis gráfico de los componentes principales
Previamente al cálculo de los componentes principales, podemos visualizar los datos multi-
or
variantes mediante herramientas gráficas. La función ggpairs del paquete GGally realiza
una matriz de gráficos. Por defecto, en la diagonal muestra una línea de densidad5 de cada
variable, debajo de la diagonal, las nubes de puntos para cada par de variables, y sobre
ad
la diagonal, los coeficientes de correlación. Cuando hay muchas variables estos gráficos se
ven muy pequeños y quizás merece la pena trazar solo algunos, filtrando las variables. Las
correlaciones se pueden visualizar con la función corrplot del paquete del mismo nombre.
rr
También podemos hacer una matriz de gráficos solo con los histrogramas o gráficos de caja
que nos pueden servir para detectar posibles errores, ya que en esta técnica es indiferente la
distribución que sigan los datos.
Bo
5
Una línea de densidad tiene la forma del histograma, pero suavizada.
252 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
variable1
0.02
Corr: Corr:
0.01
0.996 0.607
0.00
40
07
variable2
30 Corr:
0.609
20
5-
-0
7
variable3
6
5 19
20
30 40 50 20 30 40 5 6 7
library(lattice)
Bo
library(reshape2)
gdata <- melt(ejacp)
histogram(~ value | variables, data = gdata,
scales = list(x = list(relation = "free")),
breaks = NULL)
07
variable1
variable2
variable3
5-
1
-0
0.8
variable1 1 0.996 0.607
0.6
19 0.4
20
0.2
−0.2
or
−0.4
ad
−0.6
variable3 0.607 0.609 1
−0.8
rr
−1
40
Percent of Total
30
07
20
5-
10
-0
0
25 30 35 40 45 50
19
15 20 25 30 35 40 4.5 5.0 5.5 6.0 6.5 7.0 7.5
value
20
Figura 4.4: Histogramas de las variables del ejemplo
or
el siguiente aparatado veremos cómo realizar biplots más completos, pero con los cálculos
realizados hasta ahora podemos hacer un gráfico sencillo con las saturaciones para ver qué
ad
La figura 4.5 muestra una visualización de las saturaciones o cargas factoriales pa-
rr
ra las dos primeras componentes del ejemplo. Vemos claramente cómo la componente 1 se
correspondería con el significado de las variables 1 y 2, mientras que el componente 2 repre-
Bo
Cargas factoriales
0.6
variable1
variable2
0.4 variable3
Componente 2
0.2
07
0.0
5-
−0.2
-0
0.80 0.85 0.90 0.95
19 Componente 1
este apartado vamos a revisar las funciones base de R y las proporcionadas por el paquete
FactoMineR.
rr
Por defecto, los datos se centran, pero no se escalan. Este comportamiento se puede cambiar
con los argumentos center y scale.
El resultado de la función prcomp es un objeto de clase prcomp, que será una lista con cinco
elementos:
√
sdev: Desviaciones típicas de los factores, es decir, λ
rotation: Son los coeficientes o variable loadings, es decir, β i
center: Las medias de las variables originales
scale: Las desviaciones típicas de las variables originales
07
x: Las puntuaciones o scores de cada individuo en cada componente
El método print del objeto muestra solamente los dos primeros. El método summary nos
5-
devuelve para cada componente las desviaciones típicas, y proporción de varianza explicada
por cada una y acumulada. La función screeplot6 genera un gráfico de sedimentación
sencillo7 . Por último, existe un método predict que se explicará en el apartado 4.6.
-0
La función biplot crea la visualización más utilizada para el análisis de componentes prin-
cipales. Este gráfico en dos dimensiones representa las cargas factoriales de cada variable, en
19
la escala de los ejes superior y derecho, y las puntuaciones de las observaciones en los ejes
inferior e izquierdo. No obstante, los valores están escalados por los autovalores de cada com-
ponente representada (véase ?biplot.prcomp). Por defecto se representan las dos primeras
20
componentes, pero se pueden representar cualquier par de componentes con el argumento
choices. En este gráfico se interpretan las componentes en función de las variables que
mejor explican cada una de ellas. Gráficamente las variables que explican bien un factor se
situarán próximas y con valores de los loadings altos (en valor absoluto).
or
A continuación vamos a realizar el análisis de los datos del ejemplo utilizando ambas funcio-
nes.
ad
6
El método plot realiza lo mismo.
7
Por defecto, gráfico de barras, pero se puede cambiar el aspecto.
4.5. ANÁLISIS DE COMPONENTES PRINCIPALES CON R 257
modelo.cp
2.5
2.0
Variances
1.5
07
1.0
0.5
5-
0.0
-0
1 2 3
19
Figura 4.6: Gráfico de sedimentación con la función screeplot
20
modelo.cp <- prcomp(ejacp, scale = TRUE)
modelo.cp
## Importance of components:
## PC1 PC2 PC3
## Standard deviation 1.5785 0.7103 0.06214
## Proportion of Variance 0.8305 0.1682 0.00129
## Cumulative Proportion 0.8305 0.9987 1.00000
screeplot(modelo.cp, type = "l")
biplot(modelo.cp)
258 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
−2 −1 0 1 2 3
caso1
3
0.6
2
0.4
variable3
0.2
1
caso5
PC2
07
0.0
0
caso3 caso2 variable2
variable1
5- −1
caso4 caso6
−0.4
−2
-0
−0.4 0.0 0.2 0.4 0.6
19 PC1
##
or
07
## Call:
## princomp(x = ejacpt)
##
## Standard deviations:
5-
## Comp.1 Comp.2 Comp.3
## 1.44093328 0.64845440 0.05672898
-0
##
## 3 variables and 6 observations.
modelo.cp2$loadings
##
## Loadings:
19
20
## Comp.1 Comp.2 Comp.3
## variable1 0.612 0.355 0.706
## variable2 0.613 0.351 -0.708
## variable3 0.499 -0.866
or
##
## Comp.1 Comp.2 Comp.3
## SS loadings 1.000 1.000 1.000
ad
## Importance of components:
Bo
biplot(modelo.cp2)
modelo.cp2$scores
##
260 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
modelo.cp2
2.0
1.5
Variances
07
1.0
5-
0.5
-0
0.0
2
ad 0.5
caso4
1
caso6
caso3caso2 variable1
variable2
Comp.2
0.0
0
rr
caso5
−1
Bo
−0.5
variable3
−2
caso1
Comp.1
07
con los coeficientes y los autovalores.
5-
Las cargas factoriales se pueden calcular utilizando los datos almacenados en el objeto
de clase prcomp8 , como en la siguiente expresión.
-0
t(modelo.cp$rotation)*modelo.cp$sdev
Además de las funciones incluidas en la instalación base de R, hay algunos paquetes que
contienen funciones más avanzadas para realizar análisis de componentes principales. El más
conocido y uno de los más completos es FactoMineR (Husson et al., 2018)9 . La función
rr
PCA realiza el análisis de componentes principales. Permite incluir variables auxiliares para
mejorar la interpretación. El objeto creado tiene más información que las otras funciones,
Bo
tanto para cada variable como para cada observación. En concreto, para cada dimensión:
Observaciones
• Dim.X es la puntuación factorial de la observación
• ctr es la contribución de la observación a la dimensión (en porcentaje, con los
coeficientes al cuadrado)
• cos2 Es una medida de la calidad de la componente para explicar la observa-
ción, calculada como (Dim.X/Dist)^2. Cuanto más próximo a 1, mejor refleja la
componente todas las características de la observación.
9
En la Task View “Multivariate” se pueden encontrar algunos más: https://cran.r-project.org/web/views/
Multivariate.html
262 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
Además, para las observaciones se muestra Dist, que es una medida de la distancia de la
observación al centro de gravedad de los datos.
Variables
• Dim.X es la carga factorial de la variable (correlación con la componente)
• ctr es la contribución de la variable a la dimensión (en porcentaje)
• cos2 Es una medida de la calidad de la dimensión para explicar la variable,
calculada como el cuadrado de la carga factorial. Cuanto más próximo a 1, mejor
refleja la componente todas las características de la observación.
07
El paquete factoextra contiene algunas funciones para mejorar la visualización. En el si-
guiente ejemplo se explican todas estas particularidades.
5-
El código a continuación realiza el análisis de componentes principales de los datos
de ejemplo con el paquete FactoMineR. Automáticamente crea dos gráficos: uno con las
-0
puntuaciones individuales y otro con el mapa de factores (figura 4.10). El método print
muestra la descripción de los objetos guardados. Las cargas factoriales se encuentran en el
elemento var$cor. El método summary muestra los autovalores y su contribución. Además,
19
dos tablas para las observaciones y las variables, con información de cada dimensión: las
cargas factoriales para las variables, y las puntuaciones factoriales para los casos. Muestra
además dos métricas adicionales: contrib y cos2, que indican la contribución de cada va-
20
riable/observación y la calidad de la representación. Los coeficientes se encuentran en el
elemento svd$V. Las figuras 4.11 y 4.12 muestran una representación alternativa del scree-
plot y el biplot utilizando el paquete factoextra. La figura 4.13 es una visualización de las
cargas factoriales de las variables en las dos primeras componentes, con una escala de colores
or
par(mfrow=c(1,2))
ad
library(FactoMineR)
modelo.cp3 <- PCA(ejacp, ncp = 2)
modelo.cp3
rr
07
Individuals factor map (PCA) Variables factor map (PCA)
5-
1.5
4
-0
1.0
variable3
variable3
0.5
Dim 2 (16.82%)
Dim 2 (16.82%)
19
2
caso1
0.0
caso5
20
variable2
variable2
0
caso2 caso4
caso3 variable1
variable1
−0.5
caso6
−2
or
−1.5
−4
ad
07
## Dim.1 Dim.2
## variable1 0.9666173 -0.2524384
5-
## variable2 0.9674572 -0.2491799
## variable3 0.7881776 0.6154478
summary(modelo.cp3)
-0
##
##
##
##
Call:
PCA(X = ejacp, ncp = 2) 19
20
##
## Eigenvalues
## Dim.1 Dim.2 Dim.3
## Variance 2.492 0.505 0.004
or
## Individuals
## Dist Dim.1 ctr cos2 Dim.2 ctr cos2
## caso1 | 1.744 | -1.010 6.822 0.335 | 1.422 66.779 0.665 |
rr
Scree plot
80
Percentage of explained variances
60
07
40
5-
20
-0
0
1
19 2
Dimensions
3
20
Figura 4.11: Screeplot con el paquete ‘factoextra‘
or
ad
## [,1] [,2]
## [1,] 0.6123787 -0.3553737
## [2,] 0.6129108 -0.3507865
rr
factoextra::fviz_pca_biplot(modelo.cp3)
Realice la práctica 4.2 cuyo guión se encuentra en el apartado 4.7 para realizar
análisis de componentes principales en un conjunto de datos de provincias. Se utilizan tanto
las funciones base como las del paquete FactoMineR.
266 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
07
PCA − Biplot
1.5 caso1
5-
-0
1.0 variable3
19
Dim2 (16.8%)
0.5
caso5
20
0.0
or
−2 −1 0 1 2
rr
Dim1 (83.1%)
07
Variables − PCA
1.0
5-
-0
variable3
0.5
cos2
19
Dim2 (16.8%)
0.9995
0.0
20
0.9990
variable2
0.9985
variable1
−0.5
or
ad
−1.0
Dim1 (83.1%)
07
que suele redundar en una mejora en la precisión del modelo y su capacidad predictiva. Otro
enfoque sería reducir la dimensión del conjunto de datos original a unas pocas componentes
principales y ajustar el modelo sobre dichas componentes en vez de sobre las variables origi-
5-
nales. Es decir, que si tenemos una variable respuesta Y y un vector de p variables predictivas
X , en lugar de ajustar el modelo:
-0
∑
p
Y = β0 + βi Xi + ε,
19 i=1
Por definición, las variables (componentes principales) U van a estar incorreladas, lo que
ad
la regresión, βi′ . Pero esto va a depender de la interpretación que se le pueda dar a las
componentes Ui en base a las cargas factoriales.
Bo
##
## Call:
## lm.default(formula = variable4 ~ ., data = ejacpml)
07
##
## Residuals:
## caso1 caso2 caso3 caso4 caso5 caso6
5-
## -0.1953 -0.2113 0.5652 -0.2625 0.3144 -0.2106
##
## Coefficients: (2 not defined because of singularities)
-0
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.3447 2.8104 -0.478 0.6795
## variable1 0.8016 0.2400 3.340 0.0791 .
##
##
##
variable2
variable3
PC1
-0.3276
2.7172
NA
0.2768
NA
19
0.2417 -1.356
9.817
NA
0.3079
0.0102 *
NA
20
## PC2 NA NA NA NA
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
or
##
## Call:
Bo
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.878 on 3 degrees of freedom
## Multiple R-squared: 0.9925, Adjusted R-squared: 0.9875
## F-statistic: 198.9 on 2 and 3 DF, p-value: 0.0006478
ml3 <- lm(variable4 ~ PC1, ejacpml)
summary(ml3)
07
##
## Call:
## lm.default(formula = variable4 ~ PC1, data = ejacpml)
5-
##
## Residuals:
## caso1 caso2 caso3 caso4 caso5 caso6
-0
## 0.5320 -0.6218 0.1945 0.3275 0.8988 -1.3310
##
## Coefficients:
##
##
##
(Intercept) 34.3333
PC1 4.9521
0.3761
0.2610
19
Estimate Std. Error t value
91.29
18.97
Pr(>|t|)
8.63e-08 ***
4.54e-05 ***
20
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.9212 on 4 degrees of freedom
or
Supongamos que llega un nuevo caso con los valores 50, 40, y 7 para las tres variables
en estudio. ¿Qué predicción podemos hacer del valor que tomará la variable respuesta? Con
Bo
la función predict sobre el objeto prcomp podemos obtener las puntuaciones factoriales del
nuevo caso. Entonces ahora podemos hacer la predicción de la variable respuesta utilizando
el valor de la primera componente, e incluso obtener un intervalo de confianza.
Realice la práctica 4.3 cuyo guión se encuentra en el apartado 4.7 para aplicar el
análisis de componentes principales al ajuste de un modelo de regresión lineal múltiple cuando
hay multicolinealidad.
07
5-
4.7. Prácticas
En este apartado se presentan las prácticas a las que se han hecho referencia durante el
-0
capítulo. La reproducibilidad del código ha sido comprobada con la sesión de R que se
detalla en el Prefacio. El lector puede teclear el código o copiarlo y pegarlo en la consola o
el editor. También se puede descargar el script con el código de todas las prácticas con la
siguiente expresión:
19
download.file("http://emilio.lcano.com/b/adr/practicas/11-acp.R",
20
destfile = "practicas/11-acp.R")
Aparte de estas prácticas guiadas, se invita al lector a que realice un análisis de componentes
principales con el conjunto de datos iris disponible en R, y que ya se ha utilizado en capítulos
anteriores.
or
Opcionalmente, podemos en primer lugar limpiar el espacio de trabajo eliminando todos los
objetos existentes:
rr
rm(list = ls())
Vamos a considerar una serie de variables cuantitativas (escala métrica) que caracterizan a
Bo
una población. Nuestro objetivo es encontrar una serie de combinaciones lineales de estas
variables (cada combinación es una “componente principal”) que recojan la mayor parte de
la varianza de las variables originales (“comunalidad”), y que sean menos numerosas que las
variables originales, de manera que puedan usarse como variables que resumen o sintetizan
la información que las variables originales ofrecen sobre los casos que componen la muestra,
con una pérdida mínima de información, y además siendo incorrelacionadas entre sí.
Las expresiones utilizadas se encuentran en el script de las prácticas del capítulo.
Opcionalmente, se recomienda en primer lugar limpiar el espacio de trabajo eliminando todos
los objetos existentes:
272 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
rm(list = ls())
Datos
En este ejemplo vamos a introducir los datos mediante código. Introducimos los datos de las
07
variables a incluir en el modelo.
Datos <- data.frame(Casos = c("caso1", "caso2", "caso3",
5-
"caso4", "caso5", "caso6"),
Variable1 = c(23, 31, 24, 35, 52, 46),
Variable2 = c(13, 21, 14, 23, 41, 37),
-0
Variable3 = c(6.5, 5, 4.5, 5, 7.5, 6),
row.names = 1)
## caso3 24 14 4.5
## caso4 35 23 5.0
## caso5 52 41 7.5
ad
## caso6 46 37 6.0
El análisis de componentes principales tiene sentido cuando las variables originales están
muy correlacionadas entre sí. Es como si aportaran casi la misma información acerca de los
Bo
casos de la muestra. Por tanto, vamos a comprobar que exista tal correlación obteniendo la
matriz de correlaciones.
correlaciones <- cor(Datos)
correlaciones
son altas las correlaciones entre la 2 y 3, y entre la 1 y 3. Podemos visualizar estas correlacio-
nes gráficamente con el paquete corrplot. La función con el mismo nombre que el paquete
nos devuelve una matriz de gráficos con la correlación representada de distintas formas, por
ejemplo en forma de elipse. Cuanto más oscura y estrecha sea la elipse, mayor correlación.
library(corrplot)
corrplot(correlaciones, method = "ellipse" )
07
5-
Variable1
Variable2
Variable3
-0
1
Variable1 19 0.8
0.6
20
0.4
0.2
Variable2
or
−0.2
ad
−0.4
−0.6
Variable3
rr
−0.8
Bo
−1
Otra visualización interesante es la que nos proporcionan los gráficos de dispersión de las
variables dos a dos, que podemos obtener de la siguiente forma:
pairs(Datos, pch = 19, col = "steelblue")
274 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
15 20 25 30 35 40
45
Variable1
35
25
35
Variable2
07
25
15
7.5
5-
6.5
Variable3
-0
5.5
4.5
25 30 35 40 45 50
19 4.5 5.0 5.5 6.0 6.5 7.0 7.5
20
or
ad
rr
Bo
Una visualización más elaborada se puede conseguir con funciones de otros paquetes como
por ejemplo el paquete ez:
library(ez)
ezCor(Datos)
4.7. PRÁCTICAS 275
Variable1
1 .61
07
Variable2 .61
5-
-0
19 Variable3
20
or
ad
Este gráfico nos proporciona los valores numéricos de las correlaciones, los gráficos de disper-
sión dos a dos, su recta de regresión, y una representación de la densidad de cada variable.
rr
Bo
2.0
4
Frequency
Frequency
1.0
2
0.0
0
20 30 40 50 60 10 20 30 40 50
Variable1 Variable2
n:6 m:0 n:6 m:0
07
4
Frequency
5-
2
0
-0
4 5 6 7 8
Variable3
n:6 m:0
19
Para calcular componentes principales, se suelen tipificar las variables, para lo cual hacemos:
20
ZDatos <- scale(Datos)
ZDatos
## attr(,"scaled:center")
## Variable1 Variable2 Variable3
## 35.16667 24.83333 5.75000
Bo
## attr(,"scaled:scale")
## Variable1 Variable2 Variable3
## 11.754432 11.703276 1.129159
Con esta matriz de variables tipificadas, “ZDatos”, es con la que se realizarán los cálculos.
## Importance of components:
## PC1 PC2 PC3
## Standard deviation 1.5785 0.7103 0.06214
## Proportion of Variance 0.8305 0.1682 0.00129
## Cumulative Proportion 0.8305 0.9987 1.00000
07
El “summary” de las componentes calculadas y guardadas en el objeto “modelo.cp”, devuelve
3 informaciones correspondientes a las 3 componentes principales obtenidas. La “Standard
Desviation” es la raíz cuadrada de los autovalores asociados a cada componente. “Proportion
5-
of Variance” nos dice la proporción de la varianza o comportamiento de las variables origina-
les recogido por cada componente, proporción que se acumula en “Cumulative Proportion”.
-0
Nótese que las componentes aparecen ordenadas de más a menos importantes en función de
la cantidad de varianza que capturan.
19
Los coeficientes que multiplican a las variables originales (tipificadas) para cada componente
se guardan en el elemento “rotation” del objeto “modelo.cp” (que realmente es una lista de
objetos):
20
names(modelo.cp)
##
## Rotation (n x k) = (3 x 3):
## PC1 PC2 PC3
rr
Vamos a guardar estos coeficientes en un objeto de tipo data.frame que utilizaremos después:
coeficientes <- modelo.cp$rotation
Nosotros queremos menos componentes que variables (originales), porque así simplificare-
mos la información suministrada por dichas variables. Hay varios métodos de selección de
componentes principales. Nos vamos a quedar con aquel que selecciona las varianzas de las
componentes (o autovalores) mayores a uno. Para ello primero calculamos los autovalores y
los mostramos, y luego comprobaremos cuántos autovalores son mayores que 1. Esa canti-
dad se la asignaremos, en el texto del script, al objeto “selec” (directamente o utilizando un
07
vector lógico como a continuación):
autovalores <- modelo.cp$sdev^2
autovalores
5-
-0
selec <- sum(autovalores > 1)
selec
19
## [1] 2.491546458 0.504591729 0.003861813
20
or
## [1] 1
ad
rr
En nuestro caso vale 1, lo que quiere decir que con una única componente principal podemos
recoger la mayoría de la información contenida en las tres variables originales.
Bo
Gráfico de Sedimentación
2.5
2.0
1.5
Valor
07
1.0
0.5
5-
0.0
-0
1.0 1.5 2.0 2.5 3.0
19Nº de Autovalor
Posteriormente vamos a estudiar las “cargas factoriales” o “saturaciones”, que son las corre-
20
laciones entre las componentes principales retenidas y las variables originales:
cargas <- t(coeficientes[, 1:selec])*(sqrt(autovalores[1:selec]))
cargas
or
Sólo hay una fila porque sólo hemos retenido una componente principal. El primer número
muestra una alta correlación entre la primera componente y la primera variable original.
Lo mismo ocurre con la segunda variable original, mientras que la relación de la primera
rr
Por último vamos a obtener las puntuaciones (scores) que alcanza nuestra componente princi-
pal retenida para cada caso o individuo (ya sabemos que recoge 83 % de la varianza común de
las variables originales). Estos datos se encuentran en el modelo almacenado y los podemos
recuperar directamente:
modelo.cp$x[, 1]
## [,1]
## caso1 -0.9219151
## caso2 -0.7494908
## caso3 -1.7018787
## caso4 -0.4363583
## caso5 2.4975183
07
## caso6 1.3121246
Por ejemplo, para el primer caso la puntuación de la componente principal ha sido:
5-
yi1 = −1,035 · 0,612 − 1,011 · 0,613 + 0,664 · 0,499 = −0,922.
-0
Recordemos que las variables originales entran en la ecuación tipificadas.
Vamos a considerar una serie de variables cuantitativas (escala métrica) que caracterizan a la
población constituida por las provincias españolas. Nuestro objetivo es encontrar una serie de
or
variables que resumen o sintetizan la información que las variables originales ofrecen sobre
las provincias españolas, con una pérdida mínima de información.
rr
Carga de datos
Las variables originales serán:
Bo
Ahora vamos a leer el valor de las variables que están en el archivo de texto “provilogit.txt”
(podemos limpiar primero el espacio de trabajo). El fichero contiene en total 64 variables,
07
que se guardarán en el data.frame “provincias”. A continuación, de “provincias” se extraerán
las variables de nuestro análisis, que se guardan en el data.frame “Datos”.
provincias <- read.table("datos/provilogit.txt", header = TRUE,
5-
sep = "\t", dec = ",", encoding = "latin1")
colnames(provincias)
-0
## [1] "NAME_PROV" "AUTONOMIA"
## [3] "POB_05" "PORC_MUJ_05"
##
##
##
[5]
[7]
[9]
"NACIM_MIL_05"
"CREC_NAT_MIL_05"
"INMI_ESP_CIENMIL_05"
19 "DEFUN_MIL_05"
"INMI_EXT_CIENMIL_05"
"MATRIM_MIL_05"
20
## [11] "PORC_MATRIM_CIV_05" "NUM_HIJ_FERT_05"
## [13] "TAS_FECUN_05" "EDAD_MATER_05"
## [15] "NUM_NAC_05" "PROP_ANALF_05"
## [17] "PROP_EST_SUP_05" "UDS_ED_INF_0405"
## [19] "PROF_NO_SUP_0405" "ACTIVOS_MIL_05"
or
07
## CREC_NAT_MIL_05 NUM_HIJ_FERT_05 TAS_FECUN_05 ACTIVOS_MIL_05
## Min. :-8.32617 Min. :0.867 Min. :2.617 Min. : 40.05
## 1st Qu.:-2.35610 1st Qu.:1.158 1st Qu.:3.599 1st Qu.: 155.18
5-
## Median : 0.53840 Median :1.294 Median :3.969 Median : 271.61
## Mean :-0.05204 Mean :1.276 Mean :3.917 Mean : 416.55
-0
## 3rd Qu.: 2.68197 3rd Qu.:1.410 3rd Qu.:4.378 3rd Qu.: 451.31
## Max. : 5.60666 Max. :1.594 Max. :5.000 Max. :3067.55
## KM_AUTOVIAS_1000_KM2_05 DENSID_05
##
##
##
Min. : 4.852
1st Qu.:13.291
Median :24.892
Min.
19
: 8.891
1st Qu.: 26.107
Median : 57.617
20
## Mean :27.686 Mean :120.274
## 3rd Qu.:33.729 3rd Qu.:136.295
## Max. :93.298 Max. :732.407
head(Datos)
or
## KM_AUTOVIAS_1000_KM2_05 DENSID_05
## A Coruña 34.33530 139.44403
## Álava 48.73230 97.86570
## Albacete 16.08148 25.46744
## Alicante 56.38645 289.52587
## Almería 31.90883 68.78268
## Asturias 28.57412 99.84317
Hemos creado la hoja de datos o data.frame “Datos” de 6 columnas (todas variables numé-
ricas) y 50 filas (casos, las 50 provincias españolas).
4.7. PRÁCTICAS 283
El análisis de componentes principales tiene sentido cuando las variables originales (columnas
de la matriz “Datos”) están muy correlacionadas entre sí. Es como si informaran casi lo mismo
acerca de los casos de la muestra. Por tanto, vamos a comprobar que exista tal correlación:
correlaciones <- cor(Datos)
07
correlaciones
5-
-0
##
## CREC_NAT_MIL_05
19
CREC_NAT_MIL_05 NUM_HIJ_FERT_05 TAS_FECUN_05
1.0000000 0.8323874 0.8785990
20
## NUM_HIJ_FERT_05 0.8323874 1.0000000 0.9871412
## TAS_FECUN_05 0.8785990 0.9871412 1.0000000
## ACTIVOS_MIL_05 0.4280085 0.2724936 0.3364654
## KM_AUTOVIAS_1000_KM2_05 0.4289928 0.1214923 0.2219890
or
Esta instrucción nos lleva a una matriz de correlaciones en la que destacan altas correlaciones
entre algunas variables. Gráficamente:
corrplot(correlaciones, method = "number" )
284 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
KM_AUTOVIAS_1000_KM2_05
CREC_NAT_MIL_05
NUM_HIJ_FERT_05
ACTIVOS_MIL_05
TAS_FECUN_05
DENSID_05
07
1
CREC_NAT_MIL_05 1 0.83 0.88 0.43 0.43 0.43 0.8
5-
0.6
NUM_HIJ_FERT_05 0.83 1 0.99 0.27 0.12 0.16
0.4
-0
TAS_FECUN_05 0.88 0.99 1 0.34 0.22 0.25 0.2
0
ACTIVOS_MIL_05 0.43 0.27 0.34 1 0.71 0.87 −0.2
19
KM_AUTOVIAS_1000_KM2_05 0.43 0.12 0.22 0.71 1 0.87
DENSID_05 0.43 0.16 0.25 0.87 0.87 1
−0.4
−0.6
−0.8
20
−1
NUM_HIJ_FERT_05
.99 .27 .12 .16
07
ACTIVOS_MIL_05 .71 .87
5-
-0
.87
KM_AUTOVIAS_1000_KM2_05
19 DENSID_05
20
Para calcular componentes principales, se suelen tipificar las variables, para lo cual hacemos:
ZDatos <- scale(Datos)
or
head(ZDatos)
ad
Con esta matriz de variables tipificadas, “ZDatos”, es con la que se realizarán los cálculos.
286 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6
## Standard deviation 1.9004 1.3703 0.5591 0.34409 0.27039 0.08217
07
## Proportion of Variance 0.6019 0.3130 0.0521 0.01973 0.01219 0.00113
## Cumulative Proportion 0.6019 0.9149 0.9670 0.98669 0.99887 1.00000
5-
El “summary” de las componentes calculadas y guardadas en el objeto “modelo2.cp”, se
obtienen 3 informaciones correspondientes a las 6 componentes principales obtenidas. La
“Standard Desviation” es la raíz cuadrada de los autovalores asociados a cada componente.
-0
“Proportion of Variance” nos dice la proporción de la varianza o comportamiento de las va-
riables originales recogido por cada componente, proporción que se acumula en “Cumulative
Proportion”. Nótese que las componentes aparecen ordenadas de más a menos importantes
19
en función de la cantidad de varianza que capturan.
Los coeficientes que multiplican a las variables originales (tipificadas) para cada componente
20
se guardan en el elemento “rotation” del objeto “modelo.cp” (que realmente es una lista de
objetos):
names(modelo2.cp)
or
## Rotation (n x k) = (6 x 6):
## PC1 PC2 PC3 PC4
Bo
Vamos a guardar estos coeficientes en un objeto de tipo data.frame que utilizaremos después:
coeficientes <- modelo2.cp$rotation
07
5-
Selección de componentes e interpretación
-0
Nosotros queremos menos componentes que variables (originales), porque así simplificaremos
la información suministrada por dichas variables. Hay varios métodos de selección de compo-
nentes Principales. Nosotros nos vamos a quedar con aquel que selecciona las varianzas de
19
las componentes (o autovalores) mayores que uno. Para ello primero calculamos los autova-
lores y los mostramos, y luego le damos al objeto selec el valor correspondiente al número de
autovalores mayores que 1. Ese número será el número de componentes principales a retener:
20
autovalores <- modelo2.cp$sdev^2
autovalores
or
selec
rr
## [1] 2
Bo
En nuestro caso “selec” vale 2, lo que quiere decir que con 2 componentes principales podemos
recoger la mayoría de la información contenida en las 6 variables originales.
Gráfico de Sedimentación
2
Valor
07
1
5-
0
-0
1 2 3 4 5 6
19Nº de Autovalor
cargas
Con las instrucciones anteriores se generan una matriz de 2 filas (componentes retenidas)
por 6 columnas (variables originales).
Cuando se seleccionan más de dos componentes, se suele utilizar el gráfico biplot para intentar
obtener una interpretación de las componentes acorde con el problema que se está estudiando.
En nuestro caso:
biplot(modelo2.cp)
4.7. PRÁCTICAS 289
−4 −2 0 2 4 6 8
0.4 Madrid
8
6
Vizcaya Barcelona
DENSID_05
KM_AUTOVIAS_1000_KM2_05
0.2
Ourense
4
Asturias
Lugo ACTIVOS_MIL_05
ZamoraA Coruña
León Pontevedra
Guipúzcoa
PC2
2
Palencia Alicante
Salamanca Álava Valencia
Valladolid
Cantabria
Las Palmas
07
0.0
Cuenca
Burgos
0
SoriaZaragoza Málaga
Cáceres
Ávila
Teruel
Huesca Rioja
Baleares
Segovia
Albacete
Badajoz
Navarra
−2
Ciudad Real
Castellón
Granada
JaénTarragona
Sevilla
Toledo
Cádiz
Córdoba CREC_NAT_MIL_05
5-
Huelva
−0.2
Girona
Lleida Murcia
−4
Guadalajara TAS_FECUN_05
Almería
NUM_HIJ_FERT_05
-0
−0.2 0.0 0.2 0.4
PC1
19
Se trata de un gráfico bidimensional en el que los ejes horizontal y vertical representan dos
20
de las componentes elegidas. Los individuos (en nuestro caso provincias) se sitúan en sus
puntuaciones o “scores” para cada componente (escala superior y derecha). Por último, las
variables se sitúan donde corresponde a sus coeficientes (loadings, escala inferior e izquierda).
Así, se puede intentar agrupar las variables, en este caso parece más o menos claro que hay
dos grupos de variables, y podríamos decir que puntuaciones bajas de la segunda compo-
or
nente están representando a variables relacionadas con las familias, y las puntuaciones altas
con variables relacionadas con la economía. Esto desde luego es subjetivo y en todo caso
descriptivo (no estamos haciendo inferencia)
ad
Por último vamos a generar las puntuaciones que alcanzan nuestras componentes principales
retenidas para cada caso o individuo (ya sabemos que recogen el 91.49 % de la varianza
rr
head(scores)
## PC1 PC2
## A Coruña -1.1002277 1.6228455
## Álava -0.1495928 0.6607728
## Albacete -0.4950711 -0.7884073
## Alicante 1.9113407 0.8989976
## Almería 1.9340026 -2.0332879
## Asturias -2.0310979 1.8932562
Recordemos que las puntuaciones también se guardan en el elemento x del objeto guardado.
290 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
modelo2.cp$x[1:5, 1:2]
## PC1 PC2
## A Coruña -1.1002277 1.6228455
## Álava -0.1495928 0.6607728
## Albacete -0.4950711 -0.7884073
## Alicante 1.9113407 0.8989976
## Almería 1.9340026 -2.0332879
07
matricial por ZDatos, para eso calculamos esa matriz).
A continuación se incluyen las expresiones para realizar el análisis con el paquete FactoMineR.
5-
Se deja al lector como ejercicio su interpretación.
library(FactoMineR)
-0
library(factoextra)
## comp 3 96.69569
## comp 4 98.66894
## comp 5 99.88746
Bo
## comp 6 100.00000
summary(prov.fm, ncp = 2)
##
## Call:
## PCA(X = Datos, graph = FALSE)
##
##
## Eigenvalues
## Dim.1 Dim.2 Dim.3 Dim.4 Dim.5 Dim.6
4.7. PRÁCTICAS 291
07
## Almería | 2.879 | 1.954 2.114 0.460 | -2.054 4.493
## Asturias | 2.820 | -2.052 2.331 0.529 | 1.912 3.896
## Ávila | 1.947 | -1.810 1.814 0.864 | -0.254 0.069
5-
## Badajoz | 1.173 | -0.653 0.236 0.310 | -0.842 0.756
## Baleares | 1.479 | 0.887 0.436 0.359 | -0.684 0.499
## Barcelona | 5.959 | 4.993 13.806 0.702 | 2.741 8.002
-0
## cos2
## A Coruña 0.659 |
##
##
##
Álava
Albacete
Alicante
19
0.201 |
0.602 |
0.168 |
20
## Almería 0.509 |
## Asturias 0.460 |
## Ávila 0.017 |
## Badajoz 0.516 |
## Baleares 0.214 |
or
## Barcelona 0.212 |
##
ad
## Variables
## Dim.1 ctr cos2 Dim.2 ctr cos2
## CREC_NAT_MIL_05 | 0.872 21.035 0.760 | -0.365 7.100 0.133 |
## NUM_HIJ_FERT_05 | 0.742 15.225 0.550 | -0.650 22.481 0.422 |
rr
Variables − PCA
1.0
DENSID_05
KM_AUTOVIAS_1000_KM2_05
0.5
ACTIVOS_MIL_05
Dim2 (31.3%)
0.0
07
CREC_NAT_MIL_05
5-
−0.5 TAS_FECUN_05
NUM_HIJ_FERT_05
-0
−1.0
PCA − Biplot
4 Madrid
ad
DENSID_05
Ourense Vizcaya Barcelona
KM_AUTOVIAS_1000_KM2_05
Asturias cos2
rr
2 Lugo
Pontevedra ACTIVOS_MIL_05
Zamora
Dim2 (31.3%)
Guipúzcoa
A Coruña 0.96
Palencia León Santa Cruz de Tenerife Alicante
Bo
ValladolidÁlava
0.92
Salamanca
Burgos Cantabria Valencia
0 Cuenca Ávila CáceresZaragoza Las Palmas Málaga 0.88
Soria Albacete Rioja Baleares Tarragona
0.84
Teruel Segovia Castellón
Navarra
Jaén Sevilla
Huesca Badajoz Granada Cádiz
Toledo
Ciudad Real CREC_NAT_MIL_05
−2 HuelvaGirona Murcia
Córdoba TAS_FECUN_05
Almería
Guadalajara
LleidaNUM_HIJ_FERT_05
−2 0 2 4 6
Dim1 (60.2%)
4.7. PRÁCTICAS 293
07
dad) en función de las variables MATRIM_1000_05 (matrimonios por cada mil habitantes),
NUM_HIJ_FERT_05 (número de hijos por mujer en edad fértil), TAS_FECUN_05 (ta-
sa de fecundidad), POR_MUJ_ACT_05 (porcentaje de mujeres por respecto al total de
activos) y PIB_HAB_04 (P.I.B. a precios de mercado por habitante). La muestra está
5-
constituida por 16 provincias españolas.
Las expresiones utilizadas se encuentran en el script de las prácticas del capítulo. En lo
-0
sucesivo, vamos a suponer que estamos trabajando en un proyecto que contiene una carpeta
llamada “datos” donde se encuentran los ficheros de datos. El fichero se puede descargar a
19
la carpeta de datos del proyecto con la siguiente expresión:
download.file("http://emilio.lcano.com/b/adr/datos/Regre_mater.txt",
"datos/Regre_mater.txt")
20
Opcionalmente, podemos en primer lugar limpiar el espacio de trabajo eliminando todos los
objetos existentes:
rm(list = ls())
or
Carga de datos
ad
07
Unos histogramas para visualizar las distribuciones:
library(ggplot2)
library(reshape2)
5-
gdata <- melt(provincias)
-0
## No id variables; using all as measure variables
ggplot(gdata, aes(value)) +
geom_histogram(bins = 7) +
facet_wrap(variable ~ ., scales = "free")
PORC_MUJ_05
19
INMI_ESP_CIENMIL_05 MATRIM_MIL_05
20
4 4
6
3 3
2 2 4
1 1 2
or
0 0 0
49.5 50.0 50.5 51.0 25 50 75 4 5 6
5 4
4 6
3
count
3 4 2
2
rr
2 1
1
0 0 0
1.1 1.2 1.3 1.4 1.5 1.6 3.5 4.0 4.5 5.0 30.0 30.5 31.0 31.5
Bo
POR_MUJ_ACT_05 PIB_HAB_04
5 6
4
3 4
2 2
1
0 0
58 60 62 64 66 15000 20000 25000
value
En R es muy sencillo estimar una regresión lineal multivariante por mínimos cuadrados
ordinarios. La función clave es lm. Así, estimaremos nuestra regresión y la almacenaremos
4.7. PRÁCTICAS 295
en el objeto regre1 (por ejemplo). Luego visualizamos los resultados con un “summary”:
regre1 <- lm(EDAD_MATER_05 ~ MATRIM_MIL_05 + NUM_HIJ_FERT_05 + TAS_FECUN_05 + POR_MUJ_AC
data = provincias)
summary(regre1)
##
## Call:
## lm.default(formula = EDAD_MATER_05 ~ MATRIM_MIL_05 + NUM_HIJ_FERT_05 +
## TAS_FECUN_05 + POR_MUJ_ACT_05 + PIB_HAB_04, data = provincias)
07
##
## Residuals:
## Min 1Q Median 3Q Max
5-
## -0.4854 -0.1063 0.0530 0.1334 0.4120
##
## Coefficients:
-0
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.403e+01 4.265e+00 7.980 1.2e-05 ***
## MATRIM_MIL_05 1.528e-01 1.986e-01 0.770 0.459
##
##
##
TAS_FECUN_05
19
NUM_HIJ_FERT_05 -2.427e+00 5.992e+00 -0.405
-1.125e-01 1.778e+00 -0.063
POR_MUJ_ACT_05 -2.874e-02 5.587e-02 -0.514
0.694
0.951
0.618
20
## PIB_HAB_04 9.004e-05 4.457e-05 2.020 0.071 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
or
son no-significativas (valores del estadístico muy próximos a 0 y p-values muy altos). Esto
puede dar algún indicio de existencia de multicolinealidad entre los regresores. Las variables
explicativas tienen un comportamiento parecido y comparten sus efectos, dando lugar a pa-
Bo
Una estrategia, como sabemos, para comprobar de un modo exploratorio o inicial la existencia
de esta multicolinealidad es calcular las correlaciones entre las variables explicativas. Para
ello tenemos el siguiente código:
Datos <- subset(provincias, select = c(MATRIM_MIL_05, NUM_HIJ_FERT_05, TAS_FECUN_05,
POR_MUJ_ACT_05, PIB_HAB_04))
correlaciones <- cor(Datos)
296 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
Se ha creado una hoja de datos o data.frame con el nombre “Datos” con las variables expli-
cativas, y se ha calculado la correspondiente matriz de correlaciones:
correlaciones
07
## MATRIM_MIL_05 NUM_HIJ_FERT_05 TAS_FECUN_05 POR_MUJ_ACT_05
## MATRIM_MIL_05 1.0000000 0.64801785 0.68305915 -0.32203281
## NUM_HIJ_FERT_05 0.6480179 1.00000000 0.97823916 -0.06468868
5-
## TAS_FECUN_05 0.6830591 0.97823916 1.00000000 -0.20189896
## POR_MUJ_ACT_05 -0.3220328 -0.06468868 -0.20189896 1.00000000
-0
## PIB_HAB_04 -0.1030421 -0.17467692 -0.01403294 -0.62623599
## PIB_HAB_04
## MATRIM_MIL_05 -0.10304214
##
##
##
NUM_HIJ_FERT_05 -0.17467692
TAS_FECUN_05 -0.01403294
POR_MUJ_ACT_05 -0.62623599
19
20
## PIB_HAB_04 1.00000000
or
ad
Puede comprobarse como en efecto existen correlaciones altas (en valor absoluto) entre al-
gunas variables, en especial entre las variables MATRIM_1000_05, NUM_HIJ_FERT_05
y TAS_FECUN_05 por un lado; y POR_MUJ_ACT_05 y PIB_HAB_04 por otro.
rr
Bo
Gráficamente, podemos utilizar la función corrplot para visualizar las correlaciones, inclui-
do un contraste de significación de los coeficientes con la función cor.mtest, del mismo
paquete:
library(corrplot)
res1 <- cor.mtest(Datos, conf.level = 0.95)
corrplot(correlaciones, method = "number", type = "lower", p.mat = res1[[1]])
MATRIM_MIL_05
4.7. PRÁCTICAS 297
NUM_HIJ_FERT_05
TAS_FECUN_05
MATRIM_MIL_05 1
POR_MUJ_ACT_05
NUM_HIJ_FERT_05 0.65 1
07
TAS_FECUN_05
PIB_HAB_04
0.68 0.98 1
5-
POR_MUJ_ACT_05 −0.32 −0.06 −0.2 1
-0
PIB_HAB_04 −0.1 −0.17 −0.01 −0.63 1
library(car)
vif(regre1)
rr
## 3.484586
07
## Cuenca -2.08588923 -1.945650733 -2.05428691 2.03518420
## Granada 0.14601082 0.654741655 0.39207343 -0.02633628
## Huelva 1.06012443 0.682603002 0.59594904 0.34244047
5-
## Murcia 0.30775373 2.242838435 2.24071782 0.15841544
## Navarra -0.48080471 -0.069653368 0.34409469 -1.42244265
-0
## Rioja -0.22614411 -0.116088946 -0.04676685 -0.63819171
## Segovia -1.51741710 -0.487573573 -0.59698761 0.36652043
## Sevilla 2.00218799 1.379136677 1.35200633 -0.11393625
##
##
##
Toledo
Valencia
Zaragoza
0.51048453
1.29231568
-0.03583676
190.534009151
0.311118375
0.52400630
0.51491494
-0.664028771 -0.43101626
1.95585057
-1.10025138
-0.74388584
20
## PIB_HAB_04
## Albacete -0.83968167
## Alicante 0.02421934
## Badajoz -1.43213248
## Cantabria 0.55029736
or
## Granada -1.13483580
## Huelva -0.42806192
## Murcia -0.27823740
## Navarra 2.28614199
rr
## Rioja 1.23638929
## Segovia 0.77491842
Bo
## Sevilla -0.56435516
## Toledo -0.68844454
## Valencia 0.33887530
## Zaragoza 1.23494387
## attr(,"scaled:center")
## MATRIM_MIL_05 NUM_HIJ_FERT_05 TAS_FECUN_05 POR_MUJ_ACT_05
## 4.868945 1.352500 4.161720 61.087460
## PIB_HAB_04
## 17368.135018
## attr(,"scaled:scale")
## MATRIM_MIL_05 NUM_HIJ_FERT_05 TAS_FECUN_05 POR_MUJ_ACT_05
4.7. PRÁCTICAS 299
## [1] 5
07
Vamos a proceder al cálculo de las componentes principales propiamente dicho. Vamos a
utilizar la función “prcomp”:
5-
modelo3.cp <- prcomp (Datos, scale = TRUE)
summary (modelo3.cp)
-0
## Importance of components:
## PC1 PC2 PC3 PC4 PC5
## Standard deviation 1.6182 1.2795 0.7177 0.47177 0.08285
##
##
19
Proportion of Variance 0.5237 0.3274 0.1030 0.04451 0.00137
Cumulative Proportion 0.5237 0.8511 0.9541 0.99863 1.00000
20
El “summary” de las componentes calculadas y guardadas en el objeto “resul”, se obtienen
3 informaciones correspondientes a las 5 componentes principales obtenidas. La “Standard
Deviation”.es la raíz cuadrada de los autovalores asociados a cada componente. “Proportion
of Variance” nos dice la proporción de la varianza o comportamiento de las variables origina-
or
les recogido por cada componente, proporción que se acumula en “Cumulative Proportion”.
Nótese que las componentes aparecen ordenadas de más a menos importantes en función de
la cantidad de varianza que capturan
ad
Los coeficientes que multiplican a las variables originales (tipificadas) en cada componente
se obtienen como hemos visto arriba:
coeficientes <- modelo3.cp$rotation
rr
coeficientes
Bo
Selección de componentes
Seleccionamos de nuevo aquellas componentes con autovalor mayor que 1 (podría ser otro
criterio, por ejemplo que se explique más del 90 % de la variabilidad de los datos)
300 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
## [1] 2
Seleccionamos pues dos componentes, gráficamente:
07
plot(autovalores, main = "Gráfico de Sedimentación",
xlab = "Nº de Autovalor", ylab="Valor", pch = 16, col = "red4", type = "b",
5-
lwd = 2, las = 1)
abline(h = 1, lty = 2, col = "green4")
-0
Gráfico de Sedimentación
2.5
2.0
19
20
1.5
Valor
or
1.0
0.5
ad
0.0
rr
1 2 3 4 5
Bo
Nº de Autovalor
07
PCA − Biplot
Navarra
PIB_HAB_04
5-
2
Zaragoza
Cantabria Rioja
-0
Valencia
1
Alicante
Dim2 (32.7%)
0
19
Segovia
Albacete
MATRIM_MIL_05
TAS_FECUN_05
20
Ciudad Real Huelva NUM_HIJ_FERT_05
Sevilla
Murcia
Granada
−1
Badajoz
Cuenca
or
Toledo
−2 POR_MUJ_ACT_05
ad
−4 −2 0 2
Dim1 (52.4%)
rr
Los valores que, para cada caso, toman estas dos componentes, los podemos obtener direc-
tamente del objeto guardado, y añadirlas al conjunto de datos original:
Bo
##
302 CAPÍTULO 4. ANÁLISIS DE COMPONENTES PRINCIPALES CON R
## Call:
## lm.default(formula = EDAD_MATER_05 ~ PC1 + PC2, data = provincias)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.53892 -0.16163 0.01028 0.20208 0.40661
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 30.83313 0.07204 428.02 < 2e-16 ***
07
## PC1 -0.12322 0.04598 -2.68 0.018899 *
## PC2 0.29482 0.05815 5.07 0.000215 ***
## ---
5-
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.2881 on 13 degrees of freedom
-0
## Multiple R-squared: 0.7167, Adjusted R-squared: 0.6731
## F-statistic: 16.44 on 2 and 13 DF, p-value: 0.0002751
19
En primer lugar, puede destacarse que el valor del coeficiente de determinación lineal co-
rregido se incrementa, debido al aumento de grados de libertad. Además, los parámetros
correspondientes a las dos variables explicativas son significativas (p-values pequeños). El
20
efecto de PC1 (“factores demográficos”) sobre la edad media de maternidad es negativo (a
mayor número de matrimonios, número de hijos en edad fértil y tasa de fecundidad, menor
edad media); mientras que el efecto de PC2 (“factores económicos”) sobre la edad media de
maternidad es positivo (a mayor PIB por habitante y menor proporción de mujeres activas,
or
mayor edad media de maternidad) además de más intenso que el efecto de los “factores
demográficos”. Por último, puede comprobarse como la correlación entre las componentes
principales, que ahora son las variables explicativas, es prácticamente nula, y el vif es igual
ad
a 1.
cor(provincias[, 9:10])
rr
## PC1 PC2
## PC1 1.000000e+00 -1.254361e-17
Bo
## PC1 PC2
## 1 1
summary(Datos)
07
## PIB_HAB_04
## Min. :12747
## 1st Qu.:15259
## Median :16229
5-
## Mean :17368
## 3rd Qu.:19325
-0
## Max. :24744
nuevaProvincia <- data.frame(MATRIM_MIL_05 = 4.788, NUM_HIJ_FERT_05 = 1.342, TAS_FECUN_0
19
Como ya realizamos el ajuste con los datos originales, podemos obtener los scores de la nueva
provincia en las componentes con la función predict:
20
newScores <- predict(modelo3.cp, newdata = nuevaProvincia)
newScores
07
5-
-0
19
20
or
ad
rr
Bo
Capítulo 5
07
Análisis Cluster con R
5-
5.1. Introducción al análisis cluster
-0
El análisis cluster, o análisis de conglomerados, es una técnica de análisis multivariante de
interdependencias, es decir, todas las variables juegan el mismo papel, sin que unas expliquen
a otras.
19
Consiste en identificar observaciones (objetos, individuos, etc.) que son similares con respecto
20
a un criterio, y clasificarlos en grupos o tipos que internamente sean homogéneos y que
entre sí sean heterogéneos. El análisis cluster entra dentro de las técnicas de clasificación no
supervisadas. Esto quiere decir que no hay unos grupos predeterminados, sino que se van a
crear a partir de la información interna de los datos.
or
Aunque el análisis cluster se puede utilizar con variables en cualquier escala, en este capítulo
nos vamos a centrar exclusivamente en variables en escala métrica, es decir, cuantitativas.
En lo que sigue, asumimos que tenemos un conjunto de datos de n individuos en los que se
ad
han observado m variables cuantitativas. Este conjunto lo podemos simbolizar con la matriz
X = (X1 , · · · , Xj , · · · , Xm ). Así, xij será el valor de la variable Xj en el individuo i.
Para realizar las agrupaciones, necesitamos una medida de proximidad entre los individuos,
rr
que cuantifique lo que dos individuos o grupos se parecen, en función de los valores que
presente cada variable. Estas medidas pueden estar basadas en la distancia, en coeficientes
Bo
La figura 5.1 muestra visualmente un ejemplo muy sencillo de lo que vamos a hacer.
Aquí, disponemos de n = 8 observaciones y m = 2 variables. Queremos agrupar los individuos
305
306 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
15
10
X2
07
0
5-
0 5 10 15
-0
X1
19
Figura 5.1: Agrupamiento sencillo
20
en base a esas observaciones, y lo que buscamos es que sean muy parecidos (próximos) entre
ellos y que los grupos sean diferentes (lejanos). En este sencillo ejemplo se ve claramente la
agrupación natural que haríamos a simple vista. Usaremos los métodos numéricos del análisis
cluster para agrupar muchos más individuos en base a un gran número de variables.
or
2. Se establece una medida de proximidad (distancia) entre cada dos individuos, utilizan-
do los valores de las m variables.
3. Se crean los grupos utilizando el criterio de proximidad.
rr
Xj − x̄j
Zj = .
sj
07
resumir de alguna manera las m diferencias que hay entre los valores de todas y cada una
de las variables Xj , es decir, xij − xi′ j .
La distancia euclídea se define como:
5-
v
u∑
um
-0
dii′ = t (xij − xi′ j )2 .
j=1
19
En ocasiones se utiliza la distancia euclídea al cuadrado, para quitar la raíz y reducir el coste
computacional:
20
∑
m
d2ii′ = (xij − xi′ j )2 .
j=1
or
1
ad
∑
m p
Los valores más habituales de p son 1 y 2, que se corresponden con la distancia de Manhattan
y la distancia euclidea respectivamente. Además, cuando p tiende a infinito o a menos infinito,
Bo
xi − x i′ )′Σ −1 (x
Dii2 ′ = (x xi − x i′ ),
07
La tabla 5.1 muestra un conjunto de datos muy pequeño X con n = 5 observaciones
de m = 3 variables, que nos servirá para practicar. Como ejercicio, el lector debe crear un
5-
data frame llamado cdata1 en su espacio de trabajo, bien con código, bien creando los datos
en un fichero externo (hoja de cálculo o texto plano). A modo de ejemplo, a continuación se
calculan las distancias entre los dos primeros casos operando directamente con los vectores
-0
de la matriz de datos previamente tipificada con la función scale.
## [1] 3.966434
or
## [1] 15.7326
Distancia de Minkowski1 (p = 3):
rr
## [1] 3.327158
Distancia de Manhattan:
sum(abs(zdata1[1, ] - zdata1[2, ]))
## [1] 6.819042
Distancia de Chebyshev (máxima):
max(abs(zdata1[1, ] - zdata1[2, ]))
1
Puede comprobarse que para p = 2 coincide con la euclídea.
5.2. CÁLCULO DE DISTANCIAS 309
## [1] 2.631174
Distancia mínima:
min(abs(zdata1[1, ] - zdata1[2, ]))
## [1] 1.9518
Distancia de Mahalanobis:
t(zdata1[1, ] - zdata1[2, ]) %*% solve(cov(zdata1)) %*% (zdata1[1, ] - zdata1[2, ])
07
## [,1]
## [1,] 7.971831
5-
Si calculamos las distancias de todos los pares de observaciones de un conjunto de datos,
obtendríamos una matriz de distancias:
-0
d11 d12 · · · d1i ··· d1n
d21 d22 · · · d2i ··· d2n
D=
..
.
19
..
.
. . . ..
.
di1 di2 · · · dii
..
.
..
.
..
.
..
.
..
.
···
...
..
.
din
..
.
20
dn1 dn2 · · · dni ··· dnn
La matriz de distancias es una matriz simétrica, cuya diagonal son ceros, ya que la distan-
cia de una observación a sí misma (dii ) es nula. Por tanto se puede representar de forma
or
ad
d21
d31 d32
.. .. ...
. .
rr
D=
di1 di2 · · · di,i−1
.. .. .. .. ...
. . . .
Bo
Podemos obtener la matriz de distancias con R con una única expresión, utilizando la función
dist. Esta función devuelve una matriz de distancias entre observaciones a partir de un
conjunto de variables numéricas. Por defecto devuelve las distancias euclídeas, aunque se
pueden obtener también la de Manhattan, la máxima y la de Minkowski, entre otras. La
función mahalanobis calcula las distancias de Mahalanobis de cada observación con respecto
al vector de medias, por lo que hay que utilizarla dentro de una función vectorizada para
obtener una matriz con las distancias. Esta matriz se puede convertir a un objeto de clase
dist para ser utilizado en otros métodos mediante la función as.dist.
310 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
El código a continuación devuelve las matrices de distancias para los datos del ejemplo.
Nótese cómo la distancia entre los casos 1 y 2 coinciden con los calculados operando con los
vectores fila. En el caso de la distancia de Mahalanobis, es aconsejable calcular previamente
la inversa de la matriz de varianzas-covarianzas, y así reducir el tiempo de cálculo.
07
## caso 1 caso 2 caso 3 caso 4
## caso 2 3.966434
## caso 3 2.403193 1.797094
5-
## caso 4 1.150994 3.018057 1.706484
## caso 5 3.447673 0.877058 1.568540 2.607868
-0
Distancia de Minkowski2 (p = 3):
dist(zdata1, method = "minkowski", p = 3)
##
## caso 2
caso 1
3.327158
caso 2 caso 3 19
caso 4
20
## caso 3 2.076085 1.600980
## caso 4 1.028748 2.527452 1.562061
## caso 5 2.885022 0.877058 1.507939 2.252115
Distancia de Manhattan:
or
07
## [,1] [,2] [,3] [,4] [,5]
## caso 1 0.000000 7.971831 5.183099 4.591549 5.183099
## caso 2 7.971831 0.000000 4.591549 3.943662 4.591549
## caso 3 5.183099 4.591549 0.000000 7.971831 8.000000
5-
## caso 4 4.591549 3.943662 7.971831 0.000000 7.971831
## caso 5 5.183099 4.591549 8.000000 7.971831 0.000000
-0
as.dist(D)
##
##
##
##
caso
caso
caso
2
3
4
caso 1
7.971831
caso 2
5.183099 4.591549
caso 3
Ya hemos visto cómo calcular las distancias entre observaciones. Ahora bien, a medida que
vamos formando los grupos, también debemos comprobar la proximidad de las observaciones
or
a los grupos, de forma que podamos asignar la observación al grupo más próximo. Por
otra parte, hay que calcular distancias entre grupos, para cuantificar cómo de diferentes
(distantes) son los grupos. Para ambas tareas, una vez tenemos dos o más observaciones
ad
agrupadas, calculamos un valor que los represente a todos, y que llamaremos centroide.
Este centroide será un vector con valores para las m variables, calculado a partir de los
valores de las observaciones que están dentro del grupo. Lo más habitual es utilizar como
rr
centroide las medias de las observaciones en cada variable, aunque se podría utilizar cualquier
otra medida representativa, como por ejemplo la mediana.
Bo
Supongamos a modo ilustrativo que los dos primeros casos forman un grupo. Entonces,
podemos calcular el centroide de ese grupo como el vector de medias de los dos primeros
casos como se muestra en el código a continuación. Después se pueden calcular las distancias
del resto de observaciones a este centroide. La figura 5.2 muestra los centroides de los grupos
que se veían evidentes en la figura 5.2.
15
10
X2
07
0
5-
0 5 10 15
-0
X1
19
Figura 5.2: Centroides para dos variables
ción. Los distintos métodos pueden dar soluciones distintas. La idoneidad del método elegido
va a depender tanto de la estructura interna de los datos como del problema que se está abor-
dando. En general, se probarán varios métodos y se seleccionará aquella agrupación que sea
más coherente desde el punto de vista teórico, y estable desde el punto de vista empírico. En
rr
los siguientes apartados vamos a estudiar los dos métodos más extendidos de agrupación.
Bo
de nuevo las distancias del resto de observaciones al nuevo grupo. A partir de ahí, se van
creando nuevos grupos o añadiendo a alguno existente, y combinándose en función de la
distancia.
Existen varios métodos para realizar las sucesivas agrupaciones, según cómo calculemos las
distancias entre grupos. El método más sencillo sería el de los centroides, ya que bastaría con
ir sustituyendo las observaciones agrupadas por su centroide. No obstante se pueden utilizar
otros métodos:
1. Método del vecino más cercano (Single linkage). La distancia entre grupos es la dis-
tancia entre sus elementos más próximos.
07
2. Método del vecino más lejano (Complete linkage). La distancia entre grupos es la
distancia entre sus elementos más lejanos.
5-
3. Métodos UPGMA3 , WPGMA4 , basados en promedios de distancias de observaciones
de los centroides.
-0
4. Método UPGMC5 o de los centroides.
5. Método WPGMC6 o de las medianas.
19
6. Métodos de Ward. Se unen los conglomerados que dan lugar a otro cuyos individuos
tienen una menor suma de los cuadrados de sus distancias respecto al centroide de
dicho grupo (menor varianza).
20
El código a continuación realiza paso a paso la secuencia de agrupación del ejemplo
de cinco casos y tres variables utilizando el criterio de los centroides.
or
Paso 2: agrupamos los dos casos más cercanos (menor distancia), que en este caso son el 2 y
el 5. Sustituimos las dos observaciones por el nuevo grupo y recalculamos distancias.
grupo.2.5 <- colMeans(zdata1[c(2, 5), ])
agrupacion1 <- rbind(grupo.2.5, zdata1[c(1, 3,4), ]); agrupacion1
07
## caso 4 2.786129 1.150994 1.706484
Paso 3: agrupamos los dos grupos más cercanos, en este caso los casos 1 y 4 y volvemos a
reorganizar:
5-
grupo.1.4 <- colMeans(agrupacion1[c(2, 4), ])
agrupacion2 <- rbind(grupo.1.4, agrupacion1[-c(2,4), ])
-0
agrupacion2
19
## grupo.1.4 0.9647638 0.8198916 1.0734901
## grupo.2.5 -0.7893522 -1.0434984 -0.8783101
## caso 3 -0.3508232 0.4472136 -0.3903600
20
dist(agrupacion2)
## grupo.1.4 grupo.2.5
## grupo.2.5 3.218489
or
agrupacion3
## grupo.2.5.3
## grupo.1.4 2.553906
Paso 5: El último paso sería agrupar los dos grupos resultantes en uno solo con todos los
casos.
En este ejemplo con tan pocos casos, parece evidente la formación de dos grupos, uno formado
5.3. MÉTODOS JERÁRQUICOS 315
por los casos 1 y 4, y el otro formado por los casos 2, 5, y 3. Posteriormente veremos cómo
caracterizar estos grupos para darles significado.
Hemos utilizado el método de los centroides, pero podríamos haber utilizado cualquiera de los
otros. En este ejemplo tan sencillo, los resultados hubieran sido los mismos. En la práctica,
es habitual probar varios métodos y quedarse con el que mejor se adapte al problema en
cuestión. La práctica ha mostrado en numerosas ocasiones que algunos métodos funcionan
mejor que otros según sea la estructura interna de los datos. Por ejemplo:
El método del vecino más cercano es más sensible a la presencia de observaciones raras
(outliers) que el del vecino más lejano.
07
El método del vecino más lejano suele identificar grupos muy homogéneos con indivi-
duos muy parecidos entre sí.
5-
El método de Ward tiende a encontrar grupos muy compactos de tamaño similar.
El método del vecino más cercano tiende a crear menos grupos que el del vecino más
-0
lejano.
Una vez agrupadas las observaciones, debemos decidir cuáles son los grupos con los que nos
19
queremos quedar. Recordemos que partíamos de tantos grupos como observaciones, y termi-
namos con un solo grupo. En los siguientes apartados veremos criterios gráficos y numéricos
para ello.
20
5.3.2. Análisis Cluster jerárquico con R
Hemos realizado los cálculos paso paso a modo ilustrativo. Ahora vamos a ver cómo realizar
or
todo el proceso de forma sencilla con la función hclust de R. La función hclust crea un
objeto de clase hclust según varios criterios7 . La clasificación se representa gráficamente
mediante un dendrograma con la función hclust. Este dendrograma nos puede dar una idea
ad
de cuántos grupos nos interesa formar. La idea es podar el dendrograma haciendo un corte
horizontal que determine los grupos que nos interesan, digamos k grupos. Con la función
rect.hclust podemos visualizar esa poda, la dimensión de los grupos, y los casos que lo
rr
forman. Se pueden probar con varios valores de k hasta que encontremos el que más se adecúe
al problema. Se busca un equilibrio entre el número de grupos y una suficiente diferenciación
entre ellos, a la vez que homogeneidad dentro de cada uno. Una vez decididos el número de
Bo
grupos, podemos aplicar al objeto de clase hclust la función cuttree, que devuelve un vector
con los grupos formados, realizando la poda a una altura h determinada (distancia según el
criterio utilizado) o un número de grupos k. Este vector lo podemos añadir al conjunto de
datos como factor para utilizar en análisis posteriores.
Cluster Dendrogram
2.0
1.6
Altura
1.2
caso 3
07
caso 1
caso 4
0.8
5- caso 2
caso 5
-0
19 Casos
Ejemplo básico
20
Figura 5.3: Dendrograma de la agrupación del ejemplo básico
euclídeas (por defecto en la función dist) en un objeto para pasárselas como primer argu-
or
mento, y usamos el método de los centroides (argumento method). La función genérica plot
crea el dendrograma de la figura 5.3. Con esta figura podemos intuir los grupos que queremos
quedarnos. La función hclust añade la poda del dendrograma para crear 2 grupos como se
ad
ve en la figura 5.4. La altura indica cómo se han ido añadiendo los casos según el criterio
utilizado, como vemos en el mismo orden en que lo hicimos paso a paso anteriormente.
rr
07
Cluster Dendrogram
5-
2.0
-0
1.6
19
Altura
1.2
caso 3
20
caso 1
caso 4
0.8
caso 2
caso 5
or
ad
Casos
Ejemplo básico
rr
Figura 5.4: Dendrograma de la agrupación del ejemplo básico seleccionando dos grupos
Bo
318 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
En el apartado5.6 veremos algunos índices que nos pueden ayudar a decidir el número de
clusters óptimo con criterios numéricos.
07
Los métodos no jerárquicos se suelen utilizar para agrupar un gran número de observaciones.
En estos métodos, se establece de antemano el número de grupos que se van a formar, k. Se
utilizan métodos iterativos de forma que, a partir de k grupos iniciales semilla, las observa-
5-
ciones van cambiando de grupo hasta que se consigue un cierto criterio de homogeneidad
de los grupos. El método de las k-medias es el más importante, y el que veremos en este
-0
apartado.
Proceso de formación de grupos:
19
1. Se establece número k de grupos a formar
2. Se establece un centroide inicial para cada grupo
20
3. Se añaden a cada grupo las observaciones más cercanas a los centroides iniciales
4. Se calculan los nuevos centroides y se vuelven a asignar los más próximos
5. Se repite el proceso hasta que las agrupaciones se mantienen estables
or
Las iteraciones pueden hacer muy largo el proceso paso a paso, vamos a ver directamente
cómo hacerlo con las funciones de R. La función kmeans realiza el agrupamiento cluster no
jerárquico por el método de las k medias. Esta función requiere como argumento de entrada
ad
permite seleccionar entre cuatro diferentes. Por defecto se utiliza el de Hartigan and Wong
(1979); el argumento iter.max controla el número máximo de iteraciones del método, por
Bo
defecto 10; el argumento nstart indica el número de conjuntos aleatorias elegir al empezar.
Por defecto es 1, pero con frecuencia se aconseja utilizar un número mayor. La función
produce un objeto de clase kmeans que es una lista de 9 componentes. Los más importantes
son cluster, vector con el grupo al que pertenece cada observación, y centers, los centroides
de los grupos.
07
## 1 -0.6431759 -0.5465944 -0.7156601
## 2 0.9647638 0.8198916 1.0734901
##
5-
## Clustering vector:
## caso 1 caso 2 caso 3 caso 4 caso 5
## 2 1 1 2 1
-0
##
## Within cluster sum of squares by cluster:
##
##
##
[1] 2.1530322 0.6623932
(between_SS / total_SS = 76.5 %) 19
20
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss"
## [5] "tot.withinss" "betweenss" "size" "iter"
## [9] "ifault"
or
Realice la práctica 5.1 cuyo guión se encuentra en el apartado 5.7 para realizar análisis
cluster del ejemplo utilizado en el capítulo.
gráficos de dispersión como una matriz de gráficos. Esta representación se complica cuando
crece el número de variables. En este caso, podemos utilizar el análisis cluster conjuntamente
con el análisis de componentes principales, de forma que la representación la haremos de las
dos primeras componentes, identificando el grupo de cada observación.
En nuestro sencillo ejemplo solo tenemos tres variables. Podemos optar por representar
las tres combinaciones posibles de las variables como muestra la figura 5.5. La figura 5.6
muestra una matriz de gráficos con todos los pares de gráficos de una vez. La figura ??
muestra la representación de las dos componentes principales ajustadas con la función prcomp.
07
El siguiente código produce dichas figuras.
par(mfrow=c(3,1))
5-
plot(Var1 ~ Var2, data = cdata1, col = grupo, pch = 19, las = 1)
plot(Var1 ~ Var3, data = cdata1, col = grupo, pch = 19, las = 1)
plot(Var2 ~ Var3, data = cdata1, col = grupo, pch = 19, las = 1)
-0
par(mfrow=c(1,1))
library(lattice)
19
splom(~ cdata1[1:3], groups = grupo, data = cdata1, pch = 19)
Además de gráficamente, podemos caracterizar los grupos de forma numérica. La forma más
básica sería interpretando los centroides de los grupos, pero los de las variables originales, ya
or
que lo que se guarda en el objeto kmeans son los centroides de las variables tipificadas, que no
son fáciles de interpretar. No obstante, podemos obtener cualquier otro estadístico (mediana,
ad
etc.) para ver las diferencias entre los grupos. Si se ha realizado el análisis de componentes
principales para resumir la información en dos dimensiones, y los componentes tienen un
sentido que se pueda explicar, también se pueden caracterizar los grupos en términos de las
componentes principales.
rr
Bo
El código a continuación muestra las medias de las tres variables en cada grupo. Las
observaciones del grupo 1 toman valores medios más altos en las tres variables que las del
grupo 2. A modo de ejemplo, después se muestra una expresión que obtiene un resumen más
completo de la variable Var1 para cada grupo.
0.90
0.85
0.80
Var1
0.75
0.70
07
0.65
0.60
5-
Var2
-0
0.90
0.85
0.80
19
Var1
0.75
0.70
20
0.65
0.60
30 40 50 60 70
Var3
or
ad
0.80
0.75
0.70
Var2
rr
0.65
0.60
0.55
Bo
0.50
30 40 50 60 70
Var3
Figura 5.5: Representación de las variables por pares con los grupos
322 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
70
50 60 70
60
50 Var3 50
40
30 40 50
30
0.80
0.75 0.65 0.75
07
0.70
0.65 Var2 0.65
0.60
0.55
5-
0.50 0.60
0.50
0.90
0.85 0.75 0.85
-0
0.80
0.75 Var1 0.75
0.60 0.70
0.70
0.65
0.60 19
Scatter Plot Matrix
20
Figura 5.6: Matriz de gráficos de dispersión
or
0.4
caso 5
ad
caso 4
0.2
caso 1
0.0
caso 2
rr
PC2
caso 3
−2 −1 0 1
PC1
5.5. CARACTERIZACIÓN DE GRUPOS 323
## $`1`
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.800 0.825 0.850 0.850 0.875 0.900
##
## $`2`
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.6000 0.6500 0.7000 0.6667 0.7000 0.7000
07
Por último, podemos comprobar si con la agrupación que hemos realizado hemos conseguido
el objetivo que perseguíamos con esta técnica, recordemos: tener grupos que sean diferentes
entre sí, pero con los elementos del mismo grupo muy parecidos. Esto lo podemos visualizar
5-
gráficamente con gráficos de cajas. También podemos verificarlo estadísticamente mediante
el Análisis de la Varianza. Si observáramos que no hay diferencias entre dos grupos para un
-0
número importante de variables, deberíamos revisar el criterio de agrupación, e incluso el
número de grupos. Para un número importante de variables de clasificación, se puede consi-
derar realizar un análisis múltiple de la varianza (MANOVA) para comprobar las diferencias
entre los grupos conjuntamente.
19
20
La figura 5.7 muestra los gráficos de caja de las tres variables por grupos. Son muy
pocos datos, pero se aprecia la diferencia claramente. Para mayor seguridad, el ANOVA que
produce el código a continuación confirma que hay diferencias significativas, y además el test
HSD de Tukey indica que todos los grupos son diferentes en todas las variables.
or
library(reshape2)
gdata <- melt(cdata1, id.vars = 4, measure.vars = 1:3)
library(ggplot2)
ad
summary(modelo1)
07
Var1 Var2 Var3
0.9 0.8 70
5-
-0
60
0.8 0.7
19
value
50
20
0.7 0.6
40
or
ad
0.6 0.5 30
1 2 1 2 1 2
rr
grupo
##
## $grupo
## diff lwr upr p adj
## 2-1 -0.1833333 -0.3645021 -0.002164608 0.0485669
modelo2 <- aov(Var2~grupo, data = cdata1)
summary(modelo2)
07
## Residuals 3 0.03167 0.01056
TukeyHSD(modelo2)
5-
## Tukey multiple comparisons of means
## 95% family-wise confidence level
-0
##
## Fit: aov.default(formula = Var2 ~ grupo, data = cdata1)
##
## $grupo
## diff lwr upr 19 p adj
## 2-1 -0.1833333 -0.4818104 0.1151438 0.1455963
20
modelo3 <- aov(Var3~grupo, data = cdata1)
summary(modelo3)
or
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
TukeyHSD(modelo3)
rr
Realice la práctica 5.2 cuyo guión se encuentra en el apartado 5.7 para realizar análisis
cluster con datos de provincias.
326 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
07
5-
5.6.2. Análisis cluster con paquetes especializados
En este capítulo se ha introducido el análisis cluster con los métodos más habituales. Con
-0
la instalación base de R se instala el paquete cluster (Maechler et al., 2019) que tiene
algunas funciones adicionales. Existen otros métodos de agrupación como los utilizados por
el paquete mclust (Fraley et al., 2019), que está basado en modelos probabilísticos, véase
19
Everitt and Hothorn (2011). Por otra parte, el paquete NbClust (Charrad et al., 2015)
proporciona índices para la selección del número de grupos apropiado, véase Aldas and Uriel
(2017), donde aparecen además los métodos más detallados. El paquete FactoMineR (Husson
20
et al., 2018) también contiene herramientas de agrupamiento y visualización interesantes, y
el paquete factoextra proporciona herramientas de visualización muy potentes.
or
Vamos a utilizar los datos de la figura 5.1, que se muestran en la tabla 5.2, almacenados
en el objeto datos.cluster1. En la siguiente expresión, se calcula el número de clusters
óptimo según varios criterios, a partir de una medida de distancia y un método de agrupación,
ad
en este caso distancia euclídea y método de Ward. Podemos guardar el resultado en un objeto
para extraer después los índices, el número de grupos propuestos o la mejor partición que
encuentra. La salida proporciona una interpretación de todos los cálculos, informando de
rr
cuántos métodos proponen cada número de clusters, y cuál sería la decisión por mayoría. en
este ejemplo, parece claro que el número de grupos óptimo es 3, como se veía claramente
en el gráfico de la figura 5.1. Dos de los métodos son gráficos, cono se puede observar en la
Bo
El código a continuación crea los gráficos de las figuras 5.8 y 5.9 utilizando funciones
del paquete factoextra para los datos del ejemplo sencillo utilizado anteriormente.
5.6. MÁS ANÁLISIS CLUSTER 327
07
12.0 7.5 3
5-
library(factoextra)
fviz_dend(gdata1, k = 2, horiz = TRUE)
-0
fviz_cluster(object = kcdata1, data = zdata1)
un único grupo e ir dividiendo hasta tener tantos grupos como observaciones. La función
pam realiza análisis cluster no jerárquico, más robusto que el método de las k-medias. La
función clara realiza también análisis no jerárquico con el mismo algoritmo que pam, pero
ad
optimizado para conjuntos de datos grandes. La función fanny rambién realiza un análisis
no jerárquico, pero en vez de devolver a qué grupo pertenece cada observación, informa de
la probabilidad de pertenencia a cada grupo8 . Si lo que tenemos son variables binarias, la
rr
el dendrograma puede ser difícil de ver. La función bannerplot permite una visualización más
efectiva en estos casos. Por otra parte, la función clusplot representa las observaciones en
dos dimensiones sobre las coordenadas de un análisis de componentes principales, agrupadas
según un análisis cluster realizado, y con elipses que nos dan una idea de cómo de separados
están los grupos.
En las siguientes expresiones se muestran ejemplos de uso del paquete cluster con
8
Se pueden ver un ejemplo interesante en http://is-r.tumblr.com/post/37826141731/
fuzzy-clustering-with-fanny
328 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
07
Cluster Dendrogram
caso 5
5-
-0
caso 2
19 caso 3
20
or
caso 4
ad
caso 1
rr
Cluster plot
caso 5
07
caso 4
0.25
5-
-0
caso 1
caso 2
0.00
19
Dim2 (5.4%)
cluster
a 1
20
a 2
−0.25
or
ad
−0.50
rr
caso 3
Bo
−2 −1 0 1 2
Dim1 (91.2%)
caso
2.5
caso
Height
1.5
caso
07 caso 3
caso 1
caso 4
0.5
caso
caso 2
caso 5
caso
5-
0 1 2 2.86
-0
Height
zdata1
Agglomerative Coefficient = 0.6 Agglomerative Coefficient = 0.6
19
Figura 5.10: Cluster aglomerativo con paquete ‘cluster‘
20
los datos del ejemplo sencillo. La figura 5.10 muestra los gráficos del cluster aglomerativo.
La figura 5.11 muestra los gráficos del cluster no jerárquico. Con la función clusplot se puede
obtener el gráfico de la izquierda por separado.
or
par(mfrow=c(1,2))
library(cluster)
cag <- agnes(zdata1)
ad
plot(cag)
par(mfrow=c(1,1))
rr
par(mfrow=c(1,1))
El paquete FactoMineR permite realizar análisis cluster jerárquico sobre componentes prin-
cipales con la función HCPC.
5.7. PRÁCTICAS 331
1 : 2 | 0.59
caso
Component 2
0.0
caso
−0.4
07
caso 2 : 3 | 0.46
caso
−0.8
5-
−2 −1 0 1 2 0.0 0.2 0.4 0.6 0.8 1.0
-0
Silhouette width si
Component 1
These two components explain 96.63 % of the
Average
point variability.
silhouette width : 0.51
19
Figura 5.11: Cluster no jerárquico con paquete ‘cluster‘
20
La siguiente expresión realiza un clustering jerárquico sobre los datos del ejemplo,
después de extraer los componentes principales. La función produce varios gráficos. La figura
or
library(FactoMineR)
fm <- HCPC(PCA(zdata1, graph = FALSE), nb.clust = 2, graph = FALSE)
plot(fm)
rr
fviz_cluster(fm)
Bo
Realice la práctica 5.3 cuyo guión se encuentra en el apartado 5.7 para agrupar
individuos de una encuesta.
5.7. Prácticas
En este apartado se presentan las prácticas a las que se han hecho referencia durante el
capítulo. La reproducibilidad del código ha sido comprobada con la sesión de R que se
detalla en el Prefacio. El lector puede teclear el código o copiarlo y pegarlo en la consola o
el editor. También se puede descargar el script con el código de todas las prácticas con la
332 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
07
Hierarchical clustering on the factor map
5-
cluster 1
cluster 2
-0
2.5
19
2.0
1.5
20
height
1.0
Dim 2 (5.44%)
or
0.5
0.8
0.6
caso 3 0.4
0.2
0.0
−0.2
ad
−0.4
0.0
Dim 1 (91.19%)
rr
07
Cluster plot
caso 3
0.75
5-
-0
0.50
19
Dim2 (5.4%)
0.25 cluster
a 1
20
a 2
caso 2
0.00 caso 1
or
−0.25 caso 4
ad
caso 5
rr
−2 −1 0 1 2
Dim1 (91.2%)
Bo
siguiente expresión:
download.file("http://emilio.lcano.com/b/adr/practicas/12-acluster.R",
destfile = "practicas/12-acluster.R")
07
métodos de agrupación: los métodos no-jerárquicos (en concreto el método de K medias)
y los procedimientos jerárquicos. El primer tipo se usa cuando existen muchos individuos,
pero requiere que se especifique a priori el número de grupos a formar. El segundo tipo de
5-
métodos no requiere el establecimiento previo del número de grupos, sino que estos grupos
se van creando de forma sucesiva a partir de la unión de grupos precedentes, hasta llegar a
uno solo.
-0
Las expresiones utilizadas se encuentran en el script de las prácticas del capítulo. En lo
sucesivo, vamos a suponer que estamos trabajando en un proyecto que contiene una carpeta
19
llamada “datos” donde se encuentran los ficheros de datos. No obstante, en esta práctica
crearemos los datos mediante código ya que son muy pocos datos.
20
Opcionalmente, podemos en primer lugar limpiar el espacio de trabajo eliminando todos los
objetos existentes:
rm(list = ls())
or
Ahora introducimos los datos de las variables del modelo. Esta vez lo haremos mediante el
propio script.
Data <- data.frame(Casos = c("caso 1", "caso 2", "caso 3", "caso 4", "caso 5"),
ad
row.names = 1)
Se ha construido el data.fame “Data” que tiene 3 columnas (variables), y 5 casos, que son
Bo
técnicas suelen ser muy sensibles a las distintas escalas de los datos.
ZData <- scale(Data)
07
## caso 3 -0.3508232 0.4472136 -0.3903600
## caso 4 0.5262348 0.4472136 1.0734901
## caso 5 -0.3508232 -1.0434984 -0.8783101
5-
## attr(,"scaled:center")
## Var1 Var2 Var3
## 0.74 0.64 48.00
-0
## attr(,"scaled:scale")
## Var1 Var2 Var3
## 0.1140175 0.1341641 20.4939015
19
Nótese cómo además de las variables tipificadas se obtienen las medias (center) y desviaciones
típicas (scale) originales, a las que podemos acceder en caso necesario mediante los atributos
20
del objeto ZData:
attr(ZData, "scaled:center")
siderada será la distancia euclídea, muy sensible a la escala de las variables, por lo que
utilizaremos los datos tipificados (“ZData”). Primero vamos a calcular todas las distancias
y a crear la “matriz de distancias” que llamaremos “d”:
rr
Cluster Dendrogram
5
07
Distancia entre clusters
4
3
5-
2
-0
caso 3
1
caso 1
caso 4
19
caso 2
caso 5
0
20
Casos
Ejemplo básico
or
ad
La solución obtenida muestra cómo existen dos grupos de casos claramente definidos: el
formado por los casos 1 y 4; y el formado por los casos 2, 5 y 3. Podemos escribir y señalar en
Bo
el gráfico tal solución con un poco de código más. Para ello definimos la variable “Numgrupos”
(o como queramos llamarla) y le asignamos un valor de 2:
Numgrupos <- 2 # Importante!!!! Aquí fijamos el número de grupos !!!!!!
Una vez fijamos el número de grupos, podemos enmarcar los grupos con la función
rect.hclust:
plot(fit, sub = "Ejemplo básico", xlab = "Casos", ylab = "Distancia entre clusters")
rect.hclust(fit, k = Numgrupos, border = c("red4", "blue4"))
5.7. PRÁCTICAS 337
Cluster Dendrogram
5
Distancia entre clusters
4
3
2
07
caso 3
1
caso 1
caso 4
5- caso 2
caso 5
0
-0
19 Casos
Ejemplo básico
20
or
ad
rr
Hemos utilizado el método de Ward, comúnmente empleado, pero podríamos haber em-
Bo
pleado otros métodos, como el método del “vecino más cercano” (method=“single”), el del
“vecino más lejano” (method=“complete”), o el método de “vinculación intergrupos” (met-
hod=“average”). Las soluciones alcanzadas con estos métodos son coincidentes debido a la
simpleza del caso planteado. Son las siguientes:
par(mfrow = c(1, 3))
for (metodo in c("single", "complete", "average")){
fit2 <- hclust(d, method = metodo)
plot(fit, sub = paste0("Método: ", metodo), xlab = "Casos", ylab = "Distancia entre cl
rect.hclust(fit2, k = Numgrupos, border = c("red4", "blue4"))
}
338 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
5
4
4
Distancia entre clusters
07
2
5-
caso 3
caso 3
caso 3
-0
1
1
caso 1
caso 4
caso 1
caso 4
caso 1
caso 4
19
caso 2
caso 5
caso 2
caso 5
caso 2
caso 5
0
0
20
Casos Casos Casos
Método: single Método: complete Método: average
Vamos a pasar ahora al planteamiento de un análisis clúster de K-medias. Este tipo de análisis
se suele plantear cuando hay muchos casos y cuando se tiene claro el número de grupos que
ad
se quieren obtener. También necesita como input los datos previamente tipificados (no las
distancias como en caso anterior). Hemos de recordar que el número de grupos lo tenemos
guardado en la variable “Numgrupos”, y que actualmente vale 2:
rr
set.seed(1)
Data.km <- kmeans(ZData, Numgrupos)
Bo
Como la asignación de grupos se realiza de forma aleatoria, fijamos la semilla para generación
de números aleatorios de forma que todos obtengamos los mismos resultados. La función
kmeans realiza la agrupación, que podemos ver al llamar al objeto creado en la consola:
Data.km
07
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss"
5-
## [5] "tot.withinss" "betweenss" "size" "iter"
## [9] "ifault"
-0
19
Vemos las coordenadas para cada variable (tipificada) de los dos centros de los grupos ob-
20
tenidos. Luego muestra la asignación de grupo para cada caso del problema. Las sumas de
cuadrados nos dan una idea de la dispersión de los grupos, y el porcentaje de variación expli-
cada por la agrupación realizada. Podemos acceder al resto de los componentes, por ejemplo
paraa guardar el tamaño de los grupos obtenidos:
or
## [1] 2 3
Bo
Podemos visualizar gráficamente los casos y sus grupos los grupos con las variables dos a
dos (los centroides representados por medio de triángulos):
plot(ZData, col = Data.km$cluster, pch = 19, bg = Data.km$cluster)
text(ZData, dimnames(ZData)[[1]], pos = 3, cex = .6)
points(Data.km$centers, col = 1:Numgrupos, pch = 17, cex = 1.5)
340 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
caso 1
1.0
0.5
caso 3 caso 4
Var2
0.0
−0.5
07
−1.0
caso 2 caso 5
5-
−1.0 −0.5 0.0 0.5 1.0 1.5
-0
Var1
19
Nótese como el resultado vuelve a coincidir con el obtenido por los métodos jerárquicos,
debido a la extrema sencillez de los datos de ejemplo.
Repite el análisis utilizando distintos criterios para las distancias (por ejemplo Manhattan)
20
y para el método de agrupamiento (por ejemplo centroides).
En este ejemplo vamos a formar grupos de provincias españolas. Las variables que servirán
para formar los grupos serán:
ad
Una estrategia que se suele seguir si no se tiene pensado a priori un número de grupos a
formar es realizar un análisis jerárquico y, en función de los resultados, mejorar la solución
Bo
Se recomienda en primer lugar limpiar el espacio de trabajo eliminando todos los objetos
existentes:
5.7. PRÁCTICAS 341
rm(list = ls())
Ahora introducimos los datos de las variables del modelo. Esta vez lo haremos mediante
la lectura de un archivo de texto donde las variables se disponen en columnas separadas
por tabuladores. El archivo es “provilogit.txt”, y su información se guarda en el data.frame
“provincias”:
provincias <- read.table("datos/provilogit.txt",
header = TRUE,
sep = "\t",
07
dec = ",",
fileEncoding = "latin1",
row.names = 1)
5-
Utilizamos el argumento fileEncoding = latin1 porque el fichero de texto fue creado con
esa codificación, y los proyectos de RStudio trabajan por defecto con otra (utf8). Con el
-0
argumento row.names = 1 estamos diciendo que la primera columna del fichero de texto
contiene los nombres de columnas (en este caso, los nombre de las provincias españolas).
## TASA_PARO_05 PIB_HAB_04
## Min. : 4.662 Min. :12747
## 1st Qu.: 6.907 1st Qu.:15584
ad
Comprobamos cómo son los datos del conjunto de datos. Recordemos que para aplicar las
Bo
## TASA_PARO_05 PIB_HAB_04
## A Coruña 9.859223 16558.22
## Álava 7.088059 27141.54
342 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
## TASA_PARO_05 PIB_HAB_04
## Min. : 4.662 Min. :12747
## 1st Qu.: 6.907 1st Qu.:15584
07
## Median : 8.716 Median :17343
## Mean : 9.297 Mean :18495
## 3rd Qu.:10.558 3rd Qu.:21132
5-
## Max. :17.652 Max. :27142
Vemos que la escala de las variables es muy diferente para cada una de ellas. Exploremos los
-0
datos también gráficamente:
par(mfrow = c(2, 2))
Frequency
or
0 4 8
5
ad
0
26000
18
12
14000
6
En la tasa de paro hay valores candidatos a valores atípicos que quizás habría que investigar
por si son datos erróneos. Asumimos en este caso que los datos son correctos y seguimos.
5.7. PRÁCTICAS 343
A partir de “Data” creamos el data.frame “ZData”, en el que aparecen las variables clasifi-
cadoras tipificadas para que no afecte a nuestro análisis el efecto escala:
ZData <- scale(Data)
head(ZData)
## TASA_PARO_05 PIB_HAB_04
## A Coruña 0.17411452 -0.51030503
## Álava -0.68461510 2.27809666
## Albacete 0.22039331 -1.01071975
07
## Alicante 0.09747333 -0.27632763
## Almería -0.04169151 -0.02012303
## Asturias 0.29222236 -0.39821569
5-
Previamente, y puesto que tenemos sólo dos variables clasificadoras, vamos a representar los
individuos en un diagrama de dispersión para ver si, a priori, pueden detectarse grupos. Para
-0
ello, haremos:
library(scales)
##
## Attaching package: 'scales' 19
20
## The following object is masked from 'package:readr':
##
## col_factor
plot(ZData, col = alpha("blue4", 0.5), pch = 19, las = 1)
or
Madrid
2 Guipúzcoa
Navarra
Lleida Tarragona
Girona
Barcelona Vizcaya
Baleares
rr
Burgos
PIB_HAB_04
1 Rioja
Zaragoza
Castellón Valladolid
Teruel Huesca
Segovia
Soria
Bo
−1 0 1 2
TASA_PARO_05
344 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
El paquete scales nos permite incorporar transparancia a los colores con la función alpha.
De esta forma si hay puntos que se suporponen se identifican mejor.
La función text escribe el nombre de la provincia en cada punto correspondiente.
Aparentemente habrá un grupo de provincias con alto PIB y baja Tasa de Paro, otro grupo
con bajo PIB y alta tasa de paro, y un grupo central de provincias con valores “medios” en
ambas variables. Lo vamos a verificar haciendo, primero, un clúster jerárquico.
Cluster jerárquico
07
En el análisis jerárquico no se determinan a priori los grupos a formar, sino que se muestran
sucesivas agrupaciones hasta llegar a un único grupo.
5-
El procedimiento comienza con el cálculo de la “matriz de distancias” entre todos los indi-
viduos. A partir de ahí, se buscan los dos individuos más próximos, y son agrupados en un
conglomerado, que se considera como una unidad indivisible o único individuo. Así se van
-0
agrupando unidades dos a dos, hasta llegar a una única unidad o conglomerado que contiene
a todos los individuos.
19
Las distancias pueden ser cuantificadas en base a muy distintas medidas. Además, existen
también múltiples criterios o métodos para agrupar los individuos. Todo ello confiere una
gran flexibilidad al análisis; pero también cierta dificultad a la hora de extraer conclusiones,
20
ya que distintos métodos pueden ofrecer muy diferentes resultados.
Vamos a utilizar la distancia euclídea, que es usualmente utilizada, y como método de aglo-
meración el método de Ward, que es el más utilizado. Este método crea grupos cohesionados
ya que poseen la mínima varianza interna posible.
or
La distancia euclídea es muy sensible a la escala de las variables, por lo que utilizaremos
los datos tipificados (“ZData”). Primero vamos a calcular todas las distancias y a crear la
ad
La matriz “d” obtenida es demasiado grande para escribirla en estas páginas, aunque pode-
mos consultarla en pantalla. Esta sería una muestra de la misma con las primeras distancias:
Bo
as.matrix(d)[1:3, 1:3]
Cluster Dendrogram
07
30
20
Distancia entre grupos
5-
10
0
-0 Las Palmas
Badajoz
Sevilla
Valladolid
Cádiz
Huelva
Vizcaya
Palencia
Álava
Madrid
Córdoba
Jaén
Málaga
Barcelona
Guadalajara
Murcia
Zamora
Alicante
Cantabria
A Coruña
Salamanca
Castellón
Lleida
León
Albacete
Ourense
Ávila
Toledo
Almería
Valencia
Baleares
Burgos
Cuenca
Lugo
Soria
Teruel
Ciudad Real
Pontevedra
Girona
Tarragona
Rioja
Zaragoza
Asturias
Santa Cruz de Tenerife
Huesca
Segovia
Guipúzcoa
Navarra
Cáceres
Granada
19
20
Cluster jerárquico por el método de Ward para las provincias
or
En la solución se establecen dos grandes grupos de provincias, cada uno de los cuáles se divide
en otros dos. Si nos quedamos con dos grupos, el de la derecha parece que sería demasiado
ad
posterior):
Numgrupos <- 3
Cluster Dendrogram
30
20
Distancia entre grupos
10
0
Las Palmas
Badajoz
Sevilla
Valladolid
Cádiz
Huelva
Vizcaya
Palencia
Álava
Madrid
Córdoba
Jaén
Málaga
Barcelona
Guadalajara
Murcia
Zamora
Alicante
Cantabria
A Coruña
Salamanca
Castellón
Lleida
León
Albacete
Ourense
Ávila
Toledo
Almería
Valencia
Baleares
Burgos
Cuenca
Lugo
Soria
Teruel
Ciudad Real
Pontevedra
Girona
Tarragona
Rioja
Zaragoza
Asturias
Santa Cruz de Tenerife
Huesca
Segovia
Guipúzcoa
Navarra
Cáceres
Granada
07
5-
Cluster jerárquico por el método de Ward para las provincias
-0
En esta ocasión hemos utilizado una paleta de colores de las proporcionadas por el paquete
RColorBrewer (ver la ayuda del paquete para ver más opciones).
Con la función cutree obtenemos el grupo al que pertenece cada provincia:
grupos <- cutree(fit, k = Numgrupos)
grupos
19
20
## A Coruña Álava Albacete
## 1 2 1
## Alicante Almería Asturias
## 1 1 1
or
## 1 2 1
## Rioja Salamanca Santa Cruz de Tenerife
## 2 1 1
## Segovia Sevilla Soria
## 2 3 2
## Tarragona Teruel Toledo
## 2 2 1
## Valencia Valladolid Vizcaya
## 1 1 2
## Zamora Zaragoza
07
## 1 2
Esto es muy útil para comprobaciones posteriores, vamos a guardar los grupos como un
5-
factor en el conjunto de datos:
Data$GRUPO <- factor(grupos)
-0
Se obtiene así la siguiente solución. El primer grupo se corresponde con las provincias con
19
mayores PIB y menores Tasas de Paro, el segundo con las provincias con menores PIB y
mayores Tasas de Paro, y el tercero es un grupo de provincias con una solución intermedia.
Gráficamente lo podemos visualizar con el diagrama de dispersión coloreado:
20
palette(brewer.pal(Numgrupos, "Dark2"))
plot(PIB_HAB_04 ~ TASA_PARO_05, col = alpha(GRUPO, 0.75), pch = 19, data = Data, las = 1
text(Data, rownames(Data), pos = 3, cex = .6)
Álava
or
Madrid
26000 Guipúzcoa
Navarra
Lleida Tarragona
Girona
Vizcaya
24000 Barcelona
BurgosBaleares
ad
PIB_HAB_04
22000 Rioja
Zaragoza
Castellón Valladolid
Teruel Soria Huesca
Segovia
20000 Palencia Cantabria Las Palmas
Valencia Almería
Alicante
18000 Guadalajara
Santa
Salamanca A Coruña
Cruz de Tenerife
Asturias
León
Murcia
rr
Ávila CiudadPontevedra
Real Huelva
Málaga Sevilla
Zamora
16000 Cuenca
Lugo
Toledo
Albacete
Cádiz
Ourense
Granada
Cáceres
14000 Córdoba Jaén
Badajoz
Bo
6 8 10 12 14 16 18
TASA_PARO_05
Cluster Dendrogram
2.0
1.0
Las Palmas
Height
Badajoz
0.0
Cádiz
Huelva
Sevilla
Valladolid
Vizcaya
Álava
Madrid
Córdoba
Jaén
Salamanca
Guadalajara
Murcia
Palencia
Málaga
Barcelona
Zamora
Alicante
Cantabria
A Coruña
León
Castellón
Lleida
Albacete
Ourense
Almería
Valencia
Ávila
Toledo
Baleares
Burgos
Cuenca
Lugo
Soria
Teruel
Ciudad Real
Pontevedra
Girona
Tarragona
Rioja
Zaragoza
Asturias
Santa Cruz de Tenerife
Huesca
Segovia
Guipúzcoa
Navarra
Cáceres
Granada
07
5-
d
hclust (*, "average")
-0
Obteniéndose una solución diferente, donde puede apreciarse que el grupo de provincias con
menores PIB y mayores Tasas de Paro se mantiene inalterado, mientras que hay un trasvase
de provincias desde el grupo de intermedias al de provincias con mayores PIB y menores
Tasas de Paro. Podemos verlo claramente si guardamos los grupos en el data.frame:
Data$GRUPO2 <- cutree(fit2, Numgrupos)
19
20
Data
07
## Murcia 8.009366 16470.40 1 1
## Navarra 5.647241 24744.35 2 2
## Ourense 10.488246 14256.99 1 1
5-
## Palencia 7.474227 19207.71 2 2
## Pontevedra 11.021749 15878.08 1 1
## Rioja 6.180243 21357.34 2 2
-0
## Salamanca 9.088000 16611.92 1 1
## Santa Cruz de Tenerife 10.492766 17240.08 1 1
##
##
##
Segovia
Sevilla
Soria
19
6.816655
13.857495
5.118602
19868.40
15547.25
19775.75
2
3
2
2
3
2
20
## Tarragona 7.062623 24428.12 2 2
## Teruel 4.662379 19834.13 2 2
## Toledo 9.117195 15146.87 1 1
## Valencia 8.586980 18461.51 1 2
## Valladolid 9.229526 20418.43 1 2
or
Y gráficamente:
palette(brewer.pal(Numgrupos, "Dark2"))
plot(PIB_HAB_04 ~ TASA_PARO_05, col = alpha(GRUPO2, 0.75), pch = 19, data = Data, las =
text(Data, rownames(Data), pos = 3, cex = .6)
350 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
Álava
Madrid
26000 Guipúzcoa
Navarra
Lleida Tarragona
Girona
Vizcaya
24000 Barcelona
BurgosBaleares
PIB_HAB_04
22000 Rioja
Zaragoza
Castellón Valladolid
Teruel Soria Huesca
Segovia
20000 Palencia Cantabria Las Palmas
Valencia Almería
Alicante
18000 Guadalajara
Santa
Salamanca A Coruña
Cruz de Tenerife
Asturias
León
Murcia
Ávila CiudadPontevedra
Real Huelva
Málaga Sevilla
Zamora
16000 Cuenca
Lugo
Toledo
Albacete
Cádiz
Ourense
Granada
Cáceres
14000 Córdoba Jaén
Badajoz
07
6 8 10 12 14 16 18
TASA_PARO_05
5-
En conclusión, vamos a considerar la existencia de 3 grupos homogéneos, y vamos a mejorar
su composición con el método no-jerárquico de k-medias, que tiene la ventaja de permitir la
salida de casos de grupos precedentes para su incorporación en otros distintos.
-0
Cluster no jerárquico
19
La técnica consiste sintéticamente en que se seleccionan k individuos o casos con algún
criterio (los más alejados, aleatorio, etc.), siendo k el número de grupos o conglomerados
que se desea formar. Estos constituirán los “centroides” iniciales o “semillas” de cada grupo.
20
Posteriormente se asignan los individuos a cada grupo, según su proximidad a los centroides.
En una nueva iteración, se recalcula el “centroide” de cada grupo (centro de gravedad del
grupo en cuestión) según los individuos que lo conforman en la etapa precedente, y estos
nuevos centroides se toman como referencia para asignar de nuevo todos los individuos o casos.
or
El proceso parará cuando las diferencias entre los centroides de una etapa y la predecesora
sean mínimas.
El criterio para asignar individuos a los grupos o conglomerados se basa en la “distancia
ad
euclídea” que tiene cada individuo con los centroides de los grupos. El problema es que la
distancia euclídea es muy sensible a las escalas de las variables, por lo que para eliminar este
efecto distorsionador conviene trabajar con variables tipificadas (matriz “ZData”). Recorde-
rr
mos que el método va a calcular tres grupos porque es el valor que le dimos a la variable
“Numgrupos”:
Bo
set.seed(1)
Data.km <- kmeans(ZData, Numgrupos)
Data.km
##
## Clustering vector:
## A Coruña Álava Albacete
## 3 1 3
## Alicante Almería Asturias
## 3 3 3
## Ávila Badajoz Baleares
## 3 2 1
## Barcelona Burgos Cáceres
## 1 1 2
07
## Cádiz Cantabria Castellón
## 2 3 1
## Ciudad Real Córdoba Cuenca
5-
## 3 2 3
## Girona Granada Guadalajara
## 1 2 3
-0
## Guipúzcoa Huelva Huesca
## 1 2 1
##
##
##
Jaén
2
Lleida
19 Las Palmas
3
Lugo
León
3
Madrid
20
## 1 3 1
## Málaga Murcia Navarra
## 3 3 1
## Ourense Palencia Pontevedra
## 3 1 3
or
## Zamora Zaragoza
## 3 1
##
## Within cluster sum of squares by cluster:
## [1] 9.312996 3.079765 7.777594
## (between_SS / total_SS = 79.4 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss"
## [5] "tot.withinss" "betweenss" "size" "iter"
352 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
## [9] "ifault"
La primera expresión fija la semilla de la sesión de R para que los resultados sean repro-
ducibles. La seguna realiza el análisis y lo asigna al objeto “Data.km”. En nuestro caso el
resultado es la formación de tres grupos de provincias de 22, 20 y 8 provincias. Al mostrar
el objeto “Data.km” nos viene información sobre las coordenadas de los centroides de cada
grupo (en valores de las variables clasificadoras tipificadas) y la asignación de cada provincia
concreta a un grupo.
Posteriormente se asigna al objeto “datasize” el tamaño de cada uno de los grupos obtenidos
(24, 18 y 8 respectivamente):
07
datasize <- Data.km$size
datasize
5-
## [1] 20 8 22
Vamos a guardar la clasificación hecha por el método de k-medias junto con la matriz de
-0
datos tipificados en el objeto ZDatag:
ZDatag <- data.frame(ZData, GRUPO = factor(Data.km$cluster))
19
Veamos gráficamente una representación de los grupos y de sus centros (estos últimos apa-
recen como “triángulos” sin etiqueta):
20
plot(PIB_HAB_04 ~ TASA_PARO_05, col = alpha(GRUPO, 0.75), pch = 19, data = ZDatag, las =
text(ZDatag, rownames(ZDatag), pos = 3, cex = .6)
points(Data.km$centers, col = 1:Numgrupos, pch = 17, cex = 1.5)
Álava
or
Madrid
2 Guipúzcoa
Navarra
Lleida Tarragona
Girona
Barcelona Vizcaya
ad
Baleares
Burgos
PIB_HAB_04
1 Rioja
Zaragoza
Castellón Valladolid
Teruel Huesca
Segovia
Soria
rr
−1 0 1 2
TASA_PARO_05
Podemos guardar la nueva clasificación en el conjunto de datos original, y ver qué provincias
se han ido moviendo con los distintos métodos:
5.7. PRÁCTICAS 353
07
## Asturias 10.240363 16983.65 1 1 3
## Ávila 8.844508 15734.05 1 1 3
## Badajoz 17.505084 12747.37 3 3 2
5-
## Baleares 7.215780 22317.21 2 2 1
## Barcelona 6.965572 23276.77 2 2 1
-0
## Burgos 6.730066 22127.51 2 2 1
## Cáceres 12.981455 13652.79 3 3 2
## Cádiz 17.652023 15237.39 3 3 2
##
##
##
Cantabria
Castellón
Ciudad Real
19
8.502295
7.315701
10.580164
19143.67
20468.05
15954.77
1
2
1
2
2
1
3
1
3
20
## Córdoba 14.767194 13341.00 3 3 2
## Cuenca 6.478210 15296.77 1 1 3
## Girona 7.331990 24040.89 2 2 1
## Granada 12.901665 13706.60 3 3 2
## Guadalajara 7.050285 16726.07 1 1 3
or
07
Nótese que los identificadores de grupo, al ser aleatorios no significan lo mismo, hay que
mirar los “compañeros”.
5-
Caracterización
-0
Una vez establecidos los distintos grupos de individuos o casos, es conveniente caracterizar
dichos grupos con base en las variables clasificadoras que hemos empleado. Una posibilidad
es estudiar el valor que, en cada una de estas variables, toma el “centroide” de cada grupo.
19
Como ya tenemos guardado el grupo en el data.frame Data, podemos calcular los “centroides”
de cada grupo haciendo la media del valor que toman los casos pertenecientes a cada grupo
20
en cada variable con la función aggregate. Para omitir las columnas GRUPO y GRUPO2,
en el lado izquierdo de la formula ponemos sólo las columnas que nos interesan unidas con
la función cbind:
aggregate(cbind(TASA_PARO_05, PIB_HAB_04) ~ GRUPO3, data = Data, FUN = mean)
or
## 2 2 15.182221 14176.16
## 3 3 9.505996 16471.34
Se observa que, para la primera Tasa de Paro, el centro del primer grupo toma un valor
rr
muy superior al de los otros dos grupos. En cambio con el PIB por habitante, la relación es
en sentido opuesto. En definitiva, la interpretación en este ejemplo es la que ya habíamos
Bo
adelantado al principio: el grupo 1 son provincias con mucho paro y poco PIB, el grupo 2
provincias con poco paro y mucho PIB y el grupo 3 son provincias intermedias en ambos
sentidos. Hay que tener en cuenta que la interpretación de los “centroides” ya no se hace
con las variables tipificadas; sino con las variables originales a fin de recuperar el sentido
económico de los valores.
Se puede acompañar la descripción de los grupos con unos diagramas de caja a partir del
siguiente código:
par(mfrow = c(1, 2))
boxplot(TASA_PARO_05 ~ GRUPO3, main = "Boxplot de la tasa de paro", col = 1:3, data = Da
boxplot(PIB_HAB_04 ~ GRUPO3, main = "Boxplot del PIB", col = 1:3, data = Data, las = 1)
5.7. PRÁCTICAS 355
18
26000
16
24000
TASA_PARO_05
14
PIB_HAB_04
22000
12
20000
07
10
18000
8 16000
5-
6 14000
-0
1 2 3 1 2 3
summary(modelo.aov)
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
TukeyHSD(modelo.aov)
Bo
Y del PIB:
modelo.aov2 <- aov(PIB_HAB_04 ~ GRUPO3, data = Data)
summary(modelo.aov2)
07
TukeyHSD(modelo.aov2)
5-
## 95% family-wise confidence level
##
## Fit: aov.default(formula = PIB_HAB_04 ~ GRUPO3, data = Data)
-0
##
## $GRUPO3
## diff lwr upr p adj
##
##
##
19
2-1 -8272.590 -10104.7218 -6440.459 0.0000000
3-1 -5977.408 -7330.5267 -4624.289 0.0000000
3-2 2295.182 487.0013 4103.364 0.0097075
20
Efectivamente, la agrupación tiene sentido para todas las variables. Si obtuviéramos dos
grupos para los que no hubiera diferencias en ninguna variable, deberíamos unir esos grupos.
Por otra parte, también se puede comprobar la consistencia de los grupos con un análisis de
la varianza múltiple (MANOVA).
or
En este ejemplo vamos a formar grupos de individuos en función de sus respestas a una
encuesta. En principio no sabemos el número de grupos a formar, por lo que comenzaremos
aplicando el método jerárquico.
rr
llamada “datos” donde se encuentran los ficheros de datos. El fichero se puede descargar a
la carpeta de datos del proyecto con la siguiente expresión:
download.file("http://emilio.lcano.com/b/adr/datos/encuesta_anonima_2018.RData",
"datos/encuesta_anonima_2018.RData")
Se recomienda en primer lugar limpiar el espacio de trabajo eliminando todos los objetos
existentes:
rm(list = ls())
Los datos se encuentran almacenados como archivo de datos de R, “.RData”. Para cargarlos
5.7. PRÁCTICAS 357
07
## $ id : int 6 7 1 3 16 4 15 2 8 11 ...
## $ sexo : Factor w/ 2 levels "Hombre","Mujer": 2 1 1 1 2 1 2 2 1 2 ...
## $ edad : num 23 23 22 23 23 20 32 24 21 21 ...
5-
## $ peso : num 59 77 95 60 65 91 80 61 81 60 ...
## $ altura : num 170 180 197 170 165 189 192 168 190 171 ...
-0
## $ pelo : Factor w/ 3 levels "castaño","moreno",..: 1 2 3 2 1 2 1 3 1 1 ...
## $ ojos : Factor w/ 2 levels "marrón","verde": 2 1 1 1 1 1 2 1 1 1 ...
## $ nota : num 6 8 5.9 7.1 6 8.72 7 8.03 7 7.2 ...
19
## $ hermanos : num 1 1 1 2 3 1 3 1 1 1 ...
## $ distancia : num 45 0.5 1 9 45 1.2 2 42 10 0.2 ...
## $ gafas : Factor w/ 3 levels "Gafas","Lentillas",..: 2 1 3 1 3 3 3 3 1 1 ...
20
## $ movil : num 1159 220 275 570 800 ...
## $ musica : Factor w/ 3 levels "Latina (reggaeton,...)",..: 2 3 2 3 2 1 3 1 1 2 ..
## $ cine : Factor w/ 4 levels "Comedia","Drama",..: 3 4 3 2 3 3 1 1 1 2 ...
## $ acceso : num 6.3 11.1 6.33 8.37 8 ...
## $ superficie: num 120 120 200 90 200 205 100 150 80 220 ...
or
Para aplicar los métodos solo con variables en escala métrica, vamos a obtener un subconjunto
de datos solo con estas variables.
Bo
Cluster Dendrogram
10
8
6
Height
a_15
07
4
a_14
a_2
a_11
a_5
2
a_9
a_4
a_8
a_6
a_16
a_1
a_12
5-
a_3
a_13
a_7
a_10
-0
19 d
hclust (*, "ward.D")
20
or
ad
rr
Bo
Parece que hay dos grandes grupos de tamaño similar. Veamos qué nos dice la función
NbClust sobre el número óptimo de grupos. Quitamos la variable “hermanos” porque da
problemas en el cálculo de algunos de los índices.
library(NbClust)
NbClust(data = encuestaz[, -c(5)],
distance = "euclidean",
method = "ward.D", max.nc = 5)
5.7. PRÁCTICAS 359
0.0025
Hubert statistic second differences
Hubert Statistic values
0.0100
0.0015
0.0090
07
0.0080
0.0005
5-
2.0 3.0 4.0 5.0 2.0 3.0 4.0 5.0
-0
Number of clusters Number of clusters
##
19
## *** : The Hubert index is a graphical method of determining the number of clusters.
## In the plot of Hubert index, we seek a significant knee that correspo
significant increase of the value of the measure i.e the significant
20
## index second differences plot.
##
0.038
Second differences Dindex Values
or
2.7
0.034
ad
Dindex Values
2.5
rr
0.030
2.3
Bo
0.026
2.1
07
## ***** Conclusion *****
##
## * According to the majority rule, the best number of clusters is 3
5-
##
##
## *******************************************************************
-0
## $All.index
##
##
##
KL CH Hartigan
2 1.0032 3.9113
3 1.5611 3.7603
19
CCC Scott Marriot TrCovW TraceW
3.2732 -1.2815 40.2842 6439393055 235.8926 128.9686
2.1126 -1.7898 96.3474 435793364 166.9860 104.5296
20
## 4 0.7867 3.3401 2.3850 -2.6630 132.0121 83386984 131.3204 89.9174
## 5 0.8906 3.2993 2.6938 -3.1400 203.9689 1451325 104.6044 75.0093
## Friedman Rubin Cindex DB Silhouette Duda Pseudot2 Beale
## 2 14.1230 1.2794 0.4462 1.8483 0.1429 0.7085 2.8798 2.6801
## 3 45.8743 1.5785 0.5998 1.5260 0.1649 0.6323 2.3262 3.4638
or
## 2 2.7809 0.8563
## 3 2.5197 0.8220
## 4 2.2960 0.6743
## 5 2.0971 0.6510
##
## $All.CriticalValues
## CritValue_Duda CritValue_PseudoT2 Fvalue_Beale
## 2 0.5044 6.8785 0.0057
## 3 0.4060 5.8524 0.0016
## 4 0.4458 6.2167 0.0029
## 5 0.1839 4.4371 1.0000
5.7. PRÁCTICAS 361
##
## $Best.nc
## KL CH Hartigan CCC Scott Marriot TrCovW
## Number_clusters 3.0000 2.0000 3.0000 2.0000 5.0000 3 3.0000
## Value_Index 1.5611 3.9113 1.1606 -1.2815 71.9568 5651193312 68.9066
## TraceW Friedman Rubin Cindex DB Silhouette Duda
## Number_clusters 3.0000 5.0000 3.0000 2.0000 5.0000 3.0000 2.0000
## Value_Index 9.8269 187.7865 -0.0426 0.4462 1.3198 0.1649 0.7085
## PseudoT2 Beale Ratkowsky Ball PtBiserial Frey McClain
## Number_clusters 2.0000 5.0000 4.0000 3.0000 3.0000 1 2.0000
07
## Value_Index 2.8798 -0.0346 0.3201 29.6411 0.5197 NA 0.9536
## Dunn Hubert SDindex Dindex SDbw
## Number_clusters 3.0000 0 4.0000 0 5.000
5-
## Value_Index 0.6101 0 0.8113 0 0.651
##
## $Best.partition
-0
## a_6 a_7 a_1 a_3 a_16 a_4 a_15 a_2 a_8 a_11 a_13 a_10 a_5 a_12 a_9
## 1 2 3 1 1 2 3 2 2 1 1 2 2 3 2
##
##
a_14
1 19
20
or
Parece que la mayoría de métodos indican que la mejor partición es en tres clústers, aunque
ad
también hay 6 que proponen 2. Vamos a utilizar 3, aunque uno de los grupos va a quedar
con muy pocos individuos.
c2 <- kmeans(scale(encuestam), 3)
rr
Bo
Vamos a utilizar las herramientas de visualización del paquete factoextra para visualizar
estos resultados.
library(factoextra)
fviz_dend(c1, 3)
362 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
Cluster Dendrogram
10.0
7.5
07
Height
5.0
5-
2.5
-0
0.0
19
a_5
a_9
a_7
a_10
a_2
a_4
a_8
a_6
a_16
a_14
a_11
a_3
a_13
a_15
a_1
a_12
20
fviz_cluster(c2, encuestaz, show.clust.cent = TRUE,
ellipse.type = "euclid", star.plot = TRUE, repel = TRUE)
or
ad
rr
Bo
5.7. PRÁCTICAS 363
Cluster plot
a_14
2
a_11
a_5
a_13
Dim2 (19.2%)
07
0 a_3 a 1
a_12 a 2
a_6 a_4
a_2 a 3
a_16
5-
a_1
a_8
−2
-0
−2
a_15
0
19Dim1 (26%)
2
20
Vamos ahora a utilizar las funciones del paquete cluster para realizar el análisis de con-
glomerados. El análisis jerárquico lo podemos hacer aglomerativo con la función agnes y
divisivo con la función diana.
or
## Order of objects:
## [1] a_6 a_16 a_3 a_13 a_11 a_2 a_7 a_10 a_9 a_5 a_4 a_8 a_1 a_12
Bo
## [9,] 8 -8
## [10,] 7 6
## [11,] 5 9
## [12,] 11 10
## [13,] 12 3
## [14,] 13 -16
## [15,] 14 -7
## Height:
## [1] 3.472835 4.286897 2.695980 3.664288 3.952748 4.890671 2.129214
## [8] 3.295431 3.621709 4.196403 3.610680 5.061828 3.133947 5.183904
07
## [15] 5.789377
##
## 120 dissimilarities, summarized :
5-
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 2.129 4.126 4.815 4.804 5.489 7.335
## Metric : euclidean
-0
## Number of objects : 16
##
##
##
##
Available components:
[1] "order"
[7] "method"
"height" "ac"
"order.lab" "data"
19 "merge" "diss" "call"
20
plot(enc_aglo)
a_6
a_16
a_3
5
ad
a_13
a_11
a_2
4
a_7
Height
rr
a_10
a_9
3
a_5
a_6
a_16
Bo
a_4
a_8
2
a_3
a_13
a_1
a_12
a_14
a_15
## Merge:
## [,1] [,2]
07
## [1,] -2 -12
## [2,] -4 -11
## [3,] -3 -14
## [4,] -1 -5
5-
## [5,] 1 -15
## [6,] -6 -9
-0
## [7,] 2 -8
## [8,] -13 -16
## [9,] 5 -10
##
##
##
[10,]
[11,]
[12,]
4
9
10
7
6
-7
19
20
## [13,] 11 3
## [14,] 13 8
## [15,] 12 14
## Order of objects:
or
## [1] a_6 a_16 a_3 a_13 a_2 a_15 a_7 a_10 a_9 a_11 a_4 a_8 a_1 a_12
## [15] a_5 a_14
## Height:
ad
## Divisive coefficient:
## [1] 0.5169334
##
Bo
a_6
7
a_16
a_3
6
a_13
a_2
a_15
5
a_7
Height
a_10
4
a_9
07
a_11
3
a_4
a_6
a_16
a_8
2
a_1
5-
a_12
a_5
a_14
-0
7.33 6 5 4 3 2 1 0
Como hemos visto antes que el número óptimo de grupos podría se tres, vamos a aplicar el
método no jerárquico con la función pam.
enc_pam <- pam(encuestaz, 3)
plot(enc_pam)
5.7. PRÁCTICAS 367
3
2
Component 2
1
0
07
−3 −2 −1
5-
-0
−4 −3 −2 −1 0 1 2
19
Component 1
These two components explain 45.21 % of the point variability.
Silhouette plot of pam(x = encuestaz, k = 3)
20
n = 16 3 clusters Cj
j : nj | avei∈Cj si
a_16
1 : 5 | 0.10
or
a_6
a_15
a_10
ad
a_4
a_7 2 : 9 | 0.13
rr
a_14
a_11
Bo
3 : 2 | 0.38
a_12
Si usamos la función clara el resultado es el mismo. Nótese cómo el tercer grupo queda solo
de dos observaciones.
368 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
summary(enc_pam)
## Medoids:
## ID edad peso altura nota hermanos distancia
## a_3 4 0.04461441 -0.8036996 -0.6763020 -0.01847943 0.9682458 -0.3827249
## a_7 2 0.04461441 0.3348748 0.2407177 0.93189139 -0.3227486 -0.4099993
## a_12 14 0.40152972 1.7413491 0.6992275 -1.39123729 -0.3227486 -0.4083950
## movil acceso superficie tv dormir fruta
## a_3 0.4134404 -0.3776986 -0.7983481 -0.9179232 1.0978876 -0.3453727
07
## a_7 -0.6403904 0.9294779 -0.1852168 0.6280527 0.2614018 0.1569876
## a_12 -0.3995148 -1.0336809 -0.5939710 1.6587033 1.0978876 0.4918945
## Clustering vector:
5-
## a_6 a_7 a_1 a_3 a_16 a_4 a_15 a_2 a_8 a_11 a_13 a_10 a_5 a_12 a_9
## 1 2 3 1 1 2 1 2 2 2 1 2 2 3 2
-0
## a_14
## 2
## Objective function:
##
##
##
build swap
2.840709 2.840709 19
20
## Numerical information per cluster:
## size max_diss av_diss diameter separation
## [1,] 5 4.570157 2.989552 5.846619 3.353387
## [2,] 9 4.241882 3.041072 6.908179 3.353387
## [3,] 2 3.133947 1.566974 3.133947 3.696745
or
##
## Isolated clusters:
ad
## L-clusters: character(0)
## L*-clusters: [1] 3
##
## Silhouette plot information:
rr
## a_3 1 2 0.112372070
## a_6 1 3 0.100817583
## a_13 1 2 0.080085862
## a_15 1 3 0.056177025
## a_10 2 1 0.269481539
## a_5 2 1 0.234655588
## a_4 2 3 0.197533221
## a_9 2 1 0.174684352
## a_7 2 3 0.144623549
## a_8 2 3 0.128483552
## a_14 2 3 0.017919681
5.7. PRÁCTICAS 369
## a_2 2 1 0.002472266
## a_11 2 3 0.001534164
## a_1 3 2 0.399033341
## a_12 3 1 0.364938929
## Average silhouette width per cluster:
## [1] 0.1033200 0.1301542 0.3819861
## Average silhouette width of total data set:
## [1] 0.1532475
##
## 120 dissimilarities, summarized :
07
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 2.129 4.126 4.815 4.804 5.489 7.335
## Metric : euclidean
5-
## Number of objects : 16
##
## Available components:
-0
## [1] "medoids" "id.med" "clustering" "objective" "isolation"
## [6] "clusinfo" "silinfo" "diss" "call" "data"
19
Podemos añadir la información del grupo al conjunto de datos original y caracterizar los
grupos:
20
resultado <- cbind(encuestam, grupo = enc_pam$clustering)
aggregate(. ~ grupo, resultado, mean)
or
table(resultado$grupo)
##
## 1 2 3
## 5 9 2
Los objetos obtenidos con el paquete cluster también se pueden visualizar con el paquete
factoextra, por ejemplo:
fviz_cluster(enc_pam)
370 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
Cluster plot
a_14
2
a_11 a_5
a_13
a_10
Dim2 (19.2%)
07
a_3 a 1
0 a_6
a_12 a_2 a 2
a_16 a_1 a_4
a 3
5-
a_8
−2
-0
−2
a_15
0
19Dim1 (26%)
2
20
or
ad
rr
Bo
Veamos el resultado que ofrecería el análisis cluster después de obtener las componentes
principales con el paquete FactoMineR.
par(mfrow=c(1,2))
library(FactoMineR)
HCPC(PCA(encuestam), nb.clust = 3)
5.7. PRÁCTICAS 371
1.5
6
1.0
a_15
4
movil
movil altura
altura
0.5
Dim 2 (19.18%)
Dim 2 (19.18%)
edad
edadhermanos peso
2
a_8 peso
a_16 a_1
fruta
superficie fruta
07
a_12 a_2 a_4
0.0
a_6 a_3 a_9
0
acceso
acceso
a_13 a_7 a_10 nota
tv
−0.5
a_11 dormir
tv dormir
a_5
−2
5-
distancia
distancia
a_14
−4
-0
−1.5
−6
Height
a_5
Bo
a_10
a_7
rr a_9
a_4
a_2
ad
a_8
a_14
a_6
or
a_13
a_3
a_16
Hierarchical Classification
20
a_11
Hierarchical Clustering
a_15
a_12
19
a_1
0.0 1.0 2.0
-0
5-
inertia gain
07
CAPÍTULO 5. ANÁLISIS CLUSTER CON R
5.7. PRÁCTICAS 373
cluster 1
cluster 2
cluster 3
3.0
2.5
07
2.0
height
Dim 2 (19.18%)
1.5
5-
1.0
4
a_15 2
-0
0.5
−4
a_14
−3 −2 −1 0
19 1
Dim 1 (26.03%)
2 3 4
20
Factor map
or
cluster 1
4
cluster 2 a_15
cluster 3
ad
2
a_8
Dim 2 (19.18%)
rr
a_16 a_4
a_12 a_1 a_2
a_6
a_3
0
a_7 a_9
Bo
a_10
a_13 a_11 a_5
−2
a_14
−4
−4 −2 0 2 4 6
Dim 1 (26.03%)
374 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
07
## 9 "$desc.ind$para"
## 10 "$desc.ind$dist"
## 11 "$call"
5-
## 12 "$call$t"
## description
## 1 "dataset with the cluster of the individuals"
-0
## 2 "description of the clusters by the variables"
## 3 "description of the cluster var. by the continuous var."
##
##
##
19
4 "description of the clusters by the continuous var."
5 "description of the clusters by the dimensions"
6 "description of the cluster var. by the axes"
20
## 7 "description of the clusters by the axes"
## 8 "description of the clusters by the individuals"
## 9 "parangons of each clusters"
## 10 "specific individuals"
## 11 "summary statistics"
or
Por último, vamos a realizar un análisis cluster utilizando todas las variables: tanto las que
están en escala métrica como los atributos. Para ello, tenemos que calcular la matriz de
Bo
0.2
Component 2
0.0
07
−0.2
5-
−0.4
-0
−0.4 −0.2 0.0 0.2
19
Component 1
These two components explain 39.51 % of the point variability.
20
Parece que al añadir las variables de tipo atributo hemos mejorado la separación de los
grupos.
or
ad
rr
Bo
376 CAPÍTULO 5. ANÁLISIS CLUSTER CON R
07
5-
-0
19
20
or
ad
rr
Bo
Capítulo 6
07
Análisis de correspondencias con R
5-
-0
6.1. Introducción al análisis de correspondencias
19
El análisis de correspondencias es una técnica de análisis multivariante de interdependencias,
es decir, todas las variables siguen el mismo papel, sin que unas expliquen a otras. En esta
técnica estudiamos relaciones entre variables en escala nominal, es decir, variables cualita-
20
tivas o atributos que pueden tomar varios niveles o categorías en las que clasificamos a las
observaciones.
bidimensional, la relación entre las categorías de los atributos. en el caso de dos atributos,
que se resumen numéricamente mediante tablas de contingencia, la representación gráfica
muestra las distancias entre los niveles a partir de las frecuencias.
ad
cada uno de los cuales con varios niveles, en un contexto generalmente bidimensional.
Bo
Los datos de atributos se suelen resumir mediante tablas de de doble entrada, o de contin-
gencia, que representan las frecuencias absolutas conjuntas, es decir, el número de individuos
que presentan cada combinación de las categorías de los atributos. Por ejemplo, la tabla 6.1
muestra una tabla de contingencia para dos atributos (A y B) con dos niveles cada uno
(A1 , A2 y B1 , B2 respectivamente); nij es el número de observaciones que presentan el nivel i
del atributo A y el nivel j del atributo B; ni. y n.j son las frecuencias marginales del atributo
Ai y del atributo Bj respectivamente; N es el número total de observaciones, que también
se puede denotar por n.. .
Las frecuencias marginales se calculan como las sumas por filas y por columnas, correspon-
diendo el índice i a las filas, y el índice j a las columnas.
377
378 CAPÍTULO 6. ANÁLISIS DE CORRESPONDENCIAS CON R
Tabla 6.1: Tabla de doble entrada para el atributo A (filas) y el atributo B (columnas)
B1 B2
A1 n11 n12 n1.
A2 n21 n22 n2.
n,1 n,2 N
07
relación. Sobre los datos observados, podemos calcular un estadístico que mida el grado
de relación entre los atributos, en concreto el coeficiente de contingencia chi-cuadrado.
Posteriormente se puede realizar un contraste de hipótesis basado en el coeficiente de con-
5-
tingencia a través de la distribución Chi-cuadrado.
Para comprobar la relación entre atributos, vamos a utilizar el concepto contrario, es de-
-0
cir, la independencia entre variables. Si los atributos no están relacionados, entonces serán
independientes. Recordemos la definición de independencia basada en tablas de frecuencias:
fij =
nij
N
= 19
ni. n.j
N N
· = fi. · f.j ∀i, j.
Es decir, dos variables, en este caso atributos, son independientes si las frecuencias relativas
20
conjuntas fij son igual al producto de las frecuencias relativas marginales, fi · f.j .
Pero estamos trabajando con muestras de datos, y esta igualdad es muy difícil que se dé
exactamente en la realidad. Pero bajo el supuesto de que los atributos fuesen independientes,
or
y por tanto no estuvieran relacionados, podríamos obtener las frecuencias absolutas esperadas
nij de la siguiente forma:
ad
el producto de las frecuencias absolutas marginales, ni. · n.j , dividido por la frecuencia total
N . Con las frecuencias observadas y las esperadas, podemos calcular el siguiente estadístico:
Bo
∑∑ (nij − Eij )2
χ2 = ,
i j Eij
que valdrá cero si los atributos no están relacionados (frecuencias observadas igual a las
esperadas). A mayor valor del coeficiente, mayor grado de asociación.
El coeficiente de contingencia se distribuye como una Chi-cuadrado con (r −1)·(c−1) grados
de libertad, donde r es el número de categorías fila y c es el número de categorías columna.
Por tanto, se puede realizar el contraste de hipótesis:
H0 : No hay relación entre los atributos
6.2. ASOCIACIÓN ENTRE ATRIBUTOS 379
07
χ2 ⇝ χ2(r−1)·(c−1) .
El contraste tiene ciertas limitaciones que hay que tener en cuenta, la población mínima N
5-
debe ser de 20 elementos, y la estimación de cada frecuencia esperada Eij debe ser mayor o
igual a 5.
-0
Se estudia en 164 individuos los atributos “Estudios”, con dos niveles: “aprueba”
19
y “no aprueba”, y “Empleo”, con dos niveles: “trabaja” y “no trabaja”. Las frecuencias
absolutas aparecen en la tabla 6.2. El código a continuación calcula los valores esperados y
el coeficiente de contingencia, que se compara con el valor teórico para un nivel de confianza
20
del 95 %, inferior al valor empírico por lo que se rechaza la hipótesis nula para ese nivel
de confianza. Visto de otra forma, el p-valor del contraste es muy inferior a 0.01, por lo
que podemos asegurar con mucha confianza que los atributos “Estudios” y “Empleo” están
relacionados, o lo que es lo mismo, no son independientes. El código a continuación crea
la tabla de frecuencias y realiza los cálculos, primero paso a paso y después utilizando la
or
función chisq.test de R.
ad
A partir de las tablas de frecuencias, calculamos y guardamos los datos que aparecen en las
Bo
fórmulas:
N <- sum(absolutas)
## Marginales:
ma.empleo <- rowSums(absolutas)
ma.estudios <- colSums(absolutas)
mr.empleo <- rowSums(relativas)
mr.estudios <- colSums(relativas)
380 CAPÍTULO 6. ANÁLISIS DE CORRESPONDENCIAS CON R
Si los atributos no estuvieran relacionados, las siguientes dos matrices sería iguales:
mr.empleo %*% t(mr.estudios)
## Aprueba No aprueba
## [1,] 0.2208507 0.1815883
## [2,] 0.3279298 0.2696312
relativas
## Estudios
07
## Empleo Aprueba No aprueba
## Trabaja 0.1402439 0.2621951
## No trabaja 0.4085366 0.1890244
5-
Ya hemos dicho que esto es casi imposible. Vamos a calcular las frecuencias esperadas:
esperadas <- (ma.empleo %*% t(ma.estudios))/N
-0
esperadas
## Aprueba No aprueba
## [1,] 36.21951
## [2,] 53.78049
29.78049
44.21951 19
Ahora tenemos todos los datos para calcular el coeficiente de contingencia:
20
chicuadrado <- sum(((absolutas - esperadas)^2)/esperadas)
chicuadrado
## [1] 17.89444
or
## [1] 3.841459
Mucho menor, por lo que el estadístico empírico cae en la región de rechazo, y para un nivel
rr
de confianza del 95 % rechazamos la independencia entre los dos atributos. Nos lo confirma
el valor tan pequeño del p-valor obtenido para ese valor del coeficiente de contingencia:
Bo
## [1] 2.340477e-05
A modo ilustrativo se han mostrado todos los pasos del contraste, pero la práctica habitual
es realizarlo de una vez con la función chisq.test:
chisq.test(absolutas, correct = FALSE)
##
## Pearson's Chi-squared test
##
6.3. ANÁLISIS DE CORRESPONDENCIAS SIMPLES 381
## data: absolutas
## X-squared = 17.894, df = 1, p-value = 2.335e-05
El argumento correct controla si se aplica la corrección por continuidad de Yates, aquí se
puesto a FALSE para verificar el resultado anterior, aunque para tablas 2 × 2 es adecuado
utilizarlo (véase la ayuda de la función).
07
nos va a servir para determinar unas coordenadas a cada categoría de cada atributo. Estas
coordenadas nos proporcionarán una distancia, que representaremos gráficamente en un
gráfico bidimensional, en ocasiones conocido como mapa perceptual. La distancia utilizada
5-
para ubicar las categorías en las coordenadas, será la distancia chi-cuadrado.
-0
6.3.1. Análisis de correspondencias simples paso a paso
Para la aplicación del método, vamos a dar por hecho que en la tabla de contingencia el
El primer paso consiste en obtener los perfiles de fila y de columna. Los perfiles son vectores
20
(de fila y de columna) que contienen las frecuencias relativas condicionadas a esa fila o
columna. Es decir, en cada fila, dividimos la frecuencia absoluta conjunta entre la frecuencia
marginal de la fila o columna. Así, los elementos del perfil fila serán:
or
nik nik
pik = = ∑
c , k = 1, . . . , r,
ni. nij
j=1
ad
( )
pi1 pi2 . . . pic .
rr
nkj nkj
pkj = = ∑
r , k = 1, . . . , c,
n.j nij
i=1
p1j
p2j
.. .
.
prj
382 CAPÍTULO 6. ANÁLISIS DE CORRESPONDENCIAS CON R
Además de los perfiles, tenemos que calcular las masas de las filas y de las columnas. En
este caso, tenemos un solo dato por fila y columna. Las masas son las frecuencias relativas
marginales fi. y f.j . Así, la masa de la fila i es:
∑
c
nij
ni. j=1
mi. = fi. = = ∑∑ ,
n.. nij
i j
07
∑
r
nij
n.j i=1
mj. = f.j = = ∑∑ .
5-
n.. nij
i j
Con las masas y los perfiles calculamos las distancias chi-cuadrado entre las categorías de
-0
un atributo. Así, la distancia chi-cuadrado entre dos categorías i e i′ del atributo fila son:
dii′ =
19 ∑
c
k=1
(pik − pi′ k )2
m.k
,
20
y la distancia chi-cuadrado entre dos categorías j y j ′ del atributo columna son:
∑
r
(pkj − pkj ′ )2
d jj ′ = .
k=1 mk.
or
Es decir, para calcular la distancia, por ejemplo entre filas, restamos los c perfiles de las dos
filas (columnas), elevamos al cuadrado esos valores y los dividimos por la masa de su columna.
Finalmente se suman todos los valores (uno por columna). De forma análoga, para calcular
ad
la distancia entre atributos de columna, se restan los perfiles de cada fila, su cuadrado se
divide por su masa de fila, y se suman los valores de cada fila.
rr
El código a continuación calcula los perfiles y las masas del ejemplo con los atributos
“Empleo” y “Estudios” visto anteriormente.
Bo
Perfiles fila1 :
pfila <- absolutas / rowSums(absolutas)
pfila
## Estudios
## Empleo Aprueba No aprueba
## Trabaja 0.3484848 0.6515152
## No trabaja 0.6836735 0.3163265
1
R recicla el vector del denominador por columnas, de forma que el cálculo es adecuado sin más.
6.3. ANÁLISIS DE CORRESPONDENCIAS SIMPLES 383
Perfiles columna2 :
pcolumna <- absolutas / rep(colSums(absolutas), each = 2)
pcolumna
## Estudios
## Empleo Aprueba No aprueba
## Trabaja 0.2555556 0.5810811
## No trabaja 0.7444444 0.4189189
Masas fila:
07
mfila <- rowSums(absolutas)/N
mfila
5-
## Trabaja No trabaja
## 0.402439 0.597561
-0
Masa columna:
mcolumna <- colSums(absolutas)/N
mcolumna
##
##
Aprueba No aprueba
0.5487805 0.4512195
19
20
Distancia entre filas (trabajan/no trabajan):
sum((diff(pfila)^2)/mcolumna)
or
## [1] 0.4537243
Distancia entre columnas (aprueban/no aprueban):
ad
sum((diff(t(pcolumna))^2)/mfila)
## [1] 0.4406439
rr
Para representar gráficamente las distancias entre las categorías de los dos atributos, vamos
a utilizar el método de descomposición en valores singulares de la llamada matriz de dis-
crepancias. La matriz de discrepancias C es una matriz con las mismas dimensiones que la
Bo
nij − Eij
cij = √ .
Eij
C = U DV t ,
2
Aquí hay que repetir las sumas por columnas para que las divisiones se hagan correctamente.
384 CAPÍTULO 6. ANÁLISIS DE CORRESPONDENCIAS CON R
donde D es una matriz diagonal r × r cuyos elementos son las raíces cuadradas de los r
autovalores de CC t , U es una matriz cuyas columnas son los r autovectores de CC t y V es
una matriz cuyas filas son los primeros r autovectores de C t C. Además, U t U = I y V t V = I.
Las matrices U y V se utilizan para calcular las coordenadas de las categorías que después
se representarán gráficamente.
07
Cálculo matriz de discrepancias:
discrepancias <- (absolutas - esperadas)/sqrt(esperadas)
5-
discrepancias
## Estudios
-0
## Empleo Aprueba No aprueba
## Trabaja -2.196565 2.422420
## No trabaja 1.802615 -1.987964
19
Descomposición (de la matriz D solo se muestra la diagonal):
20
descomposicion <- svd(discrepancias)
descomposicion
## $d
## [1] 4.230182e+00 2.983075e-16
or
##
## $u
## [,1] [,2]
ad
## $v
## [,1] [,2]
Bo
## [,1] [,2]
## [1,] -2.196565 2.422420
3
Cuando la tabla de contingencia no es cuadrada, en general no se cumple la igualdad, aunque las
coordenadas se calcularán exactamente igual.
6.3. ANÁLISIS DE CORRESPONDENCIAS SIMPLES 385
07
para indicar el número de dimensiones. Por defecto toma el número máximo de dimensiones,
lo que siempre es adecuado en un primer análisis para deteminar cuántas son finalmente
adecuadas. La otra opción en R es la función CA del paquete FactoMineR (Husson et al.,
5-
2018), que tiene otras muchas funciones para análisis multivariante. En este capítulo vamos
a ilustrar primero el uso del paquete ca. Con el análisis de correspondencias buscamos reducir
la dimensión. De forma similar al análisis de componentes principales (véase el capítulo 4),
-0
por defecto se calculan todas las dimensiones posibles. En este caso, el número máximo de
dimensiones es el número de categorías del atributo que menos tiene menos uno, es decir:
19
mı́n{(c − 1), (r − 1)}.
20
La variabilidad explicada por cada dimensión se expresa como la inercia. Así, la primera
dimensión tendrá la mayor inercia, la segunda menos, etc., y nos quedaremos con un número
de dimensiones que expliquen suficientemente todos los datos, y sea fácilmente representable
e interpretable. Idealmente nos quedaremos con dos dimensiones. Un criterio numérico para
or
decidir cuántas dimensiones se deberían retener (Bendixen, 1995) es tomar aquellos cuya
contribución sea mayor que el máximo valor entre 1/(c − 1) y 1/(r − 1):
{ }
ad
1 1
máx , × 100 %.
c−1 r−1
Para cada dimensión tendremos un porcentaje de inercia sobre el total, y un acumulado.
rr
Además de las inercias de las nuevas dimensiones, tendremos, tanto para filas como para
columnas: las masas, la distancia chi-cuadrado al centroide, las inercias (contribución a la
Bo
inercia total de cada categoría) y las coordenadas de cada categoría. Estas inercias se calculan
como la masa de la categoría multiplicada por la distancia al centroide al cuadrado. A su
vez, el centroide es la media ponderada de las coordenadas de todas las categorías.
library(ca)
corres1 <- ca(absolutas, nd = 1)
corres1
##
## Principal inertias (eigenvalues):
## 1
## Value 0.109112
## Percentage 100%
##
07
##
## Rows:
## Trabaja No trabaja
5-
## Mass 0.402439 0.597561
## ChiDist 0.402511 0.271079
-0
## Inertia 0.065201 0.043911
## Dim. 1 -1.218544 0.820652
##
##
##
##
Columns:
Aprueba No aprueba
19
20
## Mass 0.548780 0.451220
## ChiDist 0.299524 0.364286
## Inertia 0.049234 0.059879
## Dim. 1 0.906765 -1.102822
or
corres1$colcoord
## Dim1
ad
## Aprueba 0.9067647
## No aprueba -1.1028219
corres1$rowcoord
rr
## Dim1
## Trabaja -1.2185436
Bo
## No trabaja 0.8206518
with(corres1,{
plot(x = c(rowcoord, colcoord),
y = rep(0, 4),
type = "n",
xlim = c(-2, 1),
main = "Correspondencias Empleo - Estudios",
xlab = "Distancia", ylab = "",
las = 1)
text(x = c(rowcoord, colcoord),
6.3. ANÁLISIS DE CORRESPONDENCIAS SIMPLES 387
1.0
Empleo
Estudios
0.5
No aprueba Aprueba
Trabaja No trabaja
0.0
07
−0.5
5-
−1.0
-0
−2.0 −1.5 −1.0 −0.5 0.0 0.5 1.0
19 Distancia
})
Además del gráfico bidimensional obtenido por defecto, se pueden realizar otras visualizacio-
nes y análisis de los resultados del análisis de correspondencias. Vamos a ilustrar algunos de
rr
library(FactoMineR)
data(hobbies)
388 CAPÍTULO 6. ANÁLISIS DE CORRESPONDENCIAS CON R
## profesion
07
## estado.civil No cualificado Obrero Técnico Encargado Dirección Empleado
## Soltero 242 242 109 144 215 603
## Casado1 347 660 218 424 623 1247
5-
## Viudo 108 84 10 61 58 263
## Divorciado 72 104 44 70 92 312
-0
## Casado+ 23 71 20 36 64 127
## profesion
## estado.civil Otros
##
##
##
Soltero
Casado1
Viudo
54
112
17
19
20
## Divorciado 18
## Casado+ 11
En primer lugar, comprobamos si hay relaciones entre los atributos:
or
chisq.test(frecuencias)
##
ad
Efectivamente, el p-valor es muy bajo, prácticamente cero, por lo que aceptamos que hay
relación entre los atributos con una confianza muy alta. Aunque vemos numéricamente cómo
Bo
están distribuidas las frecuencias, por ejemplo el grupo más numeroso es el de los empleados
casados solo una vez. podemos hacer una visualización gráfica de la tabla de contingencia
como la del gráfico 6.2 que se crea con el siguiente código usando el paquete gplots (Warnes
et al., 2019):
library(gplots)
balloonplot(frecuencias, main = "Muestra aficiones",
label = FALSE, show.margins = TRUE)
Muestra aficiones
07
Encargado 735
Dirección 1052
Empleado 2552
5-
Otros 212
1609 3631 601 712 352 6905
-0
Figura 6.2: Visualización de la tabla de contingencia del ejemplo de aficiones
19
bidimensional (Figura 6.3), realiza un contraste chi-cuadrado de independencia, y muestra
los objetos disponibles en el objeto creado. Con la función summary podemos obtener las
20
inercias de cada dimensión, porcentaje explicado y acumulado. Para filas y columnas, tenemos
también las incercias y otras medidas de la importancia (ctr y cos2, el cálculo difiere de la
función ca).
library(FactoMineR)
or
## name description
## 1 "$eig" "eigenvalues"
## 2 "$col" "results for the columns"
## 3 "$col$coord" "coord. for the columns"
## 4 "$col$cos2" "cos2 for the columns"
## 5 "$col$contrib" "contributions of the columns"
## 6 "$row" "results for the rows"
## 7 "$row$coord" "coord. for the rows"
## 8 "$row$cos2" "cos2 for the rows"
## 9 "$row$contrib" "contributions of the rows"
## 10 "$call" "summary called parameters"
390 CAPÍTULO 6. ANÁLISIS DE CORRESPONDENCIAS CON R
CA factor map
0.20
0.10 Técnico
Dim 2 (13.13%)
Soltero
No cualificado Otros
07
Dirección
0.00
Empleado ObreroCasado1
Encargado
Divorciado
5-
Casado+
−0.10
Viudo
-0
−0.4 −0.3 −0.2 −0.1 0.0 0.1 0.2
19 Dim 1 (75.77%)
summary(corres2, ncp = 2)
ad
##
## Call:
## CA(X = frecuencias)
##
rr
## The chi square of independence between the two variables is equal to 158.0085 (p-valu
##
Bo
## Eigenvalues
## Dim.1 Dim.2 Dim.3 Dim.4
## Variance 0.017 0.003 0.002 0.000
## % of var. 75.768 13.131 9.954 1.146
## Cumulative % of var. 75.768 88.899 98.854 100.000
##
## Rows
## Iner*1000 Dim.1 ctr cos2 Dim.2 ctr cos2
## Soltero | 4.645 | -0.112 16.948 0.633 | 0.085 56.421 0.365 |
## Casado1 | 5.071 | 0.096 27.835 0.952 | -0.007 0.748 0.004 |
## Viudo | 9.104 | -0.300 45.210 0.861 | -0.103 30.748 0.101 |
6.3. ANÁLISIS DE CORRESPONDENCIAS SIMPLES 391
07
## Empleado | 3.404 | -0.077 12.583 0.641 | -0.036 15.776 0.139 |
## Otros | 0.178 | 0.009 0.013 0.013 | 0.061 3.809 0.642 |
5-
Con las dos primeras dimensiones se explica casi el 90 % de la inercia, por lo que el gráfico
bidimensional va a ser muy adecuado. Según el criterio citado anteriormente, solo el primer
autovalor tiene una contribución mayor del 25 % (máximo entre 1/(c − 1) y 1/(r − 1)), por
-0
lo que dos son suficientes. Podemos visualizar las contribuciones de las dimensiones con un
gráfico de sedimentación (screeplot) como el que se muestra en la figura 6.4, a través del
19
paquete factoextra (Kassambara and Mundt, 2017).
max.porc <- max(1/(dim(frecuencias)-1)*100)
library(factoextra)
20
fviz_screeplot(corres2) +
geom_hline(yintercept = max.porc, linetype = 2, color = "red") +
labs(title = "Gráfico de sedimentación", x = "Dimensiones",
y = "Porcentaje de variabilidad explicada")
or
En el gráfico bidimensional vemos cómo los no cualificados están más próximos de los sol-
teros, los divorciados de los empleados, y los casados de profesiones de dirección, manuales
ad
y encargados. El grupo de viudos y el de técnicos están muy alejados de todos los demás.
Podemos visualizar las categorías fila o columna por separado, para buscar afinidades. Por
ejemplo con el siguiente código usando el paquete factoextra (figura ?(fig:carows)):
rr
La medida cos2 (coseno al cuadrado) mide la calidad de representación de las filas o columnas
Bo
de cada categoría. Podemos visualizar esta intensidad mediante una gradación de colores en
el gráfico como en la figura 6.6:
fviz_ca_row(corres2, col.row = "cos2",
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
repel = TRUE)
El valor contrib de cada categoría y columna, mide el grado de contribución a cada una de las
dimensiones. Las podemos visualizar con la función fviz_contrib del paquete factoextra.
Con el argumento axes indicamos de qué dimensiones queremos representar la contribución,
que pueden ser más de una conjuntamente como en el siguiente ejemplo. La línea roja indica
392 CAPÍTULO 6. ANÁLISIS DE CORRESPONDENCIAS CON R
07
Gráfico de sedimentación
5-
Porcentaje de variabilidad explicada
-0
60
40
19
20
20
or
ad
1 2 3 4
rr
Dimensiones
07
Row points − CA
Soltero
5-
-0
0.05
19
Dim2 (13.1%)
0.00
20
Casado1
−0.10
Viudo
−0.3 −0.2 −0.1 0.0 0.1
rr
Dim1 (75.8%)
07
Row points − CA
Soltero
5-
-0
0.05
cos2
19
Dim2 (13.1%)
0.00 0.8
20
Casado1
0.6
0.4
−0.10
Viudo
−0.3 −0.2 −0.1 0.0 0.1
rr
Dim1 (75.8%)
40
30
Contributions (%)
07
20
5-
10
-0
0
19
o
o1
ro
o+
do
ud
lte
ad
ia
ad
Vi
rc
So
as
as
ivo
C
C
20
D
Figura 6.7: Visualización de la contribución de las categorías fila a las dos primeras dimen-
siones
or
la contribución esperada si las contribuciones fueran uniformes. Vemos en la figura 6.7 que
la categoría que más contribuye a las dos dimensiones es “Viudo”.
ad
Estas contribuciones también las podemos visualizar conjuntamente con el paquete corrplot
rr
El mismo análisis que se ha hecho para las categorías fila, se puede también hacer para las ca-
tegorías columna. Además, las funciones del paquete factoextra también se pueden aplicar
a objetos creados con el paquete ca y otros utilizados para análisis de correspondencias.
Realice la práctica 6.1 cuyo guión se encuentra en el apartado 6.5 para realizar
análisis de correspondencias simple sobre un ejemplo de color de ojos y pelo de una muestra
de individuos.
396 CAPÍTULO 6. ANÁLISIS DE CORRESPONDENCIAS CON R
07
Dim 1
Dim 2
Dim 3
Dim 4
5-
80.63
Soltero 72.58
-0
64.53
Casado1
19 56.48
48.43
20
Viudo 40.38
32.33
or
Divorciado 24.28
ad
16.23
Casado+ 8.18
rr
0.13
Figura 6.8: Visualización de la contribución de las categorías fila a todas las dimensiones
Bo
6.4. ANÁLISIS DE CORRESPONDENCIAS MÚLTIPLE 397
Realice la práctica 6.2. En este caso no existe guión, consulte el apartado 6.5 para
realizar análisis de correspondencias simple sobre algunos atributos de los datos de encuesta
utilizados en el capítulo 5.
07
asociación de atributos dos a dos. Pero si queremos estudiar dicha asociación para más de dos
atributos conjuntamente, tenemos que utilizar el análisis de correspondencias múltiple. La
idea es la misma: obtener unas coordenadas en un espacio de dimensión reducida (idealmente
5-
dos) para cada categoría de cada uno de los atributos. Para obtener estas coordenadas, uno
de los métodos utilizados es disponer los datos en forma de matriz indicadora, de forma que
para cada atributo tenemos tantas columnas como categorías, y los datos son indicadores de
-0
presencia o ausencia (1 y 0 respectivamente) de la características en cada observación. Por
ejemplo para tres atributos con tres categorías cada uno:
19
20
Atributo A Atributo B Atributo C A1 A2 A3 B1 B2 B3 C1 C
or
Z = ⌊Z1 , Z2 , . . . , Zj , . . . , Zp ⌋,
rr
siendo Zj las matrices de los p atributos que forman Z. Con esta matriz se forma la llamada
matriz de Burt:
Bo
B = Z t Z.
Las coordenadas de cada modalidad se obtendrán a partir de los autovalores y autovectores
de Burt.
Vamos a añadir la información de las aficiones y las otras dos variables de atributo
al conjunto de datos. A continuación se explica el código a utilizar para el análisis.
07
"Jardinería", "Punto", "Cocinar", "Pescar",
"TV", "Sexo", "Edad")
5-
Aplicamos el análisis a los datos originales con el paquete ca. El argumento reti nos sirve
para retener la matriz indicadora.
corres3 <- mjca(aficiones, lambda = "Burt", reti = FALSE)
-0
corres3
##
##
##
Eigenvalues:
1 2 3
19 4 5 6 7
20
## Value 0.032615 0.010208 0.00886 0.004362 0.003454 0.002754 0.002537
## Percentage 29.31% 9.17% 7.96% 3.92% 3.1% 2.47% 2.28%
## 8 9 10 11 12 13 14
## Value 0.002456 0.002368 0.002331 0.002256 0.002235 0.00213 0.002118
## Percentage 2.21% 2.13% 2.09% 2.03% 2.01% 1.91% 1.9%
or
## 15 16 17 18 19 20 21
## Value 0.00203 0.00201 0.001952 0.0019 0.001877 0.00181 0.001697
ad
## 29 30 31 32 33 34 35
## Value 0.001076 0.000942 0.00092 0.000882 0.000788 0.000746 0.000699
Bo
07
## ChiDist 0.395338 0.220893 0.378707 0.253179 0.254893 0.237236
## Inertia 0.002691 0.001412 0.002420 0.001476 0.001480 0.001546
## Dim. 1 -1.892238 1.022578 -1.750577 0.856097 -0.862822 1.083658
5-
## Dim. 2 1.105876 -0.451695 0.791777 0.984424 -0.982149 0.507331
## Viajar:1 Tocar.música:0 Tocar.música:1 Coleccionar:0
## Mass 0.018345 0.037859 0.007953 0.041100
-0
## ChiDist 0.354488 0.119669 0.569460 0.076595
## Inertia 0.002305 0.000542 0.002579 0.000241
##
##
##
Dim. 1
Dim. 2
-1.619545
-0.743817 19
0.482275
0.060386
-2.289035
-0.251118
0.150601
0.084760
Coleccionar:1 Voluntariado:0 Voluntariado:1 Mecánica:0 Mecánica:1
20
## Mass 0.004712 0.038799 0.007013 0.026486 0.019326
## ChiDist 0.664750 0.102408 0.564665 0.225029 0.307082
## Inertia 0.002082 0.000407 0.002236 0.001341 0.001822
## Dim. 1 -1.302468 0.296837 -1.634708 0.711900 -0.972878
## Dim. 2 -0.678051 0.276685 -1.489569 -0.011683 0.030961
or
07
## Dim. 2 -0.882572 3.392412 -0.902882
## estado.civil:Viudo estado.civil:Divorciado estado.civil:Casado+
## Mass 0.004001 0.004333 0.002208
5-
## ChiDist 0.814808 0.676185 0.962111
## Inertia 0.002656 0.001981 0.002043
## Dim. 1 2.069383 0.105757 -0.060455
-0
## Dim. 2 -2.865332 -0.883137 -1.144997
## profesion:No cualificado profesion:Obrero profesion:Técnico
##
##
##
Mass
ChiDist
Inertia
19
0.004353
0.699801
0.002132
0.006381
0.572086
0.002088
0.002204
0.964406
0.002050
20
## Dim. 1 1.670254 1.099295 -0.605833
## Dim. 2 1.179245 1.196346 1.644403
## profesion:Encargado profesion:Dirección profesion:Empleado
## Mass 0.004040 0.005782 0.014027
## ChiDist 0.699459 0.634858 0.341206
or
## Inertia 0.002017
## Dim. 1 -0.234321
Bo
## Dim. 2 -0.496896
Nótese cómo al aumentar el número de factores la cantidad de información a interpretar
también lo hace. Aquí lo relevante es que las tres primeras dimensiones explican el 46 %
de la asociación entre categorías. En general, el porcentaje total que podemos explicar va
a ser menor que en el análisis de correspondencias simple. Podemos hacer un gráfico de
sedimentación como el de la figura 6.9, donde vemos que quizás en este caso deberíamos
coger una tercera dimensión.
fviz_screeplot(corres3, addlabels = TRUE, ylim = c(0, 45))
El gráfico de la figura 6.10 muestra la representación de las dos primeras dimensiones. Como
6.4. ANÁLISIS DE CORRESPONDENCIAS MÚLTIPLE 401
07
Scree plot
5-
40
-0
Percentage of explained variances
30 29.3%
19
20
20
or
10 9.2%
8%
3.9% 3.1% 2.5% 2.3%
ad
1 2 3 4 5 6 7 8 9 10
rr
Dimensions
Edad:[15,25]
0.4
estado.civil:Soltero
Dimension 2 (9.2%)
0.2
Edad:(25,35]
profesion:Técnico
Sexo:M Leer:0
Ordenador:1 Pescar:1 profesion:Obrero
Jardinería:0 profesion:No cualificado
Caminar:0
Deporte:1
Cine:1 Punto:0Cocinar:0
TV:0
Exposición:0
Viajar:0
Voluntariado:0
Escuchar.música:1
Edad:(35,45]
TV:1 Show:0
Coleccionar:0
Tocar.música:0
Mecánica:1 TV:4
TV:2Pescar:0Mecánica:0
0.0
Tocar.música:1
Show:1 Leer:1 TV:3
profesion:Otros
profesion:Encargado
profesion:Dirección
Coleccionar:1
Viajar:1 Cine:0Escuchar.música:0
Deporte:0
Ordenador:0
Caminar:1
Cocinar:1 estado.civil:Divorciado
estado.civil:Casado1
profesion:Empleado
Edad:(45,55] Edad:(85,100]
Exposición:1 estado.civil:Casado+
Sexo:F
07
Voluntariado:1
Jardinería:1 Edad:(75,85]
Edad:(55,65]
Edad:(65,75]
−0.2
estado.civil:Viudo
Punto:1
5-
−0.5 0.0 0.5 1.0
-0
Dimension 1 (29.3%)
19
Figura 6.10: Representación del análisis de correspondencias múltiple
20
vemos, las etiquetas se solapan y es complicada su interpretación. No obstante, las categorías
más alejadas del origen. Por ejemplo valores altos de la dimensión 1 se corresponden con
personas mayores, que no escuchan música. Sin embargo valores pequeños se corresponden
con personas jóvenes, predomina el estado civil soltero, practican deportes como el ordenador,
deporte o cine.
or
plot(corres3)
ad
Vamos a continuar el ejemplo con el paquete FactoMineR, que nos ofrece más posibilidades
de visualización. Guardamos el resultado en un objeto, y por defecto se producen dos gráficos:
uno con todas las categorías, y otro solo con las variables, véase la figura ??.
rr
par(mfrow=c(2,1))
corres4 <- MCA(aficiones, method = "Burt")
Bo
Nótese que las funciones no utilizan exactamente los mismos métodos, ya que las inercias de
las dimensiones son ligeramente diferentes, como vemos en el gráfico de sedimentación para
este nuevo análisis, en la figura 6.12. No obstante la interpretación en este caso es la misma.
fviz_screeplot(corres4, addlabels = TRUE, ylim = c(0, 45))
Ahora podemos realizar las visualizaciones que vimos para el análisis de correspondencias
simple con el paquete factoextra, por ejemplo en la figura 6.13 se representan todas las
categorías en sus coordenadas de las dos primeras dimensiones y con una gradación de color
según su contribución.
6.4. ANÁLISIS DE CORRESPONDENCIAS MÚLTIPLE 403
0.4
Punto_1
Viudo
(55,65]
(65,75] Jardinería_1
Voluntariado_1
0.2
(75,85] Casado+
(45,55]
F
Empleado
Casado1 Exposición_1
Caminar_1
Divorciado
Cocinar_1
Dirección
Encargado
Coleccionar_1
Ordenador_0
Escuchar Deporte_0
(85,100] música_0 Otros Viajar_1
Cine_0 TV_3 Leer_1 Show_1
Tocar Mecánica_1
Pescar_0
TV_2 Tocar
(35,45]
música_0 música_1
Dim 2 (9.09%)
0.0 TV_4
Coleccionar_0
Mecánica_0 TV_1
Escuchar
Show_0
Voluntariado_0 música_1
Viajar_0
Exposición_0
Punto_0
TV_0
Cocinar_0
Obrero Cine_1
Deporte_1
No cualificado
Leer_0 Pescar_1
Caminar_0
Jardinería_0 Ordenador_1
Técnico
M
profesion.NA
(25,35]
−0.2
07
Soltero
5-
[15,25]
−0.6
-0
−0.5 0.0 0.5
19 Dim 1 (28.64%)
20
1.0
or
0.8
ad
Dim 2 (9.09%)
0.6
Edad
rr
estado.civil
0.4
Bo
Punto
0.2
Jardinería
Sexo profesion
Caminar
Cocinar Leer Exposición
Ordenador
Voluntariado
Pescar TV Deporte Cine
Coleccionar
0.0
músicaShow
Mecánica
Tocar Viajar
Escuchar música
Dim 1 (28.64%)
07
Scree plot
5-
40
Percentage of explained variances
-0
30 28.6%
19
20
20
9.1%
or
10
7.9%
4% 3.1% 2.5% 2.4% 2.2% 2.2% 2.1%
ad
1 2 3 4 5 6 7 8 9 10
Dimensions
rr
‘FactoMineR‘
6.5. PRÁCTICAS 405
07
4
Exposición_0 Obrero TV_0 TV_4 TV_2 Mecánica_1 Cine_1
3
No cualificado Leer_0 Cocinar_0 M Pescar_1 Deporte_1
−0.2 2
Caminar_0 profesion.NA TV_1 Ordenador_1
5-
1
Jardinería_0 Punto_0 (25,35]
Técnico
-0
−0.4 Soltero
−0.6
−0.6 −0.4
19
−0.2
Dim1 (28.6%)
0.0 0.2
[15,25]
0.4
20
Figura 6.13: Visualización categorías MCA
or
ggtheme = theme_minimal()
)
rr
Finalmente, la figura 6.14 representa todas las variables en las dos primeras dimensiones.
fviz_mca_var(corres4, repel = TRUE, choice = "var",
ggtheme= theme_minimal())
Bo
6.5. Prácticas
En este apartado se presentan las prácticas a las que se han hecho referencia durante el
capítulo. La reproducibilidad del código ha sido comprobada con la sesión de R que se
406 CAPÍTULO 6. ANÁLISIS DE CORRESPONDENCIAS CON R
07
Variables − MCA
Edad
5-
0.5
estado.civil
-0
0.4
19
Dim2 (9.1%)
0.3
20
0.2 Punto
Jardinería
profesion
or
Sexo Caminar
0.1
Exposición Ordenador
Cocinar Leer Viajar
ad
Dim1 (28.6%)
07
El objetivo del análisis de correspondencias es representar gráficamente, en un espacio con
pocas dimensiones (preferentemente 2) las tablas de contingencia que muestran las relaciones
entre dos variables cualitativas o atributos.
5-
En este primer ejemplo (García Pérez, 2008) buscamos la relación entre los atributos “color
del pelo” y “color de ojos”, representado mediante la tabla de contingencia siguiente:
-0
library(knitr)
kable(read.table("datos/cabello_ojos.txt", header = TRUE, sep = "\t", dec = ",", row.nam
Azules
Claros
Rubio Rojizo Castaño
326
688
38
116
241
584
19Moreno Negro
110
188
3
4
20
Castaños 343 84 909 412 26
Oscuros 98 48 403 681 85
Las expresiones utilizadas se encuentran en el script de las prácticas del capítulo. En lo
sucesivo, vamos a suponer que estamos trabajando en un proyecto que contiene una carpeta
or
llamada “datos” donde se encuentran los ficheros de datos. El fichero se puede descargar a
la carpeta de datos del proyecto con la siguiente expresión:
ad
download.file("http://emilio.lcano.com/b/adr/datos/cabello_ojos.txt",
"datos/cabello_ojos.txt")
Se recomienda en primer lugar limpiar el espacio de trabajo eliminando todos los objetos
rr
existentes:
rm(list = ls())
Bo
La tabla de contingencia con los datos de la aplicación se encuentra en el archivo de texto se-
parado por tabulaciones “cabello_ojos.txt”. Obtendremos esta tabla utilizando la instrucción
“read.table”, y asignándolos al objeto de tipo data.frame “X”:
408 CAPÍTULO 6. ANÁLISIS DE CORRESPONDENCIAS CON R
07
Comprobación de la hipótesis de independencia
Lo primero que hemos de comprobar es que existe algún grado de relación (asociación) entre
5-
los niveles de cada atributo. Para ello, recordemos que se calculan las frecuencias teóricas o
esperadas en caso de independencia, y se comparan globalmente con las realmente observadas
-0
en la muestra, mediante un estadístico que, bajo la hipótesis nula de independencia, se
comporta como una χ-Cuadrado de (r − 1) × (c − 1) grados de libertad (r = número de filas;
c = número de columnas). La función para realizar este contraste es chisq.test:
chisq.test(X)
##
19
20
## Pearson's Chi-squared test
##
## data: X
## X-squared = 1240, df = 12, p-value < 2.2e-16
or
chisq.test(X)$observed
Análisis de correspondencias
La pregunta, ahora que sabemos que hay asociación, es qué niveles concretos de cada factor
están relacionados entre sí, y cuáles no, y con qué intensidad. Esta cuestión puede ser resuelta
gráficamente mediante el Análisis de Correspondencias. Vamos a suponer que el número de
filas r es menor o igual que el número de columnas c de la tabla de contingencia. Si no es así,
la tabla se traspone.
Se construye una matriz de discrepancias C que recoge los cuadrados de las diferencias entre
las frecuencias conjuntas de cada combinación fila/columna de categorías de atributos y las
07
frecuencias esperadas en caso de independencia, divididas por la raíz de dichas frecuencias
esperadas. Se realiza una descomposición de dicha matriz y se obtiene la matriz D diagonal
(rxr) cuyos elementos son las raíces cuadradas de los r autovalores de CC t . A partir de estas
matrices se obtienen las coordenadas de cada nivel de cada factor para una dimensión dada,
5-
usualmente 2 (que es lo que supone la función ca por defecto). Vamos a guardar nuestro
análisis de correspondencias en un objeto con el nombre de, por ejemplo, “acorres”, y lo
-0
vamos a mostrar:
acorres <- ca(X)
acorres
##
## Principal inertias
19
(eigenvalues):
20
## 1 2 3
## Value 0.199245 0.030087 0.000859
## Percentage 86.56% 13.07% 0.37%
##
or
##
## Rows:
## Azules Claros Castaños Oscuros
ad
##
## Columns:
## Rubio Rojizo Castaño Moreno Negro
## Mass 0.270095 0.053091 0.396696 0.258214 0.021905
## ChiDist 0.571235 0.265854 0.212526 0.597901 1.132193
## Inertia 0.088134 0.003752 0.017918 0.092308 0.028079
## Dim. 1 -1.218714 -0.522575 -0.094147 1.318885 2.451760
## Dim. 2 1.002243 0.278336 -1.200909 0.599292 1.651357
Las informaciones más relevantes que nos aporta la función ca son las Inercias Principales,
que nos orientarán acerca de si dos es un número de dimensiones adecuada o es preferible otra
410 CAPÍTULO 6. ANÁLISIS DE CORRESPONDENCIAS CON R
dimensión. En nuestro caso, con una sola dimensión recogeríamos el 86.5 % de la “Inercia
Total”. Recordemos que este análisis es muy parecido al de “Componentes Principales”, y
que “Inercia” puede considerarse un sinónimo de “Varianza”.
También se nos ofrecen las informaciones concernientes a los niveles de los factores o atributos,
07
tanto el dispuesto en filas como en columnas. Entre estas informaciones destacan las masas
o porcentajes que cada categoría del factor representa con respecto al total de individuos,
las distancias chi-cuadrado correspondientes a cada categoría de cada factor con respecto al
centroide, las inercias de cada categoría de cada factor (su suma debe dar igual a la inercia
5-
total), y las coordenadas de cada nivel de cada atributo o factor.
-0
Por último, para representar la solución final vamos a aplicar la función plot, con lo que se
obtiene:
plot(acorres, what = c("all", "all"), mass = TRUE,
19
contrib = "relative", main = "Análisis de Correspondencias Simple")
Negro
or
Dimension 2 (13.1%)
0.2
Rubio Azules
Oscuros
Claros Moreno
ad
Rojizo
0.0
rr
−0.2
Castaño
Castaños
Bo −0.4
Dimension 1 (86.6%)
Parece existir una relación estrecha en poseer ojos azules y/o claros y el pelo rubio o rojizo.
Por otro lado, los ojos castaños normalmente vienen asociados al pelo castaño. Y por último,
los ojos oscuros se asocian al pelo moreno o negro. El tamaño del punto que representa a una
categoría indica la masa o proporción de casos que cumplen con esa categoría con respecto
6.5. PRÁCTICAS 411
al total.
07
los datos de la encuesta
En esta práctica no existe un guión tan estructurado como en el resto. Se trata de realizar
análisis de correspondencias simple sobre atributos de un conjunto de datos que contiene
5-
respuestas a un cuestionario. El fichero se puede descargar a la carpeta datos con la siguiente
expresión:
-0
download.file("http://emilio.lcano.com/b/adr/datos/encuesta_anonima_2018.RData",
"datos/encuesta_anonima_2018.RData")
19
Se recomienda en primer lugar limpiar el espacio de trabajo eliminando todos los objetos
existentes:
20
rm(list = ls())
Los datos se encuentran almacenados como archivo de datos de R, “.RData”. Para cargarlos
en el espacio de trabajo, utilizamos la función load.
or
load("datos/encuesta_anonima_2018.RData")
A partir de aquí:
ad
Identifique las variables de tipo atributo sobre las que puede realizar análisis de corres-
pondencias
Encuentre algún/algunos pares de atributos para los que se confirme que hay asociación
rr
07
Se recomienda en primer lugar limpiar el espacio de trabajo eliminando todos los objetos
existentes:
rm(list = ls())
5-
Necesitaremos el paquete ca, luego vamos a cargarlo:
-0
library (ca)
La tabla con los datos de la aplicación se encuentra en el archivo de texto separado por
19
tabulaciones “granja.txt”. Obtendremos esta tabla utilizando la instrucción “read.table”, y
asignándolos al objeto data.frame “granjas”:
granjas <- read.table("datos/granjas.txt",
20
header = T, sep = "\t", dec = ",",
row.names = 1, fileEncoding = "latin1")
recogidos, con la categoría que toman para cada caso o granja, en el data.frame “granjas”,
obteniéndose:
ad
granjas
## Granja2 h1 u2 c2 bio
## Granja3 h2 u2 c4 es
Bo
## Granja4 h2 u2 c4 es
## Granja5 h1 u1 c2 re
## Granja6 h1 u2 c2 re
## Granja7 h1 u3 c3 re
## Granja8 h5 u3 c3 re
## Granja9 h4 u1 c1 re
## Granja10 h2 u1 c1 bio
## Granja11 h1 u3 c1 bio
## Granja12 h4 u2 c2 es
## Granja13 h5 u2 c3 es
## Granja14 h5 u3 c0 con
6.5. PRÁCTICAS 413
## Granja15 h5 u2 c0 con
## Granja16 h5 u3 c3 es
Análisis de correspondencias
A continuación se obtiene la solución, mediante la función “mjca” suponiendo una represen-
tación de las categorías de los atributos en dos dimensiones. La solución se guarda en un
objeto al que hemos llamado, por ejemplo, “b”:
b <- mjca(granjas, lambda = "Burt")
07
print(b)
##
5-
## Eigenvalues:
## 1 2 3 4 5 6 7
-0
## Value 0.498902 0.359584 0.205281 0.153415 0.109793 0.0429 0.01938
## Percentage 35.66% 25.7% 14.67% 10.96% 7.85% 3.07% 1.39%
## 8 9 10 11 12
##
##
##
Value 0.005709
Percentage 0.41% 0.25% 0.03%19
0.0035 0.000476 0.000226 0
0.02% 0%
20
##
## Columns:
## Humedad:h1 Humedad:h2 Humedad:h4 Humedad:h5 Uso_Pasto:u1
## Mass 0.093750 0.046875 0.031250 0.078125 0.046875
## ChiDist 0.797566 1.374369 1.551881 1.143095 1.408966
or
Se obtienen unos resultados que indican que al seleccionar dos dimensiones se recoge el 61,3 %
de la Inercia Principal. Por lo tanto confirmamos que un número de dimensiones de 2 recoge
buena parte del comportamiento de las granjas estudiadas.
También se nos ofrecen las informaciones concernientes a los niveles de los factores o atribu-
tos (masas o porcentajes que cada categoría del factor representa con respecto al total de
individuos, las distancias chi-cuadrado correspondientes a cada categoría de cada factor con
07
respecto al centroide, las inercias de cada categoría de cada factor). Entre estas informaciones
destacan las coordenadas de cada nivel de cada atributo o factor.
5-
plot (b, mass = TRUE, main = "Análisis de Correspondencias Múltiple")
-0
Análisis de Correspondencias Múltiple
Uso_Abono:c1
Uso_Pasto:u1
19
Utilizacion:re
Uso_Pasto:u3
0.5
Utilizacion:bio
20
Humedad:h4
Humedad:h1 Uso_Abono:c3 Uso_Abono:c0
Utilizacion:con
Uso_Abono:c2 Humedad:h5
Dimension 2 (25.7%)
0.0
or
ad
−0.5
Uso_Pasto:u2
Utilizacion:es
rr
Humedad:h2
−1.0
Bo
Uso_Abono:c4
Dimension 1 (35.7%)
El argumento “mass” indica si los puntos tendrán un tamaño proporcional a las masas de
las categorías correspondientes. A partir de aquí, correspondería analizar el gráfico con el
conocimiento del problema concreto. Por ejemplo, se ve cómo se agrupan u3, c3, y h5.
6.5. PRÁCTICAS 415
07
análisis de correspondencias simple sobre atributos de un conjunto de datos que tiene res-
puestas a un cuestionario. El fichero se puede descargar a la carpeta datos con la siguiente
expresión:
5-
download.file("http://emilio.lcano.com/b/adr/datos/encuesta_anonima_2018.RData",
"datos/encuesta_anonima_2018.RData")
-0
Se recomienda en primer lugar limpiar el espacio de trabajo eliminando todos los objetos
existentes:
rm(list = ls())
19
Los datos se encuentran almacenados como archivo de datos de R, “.RData”. Para cargarlos
20
en el espacio de trabajo, utilizamos la función load.
load("datos/encuesta_anonima_2018.RData")
A partir de aquí, realice análisis de correspondencias con algunos o todos los atributos de la
or
07
5-
-0
19
20
or
ad
rr
Bo
07
5-
Parte III
-0
19
Extensiones del modelo lineal
20
or
ad
rr
Bo
417
Bo
rr
ad
or
20
19
-0
5-
07
419
El modelo lineal se queda corto en muchísimas situaciones reales. En los siguientes capítulos
se abordará cómo afrontar estas situaciones ajustando modelos adecuados con R, incluyendo
modelos lineales mixtos, modelos aditivos, modelos lineales generalizados (respuesta binaria
y de Poisson).
07
5-
-0
19
20
or
ad
rr
Bo
420
Bo
rr
ad
or
20
19
-0
5-
07
Capítulo 7
07
5-
Modelos lineales mixtos
-0
7.1. Introducción 19
20
Uno de los primeros problemas que se encuentra un analista es identificar qué modelo es
el adecuado para su problema. Primero, obviamente, ha debido definir el problema con
precisión, cuáles son los objetivos del análisis y la información que es capaz de recabar. En
or
los distintos apartados del capítulo se incluyen pistas para la identificación del modelo, más
uno o dos ejemplos de su aplicación.
ad
rr
421
422 CAPÍTULO 7. MODELOS LINEALES MIXTOS
07
En realidad, estos modelos son prácticamente iguales que los modelos de medidas repetidas.
No obstante, en aplicaciones de economía y empresa tiene algunas connotaciones por las que
5-
merece la pena tratarlas en un apartado distinto.
-0
7.5. Modelo de efectos aleatorios
filosóficas, según los autores. Es por esto que al utilizar este paquete se tienen que
obtener con otras funciones.
ad
7.6.1. Recursos
Guide to mixed models
rr
423
20
19
-0
5-
07
424 CAPÍTULO 8. CAPÍTULOS EN PREPARACIÓN
Capítulo 8
07
Capítulos en preparación
5-
8.1. Visualización de datos avanzada
-0
8.2. Probabilidad e inferencia básicas
8.3. Modelos lineales 19
20
8.4. Series temporales
8.5. Extensiones del modelo lineal
or
07
Símbolos
5-
Este apéndice contiene una relación símbolos matemáticos y caligráficos utilizados en el libro
-0
como referencia para el lector no acostumbrado a la notación matemática.
∗
Mayúsculas
ad
A.2. Símbolos
rr
Símbolo Se lee
Bo
425
426 APÉNDICE A. SÍMBOLOS
Símbolo Se lee
∈ Pertenece/perteneciente
∃ Existe
=⇒ Implica/entonces
≃ Aproximadamente igual1
07
5-
-0
19
20
or
ad
rr
Bo
1
En este libro se usa sobre todo para indicar que se ha redondeado un número decimal
Apéndice B
07
Créditos
5-
Los gráficos y diagramas generados son creación y propiedad del autor, salvo que se indique
-0
lo contrario. Su licencia de uso es la misma que la del resto de la obra, véase el Prefacio.
Las imágenes de tipo clipart usadas en esta obra pertenecen al dominio público gracias
a openclipart.org.
19
Las capturas de pantalla de páginas web se han obtenido de sys respectivos sitios
on-line a fecha 2017-03-20
20
The R logo is (c) 2016 The R Foundation.
or
ad
rr
Bo
427
428 APÉNDICE B. CRÉDITOS
07
5-
-0
19
20
or
ad
rr
Bo
Bibliografía
07
Aldas, J. and Uriel, E. (2017). Análisis multivariante aplicado con R. Ediciones Paraninfo,
S.A.
5-
Allaire, J., Xie, Y., McPherson, J., Luraschi, J., Ushey, K., Atkins, A., Wickham, H., Cheng,
J., Chang, W., and Iannone, R. (2019). rmarkdown: Dynamic Documents for R. R package
version 1.12.
-0
Allen, T. T. (2010). Introduction to Engineering Statistics and Lean Six Sigma - Statistical
Quality Control and Design of Experiments and Systems. Springer.
19
Bendixen, M. T. (1995). Compositional perceptual mapping using chi‐squared trees analysis
and correspondence analysis. Journal of Marketing Management, 11(6):571–581.
20
Bryan, J. (2019). Happy Git and GitHub for the useR. On-line book.
Bryer, J. and Speerschneider, K. (2016). likert: Analysis and Visualization Likert Items. R
package version 1.3.5.
or
Cano, E. L., Moguerza, J. M., and Corcoba, M. P. (2015). Quality Control with R. An ISO
Standards Approach. Use R! Springer.
ad
Chang, W., Cheng, J., Allaire, J., Xie, Y., and McPherson, J. (2019). shiny: Web Application
Framework for R. R package version 1.3.2.
rr
Charrad, M., Ghazzali, N., Boiteau, V., and Niknafs, A. (2015). NbClust: Determining the
Best Number of Clusters in a Data Set. R package version 3.0.
Bo
Cheng, J., Karambelkar, B., and Xie, Y. (2018). leaflet: Create Interactive Web Maps with
the JavaScript ’Leaflet’ Library. R package version 2.0.2.
Faraway, J. (2016). Extending the Linear Model with R: Generalized Linear, Mixed Effects
and Nonparametric Regression Models. Chapman & Hall/CRC Texts in Statistical Science.
CRC Press.
Feys, J. (2016). Nonparametric tests for the interaction in two-way factorial designs using r.
The R Journal, 8(1):367–378.
429
430 BIBLIOGRAFÍA
Fraley, C., Raftery, A. E., and Scrucca, L. (2019). mclust: Gaussian Mixture Modelling for
Model-Based Clustering, Classification, and Density Estimation. R package version 5.4.3.
Greenacre, M. and Nenadic, O. (2018). ca: Simple, Multiple and Joint Correspondence
Analysis. R package version 0.71.
Gross, J. and Ligges, U. (2015). nortest: Tests for Normality. R package version 1.0-4.
07
Journal of the Royal Statistical Society. Series C (Applied Statistics), 28(1):100–108.
5-
0.6-14.
Husson, F., Josse, J., Le, S., and Mazet, J. (2018). FactoMineR: Multivariate Exploratory
-0
Data Analysis and Data Mining. R package version 1.41.
Hyndman, R., Athanasopoulos, G., Bergmeir, C., Caceres, G., Chhay, L., O’Hara-Wild, M.,
19
Petropoulos, F., Razbash, S., Wang, E., and Yasmeen, F. (2019). forecast: Forecasting
Functions for Time Series and Linear Models. R package version 8.7.
Kassambara, A. and Mundt, F. (2017). factoextra: Extract and Visualize the Results of
Multivariate Data Analyses. R package version 1.0.5.
or
Lawson, J. (2015). Design and Analysis of Experiments with R. Chapman & Hall/CRC
Texts in Statistical Science. CRC Press.
Bo
Leisch, F. (2002). Sweave: Dynamic generation of statistical reports using literate data
analysis. In Compstat, pages 575–580. Springer.
López Cano, E. (2018). Estadística económica y empresarial. Libro de apuntes con licencia
Creative Commons.
Maechler, M., Rousseeuw, P., Struyf, A., and Hubert, M. (2019). cluster: ”Finding Groups
in Data”: Cluster Analysis Extended Rousseeuw et al. R package version 2.0.9.
Moen, R., Nolan, T., and Provost, L. (2012). Quality Improvement Through Planned Expe-
rimentation 3/E. McGraw-Hill Education.
BIBLIOGRAFÍA 431
Ooms, J., James, D., DebRoy, S., Wickham, H., Horner, J., and RStudio (2018). RMySQL:
Database Interface and ’MySQL’ Driver for R. R package version 0.2-15.
R Core Team (2018). foreign: Read Data Stored by ’Minitab’, ’S’, ’SAS’, ’SPSS’, ’Stata’,
’Systat’, ’Weka’, ’dBase’, ... R package version 0.8-71.
R Core Team (2019). R: A Language and Environment for Statistical Computing. R Foun-
dation for Statistical Computing, Vienna, Austria.
R Special Interest Group on Databases (R-SIG-DB), Wickham, H., and Müller, K. (2018).
07
DBI: R Database Interface. R package version 1.0.0.
5-
Ripley, B. and Lapsley, M. (2017). RODBC: ODBC Database Access. R package version
1.3-15.
-0
Schloerke, B., Crowley, J., Cook, D., Briatte, F., Marbach, M., Thoen, E., Elberg, A., and
Larmarange, J. (2018). GGally: Extension to ’ggplot2’. R package version 1.4.0.
19
Sievert, C., Parmer, C., Hocking, T., Chamberlain, S., Ram, K., Corvellec, M., and Despouy,
P. (2019). plotly: Create Interactive Web Graphics via ’plotly.js’. R package version 4.9.0.
20
Spinu, V., Grolemund, G., and Wickham, H. (2018). lubridate: Make Dealing with Dates a
Little Easier. R package version 1.7.4.
Vaidyanathan, R., Xie, Y., Allaire, J., Cheng, J., and Russell, K. (2018). htmlwidgets: HTML
ad
Venables, W. and Ripley, B. (2002). Modern applied statistics with S. Statistics and compu-
ting. Springer.
rr
Walker, A. (2018). openxlsx: Read, Write and Edit XLSX Files. R package version 4.1.0.
Bo
Warnes, G. R., Bolker, B., Bonebakker, L., Gentleman, R., Liaw, W. H. A., Lumley, T.,
Maechler, M., Magnusson, A., Moeller, S., Schwartz, M., and Venables, B. (2019). gplots:
Various R Programming Tools for Plotting Data. R package version 3.0.1.1.
Wickham, H. (2015). Advanced R. Chapman & Hall/CRC The R Series. CRC Press.
Wickham, H. (2019). stringr: Simple, Consistent Wrappers for Common String Operations.
R package version 1.4.0.
432 BIBLIOGRAFÍA
Wickham, H. and Bryan, J. (2019). readxl: Read Excel Files. R package version 1.3.1.
Wickham, H., Chang, W., Henry, L., Pedersen, T. L., Takahashi, K., Wilke, C., and Woo,
K. (2019a). ggplot2: Create Elegant Data Visualisations Using the Grammar of Graphics.
R package version 3.1.1.
Wickham, H., François, R., Henry, L., and Müller, K. (2019b). dplyr: A Grammar of Data
Manipulation. R package version 0.8.0.1.
Wickham, H. and Grolemund, G. (2016). R for Data Science. O’Reilly Media.
07
Wickham, H. and Henry, L. (2019). tidyr: Easily Tidy Data with ’spread()’ and ’gather()’
Functions. R package version 0.8.3.
Wickham, H., Hester, J., and Francois, R. (2018). readr: Read Rectangular Text Data. R
5-
package version 1.3.1.
Wickham, H. and Miller, E. (2019). haven: Import and Export ’SPSS’, ’Stata’ and ’SAS’
-0
Files. R package version 2.1.0.
Wickham, H. and Pedersen, T. L. (2019). gtable: Arrange ’Grobs’ in Tables. R package
version 0.3.0.
19
Wikipedia (2018). Navaja de ockham — wikipedia, la enciclopedia libre. [Internet; descar-
20
gado 25-enero-2019].
Wikipedia (2019). Paradoja de simpson — wikipedia, la enciclopedia libre. [Internet; des-
cargado 25-enero-2019].
or
Xie, Y. (2016). bookdown: Authoring Books and Technical Documents with R Markdown.
Chapman & Hall/CRC The R Series. CRC Press.
ad
Xie, Y. (2018). bookdown: Authoring Books and Technical Documents with R Markdown. R
package version 0.9.
Xie, Y. (2019a). blogdown: Create Blogs and Websites with R Markdown. R package version
rr
0.12.
Xie, Y. (2019b). knitr: A General-Purpose Package for Dynamic Report Generation in R. R
Bo