Você está na página 1de 59

Tutorial R:

Métodos de Investigación
Cuantitativa en Ciencias Sociales
Pablo De Tezanos-Pinto C.
padeteza@uc.cl
2012-2014

Para este tutorial vamos a ocupar RStudio (disponbile en http://www.rstudio.com/), porque facilita un poco las
cosas. En todo caso, los comandos funcionan exactamente igual en cualquier programa que ocupe R.

La idea es que lean esto directamente en RStudio para que puedan ir ejecutando los comandos a medida que
avanzamos. Si bien no es necesario, puede ser una buena idea que vayan escribiendo en este mismo archivo
sus comentarios, e intentando hacer los análisis por su cuenta con otras variables o con su propia base de
datos.

Configuración de RStudio.
Depediendo de la configuración de su computador, puede que no alcancen a ver bien este texto. En ese caso,
les recomiendo ajustar esta ventana con el mouse y cambiar el tamaño de la letra (en Tools -> Options ->
Appearance).

También pueden aprovechar de cambiar otra configuración importante, en Tools -> Options -> General. “Save
workspace to .RData on exit” dice “Ask”. Debería decir “Always”. De esta forma, los objetos que vamos a ir
creando van a quedar guardados para la próxima vez que abran el programa.

Introducción a R
R funciona escribiendo comandos en esta ventana -el editor- o en la consola -la ventana justo abajo de ésta.
En general, los comandos están compuestos de dos cosas: una función y un objeto.

las funciones son simplemente procesamientos que le pedimos a R, por ejemplo

2 + 2 # o
## [1] 4
mean(c(1,4,7,3,2)) # o incluso
## [1] 3.4
help(mean)

son ejemplos de funciones. Si están leyendo esto en RStudio, pueden ejecutar cada una de las funciones
presionando “ctrl + Enter” (en Mac, es “Command + Enter”) en la línea correspondiente -por ejemplo en la
línea 18 para calcular 2 + 2. El resultado de la función va a aparecer abajo, en la consola, con la excepción de
“help()”, que abre el archivo de ayuda de R, en este caso con información sobre la función “mean”.

La idea es que a medida que avanzan en este tutorial vayan ejecutando todas las funciones que estamos
revisando.
Normalmente, los resultados de las funciones son asignados a objetos, lo que permite seguir trabajando con
esos resultados. Por ejemplo, en vez de 2 + 2, podemos escribir

resultado = 2+2 # (apreten "ctrl + Enter" para crear el objeto)

Esto asigna el resultado de la función “2 + 2” a un objeto llamado “resultado” (¡podríamos haber puesto
cualquier nombre!) En la ventana de la derecha (Workspace), RStudio lista los objetos que hemos creado. La
gracia es que ahora podemos seguir trabajando con este objeto:

resultado + 1
## [1] 5

es igual a 5, y si lo ejecutan el resultado va a aparecer en la consola. Si ejecutan simplemente “resultado”, R


entrega el valor asignado a este objeto.

resultado
## [1] 4

Los objetos pueden ser el resultado de cualquier operación, incluyendo los resultados de análisis estadísticos,
bases de datos, tablas, listas y variables.

La función remove() elimina el objeto de su espacio de trabajo. También pueden ocupar ls() para ver una lista
de los objetos creados.

ls()
## [1] "resultado"

Un detalle importante… en R las mayúsculas y minúsculas no son lo mismo.

Resultado # y
## Error: object 'Resultado' not found
Help(mean)
## Error: could not find function "Help"

van a generar un mensaje de error en la consola, porque no son lo mismo que “resultado” y “help(mean)”.

Librerías de R
Una de las principales virtudes de R es que el código es abierto (open source), lo que permite que sea
desarrollado y actualizado permanentemente y que distintas personas puedan extender este programa
desarrollando “paquetes” o “librerías” para que R sea capaz de realizar nuevos análisis.

Por ejemplo, una librería que vamos a ocupar bastante es “psych”, que incluye una serie de funciones
típicamente utilizadas en investigación en psicología.

Antes de poder utilizar estas funciones en R, es necesario instalar “psych”. Para esto, pueden ir a menú
“Packages” en la ventana de abajo a la derecha -al lado de “Help”- presionar el botón “Install Packages” y
escribir psych en el cuadro de diálogo. Esto va a descargar la librería e instalarla en su computador. Como
siempre, también es posible hacer esto ocupando una función, en este caso:

install.packages("psych") # El progreso de la instalación aparece en la


consola.
Luego de que una librería ya está instalada, es necesario abrirla antes de poder ocupar sus funciones. Es una
buena idea agregar las librerías utilizadas al comienzo del archivo con los análisis. La función para cargar una
librería instalada es

library(psych)

Si abren el archivo de ayuda de esta librería,

help(psych)

pueden ver una descripción de todas las nuevas funciones que ahora están disponibles. Además de
funciones, esta librería incluye bases de datos que podemos ocupar como ejemplos. El comando

personalidad = epi.bfi # la librería psych tiene que estar instalada y


cargada

crea un nuevo objeto, una base de datos llamada “personalidad”, ocupando los datos disponibles en la librería
psych (epi.bfi). La base de datos incluye 13 variables de personalidad medidas en 231 personas. Esta
información aparece en la ventana de la derecha (Workspace), donde se listan los objetos que hemos creado
en nuestro espacio de trabajo. En RStudio, pueden hacer click en este objeto para ver los datos, o ejecutar

View(personalidad)

Pueden ver más información sobre esta base de datos ejecutando

help(epi.bfi)

Simplemente a modo de ejemplo, ahora podemos pedir un dispersiograma que muestra la relación entre
extroversión y apertura a la experiencia. Este comando tiene dos líneas (aunque podría haberlo escrito en
una), por lo que antes de ejecutarlo tienen que seleccionar ambas.

with(personalidad,
plot(bfext,bfopen))

El gráfico que aparece en “Plots” muestra que en general las personas más extrovertidas tienen también
mayores puntajes de apertura a la experiencia.

Antes de terminar esta sección me gustaría notar la importancia de escribir una sintaxis ordenada.
Obviamente, a R le da exactamente lo mismo si la sintaxis está ordenada o no. ¡Pero R no es el único que
tiene que leerla! Para los lectores humanos -para ustedes mismos y para las personas con quienes colaboran-
es mucho más fácil entender una sintaxis ordenada:

a) Escojan nombres amigables para las variables y los objetos. Es decir, nombres que sean cortos pero que
sean legibles y describan de qué estamos hablando. Por ejemplo, “bfext” es un nombre relativamente bueno
(se refiere al constructo extroversión en el contexto de una medición de personalidad “big five”); bffac3 (factor
3 de la medición big-five), en cambio, es malo. Aunque puedo imaginarme peores nombres.

b) Ocupen generosamente la opción de hacer comentarios en la sintaxis. Cualquier texto que sea precedido
por un signo # es ignorado por R, pero puede ser tremendamente útil para quien está leyendo y tratando de
entender la sintaxis.

c) Indenten los comandos de forma que sean más fáciles de entender. El ejemplo del gráfico de dispersión
que acabamos de hacer
with(personalidad,
plot(bfext,bfopen))

está indentado porque esto facilita su interpretación. La primera línea indica que el comando será ejecutado
usando la base de datos “personalidad”, y la segunda línea indica que se está pidiendo un gráfico que
relacione las variables bfext y bfopen. Para comandos más complicados, con varias líneas, indentar hace una
diferencia mucho más grande. Por consenso, y porque ocupar “Tab” tiene comportamientos diferentes en
distintos editores de texto, normalmente se ocupa la barra espacio para indentar.

Explorando una base de datos


Abrir una base de datos en R puede ser un proceso complicado, pero para eso está este tutorial. En verdad
no tiene por qué ser complicado. Típicamente se ocupa Excel para digitar los datos de un estudio. Si bien es
posible importar directamente los datos desde Excel, lo más fácil es guardar los datos en formato de texto,
porque es el formato preferido de R.

Específicamente, les recomiendo guardar los datos en formato .csv (comma separated values). Todo lo que
tienen que hacer es abrir el archivo Excel, poner “guardar como” y seleccionar este formato. En este tutorial
incluye una base de datos en Excel llamada alumnos2012.xlsx, que tiene los datos de un estudio hecho con
los alumnos del curso durante el año 2012, en que grupos de alumnos generaron varias preguntas para medir
distintos constructos. Incluye temas tan diversos como las actitudes hacia el aborto, hacia el Starbucks en la
universidad y el horóscopo de cada alumno. El archivo alumnos2012.pdf contiene más información sobre esta
base de datos, que vamos a ocupar como ejemplo a lo largo de este tutorial.

Abran los datos en Excel, y guardénla como alumnos2012.csv (valores separados por comas) en la misma
carpeta donde está este archivo (Tutorial R.R). Es posible abrir el archivo sólo con comandos, pero
probablemente la opción más fácil es abrirlo ocupando un menú. Pueden hacer esto en la ventana de
“Workspace” presionando el botón “Import Dataset”, o pueden ocupar el siguiente comando para abrir un
cuadro de diálogo. Les recomiendo esta segunda opción, porque así queda un registro de la necesidad de
abrir una base de datos para continuar. El comando

estudio2012 = read.csv(file.choose(),
header = TRUE) # abrir archivo alumnos2012.csv

abre un cuadro de diálogo donde pueden seleccionar el archivo alumnos2012.csv. Les recomiendo que
siempre pongan un comentario indicando el nombre del archivo que hay que abrir -en beneficio de sus
colaboradores y de ustedes mismos.

Dependiendo de la configuración del computador, es posible que el archivo está separado por ; en vez de
comas (porque en español se ocupa coma para indicar decimales). En este caso, hay que explicitar el
separador.

estudio2012 = read.csv(file.choose(), # abrir archivo alumnos2012.csv


header = TRUE,
sep=";") # Ocupar ; como separador

En detalle, este comando hace lo siguiente:

estudio2012 = # crea un objeto llamado estudio2012


read.csv( # lee un archivo .csv
file.choose(), # abre un cuadro de diálogo para elegir un
archivo
header = TRUE # indica que la primera línea del archivo
) # incluye los nombres de las variables.
Si todo salió bien, ahora tienen un objeto llamado “estudio2012” en su espacio de trabajo. Pueden hacer click
sobre este objeto para mirar los datos. El estudio incluye 84 variables medidas en 112 alumnos.

Una buena práctica es tener este archivo (con los comandos) y la base de datos en la misma carpeta. Pueden
definir esta misma carpeta como su directorio de trabajo (“working directory”), lo que permite leer y escribir
archivos sin tener que poner la dirección completa.

getwd() # obtiene su directorio de trabajo

Si estudio2012.csv está en este directorio, pueden ocupar

estudio2012 = read.csv("alumnos2012.csv", header = TRUE) # o agregando


sep = ";"

para cargar el archivo.

Un detalle técnico…

Si se fijan, el archivo se llamaba “alumnos2012” pero el objeto que creamos se llama “estudio2012”. Esto es
precisamente para que quede claro que el archivo con los datos y la base de datos que creamos en R son
cosas distintas. Pueden modificar todo lo que quieran el objeto de R, y eso no va a cambiar el archivo original
con los datos. ¡Esto es tremendamente bueno para su paz mental! En caso de cualquier problema,
simplemente pueden volver a cargar los datos originales.

El comando

names(estudio2012)

nos entrega los nombres de todas las variables incluidas en la base de datos.

Probablemente nadie se va a aprender de memoria todos los nombres de las variables, por lo que names() es
un comando tremendamente útil.

Una de las primeras cosas que debiéramos hacer cuando abrimos una base de datos es revisar los
descriptivos para cada una de las variables. Más allá de ser una primera mirada a los resultados del estudio,
esto permite identificar cualquier error en la digitación o en la construcción de la base de datos.

describe(estudio2012)
head(describe(estudio2012)) # solo los primeros casos
## vars n mean sd median trimmed mad min max range skew
## n 1 112 56.50 32.48 56.5 56.50 41.51 1 112 111 0.00
## sitsent* 2 112 2.94 0.98 3.0 2.93 1.48 1 4 3 0.07
## desconf1 3 111 4.47 1.66 5.0 4.54 1.48 1 7 6 -0.51
## desconf2 4 111 3.45 1.80 3.0 3.37 2.97 1 7 6 0.19
## desconf3 5 111 2.81 1.66 2.0 2.64 1.48 1 7 6 0.63
## desconf4 6 109 4.61 1.63 5.0 4.69 1.48 1 7 6 -0.46
## kurtosis se
## n -1.23 3.07
## sitsent* -1.85 0.09
## desconf1 -0.52 0.16
## desconf2 -1.09 0.17
## desconf3 -0.66 0.16
## desconf4 -0.68 0.16

es una función de la librería “psych” que entrega los descriptivos de cada una de las variables. En cuanto a la
calidad de la base de datos lo más importante es revisar el n, que nos indica la cantidad de personas que
contestaron cada pregunta (un n de cero en una pregunta probablemente refleja un error en la creación de la
base de datos) y el rango de respuesta (min y max). Las preguntas del cuestionario tenían un rango de 1 a 7;
claramente habría un error en la base de datos si en alguna pregunta el rango fuera distinto (de 1 a 34, por
ejemplo).

Además de esto, describe() entrega una buena cantidad de información descriptiva. El promedio, la mediana,
la desviación estándar y el grado de asimetría (skew).

Algunas de las variables tienen un * junto a su nombre. Esto significa que son variables categóricas (porque
están codificadas como texto en la base de datos). La variable sitsent (situación sentimental) incluía tres
opciones,

table(estudio2012$sitsent)
##
## En una relacion Es complicado Soltero/a
## 1 54 8 49

El promedio de esta variable no tiene ningún sentido. R simplemente asigna un número a cada categoría y la
función describe() promedia todas las variables, aunque sean categóricas.

Es común querer transformar una tabla de frecuencia a porcentajes o proporciones. La función prop.table()
hace esta transformación a partir de los resultados de table():

x = table(estudio2012$sitsent) # asigna la tabla al objeto x

prop.table(x) # proporciones por celda


prop.table(x, 1) # proporciones por fila
prop.table(x, 2) # proporciones por columna

Descriptivos.
La información descriptiva entregada con el comando describe() es más que suficiente para tener una buena
idea del comportamiento de las variables. En general, vamos a estar interesados en el promedio (mean), la
mediana (median) y la desviación estándar (sd). Todos estos indicadores pueden ser solicitados con su propio
comando.

En la mayoría de las situaciones vamos a querer referirnos a variables específicas, no a la base de datos
completa como hicimos con describe(estudio2012). Como en R podemos tener múltiples bases de datos en
nuestro espacio de trabajo, es necesario indicar tanto el nombre de la variable como la base de datos a la que
pertenece. Hay dos formas principales para hacer esto, y pueden ocupar cualquiera de las dos dependiendo
de lo que sea más fácil para cada situación.

La primera es ocupar el signo $ para indicar base de datos y el nombre de la variable:

mean(estudio2012$insom1, na.rm=TRUE)
## [1] 3.441

En este comando, se pide el promedio de la variable “insom1” en la base de datos “estudio2012”. La función
mean() requiere especificar qué hacer con los datos perdidos (la gente que no contesta). na.rm=TRUE
simplemente le dice a R que ignore a estos participantes para calcular el promedio.

La otra forma, que ya ocupamos más arriba, es con el comando with().

help(with)

Esto es especialmente útil cuando queremos ocupar varias variables. El comando


insomnio = with(estudio2012,
data.frame(insom1, insom2, insom3, insom4, insom5))

crea una nueva base de datos -ocupando la función data.frame()- que sólo tiene la información de los ítems
de insomnio. Esto permite hacer análisis con la escala completa sin tener que volver a escribir cada variable.

describe(insomnio)
## vars n mean sd median trimmed mad min max range skew
kurtosis
## insom1 1 111 3.44 2.03 3.0 3.30 2.97 1 7 6 0.46 -
1.16
## insom2 2 111 3.27 2.00 3.0 3.10 2.97 1 7 6 0.49 -
1.09
## insom3 3 110 3.10 2.00 2.5 2.93 2.22 1 7 6 0.48 -
1.19
## insom4 4 110 4.08 2.20 4.0 4.10 2.97 1 7 6 0.04 -
1.46
## insom5 5 110 3.88 2.27 4.0 3.85 2.97 1 7 6 0.08 -
1.47
## se
## insom1 0.19
## insom2 0.19
## insom3 0.19
## insom4 0.21
## insom5 0.22

Otras funciones descriptivas son:

sd(estudio2012$insom1, na.rm=TRUE)
## [1] 2.035
median(estudio2012$insom1, na.rm=TRUE)
## [1] 3

y summary(), que es más o menos equivalente a describe() pero no requiere cargar una librería.

summary(insomnio)
## insom1 insom2 insom3 insom4 insom5
## Min. :1.00 Min. :1.00 Min. :1.0 Min. :1.00 Min.
:1.00
## 1st Qu.:2.00 1st Qu.:2.00 1st Qu.:1.0 1st Qu.:2.00 1st
Qu.:2.00
## Median :3.00 Median :3.00 Median :2.5 Median :4.00 Median
:4.00
## Mean :3.44 Mean :3.27 Mean :3.1 Mean :4.08 Mean
:3.88
## 3rd Qu.:5.00 3rd Qu.:5.00 3rd Qu.:5.0 3rd Qu.:6.00 3rd
Qu.:6.00
## Max. :7.00 Max. :7.00 Max. :7.0 Max. :7.00 Max.
:7.00
## NA's :1 NA's :1 NA's :2 NA's :2 NA's :2

Tablas y gráficos de frecuencia.


Además de indicadores descriptivos básicos como el promedio y la desviación estándar, muchas veces nos
interesa revisar la distribución de una variable. El item insom1 es un buen indicador general de insomnio:
“Generalmente me cuesta conciliar el sueño o despierto muchas veces en la noche”. A partir de los
descriptivos,

describe(estudio2012$insom1)
## vars n mean sd median trimmed mad min max range skew kurtosis
se
## 1 1 111 3.44 2.03 3 3.3 2.97 1 7 6 0.46 -1.16
0.19

podemos observar que los niveles de insomnio están aproximadamente en el punto medio de la escala (M =
3.44), que hay una variación considerable entre los participantes (SD = 2.03), y que la distribución es algo
asimétrica: la mayoría de los participantes están a la izquierda de la distribución (Skew = .46). Esto es visible
también a partir de una simple tabla de frecuencia:

table(estudio2012$insom1)
##
## 1 2 3 4 5 6 7
## 22 24 21 10 7 15 12

En esta tabla, queda claro que hay una importante variación en el grado de acuerdo con este ítem, aunque
hay más personas en desacuerdo que de acuerdo. En vez de mirar un montón de números, podemos pedirle
a R que nos dibuje un gráfico. El comando

barplot(table(estudio2012$insom1))

dibuja un gráfico de barras con la información de la tabla que pedimos antes. Además de los datos para el
gráfico, podemos agregar un título y otras cosas. Esto no es necesario si están revisando el gráfico para
ustedes mismos, para tener una idea de cómo se comportan los datos, pero si es necesario cuando quieren
mostrar estos resultados en un informe, artículo o presentación.

Abajo vamos a pedir el mismo gráfico, pero agregando opciones para mejorar la presentación:

barplot(table(estudio2012$insom1), # datos del gráfico


main="Insomnio en estudiantes", # título principal
xlab="Grado de acuerdo", # etiqueta eje horizontal
ylab="Frecuencia", # etiqueta eje vertical
col="lightblue" # cambio de color. ver colors()
)

Estas opciones están disponibles, con la misma sintaxis, para todo tipo de gráficos. Si están ocupando
RStudio, pueden guardar el gráfico como imagen, pdf, o simplemente copiarlo en la memoria (para pegarlo en
Word, por ejemplo) seleccionando la opción correspondiente en el botón “Export”. Si apretan el botón “Zoom”,
el gráfico se abre en una nueva ventana, lo que puede ser útil para cambiar sus dimensiones. En ese caso
hay que hacer click derecho para copiarlo o exportarlo.

Cuando las variables son continuas, hacer una tabla de frecuencia es poco práctico y no entrega información
útil. Consideremos por ejemplo el promedio de todos los ítems de insomnio:

estudio2012$insom = with(insomnio,
(insom1 + insom2 + insom3 + insom4 + insom5)/5)

describe(estudio2012$insom)
## vars n mean sd median trimmed mad min max range skew kurtosis
se
## 1 1 108 3.57 1.43 3.4 3.51 1.48 1 7 6 0.32 -0.67
0.14
Esta escala sigue siendo de 1 a 7, pero ahora tiene valores relativamente continuos. Por este motivo, hacer
una tabla de frecuencia es una mala idea:

table(estudio2012$insom)
##
## 1 1.4 1.6 1.8 2 2.2 2.4 2.6 2.8 3 3.2 3.4 3.6 3.8 4 4.2 4.4
4.6
## 1 6 4 4 5 4 4 4 9 3 4 9 1 8 5 5 3
3
## 4.8 5 5.2 5.4 5.8 6.2 6.4 6.6 6.8 7
## 1 7 8 2 1 2 1 2 1 1
barplot(table(estudio2012$insom))

La solución es hacer un histograma. Los histogramas grafican una tabla de intervalos, donde queremos saber
cuántas personas tienen puntajes entre 1 y 2, 2 y 3, etc. El comando es simplemente:

hist(estudio2012$insom)

Al igual que en los gráficos anteriores, podemos agregar opciones para mejorar la presentación.

hist(estudio2012$insom, # datos del gráfico


main="Histograma escala de Insomnio", # título principal
xlab="Grado de acuerdo", # etiqueta eje horizontal
ylab="Frecuencia", # etiqueta eje vertical
col="lightgray" # cambio de color
)

¿Por qué no ocupamos desde un comienzo hist() para hacer el gráfico de frecuencias? Los histogramas están
diseñados para variables continuas (por eso las barras están juntas), y desgraciadamente R se confunde
cuando le ponemos una variable discreta, como el primer item de la escala.

hist(estudio2012$insom1)

dibuja una situación muy distinta, y menos preocupante, que la situación real:

barplot(table(estudio2012$insom1))

De todas formas, esto es un error con la función hist(), que está sumando a las personas que marcan 1 y las
que marcan 2 en la primera barra. Espero que lo solucionen pronto. La función truehist() de la librería MASS
no tiene este problema.

El punto que hay que recordar es que los histogramas son para variables continuas, no para variables
discretas.

Medidas de tendencia central


Podemos ocupar el mismo comando que ocupamos antes (barplot) para hacer un gráfico con los promedios
de múltiples variables. Por ejemplo,

colMeans(insomnio, na.rm=TRUE) # imprime una tabla con los promedios de


los ítems
## insom1 insom2 insom3 insom4 insom5
## 3.441 3.270 3.100 4.082 3.882
barplot(colMeans(insomnio, na.rm=TRUE)) # grafica esta tabla

Simplemente, la función barplot() saca los datos de una tabla de promedios en vez de una tabla de frecuencia.

Abajo les copio un comando para el mismo gráfico, pero con mejor presentación. Como ven, indentar y poner
comentarios es más útil cuando los comandos son más largos.

barplot(colMeans(insomnio, na.rm=TRUE),
main="Promedios itemes escala insomnio", # título principal

ylab="Grado de acuerdo", # etiqueta eje vertical

names=c("Item 1", "Item 2",


"Item 3", "Item 4", "Item 5"), # Nombres para las
variables

col=rainbow(20, alpha = .6), # R incluye también


paletas de color.
# pueden ejecutar
help(rainbow)
# para más información

ylim=c(1,7), # la pregunta era de 1 a


7.
xpd=F) # Es necesario para que
las barras no comiencen en el valor 0

Si bien muchas veces basta con graficar los promedios, también es bueno incluir más información -dispersión
y asimetría, por ejemplo. Una forma simple de hacerlo es con un boxplot. R tiene un comando especialmente
para este tipo de gráficos:

boxplot(insomnio)

Simple, ¿cierto? Abajo lo copio con algunas opciones para mejorar la presentación.

boxplot(insomnio,
main="Itemes escala insomnio",
ylab="Grado de acuerdo",
names=c("Item 1", "Item 2", "Item 3", "Item 4", "Item 5"),
col=rainbow(5, alpha = .3)
)
Si no hubiéramos hecho la base de datos con los ítems de insomnio, el comando sería un poco más largo.
Abajo está hecho para los ítems de ansiedad ante las evaluaciones:

with(estudio2012,
boxplot(data.frame(ansev1, ansev2, ansev3, ansev4, ansev5),
main="Ansiedad ante evaluaciones",
sub="Frecuencia de distintas conductas en periodos de
evaluacion",
ylab="Frecuencia conductas",
names=c("Dificultad dormir", "Despertar frecuente",
"Irritable", "Dolores", "Incapacidad de
desconectarse"),
col=rainbow(5, alpha = .3))
)

Esta vez pusimos nombres descriptivos a los distintos ítems, por lo que probablemente es necesario abrir el
gráfico en una nueva ventana para verlos bien (apretando Zoom).

Comparando distintos grupos.


La base de datos alumnos2012.csv que importamos incluía una serie de variables que identifican distintos
grupos a los que pertenecen las personas. Por ejemplo, si son hombres o mujeres, o su situación sentimental.

table(estudio2012$genero)
##
## Femenino Masculino
## 3 82 27
table(estudio2012$sitsent)
##
## En una relacion Es complicado Soltero/a
## 1 54 8 49

Estas variables están codificadas como texto, y en los casos en que alguien no contestó estas preguntas (3
personas no indicaron su género y 1 persona no indicó su situación sentimental) los datos tienen simplemente
una celda vacía.

Todo esto significa que tenemos que hacer algo de trabajo antes de poder ocupar estas variables para
nuestros análisis. Por ejemplo, si hacemos un gráfico de barras para situación sentimental,

barplot(table(estudio2012$sitsent))

Vemos que hay una barra extra con la persona que prefirió no contestar esta pregunta.

Las variables categóricas son importantes y las vamos a ocupar para una serie de análisis, por lo que vale la
pena hacer un procesamiento preliminar de los datos.

El siguiente comando crea una nueva variable -sitsentf- en la base de datos estudio2012 donde se
seleccionan solamente los grupos que nos interesan.

estudio2012$sitsentf = factor(estudio2012$sitsent,
# Esto crea una variable nueva a partir de
sitsent,
# considerándola como un factor (una
variable categórica)
# por eso le puse el nombre sitsentf

levels=c("En una relacion",


"Es complicado", "Soltero/a"))

# Esto selecciona los niveles que nos


interesan, es decir,
# sin incluir las personas que no
contestaron.

El comando

estudio2012$sitsentf
## [1] En una relacion En una relacion Soltero/a Soltero/a
## [5] Soltero/a Soltero/a Es complicado Soltero/a
## [9] Soltero/a En una relacion Soltero/a En una relacion
## [13] En una relacion Soltero/a En una relacion En una relacion
## [17] Soltero/a En una relacion En una relacion Soltero/a
## [21] Es complicado Soltero/a Soltero/a Soltero/a
## [25] En una relacion En una relacion Es complicado En una relacion
## [29] En una relacion En una relacion En una relacion Soltero/a
## [33] Es complicado Soltero/a En una relacion En una relacion
## [37] En una relacion Soltero/a En una relacion En una relacion
## [41] En una relacion Soltero/a Es complicado Es complicado
## [45] Soltero/a Soltero/a Es complicado En una relacion
## [49] Soltero/a Soltero/a Soltero/a <NA>
## [53] Soltero/a Soltero/a Soltero/a Soltero/a
## [57] En una relacion En una relacion Soltero/a Soltero/a
## [61] En una relacion En una relacion En una relacion Soltero/a
## [65] En una relacion Soltero/a Soltero/a En una relacion
## [69] Soltero/a En una relacion Soltero/a En una relacion
## [73] Soltero/a Soltero/a En una relacion En una relacion
## [77] Soltero/a En una relacion En una relacion Soltero/a
## [81] En una relacion En una relacion En una relacion Soltero/a
## [85] En una relacion En una relacion Soltero/a En una relacion
## [89] En una relacion Soltero/a En una relacion Soltero/a
## [93] En una relacion Soltero/a En una relacion En una relacion
## [97] En una relacion En una relacion Soltero/a En una relacion
## [101] Soltero/a En una relacion Es complicado Soltero/a
## [105] En una relacion Soltero/a En una relacion Soltero/a
## [109] En una relacion Soltero/a Soltero/a En una relacion
## Levels: En una relacion Es complicado Soltero/a

imprime todos los datos de esta variable en la consola. El participante 52 ahora tiene en vez de “”.

estudio2012[52,]$sitsentf # muestra la situación sentimental del


participante 52 (NA)
## [1] <NA>
## Levels: En una relacion Es complicado Soltero/a

Cuando pedimos la tabla, ahora ya no incluye a este participante:

table(estudio2012$sitsentf)
##
## En una relacion Es complicado Soltero/a
## 54 8 49
La base de datos,

names(estudio2012)
## [1] "n" "sitsent" "desconf1" "desconf2" "desconf3" "desconf4"
## [7] "desconf5" "vidau1" "vidau2" "vidau3" "vidau4" "vidau5"
## [13] "starb1" "starb2" "starb3" "starb4" "starb5" "ayude1"
## [19] "ayude2" "ayude3" "ayude4" "ayude5" "abor1" "abor2"
## [25] "abor3" "abor4" "abor5" "tolsex1" "tolsex2" "tolsex3"
## [31] "tolsex4" "tolsex5" "intex1" "intex2" "intex3" "intex4"
## [37] "intex5" "acogex1" "acogex2" "acogex3" "acogex4" "acogex5"
## [43] "ansev1" "ansev2" "ansev3" "ansev4" "ansev5" "insom1"
## [49] "insom2" "insom3" "insom4" "insom5" "intui1" "intui2"
## [55] "intui3" "intui4" "intui5" "valma1" "valma2" "valma3"
## [61] "valma4" "valma5" "streu1" "streu2" "streu3" "streu4"
## [67] "streu5" "intay1" "intay2" "intay3" "intay4" "intay5"
## [73] "tprej1" "tprej2" "tprej3" "tprej4" "tprej5" "genero"
## [79] "zodiaco" "orienpol" "mencion" "votop" "herman" "lugar"
## [85] "insom" "sitsentf"

ahora incluye al final una nueva variable “sitsentf”. Esta variable está en la base de datos estudio2012 que
tenemos en nuestro espacio de trabajo. No en el archivo alumnos2012.csv.

Vamos a hacer el mismo procesamiento con genero

table(estudio2012$genero)
##
## Femenino Masculino
## 3 82 27
estudio2012$generof = factor(estudio2012$genero,
levels=c("Femenino","Masculino"),
labels=c("Mujer","Hombre"))
# con "labels" podemos cambiar los nombres
de las
# categorías

table(estudio2012$generof)
##
## Mujer Hombre
## 82 27

y con orientación política

table(estudio2012$orienpol)
##
## Centro Centro Derecha Centro Izquierda
## 2 8 18 20
## Derecha Independiente Izquierda Ninguna
## 19 8 18 19
estudio2012$orienpolf = factor(estudio2012$orienpol,

# Al seleccionar los niveles, podemos


hacer varias cosas
# con esta variable: ordenarlos de
izquierda a derecha,
# omitir los independientes y los que
dicen "ninguna",
# y omitir a los que no contestaron. Todos
estos van a
# quedar como NA. (por supuesto, para
otros análisis
# podríamos querer mantener a los
independientes y a los
# que no se identifican)

levels=c("Izquierda","Centro
Izquierda","Centro",
"Centro Derecha","Derecha"))

table(estudio2012$orienpolf)
##
## Izquierda Centro Izquierda Centro Centro Derecha
## 18 20 8 18
## Derecha
## 19

Descripción de la muestra.
Una de las cosas más simples que podemos querer hacer con este tipo de variables es describir la cantidad
de personas que pertenecen a cada grupo, por ejemplo a través de gráficos de barra

barplot(table(estudio2012$orienpolf),
col=rainbow(30, alpha=.6))

Si quieren hacer un gráfico de torta, el comando es pie()

pie(table(estudio2012$sitsentf),
main="Situacion sentimental estudiantes 2012",
col=terrain.colors(5, alpha = .6),
radius = .8)

También es común querer cruzar dos tablas de frecuencia (crosstabs), lo que se hace simplemente
agregando otra variable al comando table():

table(estudio2012$sitsentf,estudio2012$generof)
##
## Mujer Hombre
## En una relacion 44 9
## Es complicado 4 4
## Soltero/a 33 14

¿Cómo podemos graficar esto? Una buena opción es ocupar nuevamente un gráfico de barras.

barplot(table(estudio2012$sitsentf, estudio2012$generof),
legend=TRUE, # agrega automáticamente una leyenda
col=heat.colors(3, alpha=.6)
)

Para hacer que cada grupo tenga una barra, hay que ocupar el argumento “beside”.

barplot(table(estudio2012$sitsentf, estudio2012$generof),
legend=TRUE,
col=heat.colors(3, alpha=.6),
beside=TRUE # esta opción hace que cada grupo tenga una barra
)

Por último, es común querer comparar los grupos en una o más variables continuas, como querer ver los
niveles de insomnio separado por hombres y mujeres. En un boxplot, podemos ocupar el signo ~ para indicar
que se quiere separar por grupos. En general, ~ significa “predicho por” en R. (En mi computador, tengo que
presionar alt+ñ para escribir este tilde, pero eso va a depender de la configuración de su teclado).

boxplot(insom1~sitsentf, data=estudio2012,
main="Problemas de insomnio en relaciones complicadas",
ylab="Insomnio",
col=heat.colors(3,alpha=.6))

Aunque creo que comparar grupos a partir de boxplots es mejor, también pueden hacer un gráfico de barras
con los promedios. La función tapply() es ideal para obtener los promedios de distintos grupos.

El formato de esta función es poner primero la variable dependiente, después el factor que define los grupos y
después la función que se quiere ocupar. El resultado de tapply() puede ser entregado directamente a
barplot().

tapply(estudio2012$insom1, estudio2012$sitsentf, mean, na.rm=TRUE)


## En una relacion Es complicado Soltero/a
## 3.278 4.375 3.438
barplot(tapply(estudio2012$insom1, estudio2012$sitsentf, mean,
na.rm=TRUE))

Abajo lo copio mejorando la presentación.

barplot(tapply(estudio2012$insom1, estudio2012$sitsentf, mean,


na.rm=TRUE),
main="Problemas de insomnio en relaciones complicadas",
ylab="Insomnio",
col=heat.colors(3,alpha=.6),
ylim=c(1,7), # la pregunta era de 1 a
7.
xpd=F) # Es necesario para que
las barras

# no comiencen en el
valor 0

Finalmente, la función tapply() también permite ocupar dos o más factores para definir los grupos. Todo lo que
hay que hacer es ocupar el comando list() para hacer una lista con los factores a ocupar. El comando de abajo
hace una tabla con los promedios de insomnio según situación sentimental, separando además hombres de
mujeres.

tapply(estudio2012$insom1,
list(estudio2012$sitsentf, estudio2012$generof), mean, na.rm=TRUE)
## Mujer Hombre
## En una relacion 3.068 3.889
## Es complicado 5.000 3.750
## Soltero/a 3.515 3.000

Esta vez vamos a asignar esta tabla a un objeto para simplificar los comandos siguientes. Como es un objeto
temporal, le vamos a poner “x”. Si tuviera un uso más permanente sería mejor ponerle un nombre más
descriptivo.

x = tapply(estudio2012$insom1,
list(estudio2012$sitsentf, estudio2012$generof), mean,
na.rm=TRUE)

Gráfico sin mayores opciones de formato.

barplot(x,
beside=TRUE)

Gráfico formateado para documentos, presentaciones, etc.

barplot(x,
legend=TRUE,
beside=TRUE,
main="Insomnio segun genero y situacion sentimental",
ylab="Insomnio",
col=heat.colors(3,alpha=.6),
ylim=c(1,7),
xpd=F)

Especialmente al reportar experimentos, es común hacer un gráfico de líneas para reportar interacciones
entre dos factores. R tiene un comando para esto, interaction.plot(factor eje x, factor con diferentes líneas,
variable dependiente).

with(estudio2012,
interaction.plot(generof, sitsentf, insom1))

Nuevamente, podemos mejorar la presentación del gráfico agregando más parámetros:

with(estudio2012,
interaction.plot(generof, sitsentf, insom1,
ylim=c(1,7),
lty = 1,
col=c("red","blue","darkgreen"),
main="Insomnio según género y situación
sentimental",
ylab="Insomnio",
xlab=""))
Desgraciadamente esta función no reacciona bien a NAs en la variable dependiente. Por ejemplo, el cuarto
ítem de desconfianza en la pareja, “Si mi pareja reacciona de manera fría, tiendo a pensar que tiene un
problema conmigo” tiene 3 personas que no contestaron.

summary(estudio2012$desconf4) # ver NA's


## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 1.00 4.00 5.00 4.61 6.00 7.00 3

Si hacemos el gráfico tal como lo hicimos antes, nos van a faltar varias líneas

with(estudio2012,
interaction.plot(generof, sitsentf, desconf4,
ylim=c(1,7)))

La solución es explicitar que la fórmula para el promedio tiene que ignorar los datos perdidos,

with(estudio2012,
interaction.plot(generof, sitsentf, desconf4,

# agregando el siguiente argumento:


fun=function(x) mean(x, na.rm=TRUE)))

Pareciera que los hombres, pero no las mujeres, tienden a tener mayor desconfianza o inseguridad en
relaciones complicadas (recuerden que hay solo 4 participantes hombres que reportan su situación
sentimental como complicada, ¡no se tomen muy en serio estos resultados!)

table(estudio2012$sitsentf, estudio2012$generof)
##
## Mujer Hombre
## En una relacion 44 9
## Es complicado 4 4
## Soltero/a 33 14

Relaciones entre variables continuas.


Es tremendamente común el psicología querer relacionar distintas variables continuas a partir de
dispersiogramas, como ya hicimos al comienzo de este tutorial con los niveles de extroversión y de apertura a
la experiencia. Revisemos la relación entre insomnio y ansiedad en periodo de evaluaciones.

Primero tenemos que calcular el promedio de la escala. Dado que vamos a relacionarla con los niveles de
insomnio, prefiero no ocupar los ítems que se refieren a problemas de dormir en periodos de evaluaciones.

estudio2012$ansev = with(estudio2012,
(ansev3+ansev4+ansev5)/3)

Ahora podemos pedir un dispersiograma

plot(estudio2012$ansev, estudio2012$insom,
main="Relacion entre ansiedad ante evaluaciones e insomnio",
col="cadetblue4",
xlab="Ansiedad ante evaluaciones",
ylab="Insomnio"
)

Como se observa en el gráfico, hay una correlación positiva entre las dos variables. Quienes reportan más
ansiedad en periodos de evaluaciones reportan también mayores niveles de insomnio.

Para obtener el coeficiente de correlación entre estas variables pueden ocupar la función cor().

cor(estudio2012$ansev, estudio2012$insom,
use = "pairwise.complete.obs" # necesario cuando hay NAs
)
## [1] 0.3182

Este tipo de gráficos permite además agregar más información. Por ejemplo, poner una línea que indica la
relación lineal entre las variables:

abline(lm(estudio2012$insom~estudio2012$ansev),
col="firebrick")
## Error: plot.new has not been called yet

Para hacer esto más complicado, la función lm() ocupa un orden distinto para las variables x e y. El comando
plot tiene el formato (x, y), mientras que el comando lm() tiene el formato y~x (y predicho por x).

Otra opción es dibujar una linea que se ajuste a los datos, pero no forzar que sea una linea recta. supsmu() es
una buena función para hacer esto.

lines(supsmu(estudio2012$ansev, estudio2012$insom,
bass=2), # de 0 a 10, controla el nivel de "smoothness" de la linea
col="royalblue1")
## Warning: 5 observations with NAs, NaNs and/or Infs deleted
## Error: plot.new has not been called yet

A veces nos interesa revisar la relación de dos variables continuas, pero separando por distintos grupos. Una
forma simple de hacer esto es con la librería lattice.

install.packages("lattice") # Una vez que ya lo tienen instalado no es


necesario
# ejecutar nuevamente este comando.
library(lattice)

La función xyplot() de lattice funciona con la misma sintaxis que lm(): y~x, pero además permite separar por
grupos ocupando el signo | (en mi computador, esto es alt+1).

xyplot(insom~ansev|generof, estudio2012)

La librería lattice tiene una gran cantidad de comandos para hacer gráficos, que pueden explorar libremente.
En general opté por ocupar librerías solamente cuando facilita substancialmente las cosas. Ahora vamos a ver
una opción para visualizar estos datos sin ocupar lattice.

En vez de hacer gráficos por separado, podemos hacer que los círculos en el dispersiograma tengan un color
distinto en base al grupo al que pertenece la persona.
Hacer el gráfico por separado para hombres y mujeres es más que suficiente, pero al explicar cómo incluir
ambos en el mismo gráfico vamos a aprovechar de explicar algunas funciones más fundamentales de R y
ejemplificar cómo podemos usar las funciones de forma creativa para llegar al resultado que queremos.

Primero tenemos que hacer un objeto con los colores que vamos a ocupar:

colores = c("red","blue")

Esto simplemente crea un objeto con una lista de dos colores. La función c(), que ya habíamos ocupado más
arriba sin explicar, simplemente concatena los elementos para que queden en una lista.

colores
## [1] "red" "blue"

En vez de ocupar rainbow() o repetir los colores que se van a ocupar en cada gráfico, cuando están haciendo
un informe puede ser útil hacer una paleta de colores personalizada ocupando esta función. Esto permite
además cambiar los colores de todos los gráficos sin tener que modificar cada uno de los comandos. Basta
reemplazar los colores en el objeto que crearon.

Lo que tenemos ahora es una lista en que el elemento 1 es “red” y el elemento 2 es “blue”. Los factores (las
variables categóricas) también están codificados como una lista. La función

levels(estudio2012$generof)
## [1] "Mujer" "Hombre"

muestra los valores que puede tener la variable generof. El primer elemento es “Mujer”, y el segundo elemento
es “Hombre”.

La gracia es que ahora podemos reemplazar “Mujer” y “Hombre” por “red” o “blue” tal como aparecen en el
objeto “colores”:

colores[estudio2012$generof] # obtiene los datos de "generof",


## [1] "red" "red" "red" "red" "red" "red" "blue" "blue" "red"
"red"
## [11] "blue" NA "red" "blue" "red" "red" "blue" "red" "blue"
"red"
## [21] "blue" "red" "red" "red" "red" "red" "red" "red" "red"
"red"
## [31] "red" "red" "red" "blue" "red" "red" "red" "blue" "red"
"blue"
## [41] "red" "red" "blue" "red" "blue" "red" "blue" "blue" "red"
"red"
## [51] "red" "red" "red" NA "blue" "red" "red" "red" "red"
"blue"
## [61] "red" "red" "red" "blue" "blue" "red" "red" "red" "blue"
"red"
## [71] "red" "red" "red" "red" "red" "red" "blue" "red" "blue"
"blue"
## [81] "blue" "red" "red" "red" "red" "red" "red" "blue" "red"
"red"
## [91] "red" "blue" "red" "red" "red" "blue" "red" "red" "red"
"red"
## [101] "red" "blue" "red" NA "red" "red" "red" "red" "red"
"red"
## [111] "red" "red"
# ocupando los elementos del objeto
"colores"

Ok, no importa por qué funciona. Lo que importa es que podemos hacer el siguiente gráfico de dispersión:
plot(estudio2012$ansev, estudio2012$insom,
main="Relacion entre ansiedad ante evaluaciones e insomnio",

col=colores[estudio2012$generof], # Magia
xlab="Ansiedad ante evaluaciones",
ylab="Insomnio"
)

También podemos agregar una leyenda con los colores:

legend("topleft", # Ubicación de la leyenda


levels(estudio2012$generof), # Texto de la leyenda.
# Podríamos haber escrito
c("Mujer","Hombre")
col = colores, # Los colores asociados con el
texto
pch=19 # El símbolo a ocupar en la
leyenda
)

También podemos incluir una línea para cada grupo. Esto requiere ocupar solamente a los participantes
hombres o mujeres según corresponda.

Al comienzo de este tutorial, vimos los datos del participante 52 con el comando

estudio2012[52,]

En este caso, lo que está entre corchetes es un subgrupo de la base de datos, con la forma: datos[filas,
columnas]. Si quisiéramos ver los datos de la segunda columna (la situación sentimental), podemos ejecutar

estudio2012[,2]
## [1] En una relacion En una relacion Soltero/a Soltero/a
## [5] Soltero/a Soltero/a Es complicado Soltero/a
## [9] Soltero/a En una relacion Soltero/a En una relacion
## [13] En una relacion Soltero/a En una relacion En una relacion
## [17] Soltero/a En una relacion En una relacion Soltero/a
## [21] Es complicado Soltero/a Soltero/a Soltero/a
## [25] En una relacion En una relacion Es complicado En una relacion
## [29] En una relacion En una relacion En una relacion Soltero/a
## [33] Es complicado Soltero/a En una relacion En una relacion
## [37] En una relacion Soltero/a En una relacion En una relacion
## [41] En una relacion Soltero/a Es complicado Es complicado
## [45] Soltero/a Soltero/a Es complicado En una relacion
## [49] Soltero/a Soltero/a Soltero/a
## [53] Soltero/a Soltero/a Soltero/a Soltero/a
## [57] En una relacion En una relacion Soltero/a Soltero/a
## [61] En una relacion En una relacion En una relacion Soltero/a
## [65] En una relacion Soltero/a Soltero/a En una relacion
## [69] Soltero/a En una relacion Soltero/a En una relacion
## [73] Soltero/a Soltero/a En una relacion En una relacion
## [77] Soltero/a En una relacion En una relacion Soltero/a
## [81] En una relacion En una relacion En una relacion Soltero/a
## [85] En una relacion En una relacion Soltero/a En una relacion
## [89] En una relacion Soltero/a En una relacion Soltero/a
## [93] En una relacion Soltero/a En una relacion En una relacion
## [97] En una relacion En una relacion Soltero/a En una relacion
## [101] Soltero/a En una relacion Es complicado Soltero/a
## [105] En una relacion Soltero/a En una relacion Soltero/a
## [109] En una relacion Soltero/a Soltero/a En una relacion
## Levels: En una relacion Es complicado Soltero/a

Noten que ahora el número está después de la coma, porque se refiere a una columna. Si quisiéramos saber
la situación sentimental del participante 86, tenemos que ejecutar

estudio2012[86,2]
## [1] En una relacion
## Levels: En una relacion Es complicado Soltero/a

Pero los números de fila y columna también pueden ser expresiones lógicas, lo que nos permite seleccionar
parte de la base de datos según alguna condición, por ejemplo que los participantes sean hombres:

estudio2012[estudio2012$generof=="Hombre",]

Noten que la condición está puesta antes de la coma, queremos seleccionar las filas donde el valor de generof
es “Masculino”. El uso de “==” también es importante. Esto es para distinguirlo de “=”, que se ocupa para
asignar el resultado de una función a un objeto. Para dibujar las líneas que mejor se ajustan a los datos de
mujeres y hombres, podemos correr el mismo comando de antes, abline(), pero ocupando un subset de la
base de datos:

plot(estudio2012$ansev, estudio2012$insom,
main="Relacion entre ansiedad ante evaluaciones e insomnio",

col=colores[estudio2012$generof], # Magia

xlab="Ansiedad ante evaluaciones",


ylab="Insomnio"
)
with(estudio2012[estudio2012$generof=="Mujer", ], # Selecciona únicamente
a las mujeres
abline(lm(insom~ansev),
col=colores[1])) # Selecciona el primer color de la
lista

with(estudio2012[estudio2012$generof=="Hombre", ], # Selecciona
únicamente a los hombres
abline(lm(insom~ansev),
col=colores[2])) # Selecciona el segundo color de la
lista

Matriz de correlaciones.
Para terminar con el tema de los gráficos y de la exploración de datos, queda por mencionar que la función
plot() también puede graficar las correlaciones entre múltiples variables. Por ejemplo, podemos ver las
correlaciones entre los cinco factores de personalidad del “big five” en la base de datos que viene con la
librería psych.

En caso de que no la tengan cargada:

library(psych)
personalidad = epi.bfi

La función plot hace automáticamente la matriz de dispersiogramas si le entregan más de dos variables. Para
simplificar los comandos, vamos a crear una nueva base de datos solamente con los factores del big-five.
bf = with(personalidad,
data.frame(bfagree, bfcon, bfext, bfneur, bfopen))

plot(bf)

Si quieren ver la tabla de correlaciones en la consola, pueden ejecutar:

cor(bf)
## bfagree bfcon bfext bfneur bfopen
## bfagree 1.00000 0.4499 0.47848 -0.04462 0.3942
## bfcon 0.44990 1.0000 0.26675 0.04450 0.3052
## bfext 0.47848 0.2668 1.00000 0.03713 0.4588
## bfneur -0.04462 0.0445 0.03713 1.00000 0.2935
## bfopen 0.39415 0.3052 0.45876 0.29348 1.0000

La función round() permite quitar decimales a ésta o cualquier otra tabla.

round(cor(bf), 2)
## bfagree bfcon bfext bfneur bfopen
## bfagree 1.00 0.45 0.48 -0.04 0.39
## bfcon 0.45 1.00 0.27 0.04 0.31
## bfext 0.48 0.27 1.00 0.04 0.46
## bfneur -0.04 0.04 0.04 1.00 0.29
## bfopen 0.39 0.31 0.46 0.29 1.00

La librería psych también tiene funciones gráficas para esto, con algunas opciones extra. En mi opinión estos
gráficos son horribles, pero son útiles para explorar rápidamente las variables. Por defecto, la función
pairs.panels() entrega dispersiogramas con una línea de ajuste, histogramas para ver la distribución de las
variables, y además los coeficientes de correlación.

pairs.panels(bf)

Obviamente, este tipo de gráficos pierde sentido a medida que aumenta el número de variables. Ejecutar

plot(personalidad)

es poco práctico. Pero la librería psych incluye un gráfico que es perfecto para esto, y que no es horrible:
cor.plot(). Este gráfico pone distintos colores dependiendo de qué tan fuerte es la correlación entre dos
variables. A diferencia de plot() o de pairs.panels(), cor.plot() requiere los datos de una tabla de correlaciones.

cor(personalidad)
cor.plot(cor(personalidad))

Como ven, el gráfico permite identificar de manera rápida cuáles son las variables que correlacionan entre si.

Cálculo de escalas y psicometría.


El gráfico de correlaciones que entrega cor.plot() es una excelente introducción al tema de la psicometría
ycómo calcular escalas. Normalmente, al medir constructos psicológicos es preferible ocupar múltiples itemes
ya que cada uno de ellos es un indicador imperfecto de los niveles del constructo. Pero si los ítems
efectivamente están midiendo el mismo constructo, uno esperaría que la correlación entre ellos sea alta. Por
ejemplo, veamos la correlación entre los ítems de insomnio:

x = cor(insomnio, # Vamos a asignar las correlaciones a un objeto, x


use = "pairwise.complete.obs") # necesario cuando hay NAs

round(x, 2) # Imprime la tabla de correlaciones en la consola


## insom1 insom2 insom3 insom4 insom5
## insom1 1.00 0.90 0.37 0.37 0.30
## insom2 0.90 1.00 0.35 0.35 0.31
## insom3 0.37 0.35 1.00 0.09 0.05
## insom4 0.37 0.35 0.09 1.00 0.56
## insom5 0.30 0.31 0.05 0.56 1.00
cor.plot(x) # Grafica la tabla de correlaciones

Claramente, los ítems 1 y 2 correlacionan muy fuertemente entre si (r = .9), y bastante bien con el resto. El
ítem 3 correlaciona algo con el 1 y 2, pero no correlaciona con los ítems 4 y 5, que si correlacionan entre si.

Hay dos formas principales de simplificar toda esta información para poder decidir si estos itemes son una
medición confiable de los niveles de insomnio, o si están midiendo más de un constructo.

La primera, y la más simple, es analizar la confiabilidad de la escala por medio del alpha de Cronbach. La
librería psych tiene un comando para hacer esto.

alpha(insomnio) # Probablemente tienen que moverse en la consola para ver


##
## Reliability analysis
## Call: alpha(x = insomnio)
##
## raw_alpha std.alpha G6(smc) average_r S/N ase mean sd
## 0.74 0.74 0.79 0.36 2.8 0.066 3.6 1.5
##
## lower alpha upper 95% confidence boundaries
## 0.61 0.74 0.87
##
## Reliability if an item is dropped:
## raw_alpha std.alpha G6(smc) average_r S/N alpha se
## insom1 0.61 0.61 0.60 0.28 1.6 0.090
## insom2 0.62 0.62 0.61 0.29 1.6 0.090
## insom3 0.77 0.78 0.82 0.46 3.4 0.071
## insom4 0.70 0.71 0.75 0.38 2.4 0.079
## insom5 0.73 0.73 0.76 0.40 2.7 0.076
##
## Item statistics
## n r r.cor r.drop mean sd
## insom1 111 0.84 0.88 0.70 3.4 2.0
## insom2 111 0.83 0.87 0.69 3.3 2.0
## insom3 110 0.53 0.32 0.27 3.1 2.0
## insom4 110 0.67 0.55 0.48 4.1 2.2
## insom5 110 0.63 0.49 0.42 3.9 2.3
##
## Non missing response frequency for each item
## 1 2 3 4 5 6 7 miss
## insom1 0.20 0.22 0.19 0.09 0.06 0.14 0.11 0.01
## insom2 0.24 0.22 0.14 0.09 0.13 0.09 0.09 0.01
## insom3 0.32 0.18 0.11 0.09 0.13 0.12 0.05 0.02
## insom4 0.15 0.17 0.11 0.13 0.11 0.09 0.24 0.02
## insom5 0.24 0.13 0.08 0.14 0.13 0.07 0.22 0.02
# el output completo de este análisis
help(alpha)

A pesar de los problemas con el ítem 3, la escala tiene un alpha adecuado (std.alpha=.74), pero que podría
ser un poco mejor al eliminar este ítem (.78), que tiene una correlación con el total relativamente baja (r.cor =
.32).

En estos casos, la decisión es más conceptual que estadística. Considerando el contenido del ítem 3 “A veces
me despierto mucho antes de lo que tenía presupuestado”, quizás sea mejor eliminarlo de la escala y ocuparlo
por separado, ya que se refiere a un tipo de insomnio diferente, que además es menos frecuente en personas
jóvenes.

Antes de calcular el puntaje de insomnio sin el ítem 3, revisemos la confiabilidad de esta nueva escala. Ahora
que no podemos ocupar el objeto insomnio que habíamos creado antes, tenemos que escribir cada una de las
variables en la base de datos estudio2012.

La función cbind() combina objetos de R, en este caso columnas en la base de datos estudio2012. También
podríamos haber ocupado data.frame().

with(estudio2012,
alpha(cbind(insom1, insom2, insom4, insom5)))
##
## Reliability analysis
## Call: alpha(x = cbind(insom1, insom2, insom4, insom5))
##
## raw_alpha std.alpha G6(smc) average_r S/N ase mean sd
## 0.77 0.78 0.82 0.46 3.4 0.071 3.7 1.7
##
## lower alpha upper 95% confidence boundaries
## 0.63 0.77 0.91
##
## Reliability if an item is dropped:
## raw_alpha std.alpha G6(smc) average_r S/N alpha se
## insom1 0.67 0.67 0.60 0.40 2.0 0.101
## insom2 0.67 0.67 0.60 0.41 2.0 0.101
## insom4 0.74 0.75 0.79 0.50 3.0 0.091
## insom5 0.77 0.78 0.80 0.54 3.5 0.087
##
## Item statistics
## n r r.cor r.drop mean sd
## insom1 111 0.83 0.85 0.65 3.4 2.0
## insom2 111 0.83 0.85 0.65 3.3 2.0
## insom4 110 0.73 0.58 0.53 4.1 2.2
## insom5 110 0.70 0.53 0.47 3.9 2.3
##
## Non missing response frequency for each item
## 1 2 3 4 5 6 7 miss
## insom1 0.20 0.22 0.19 0.09 0.06 0.14 0.11 0.01
## insom2 0.24 0.22 0.14 0.09 0.13 0.09 0.09 0.01
## insom4 0.15 0.17 0.11 0.13 0.11 0.09 0.24 0.02
## insom5 0.24 0.13 0.08 0.14 0.13 0.07 0.22 0.02

Ahora el alpha subió a .78, y vemos que los ítems 4 y 5 funcionan un poco peor. Más adelante vamos a ver
por qué, pero por ahora vamos a calcular la escala de insomnio con estos cuatro ítems.

Calculo de escalas:
estudio2012$insom = with(estudio2012,
rowMeans(cbind(insom1, insom2, insom4, insom5),
na.rm=TRUE))

Para simplificar las cosas, antes habíamos calculado la escala sumando las variables y dividiendo por el
número de elementos. El principal problema de esto es que no permite especificar qué hacer con los datos
perdidos. Al incluir na.rm=TRUE en la función rowMeans(), especificamos que si alguien contestá solamente
algunos de los cuatro ítems, se calcule el promedio con la información que sí está disponible. De otra forma
ese participante quedaría con un valor NA en esta escala. Ocupando esta opción, un participante quedaría
con NA solamente cuando no haya contestado ninguno de los ítems.

summary(estudio2012$insom)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 1.00 2.50 3.50 3.67 4.75 7.00 1

Revisemos los ítems de ansiedad ante evaluaciones:

names(estudio2012) # ¿Se acuerdan cuál era el nombre de estas variables?


## [1] "n" "sitsent" "desconf1" "desconf2" "desconf3"
## [6] "desconf4" "desconf5" "vidau1" "vidau2" "vidau3"
## [11] "vidau4" "vidau5" "starb1" "starb2" "starb3"
## [16] "starb4" "starb5" "ayude1" "ayude2" "ayude3"
## [21] "ayude4" "ayude5" "abor1" "abor2" "abor3"
## [26] "abor4" "abor5" "tolsex1" "tolsex2" "tolsex3"
## [31] "tolsex4" "tolsex5" "intex1" "intex2" "intex3"
## [36] "intex4" "intex5" "acogex1" "acogex2" "acogex3"
## [41] "acogex4" "acogex5" "ansev1" "ansev2" "ansev3"
## [46] "ansev4" "ansev5" "insom1" "insom2" "insom3"
## [51] "insom4" "insom5" "intui1" "intui2" "intui3"
## [56] "intui4" "intui5" "valma1" "valma2" "valma3"
## [61] "valma4" "valma5" "streu1" "streu2" "streu3"
## [66] "streu4" "streu5" "intay1" "intay2" "intay3"
## [71] "intay4" "intay5" "tprej1" "tprej2" "tprej3"
## [76] "tprej4" "tprej5" "genero" "zodiaco" "orienpol"
## [81] "mencion" "votop" "herman" "lugar" "insom"
## [86] "sitsentf" "generof" "orienpolf" "ansev"
x = cor(with(estudio2012,
cbind(ansev1, ansev2, ansev3, ansev4, ansev5)),
use = "pairwise.complete.obs")

round(x, 2)
## ansev1 ansev2 ansev3 ansev4 ansev5
## ansev1 1.00 0.53 0.32 0.32 0.17
## ansev2 0.53 1.00 0.23 0.31 0.19
## ansev3 0.32 0.23 1.00 0.47 0.31
## ansev4 0.32 0.31 0.47 1.00 0.40
## ansev5 0.17 0.19 0.31 0.40 1.00
cor.plot(x)

Esta escala se ve mucho mejor, ya que todos los ítems correlacionan entre si.

alpha(with(estudio2012,
cbind(ansev1, ansev2, ansev3, ansev4, ansev5)))
##
## Reliability analysis
## Call: alpha(x = with(estudio2012, cbind(ansev1, ansev2, ansev3,
ansev4,
## ansev5)))
##
## raw_alpha std.alpha G6(smc) average_r S/N ase mean sd
## 0.71 0.71 0.69 0.32 2.4 0.07 4 1.3
##
## lower alpha upper 95% confidence boundaries
## 0.57 0.71 0.85
##
## Reliability if an item is dropped:
## raw_alpha std.alpha G6(smc) average_r S/N alpha se
## ansev1 0.65 0.65 0.60 0.32 1.9 0.087
## ansev2 0.66 0.66 0.61 0.33 2.0 0.085
## ansev3 0.65 0.65 0.62 0.32 1.9 0.086
## ansev4 0.63 0.62 0.59 0.29 1.7 0.090
## ansev5 0.69 0.69 0.66 0.36 2.3 0.081
##
## Item statistics
## n r r.cor r.drop mean sd
## ansev1 111 0.69 0.59 0.48 3.8 2.0
## ansev2 111 0.67 0.56 0.45 3.1 1.9
## ansev3 110 0.69 0.57 0.48 4.5 1.8
## ansev4 111 0.74 0.65 0.54 4.1 2.0
## ansev5 111 0.61 0.45 0.37 4.6 1.8
##
## Non missing response frequency for each item
## 1 2 3 4 5 6 7 miss
## ansev1 0.15 0.23 0.08 0.10 0.18 0.19 0.07 0.01
## ansev2 0.27 0.23 0.12 0.08 0.16 0.07 0.06 0.01
## ansev3 0.08 0.08 0.11 0.15 0.24 0.24 0.11 0.02
## ansev4 0.14 0.09 0.20 0.10 0.18 0.13 0.16 0.01
## ansev5 0.06 0.08 0.13 0.16 0.22 0.18 0.17 0.01

La confiabilidad es adecuada (.71) y no mejora al eliminar ningún ítem.

estudio2012$ansev = with(estudio2012,
rowMeans(cbind(ansev1, ansev2, ansev3, ansev4,
ansev5),
na.rm=TRUE))

describe(estudio2012$ansev)
## vars n mean sd median trimmed mad min max range skew kurtosis
se
## 1 1 111 4.03 1.29 4 4 1.48 1 7 6 0.15 -0.51
0.12

Análisis factorial
Es perfectamente posible que una serie de ítems que fueron desarrollados para medir un constructo están en
realidad midiendo dos o tres. Eso es exactamente lo que está ocurriendo con los ítems de insomnio. Aunque
ahora nos vamos a concentrar en el análisis estadístico, este proceso debiera integrar también un análisis
teórico y conceptual.

Entender exactamente cómo funciona un análisis factorial es mucho más avanzado de lo que vamos a cubrir
en el curso. Pero eso no significa que no lo podamos ocupar.

¿Cuántos factores estamos midiendo con los ítems de insomnio? Una forma de responder a esta pregunta es
ejecutar la siguiente función:

fa.parallel(insomnio)
## Loading required package: parallel
## Loading required package: MASS
## Parallel analysis suggests that the number of factors = 2 and the
number of components = 2

fa.parallel() es una función de la librería psych nos ayuda a evaluar cuál es la solución más optima en
términos de cantidad de factores considerando parsimonia -donde tener menos factores es mejor- y ajuste con
los datos -donde tener más factores es mejor.

El gráfico entrega más información de la que realmente necesitamos, lo que importa es la línea de FA (análisis
factorial). El primer factor logra explicar más varianza en la escala que el segundo factor, que a su vez logra
explicar más varianza en la escala que el tercer factor. Agregar un tercer factor es ciertamente poco práctico,
ya que dos factores pueden explicar la mayor parte de la varianza. De hecho, probablemente un solo factor
también es aceptable en este caso.

Con esta información, podemos hacer un análisis factorial exploratorio con dos factores, ocupando la función
fa() de la librería psych.

fa(insomnio, # las variables a incluir en el análisis


2) # la cantidad de factores
## Loading required package: GPArotation
## Factor Analysis using method = minres
## Call: fa(r = insomnio, nfactors = 2)
## Standardized loadings (pattern matrix) based upon correlation matrix
## MR1 MR2 h2 u2 com
## insom1 0.99 -0.01 0.98 0.025 1.0
## insom2 0.90 0.03 0.84 0.164 1.0
## insom3 0.41 -0.09 0.15 0.853 1.1
## insom4 0.15 0.59 0.43 0.567 1.1
## insom5 -0.04 0.89 0.77 0.235 1.0
##
## MR1 MR2
## SS loadings 2.00 1.15
## Proportion Var 0.40 0.23
## Cumulative Var 0.40 0.63
## Proportion Explained 0.63 0.37
## Cumulative Proportion 0.63 1.00
##
## With factor correlations of
## MR1 MR2
## MR1 1.00 0.39
## MR2 0.39 1.00
##
## Mean item complexity = 1
## Test of the hypothesis that 2 factors are sufficient.
##
## The degrees of freedom for the null model are 10 and the objective
function was 2.38 with Chi Square of 258.2
## The degrees of freedom for the model are 1 and the objective function
was 0
##
## The root mean square of the residuals (RMSR) is 0
## The df corrected root mean square of the residuals is 0.01
##
## The harmonic number of observations is 110 with the empirical chi
square 0.04 with prob < 0.84
## The total number of observations was 112 with MLE Chi Square = 0.21
with prob < 0.65
##
## Tucker Lewis Index of factoring reliability = 1.032
## RMSEA index = 0 and the 90 % confidence intervals are NA 0.193
## BIC = -4.51
## Fit based upon off diagonal values = 1
## Measures of factor score adequacy
## MR1 MR2
## Correlation of scores with factors 0.99 0.90
## Multiple R square of scores with factors 0.98 0.81
## Minimum correlation of possible factor scores 0.96 0.61

Puede ser que también sea necesario instalar GPArotation, si es que no se instaló con psych.

install.packages("GPArotation")
library(GPArotation)

La información entregada en la primera tabla nos indica cuánto se relaciona cada ítem con cada uno de los
factores. Esto puede verse de forma gráfica con

plot(fa(insomnio,2))

Los ítems 1 y 2 se relacionan fuertemente con el primer factor (MR1), y los ítems 4 y 5 se relacionan
fuertemente con el segundo factor (MR2). El ítem 3 está más relacionado con el primer factor (.41) que con el
segundo (-.09).

¿Qué significa esto? Significa que la escala mide dos cosas, que de hecho son perfectamente comprensibles
al leer los ítems:

Factor 1: Problemas de insomnio. Generalmente me cuesta conciliar el sueño o despierto muchas veces en la
noche (insom1) Suelo presentar grandes dificultades para iniciar y mantener el sueño (insom2) A veces me
despierto mucho antes de lo que tenía presupuestado (insom3)

Factor 2: Conductas problemáticas de higiene del sueño. Cuando es hora de dormir, me dan ganas de ver
televisión, leer o hacer otra cosa (insom4) Suelo tener horarios de sueño desordenados, dormir siestas o
pasar un tiempo excesivo en la cama (insom5)

Obviamente estos dos constructos están relacionados, de hecho tienen una correlación de .39 según el
análisis factorial. Pero no son lo mismo.

Revisemos la confiabilidad antes de calcular cada escala.

Problemas de insomnio:

alpha(with(estudio2012,
cbind(insom1, insom2, insom3)))
##
## Reliability analysis
## Call: alpha(x = with(estudio2012, cbind(insom1, insom2, insom3)))
##
## raw_alpha std.alpha G6(smc) average_r S/N ase mean sd
## 0.78 0.78 0.8 0.54 3.5 0.085 3.3 1.7
##
## lower alpha upper 95% confidence boundaries
## 0.61 0.78 0.95
##
## Reliability if an item is dropped:
## raw_alpha std.alpha G6(smc) average_r S/N alpha se
## insom1 0.51 0.51 0.35 0.35 1.1 0.16
## insom2 0.54 0.54 0.37 0.37 1.2 0.16
## insom3 0.95 0.95 0.90 0.90 18.4 0.10
##
## Item statistics
## n r r.cor r.drop mean sd
## insom1 111 0.91 0.93 0.77 3.4 2
## insom2 111 0.90 0.92 0.76 3.3 2
## insom3 110 0.69 0.38 0.37 3.1 2
##
## Non missing response frequency for each item
## 1 2 3 4 5 6 7 miss
## insom1 0.20 0.22 0.19 0.09 0.06 0.14 0.11 0.01
## insom2 0.24 0.22 0.14 0.09 0.13 0.09 0.09 0.01
## insom3 0.32 0.18 0.11 0.09 0.13 0.12 0.05 0.02

El alpha es .78.

estudio2012$insom = with(estudio2012,
rowMeans(cbind(insom1, insom2, insom3),
na.rm=TRUE))
summary(estudio2012$insom)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 1.00 2.00 3.00 3.26 4.33 7.00 1

Conductas problemáticas insomnio:

alpha(with(estudio2012,
cbind(insom4, insom5)))
##
## Reliability analysis
## Call: alpha(x = with(estudio2012, cbind(insom4, insom5)))
##
## raw_alpha std.alpha G6(smc) average_r S/N ase mean sd
## 0.71 0.71 0.56 0.56 2.5 0.14 4 2
##
## lower alpha upper 95% confidence boundaries
## 0.44 0.71 0.99
##
## Reliability if an item is dropped:
## raw_alpha std.alpha G6(smc) average_r S/N alpha se
## insom4 0.56 0.56 0.31 0.56 NA NA
## insom5 0.56 0.56 0.31 0.56 NA NA
##
## Item statistics
## n r r.cor r.drop mean sd
## insom4 110 0.88 0.66 0.56 4.1 2.2
## insom5 110 0.88 0.66 0.56 3.9 2.3
##
## Non missing response frequency for each item
## 1 2 3 4 5 6 7 miss
## insom4 0.15 0.17 0.11 0.13 0.11 0.09 0.24 0.02
## insom5 0.24 0.13 0.08 0.14 0.13 0.07 0.22 0.02

El alpha es .71, aunque con dos ítems normalmente se reporta la correlación (.56)

estudio2012$cinsom = with(estudio2012,
rowMeans(cbind(insom4, insom5),
na.rm=TRUE))

summary(estudio2012$cinsom)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 1.00 2.00 4.00 3.98 5.50 7.00 1
¿qué pasa cuando hacemos un análisis factorial para los ítems de ansiedad en periodo de evaluaciones? De
acuerdo al scree plot,

fa.parallel(with(estudio2012,
cbind(ansev1, ansev2, ansev3, ansev4, ansev5)))

## Parallel analysis suggests that the number of factors = 2 and the


number of components = 1

parece que la mejor solución es ocupar dos factores, aunque también sería aceptable ocupar uno.

x = fa(with(estudio2012,
cbind(ansev1, ansev2, ansev3, ansev4, ansev5)),2)

esta vez asignamos el análisis factorial a un objeto x

x
## Factor Analysis using method = minres
## Call: fa(r = with(estudio2012, cbind(ansev1, ansev2, ansev3, ansev4,
## ansev5)), nfactors = 2)
## Standardized loadings (pattern matrix) based upon correlation matrix
## MR2 MR1 h2 u2 com
## ansev1 -0.01 1.00 1.00 0.005 1.0
## ansev2 0.19 0.45 0.32 0.685 1.4
## ansev3 0.56 0.09 0.37 0.633 1.0
## ansev4 0.79 -0.01 0.62 0.379 1.0
## ansev5 0.53 -0.05 0.26 0.738 1.0
##
## MR2 MR1
## SS loadings 1.30 1.26
## Proportion Var 0.26 0.25
## Cumulative Var 0.26 0.51
## Proportion Explained 0.51 0.49
## Cumulative Proportion 0.51 1.00
##
## With factor correlations of
## MR2 MR1
## MR2 1.00 0.43
## MR1 0.43 1.00
##
## Mean item complexity = 1.1
## Test of the hypothesis that 2 factors are sufficient.
##
## The degrees of freedom for the null model are 10 and the objective
function was 0.96 with Chi Square of 104.4
## The degrees of freedom for the model are 1 and the objective function
was 0
##
## The root mean square of the residuals (RMSR) is 0.01
## The df corrected root mean square of the residuals is 0.03
##
## The harmonic number of observations is 111 with the empirical chi
square 0.26 with prob < 0.61
## The total number of observations was 112 with MLE Chi Square = 0.31
with prob < 0.58
##
## Tucker Lewis Index of factoring reliability = 1.075
## RMSEA index = 0 and the 90 % confidence intervals are NA 0.205
## BIC = -4.41
## Fit based upon off diagonal values = 1
## Measures of factor score adequacy
## MR2 MR1
## Correlation of scores with factors 0.86 1.00
## Multiple R square of scores with factors 0.74 1.00
## Minimum correlation of possible factor scores 0.48 0.99
plot(x)

Los ítems 3, 4 y 5 cargan en un factor (MR2), y los ítems 1 y 2 cargan en otro (MR1). El factor MR2 puede ser
más propiamente llamado ansiedad en periodo de evaluaciones (irritable, dolores e incapacidad de
desconectarse), el segundo factor son los ítems de insomnio durante este periodo. Al revisar la confiabilidad
que tendrían estas escalas,

alpha(with(estudio2012,
cbind(ansev3, ansev4, ansev5)))
##
## Reliability analysis
## Call: alpha(x = with(estudio2012, cbind(ansev3, ansev4, ansev5)))
##
## raw_alpha std.alpha G6(smc) average_r S/N ase mean sd
## 0.66 0.66 0.57 0.39 1.9 0.1 4.4 1.4
##
## lower alpha upper 95% confidence boundaries
## 0.46 0.66 0.86
##
## Reliability if an item is dropped:
## raw_alpha std.alpha G6(smc) average_r S/N alpha se
## ansev3 0.57 0.57 0.40 0.40 1.3 0.16
## ansev4 0.47 0.47 0.31 0.31 0.9 0.17
## ansev5 0.64 0.64 0.47 0.47 1.8 0.15
##
## Item statistics
## n r r.cor r.drop mean sd
## ansev3 110 0.77 0.58 0.47 4.5 1.8
## ansev4 111 0.81 0.66 0.54 4.1 2.0
## ansev5 111 0.74 0.50 0.42 4.6 1.8
##
## Non missing response frequency for each item
## 1 2 3 4 5 6 7 miss
## ansev3 0.08 0.08 0.11 0.15 0.24 0.24 0.11 0.02
## ansev4 0.14 0.09 0.20 0.10 0.18 0.13 0.16 0.01
## ansev5 0.06 0.08 0.13 0.16 0.22 0.18 0.17 0.01
alpha(with(estudio2012,
cbind(ansev1, ansev2))) # normalmente se reporta la correlación
cuando hay 2 ítemes
##
## Reliability analysis
## Call: alpha(x = with(estudio2012, cbind(ansev1, ansev2)))
##
## raw_alpha std.alpha G6(smc) average_r S/N ase mean sd
## 0.69 0.69 0.53 0.53 2.3 0.14 3.4 1.7
##
## lower alpha upper 95% confidence boundaries
## 0.41 0.69 0.97
##
## Reliability if an item is dropped:
## raw_alpha std.alpha G6(smc) average_r S/N alpha se
## ansev1 0.53 0.53 0.28 0.53 NA NA
## ansev2 0.53 0.53 0.28 0.53 NA NA
##
## Item statistics
## n r r.cor r.drop mean sd
## ansev1 111 0.87 0.64 0.53 3.8 2.0
## ansev2 111 0.87 0.64 0.53 3.1 1.9
##
## Non missing response frequency for each item
## 1 2 3 4 5 6 7 miss
## ansev1 0.15 0.23 0.08 0.10 0.18 0.19 0.07 0.01
## ansev2 0.27 0.23 0.12 0.08 0.16 0.07 0.06 0.01

vemos que es usable, pero ciertamente no es buena. ¿qué hacer en este caso? La respuesta no está en los
análisis estadísticos, sino en un análisis conceptual y de los objetivos de investigación. Los dos ítems de
insomnio (ansev1 y ansev2) no correlacionan muy bien, y además ya tenemos otra escala para medir
insomnio en general. Por lo tanto, creo que lo mejor es ocupar solamente el primer factor sin incluir los ítems
de insomnio.

estudio2012$ansev = with(estudio2012,
rowMeans(cbind(ansev3, ansev4, ansev5),
na.rm=TRUE))

summary(estudio2012$ansev)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 1.00 3.33 4.67 4.42 5.67 7.00 1

Itemes invertidos.
Es común que las escalas incluyan ítems invertidos, donde un mayor puntaje en el item refleja un menor nivel
en el constructo que se quiere medir. Por ejemplo, la escala de “tolerancia hacia la diversidad sexual” tiene los
siguientes ítems:

(tolsex1) Me siento incómodo compartiendo socialmente con personas que son de distinta orientación sexual
a la mía. (tolsex2) Las relaciones de pareja no heterosexuales son “anti naturales”. (tolsex3) Las parejas del
mismo sexo no deberían andar de la mano ni besarse en público. (tolsex4) Considero que el matrimonio
debiera ser sólo entre un hombre y una mujer. (tolsex5) Me gustaría que cambiaran las leyes para promover
un mayor respeto a las minorías sexuales.

En realidad, esta escala debiera llamarse “intolerancia” a la diversidad sexual. Un mayor puntaje en los ítems
1, 2, 3 o 4 se asocia a una mayor intolerancia. Pero el quinto ítem está invertido: un mayor puntaje se asocia a
una menor intolerancia.

Veamos que pasa con estos ítems en un análisis factorial.

tolsex = with(estudio2012,
data.frame(tolsex1, tolsex2, tolsex3, tolsex4, tolsex5))

fa.parallel(tolsex)

## Parallel analysis suggests that the number of factors = 1 and the


number of components = 1

A diferencia de las escalas que revisamos antes, estos ítems se agrupan claramente en un factor.

fa(tolsex)
## Factor Analysis using method = minres
## Call: fa(r = tolsex)
## Standardized loadings (pattern matrix) based upon correlation matrix
## MR1 h2 u2 com
## tolsex1 0.25 0.063 0.94 1
## tolsex2 0.80 0.640 0.36 1
## tolsex3 0.75 0.565 0.43 1
## tolsex4 0.88 0.774 0.23 1
## tolsex5 -0.61 0.367 0.63 1
##
## MR1
## SS loadings 2.41
## Proportion Var 0.48
##
## Mean item complexity = 1
## Test of the hypothesis that 1 factor is sufficient.
##
## The degrees of freedom for the null model are 10 and the objective
function was 1.81 with Chi Square of 196.2
## The degrees of freedom for the model are 5 and the objective function
was 0.03
##
## The root mean square of the residuals (RMSR) is 0.03
## The df corrected root mean square of the residuals is 0.05
##
## The harmonic number of observations is 111 with the empirical chi
square 2.38 with prob < 0.79
## The total number of observations was 112 with MLE Chi Square = 3.12
with prob < 0.68
##
## Tucker Lewis Index of factoring reliability = 1.02
## RMSEA index = 0 and the 90 % confidence intervals are NA 0.102
## BIC = -20.47
## Fit based upon off diagonal values = 1
## Measures of factor score adequacy
## MR1
## Correlation of scores with factors 0.94
## Multiple R square of scores with factors 0.88
## Minimum correlation of possible factor scores 0.75
plot(fa(tolsex))

Como debiera ser, el ítem 5 tiene una relación negativa con el factor. Esto está indicado al comienzo de los
resultados del análisis factorial, en la columna MR1 de los loadings estandarizados. Además, el ítem 1 parece
no estar funcionando muy bien con el resto de la escala, su relación con el factor general es claramente
menor al resto (0.25). Si hacemos un análisis de confiabilidad,

alpha(tolsex)
## Warning: Some items were negatively correlated with total scale and
were
## automatically reversed.
##
## Reliability analysis
## Call: alpha(x = tolsex)
##
## raw_alpha std.alpha G6(smc) average_r S/N ase mean sd
## 0.79 0.79 0.78 0.43 3.7 0.059 2.2 1.4
##
## lower alpha upper 95% confidence boundaries
## 0.67 0.79 0.9
##
## Reliability if an item is dropped:
## raw_alpha std.alpha G6(smc) average_r S/N alpha se
## tolsex1 0.83 0.84 0.81 0.57 5.4 0.063
## tolsex2 0.71 0.71 0.69 0.38 2.5 0.078
## tolsex3 0.72 0.71 0.70 0.38 2.4 0.076
## tolsex4 0.69 0.69 0.66 0.36 2.2 0.081
## tolsex5- 0.75 0.75 0.75 0.43 3.1 0.072
##
## Item statistics
## n r r.cor r.drop mean sd
## tolsex1 111 0.49 0.28 0.24 1.9 1.5
## tolsex2 111 0.80 0.77 0.69 2.0 1.7
## tolsex3 111 0.81 0.76 0.69 1.9 1.5
## tolsex4 111 0.85 0.84 0.74 2.9 2.4
## tolsex5- 111 0.72 0.61 0.55 2.2 1.9
##
## Non missing response frequency for each item
## 1 2 3 4 5 6 7 miss
## tolsex1 0.59 0.20 0.08 0.05 0.02 0.03 0.04 0.01
## tolsex2 0.65 0.11 0.07 0.06 0.04 0.02 0.05 0.01
## tolsex3 0.65 0.13 0.06 0.04 0.08 0.04 0.01 0.01
## tolsex4 0.58 0.03 0.04 0.05 0.07 0.08 0.15 0.01
## tolsex5 0.06 0.04 0.04 0.10 0.05 0.10 0.62 0.01

R automáticamente invierte el ítem 5, imprime un aviso en la consola, e indica que se invirtió el ítem con un
signo - junto a su nombre. El alpha de la escala es bueno (.79), pero quedaría mejor si se elimina el ítem 1
(.84).

Nuevamente, esta decisión tiene que ser conceptual también. A mí me parece adecuado eliminarlo, no porque
sea un mal ítem, sino porque está midiendo algo ligeramente distinto -una reacción emocional vs. actitudes
conservadoras más discursivas.

Antes de promediar los ítems, en todo caso, ¡tenemos que invertir los valores de tolsex5! Lo más fácil es
hacerlo directamente con la fórmula:

Puntaje invertido = Máximo + Mínimo - Puntaje original.

estudio2012$tolsex5i = 7 + 1 - estudio2012$tolsex5

summary(estudio2012$tolsex5i)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 1.00 1.00 1.00 2.19 3.00 7.00 1

Ahora podemos calcular la escala, donde un mayor puntaje va a reflejar un menor nivel de tolerancia hacia la
diversidad sexual. Por lo tanto, vamos a aprovechar de cambiarle el nombre a “intolsex” (mayor puntaje mayor
intolerancia)

estudio2012$intolsex = with(estudio2012,
rowMeans(cbind(tolsex2, tolsex3, tolsex4,
tolsex5i),
na.rm=TRUE))

summary(estudio2012$intolsex)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 1.00 1.00 1.25 2.25 3.00 7.00 1
Contraste de hipótesis y
estimación de parámetros
poblacionales
Hasta ahora, hemos visto una serie de análisis, gráficos y tablas para visualizar la información obtenida en la
muestra. Las siguientes secciones tratan en cambio sobre la estimación de lo que está ocurriendo en la
población, a partir de los datos muestrales.

Chi-cuadrado
Relaciones entre variables categóricas.
En las secciones anteriores vimos cómo producir una tabla para ver la cantidad de personas que pertenecen a
ciertos grupos o categorías,

table(estudio2012$sitsentf)
##
## En una relacion Es complicado Soltero/a
## 54 8 49

o hacer un cruce entre dos variables categóricas, como por ejemplo comparar la situación sentimental de
hombres y mujeres:

table(estudio2012$sitsentf, estudio2012$generof)
##
## Mujer Hombre
## En una relacion 44 9
## Es complicado 4 4
## Soltero/a 33 14

¿Cómo saber si estas dos variables están relacionadas? ¿Es más probable que los hombres tengan
relaciones complicadas? El análisis que corresponde ocupar para contestar esta pregunta es un análisis de
chi-cuadrado, que puede aplicarse a la frecuencia de una sola variable categórica, o a un cruce de varias
variables.

La función para hacer un análisis de chi-cuadrado es chisq.test(), y requiere la información de una tabla de
frecuencia -que puede obtenerse con table(). Por ejemplo,

table(estudio2012$generof) # Obtiene la cantidad de hombres y mujeres en


la muestra.
##
## Mujer Hombre
## 82 27
chisq.test(table(estudio2012$generof)) # Hace un análisis de chi-cuadrado
con esta tabla.
##
## Chi-squared test for given probabilities
##
## data: table(estudio2012$generof)
## X-squared = 27.75, df = 1, p-value = 1.379e-07
A partir de este análisis de chi-cuadrado vemos que la probabilidad de que nuestra muestra venga de una
población donde hay igual cantidad de hombres y mujeres es tremendamente baja (x2 = 27.75, p < .05). Esto
nos indica que debemos rechazar esta hipótesis nula y concluir que en la carrera de psicología en nuestra
universidad hay más mujeres que hombres.

Al parecer las mujeres tienen menos probabilidades de estar solteras que los hombres, quienes además
tienen más probabilidades de estar en relaciones complicadas.

table(estudio2012$sitsentf, estudio2012$generof)
##
## Mujer Hombre
## En una relacion 44 9
## Es complicado 4 4
## Soltero/a 33 14

Veamos si podemos generalizar esto a la población de estudiantes de psicología.

chisq.test(table(estudio2012$sitsentf, estudio2012$generof))
## Warning: Chi-squared approximation may be incorrect
##
## Pearson's Chi-squared test
##
## data: table(estudio2012$sitsentf, estudio2012$generof)
## X-squared = 5.059, df = 2, p-value = 0.07971

Como se observa en la consola, la relación entre estas variables no alcanza a ser estadísticamente
significativa (x2 = 5.05, p = .08). Además, R imprime un mensaje advirtiendo que la estimación del chi-
cuadrado puede ser incorrecta. Esto se debe a que hay muy pocas mujeres y muy pocos hombres (menos de
5) que tienen una relación complicada.

La función table() tiene un argumento especialmente diseñado para estos casos, es decir, para excluir ciertas
categorías del análisis:

table(estudio2012$sitsentf, estudio2012$generof,
exclude="Es complicado")
##
## Mujer Hombre
## En una relacion 44 9
## Soltero/a 33 14

Esta vez, vamos a asignar el resultado del análisis a un objeto llamado x2 (podríamos haber puesto cualquier
nombre)

x2 = chisq.test(table(estudio2012$sitsentf, estudio2012$generof,
exclude="Es complicado"))

x2
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: table(estudio2012$sitsentf, estudio2012$generof, exclude = "Es
complicado")
## X-squared = 1.64, df = 1, p-value = 0.2003

La probabilidad de que esta muestra venga de una población donde el género no se relaciona con estar
soltero(a) o en un una relación es mayor a .05 (x2 = 1.64, p = .2), por lo que no corresponde rechazar la
hipótesis nula. Los hombres y las mujeres que están estudiando psicología tienen la misma probabilidad de
estar en una relación.
También podríamos haber ocupado una simulación para calcular el valor de p, lo que es más adecuado
cuando tenemos poco n. El resultado es básicamente el mismo, no hay una relación significativa entre género
y situación sentimental.

chisq.test(table(estudio2012$sitsentf, estudio2012$generof),
simulate.p.value=TRUE)
##
## Pearson's Chi-squared test with simulated p-value (based on 2000
## replicates)
##
## data: table(estudio2012$sitsentf, estudio2012$generof)
## X-squared = 5.059, df = NA, p-value = 0.07996

El análisis de chi-cuadrado, como la mayoría de los análisis que vamos a ver de ahora en adelante, son
objetos más complejos que los que hemos visto hasta ahora.

Si bien ejecutar

x2 # el nombre del objeto al que asignamos el análisis de chi-cuadrado


##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: table(estudio2012$sitsentf, estudio2012$generof, exclude = "Es
complicado")
## X-squared = 1.64, df = 1, p-value = 0.2003

nos entrega la información básica, el objeto “x2” tiene más información. Para acceder a esta información se
ocupa el mismo formato con que seleccionamos una variable en una base de datos. Por ejemplo, para
obtener la tabla de valores observados, podemos ocupar

x2$observed
##
## Mujer Hombre
## En una relacion 44 9
## Soltero/a 33 14

lo que es exactamente lo mismo que la tabla original con que hicimos el análisis. Para obtener los valores
esperados según la hipótesis nula, podemos ejecutar

x2$expected
##
## Mujer Hombre
## En una relacion 40.81 12.19
## Soltero/a 36.19 10.81

En cualquier análisis, los valores que pueden obtenerse están listados en la página de ayuda.

help(chisq.test) # ver "Value"

Estimación del promedio poblacional y relaciones entre variables categóricas y numéricas.

Prueba t
Prueba t para una muestra:
Estimación del promedio de la población.
En caso de querer estimar los niveles poblacionales de una variable numérica, pueden hacer una prueba t
para una muestra en esta variable con la función t.test(). Por ejemplo, los datos de escala de intolerancia a la
diversidad sexual

t.test(estudio2012$intolsex)
##
## One Sample t-test
##
## data: estudio2012$intolsex
## t = 15.04, df = 110, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
## 1.950 2.541
## sample estimates:
## mean of x
## 2.245

indican que el promedio poblacional está entre 1.95 y 2.54 ocupando un intervalo de confianza de 95%.
Considerando que la escala es de 1 a 7, el nivel es bastante bajo. Por defecto, la hipótesis nula de esta
prueba es que el promedio poblacional es igual a cero, algo que por supuesto no tiene sentido en esta escala
de 1 a 7. Para cambiar la hipótesis nula, por ejemplo para estimar la probabilidad de que esta muestra venga
de una población en que el promedio es cuatro (el punto medio de la escala), es necesario agregar el
parámetro mu:

t.test(estudio2012$intolsex, mu=4)
##
## One Sample t-test
##
## data: estudio2012$intolsex
## t = -11.76, df = 110, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 4
## 95 percent confidence interval:
## 1.950 2.541
## sample estimates:
## mean of x
## 2.245

Obviamente, la probabilidad es tremendamente baja (p < 2.2e-16; eso son 16 ceros después de la coma).

La librería psych incluye un comando para hacer gráficos con barras de error ocupando intervalos de
confianza.

error.bars(with(estudio2012,
data.frame(ansev1, ansev2, ansev3, ansev4, ansev5)),
eyes = FALSE, ylim=c(1,7))

Este gráfico puede ser una forma útil de comparar los niveles de diferentes variables considerando
información de estadística inferencial, pero es importante destacar que no es una prueba de hipótesis
estadísticas. Son estimaciones independientes del promedio poblacional en cada ítem.

Prueba t para muestras independientes:


Comparación del promedio de dos grupos.
La misma función que ocupamos en la sección anterior, t.test(), puede ser ocupada para comparar los
promedios de dos grupos de participantes, y evaluar la hipótesis nula de que ambos tienen el mismo promedio
en la población. El formato para hacer este análisis es el mismo que ya hemos visto otras veces: la variable
dependiente predicha por la variable independiente (y~x). A modo de ejemplo, podemos evaluar si los niveles
de intolerancia a la diversidad sexual son diferentes según el género de los participantes:

t.test(estudio2012$intolsex~estudio2012$generof)
##
## Welch Two Sample t-test
##
## data: estudio2012$intolsex by estudio2012$generof
## t = 2.483, df = 64.78, p-value = 0.01562
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## 0.1401 1.2920
## sample estimates:
## mean in group Mujer mean in group Hombre
## 2.392 1.676

Curiosamente, las mujeres muestran mayores niveles de intolerancia que los hombres (t(64)=2.48, p < .05).
Es importante recordar que estos resultados son generalizables a una población particular; estudiantes de
psicología de nuestra universidad, y no a los hombres y mujeres de chile, por ejemplo. Al revisar los
resultados de otras variables, como opiniones hacia el aborto y orientación política, pareciera que las mujeres
tienden a ser más conservadoras que los hombres en esta población, lo que podría explicar las diferencias en
tolerancia hacia la diversidad sexual.

table(estudio2012$orienpolf, estudio2012$generof)
##
## Mujer Hombre
## Izquierda 10 8
## Centro Izquierda 16 4
## Centro 7 1
## Centro Derecha 15 3
## Derecha 18 0

Volviendo a la revisión del output de una prueba t de muestras independientes, es importante notar un par de
aspectos más técnicos.

t.test(estudio2012$intolsex~estudio2012$generof)
##
## Welch Two Sample t-test
##
## data: estudio2012$intolsex by estudio2012$generof
## t = 2.483, df = 64.78, p-value = 0.01562
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## 0.1401 1.2920
## sample estimates:
## mean in group Mujer mean in group Hombre
## 2.392 1.676

El título de esta prueba indica que se realizó una prueba t de Welch. Esto es porque las varianzas de los
grupos no son iguales, y R automáticamente realiza el ajuste apropiado. Para forzar una prueba t clásica se
puede agregar el argumento

t.test(estudio2012$intolsex~estudio2012$generof,
var.equal=TRUE)
##
## Two Sample t-test
##
## data: estudio2012$intolsex by estudio2012$generof
## t = 2.073, df = 106, p-value = 0.04059
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## 0.03124 1.40086
## sample estimates:
## mean in group Mujer mean in group Hombre
## 2.392 1.676

que indica que deben asumirse varianzas iguales. Esto no es recomendado, ¡para eso existe este ajuste!

Otro detalle es que esta función realiza por defecto un contraste de hipótesis bilateral. En caso de que se
quiera hacer un contraste unilateral, pueden ocupar el argumento:

t.test(estudio2012$intolsex~estudio2012$generof,
alternative="greater")
##
## Welch Two Sample t-test
##
## data: estudio2012$intolsex by estudio2012$generof
## t = 2.483, df = 64.78, p-value = 0.007811
## alternative hypothesis: true difference in means is greater than 0
## 95 percent confidence interval:
## 0.2349 Inf
## sample estimates:
## mean in group Mujer mean in group Hombre
## 2.392 1.676

Pero incluso aunque quieran hacer un contraste unilateral esto no es necesario, la probabilidad asociada a la
hipótesis nula en un contraste unilateral es simplemente la mitad de la probabilidad obtenida en un contraste
bilateral.

Prueba t para muestras dependientes


Comparar el promedio poblacional de dos variables
en un grupo.
Para realizar una prueba t para muestras dependientes simplemente hay que agregar un argumento a la
función t.test(): paired=TRUE.

Esta prueba asume que las variables efectivamente son comparables, lo que no siempre es cierto. En este
estudio, la escala de empatía frente al aborto parece adecuada, ya que los participantes tenían que contestar
la misma pregunta pero referida a distintas situaciones:

“Imagina que una mujer recientemente tuvo un aborto y te relata su experiencia. ¿Qué tanto puedes empatizar
con ella en las siguientes situaciones?” (desde 1 = nada, hasta 7 = mucho).

Las situaciones presentadas fueron las siguientes:

abor1 Mi embarazo era un riesgo grave para mi salud. abor2 Mi hijo hubiese nacido con una enfermedad
genética grave que lo condenaba a sufrir. abor3 Fui víctima de violación, tenerlo hubiera sido un recuerdo
constante de mi experiencia traumática. abor4 Por razones económicas era incapaz de hacerme cargo de un
hijo, no hubiese podido abastecerlo ni en sus necesidades más básicas. abor5 Hubiera sido una madre
soltera, estigmatizada por el resto de mi vida.

En general, los niveles de empatía reportados disminuyen progresivamente:

with(estudio2012,
describe(data.frame(abor1, abor2, abor3, abor4, abor5)))
## vars n mean sd median trimmed mad min max range skew
kurtosis
## abor1 1 111 5.26 1.83 6 5.51 1.48 1 7 6 -0.81 -
0.51
## abor2 2 111 4.60 2.01 5 4.75 2.97 1 7 6 -0.49 -
1.01
## abor3 3 110 4.85 2.07 5 5.05 2.97 1 7 6 -0.50 -
1.14
## abor4 4 111 3.08 1.95 3 2.90 2.97 1 7 6 0.51 -
1.03
## abor5 5 111 2.03 1.40 1 1.76 0.00 1 7 6 1.38
1.15
## se
## abor1 0.17
## abor2 0.19
## abor3 0.20
## abor4 0.19
## abor5 0.13

Dado que es la misma escala para cada situación, podemos comparar dos de ellas con una prueba t de
muestras dependientes. Por ejemplo, ¿Produce más empatía una situación de riesgo grave para la salud de la
madre que una situación donde se encuentra una enfermedad genética grave en el hijo(a)?

t.test(estudio2012$abor1, estudio2012$abor2,
paired=TRUE)
##
## Paired t-test
##
## data: estudio2012$abor1 and estudio2012$abor2
## t = 3.97, df = 110, p-value = 0.0001283
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## 0.3294 0.9859
## sample estimates:
## mean of the differences
## 0.6577

Sí, al menos en esta población. La probabilidad de obtener una diferencia mayor o igual a ésta si los
promedios fueran iguales en la población es menor a .05, por lo que podemos rechazar la hipótesis nula.

ANOVA Simple
Comparación de los promedios de
múltiples grupos.
Para comparar los promedios de más de dos grupos es necesario hacer un análisis de varianza. La función
para hacer esto en R es aov(). Para estos análisis, vamos a ocupar la escala de intuición:
intui1 Muchas veces tengo muy claro la decisión que voy a tomar, aunque no podría explicar por qué. intui2 A
veces siento que puedo predecir lo que va a pasar antes de que suceda, como por ejemplo que me llamar?
alguien.??? intui3 Siento que puedo sabercómo es una persona casi inmediatamente, incluso antes de
conversar con ella. intui4 Si en una prueba o examen de alternativas no me acuerdo de la materia, muchas
veces puedo elegir de forma intuitiva, porque “algo” me dice que es la respuesta correcta. intui5 Para cosas
realmente importantes, confío más en mis sentimientos e intuición que en argumentos racionales.

alpha(with(estudio2012,
data.frame(intui1, intui2, intui3, intui4, intui5)))
##
## Reliability analysis
## Call: alpha(x = with(estudio2012, data.frame(intui1, intui2, intui3,
## intui4, intui5)))
##
## raw_alpha std.alpha G6(smc) average_r S/N ase mean sd
## 0.67 0.67 0.63 0.29 2.1 0.076 3.8 1.1
##
## lower alpha upper 95% confidence boundaries
## 0.52 0.67 0.82
##
## Reliability if an item is dropped:
## raw_alpha std.alpha G6(smc) average_r S/N alpha se
## intui1 0.67 0.68 0.62 0.34 2.1 0.084
## intui2 0.60 0.60 0.54 0.28 1.5 0.094
## intui3 0.58 0.59 0.52 0.26 1.4 0.096
## intui4 0.61 0.61 0.55 0.28 1.6 0.092
## intui5 0.62 0.63 0.57 0.30 1.7 0.091
##
## Item statistics
## n r r.cor r.drop mean sd
## intui1 111 0.57 0.37 0.30 4.1 1.7
## intui2 110 0.69 0.57 0.46 3.4 1.9
## intui3 111 0.71 0.62 0.51 3.7 1.6
## intui4 110 0.68 0.55 0.44 3.7 1.5
## intui5 111 0.65 0.51 0.42 3.9 1.6
##
## Non missing response frequency for each item
## 1 2 3 4 5 6 7 miss
## intui1 0.07 0.15 0.14 0.16 0.24 0.14 0.09 0.01
## intui2 0.24 0.19 0.12 0.05 0.24 0.12 0.05 0.02
## intui3 0.08 0.18 0.19 0.21 0.23 0.08 0.04 0.01
## intui4 0.06 0.20 0.21 0.21 0.19 0.09 0.04 0.02
## intui5 0.07 0.14 0.19 0.25 0.18 0.11 0.05 0.01

Parece mejor eliminar el ítem 1.

estudio2012$intui = with(estudio2012,
rowMeans(data.frame(intui2, intui3, intui4,
intui5),
na.rm=TRUE))

¿Está relacionada la intuición con el signo zodiacal? Primero tenemos que preparar la variable zodiaco.

table(estudio2012$zodiaco)
##
## ...
## 2
## Acuario (21 Enero - 19 Febrero)
## 8
## Aries (21 Marzo - 20 Abril)
## 7
## Cancer (21 Junio - 22 Julio)
## 10
## Capricornio (22 Diciembre - 20 Enero)
## 8
## Escorpion (24 Octubre - 21 Noviembre)
## 7
## Geminis (21 Mayo - 20 Junio)
## 9
## Leo (23 Julio - 22 Agosto)
## 7
## Libra (23 Septiembre - 23 Octubre)
## 11
## Piscis (20 Febrero - 20 Marzo)
## 12
## Sagitario (22 Noviembre - 21 Diciembre)
## 10
## Tauro (21 Abril - 20 Mayo)
## 12
## Virgo (23 Agosto - 22 Septiembre)
## 9
estudio2012$zodiacof = factor(estudio2012$zodiaco,
levels=c("Acuario (21 Enero - 19 Febrero)",
"Piscis (20 Febrero - 20 Marzo)",
"Aries (21 Marzo - 20 Abril)",
"Tauro (21 Abril - 20 Mayo)",
"Geminis (21 Mayo - 20 Junio)",
"Cancer (21 Junio - 22 Julio)",
"Leo (23 Julio - 22 Agosto)",
"Virgo (23 Agosto - 22
Septiembre)",
"Libra (23 Septiembre - 23
Octubre)",
"Escorpion (24 Octubre - 21
Noviembre)",
"Sagitario (22 Noviembre - 21
Diciembre)",
"Capricornio (22 Diciembre - 20
Enero)"),
labels=c("Acuario",
"Piscis",
"Aries",
"Tauro",
"Geminis",
"Cancer",
"Leo",
"Virgo",
"Libra",
"Escorpion",
"Sagitario",
"Capricornio"))

barplot(table(estudio2012$zodiacof))

Ahora podemos hacer un ANOVA para ver si el signo zodiacal está relacionado con los niveles de intuición.

Ejecutar simplemente,

aov(intui~zodiacof, data=estudio2012)
## Call:
## aov(formula = intui ~ zodiacof, data = estudio2012)
##
## Terms:
## zodiacof Residuals
## Sum of Squares 17.54 135.98
## Deg. of Freedom 11 98
##
## Residual standard error: 1.178
## Estimated effects may be unbalanced
## 2 observations deleted due to missingness

nos entrega una tabla con la suma de cuadrados y los grados de libertad, lo que no es suficiente información.
Para este análisis, es absolutamente necesario asignar el resultado a un objeto, que vamos a llamar “aov”
(podemos poner cualquier nombre).

aov = aov(intui~zodiacof, data=estudio2012)

Ahora podemos ocupar la función summary() para ver el resultado de este análisis.

summary(aov)
## Df Sum Sq Mean Sq F value Pr(>F)
## zodiacof 11 17.5 1.59 1.15 0.33
## Residuals 98 136.0 1.39
## 2 observations deleted due to missingness

En base a los resultados del ANOVA, podemos concluir que no existe una relación entre el signo zodiacal y
los niveles de intuición (F(11,98) = 1.15, p = .33). Pero es importante notar que los n de cada grupo son muy
pequeños para este análisis. Si vemos la información descriptiva,

boxplot(intui~zodiacof, data=estudio2012)

Los participantes del signo Cáncer son los que reportan mayores niveles de intuición, lo que es consistente
con la descripción entregada en http://www.astrology-online.com/cancer.htm

De acuerdo a Astro Lady, en todo caso, Cáncer, Escorpión y Picis son los signos más intuitivos (asociados al
agua). ver http://answers.yahoo.com/question/index?qid=20080124235717AAdSk0S Esto no parece cumplirse
en esta muestra.

Quizás la intuición está relacionada con la mención que quieren elegir los alumnos de psicología…

table(estudio2012$mencion)
##
## Clinica Comunitaria
## 4 65 5
## De la salud Educacional Laboral/Organizacional
## 3 13 22

Dado que desgraciadamente hay muy pocas personas que reportan estar interesados en psicología
comunitaria o psicología de la salud, vamos a sacarlos del análisis.

estudio2012$mencionf = factor(estudio2012$mencion,
levels=c("Clinica",
"Educacional",
"Laboral/Organizacional"))

Ahora podemos hacer el ANOVA

aov = aov(intui~mencionf, data=estudio2012)


summary(aov)
## Df Sum Sq Mean Sq F value Pr(>F)
## mencionf 2 10.7 5.37 3.91 0.023 *
## Residuals 97 133.2 1.37
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 12 observations deleted due to missingness

Esta vez, los resultados si son estadísticamente significativos. Pero qué grupos son diferentes de cuáles? La
información descriptiva

boxplot(intui~mencionf, data=estudio2012)

parece indicar que las personas que quieren tomar psicología organizacional reportan un menor nivel de
intuición. Para evaluar qué grupos presentan diferencias estadísticamente significativas es necesario hacer un
test de Tukey, ocupando la función TukeyHSD(), que requiere el resultado de un análisis de varianza.

TukeyHSD(aov)
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = intui ~ mencionf, data = estudio2012)
##
## $mencionf
## diff lwr upr p adj
## Educacional-Clinica 0.07051 -0.7771 0.9181 0.9786
## Laboral/Organizacional-Clinica -0.77710 -1.4652 -0.0890 0.0228
## Laboral/Organizacional-Educacional -0.84761 -1.8235 0.1283 0.1021

Al hacer las comparaciones entre estos grupos, vemos que la única diferencia estadísticamente significativa
es la comparación entre los alumnos que quieren especializarse en clínica y los alumnos que quieren
especializarse en psicología organizacional. Los alumnos interesados en clínica reportan mayores niveles de
intuición que los interesados en organizacional (p = .02).

Uno de los supuestos del ANOVA es que las varianzas de los grupos son iguales. Para evaluar si se cumple
este supuesto, pueden hacer una prueba de levene ocupando la función levene.test() de la librería lawstat:

install.packages("lawstat") # requiere estar conectado a internet


library(lawstat)
## Loading required package: mvtnorm
## Loading required package: VGAM
## Loading required package: splines
## Loading required package: stats4
##
## Attaching package: 'VGAM'
##
## The following objects are masked from 'package:psych':
##
## fisherz, logit
levene.test(estudio2012$intui, estudio2012$mencionf)
##
## modified robust Brown-Forsythe Levene-type test based on the
## absolute deviations from the median
##
## data: estudio2012$intui
## Test Statistic = 0.0111, p-value = 0.9165
help(levene.test)
En este caso, la prueba no es estadísticamente significativa, por lo que podemos asumir que las varianzas de
los grupos en la población efectivamente son iguales. Si las varianzas fueran diferentes, corresponde hacer un
ANOVA de Welch, que no asume varianzas iguales:

oneway.test(intui~mencionf, data=estudio2012)
##
## One-way analysis of means (not assuming equal variances)
##
## data: intui and mencionf
## F = 3.561, num df = 2.00, denom df = 28.63, p-value = 0.0416
help(oneway.test)

Estos resultados se reportan así: F de Welch (2, 28.63) = 3.56, p < .05.

Desgraciadamente, R no incluye por defecto el R2 en el output de ANOVA. para obtenerlo, podemos ocupar la
función summary.lm() en el objeto que creamos para el análisis.

summary.lm(aov) # ver al final, "Adjusted R-squared": 0.06


##
## Call:
## aov(formula = intui ~ mencionf, data = estudio2012)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.6218 -0.8447 -0.0947 0.8782 2.4053
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.8718 0.1454 26.63 <2e-16
***
## mencionfEducacional 0.0705 0.3561 0.20 0.8434
## mencionfLaboral/Organizacional -0.7771 0.2891 -2.69 0.0085 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.17 on 97 degrees of freedom
## (12 observations deleted due to missingness)
## Multiple R-squared: 0.0745, Adjusted R-squared: 0.0555
## F-statistic: 3.91 on 2 and 97 DF, p-value: 0.0234

En este caso, la mención preferida explica aproximadamente un 6% de la varianza en intuición.

ANOVA Factorial
Relación entre una variable numérica y
múltiples variables categóricas.
La función aov() también permite agregar más de una variable categórica, y evaluar la interacción entre estas
variables con el formato aov(variable dependiente~factor1*factor2). Nuevamente sería ideal tener más n del
que tenemos en este estudio, especialmente para evaluar la interacción entre los dos factores pero vamos a
ver un ejemplo de todas formas, agregando género al análisis que acabamos de hacer.

Hagamos primero un gráfico para ver los descriptivos.

with(estudio2012,
interaction.plot(generof, mencionf, intui))

Y ahora el análisis de varianza.

aov = aov(intui~mencionf*generof, data=estudio2012)


summary(aov)
## Df Sum Sq Mean Sq F value Pr(>F)
## mencionf 2 10.3 5.17 3.92 0.023 *
## generof 1 6.9 6.86 5.19 0.025 *
## mencionf:generof 2 2.4 1.18 0.89 0.413
## Residuals 93 122.7 1.32
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 13 observations deleted due to missingness

Si bien al parecer el género tiene un efecto más grande en los estudiantes interesados en psicología
educacional, la interacción entre estos dos factores no es estadísticamente significativa. En cambio, hay un
efecto principal de género, donde los hombres reportan menos intuición que las mujeres (F(1,93) = 6.86, p <
.05), y de mención, donde las personas interesadas en especializarse en clínica reportan mayores niveles de
intuición (F(2,93) = 10.34, p < .05).

También pueden pedir los descriptivos para cada factor y sus interacciones con model.tables(), lo que además
tiene la ventaja de que incluye el n de cada grupo (rep). Solamente una de las personas que está interesada
en psicología educacional es hombre.

model.tables(aov, "means")
## Tables of means
## Grand mean
##
## 3.697
##
## mencionf
## Clinica Educacional Laboral/Organizacional
## 3.854 3.942 3.095
## rep 64.000 13.000 22.000
##
## generof
## Mujer Hombre
## 3.846 3.256
## rep 74.000 25.000
##
## mencionf:generof
## generof
## mencionf Mujer Hombre
## Clinica 3.96 3.50
## rep 49.00 15.00
## Educacional 4.10 2.00
## rep 12.00 1.00
## Laboral/Organizacional 3.38 2.68
## rep 13.00 9.00

Ahora el test de Tukey va a incluir comparaciones múltiples para género, para mención y también para la
interacción entre estos dos factores, aunque típicamente las coparaciones uno a uno entre las combinaciones
de factores no se reportan.

TukeyHSD(aov)
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = intui ~ mencionf * generof, data = estudio2012)
##
## $mencionf
## diff lwr upr p adj
## Educacional-Clinica 0.08814 -0.7443 0.92056 0.9656
## Laboral/Organizacional-Clinica -0.75947 -1.4357 -0.08322 0.0238
## Laboral/Organizacional-Educacional -0.84761 -1.8048 0.10960 0.0935
##
## $generof
## diff lwr upr p adj
## Hombre-Mujer -0.5899 -1.118 -0.06218 0.0289
##
## $`mencionf:generof`
## diff
lwr
## Educacional:Mujer-Clinica:Mujer 0.1416 -
0.9352
## Laboral/Organizacional:Mujer-Clinica:Mujer -0.5780 -
1.6209
## Clinica:Hombre-Clinica:Mujer -0.4626 -
1.4491
## Educacional:Hombre-Clinica:Mujer -1.9626 -
5.3396
## Laboral/Organizacional:Hombre-Clinica:Mujer -1.2867 -
2.4990
## Laboral/Organizacional:Mujer-Educacional:Mujer -0.7196 -
2.0578
## Clinica:Hombre-Educacional:Mujer -0.6042 -
1.8989
## Educacional:Hombre-Educacional:Mujer -2.1042 -
5.5837
## Laboral/Organizacional:Hombre-Educacional:Mujer -1.4282 -
2.9024
## Clinica:Hombre-Laboral/Organizacional:Mujer 0.1154 -
1.1514
## Educacional:Hombre-Laboral/Organizacional:Mujer -1.3846 -
4.8538
## Laboral/Organizacional:Hombre-Laboral/Organizacional:Mujer -0.7087 -
2.1583
## Educacional:Hombre-Clinica:Hombre -1.5000 -
4.9527
## Laboral/Organizacional:Hombre-Clinica:Hombre -0.8241 -
2.2336
## Laboral/Organizacional:Hombre-Educacional:Hombre 0.6759 -
2.8479
## upr p
adj
## Educacional:Mujer-Clinica:Mujer 1.21834
0.9989
## Laboral/Organizacional:Mujer-Clinica:Mujer 0.46499
0.5924
## Clinica:Hombre-Clinica:Mujer 0.52389
0.7479
## Educacional:Hombre-Clinica:Mujer 1.41439
0.5410
## Laboral/Organizacional:Hombre-Clinica:Mujer -0.07429
0.0308
## Laboral/Organizacional:Mujer-Educacional:Mujer 0.61873
0.6237
## Clinica:Hombre-Educacional:Mujer 0.69059
0.7517
## Educacional:Hombre-Educacional:Mujer 1.37538
0.4966
## Laboral/Organizacional:Hombre-Educacional:Mujer 0.04590
0.0632
## Clinica:Hombre-Laboral/Organizacional:Mujer 1.38217
0.9998
## Educacional:Hombre-Laboral/Organizacional:Mujer 2.08462
0.8538
## Laboral/Organizacional:Hombre-Laboral/Organizacional:Mujer 0.74095
0.7133
## Educacional:Hombre-Clinica:Hombre 1.95267
0.8035
## Laboral/Organizacional:Hombre-Clinica:Hombre 0.58547
0.5345
## Laboral/Organizacional:Hombre-Educacional:Hombre 4.19980
0.9934

Para hacer un anova con múltiples factores sin incluir sus interacciones, basta reemplazar el signo * por un +.

aov = aov(intui~mencionf+generof, data=estudio2012)


summary(aov)
## Df Sum Sq Mean Sq F value Pr(>F)
## mencionf 2 10.3 5.17 3.93 0.023 *
## generof 1 6.9 6.86 5.21 0.025 *
## Residuals 95 125.1 1.32
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 13 observations deleted due to missingness

El anova simple con mención explicaba un 6% de la varianza en los niveles de intuición. Al incluir género el
nivel de varianza explicada es ahora un 9%.

summary.lm(aov)
##
## Call:
## aov(formula = intui ~ mencionf + generof, data = estudio2012)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.750 -0.745 -0.128 0.750 2.372
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.99993 0.15702 25.47 <2e-16
***
## mencionfEducacional -0.00978 0.35173 -0.03 0.978
## mencionfLaboral/Organizacional -0.65081 0.28757 -2.26 0.026 *
## generofHombre -0.62191 0.27256 -2.28 0.025 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.15 on 95 degrees of freedom
## (13 observations deleted due to missingness)
## Multiple R-squared: 0.121, Adjusted R-squared: 0.0931
## F-statistic: 4.35 on 3 and 95 DF, p-value: 0.00642

ANCOVA
Para hacer un ancova y controlar estadísticamente por el efecto de una variable continua, simplemente puede
agregarse esta variable como predictor en la función aov(), con +, ya que normalmente no nos interesan sus
interacciones.
Relaciones entre variables lineales.
Prueba estadística para correlaciones.
En la sección de descriptivos, vimos que era posible obtener el coeficiente de correlación entre dos variables
continuas con la función cor():

cor(estudio2012$insom, estudio2012$cinsom,
use = "pairwise.complete.obs")
## [1] 0.3545

Para saber si esta correlación es estadísticamente significativa, la función que hay que ocupar es

cor.test(estudio2012$insom, estudio2012$cinsom)
##
## Pearson's product-moment correlation
##
## data: estudio2012$insom and estudio2012$cinsom
## t = 3.958, df = 109, p-value = 0.0001349
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.1800 0.5074
## sample estimates:
## cor
## 0.3545

Esta función no requiere especificar que deben omitirse los participantes con NA, por lo que probablemente es
más práctica que cor() para obtener una correlación. Aún así, la gracia de cor es que permite hacer una matriz
de correlaciones, lo que no es posible con cor.test().

El output de esta prueba nos entrega la significación estadística (r = .35, p < .01), y también un intervalo de
confianza para la correlación. En este caso, entre .18 y .50.

Al igual que en una prueba t (de hecho esto es una prueba t) podemos hacer una hipótesis unilateral o
bilateral. En caso de que tengan una hipótesis unilateral, simplemente tienen que agregar alternative=“greater”
(o “less”) a la función cor.test(). En general esto no es necesario. Simplemente pueden reportar la mitad de p
cuando el contraste es unilateral.

cor.test(estudio2012$insom, estudio2012$cinsom,
alternative="greater")
##
## Pearson's product-moment correlation
##
## data: estudio2012$insom and estudio2012$cinsom
## t = 3.958, df = 109, p-value = 6.747e-05
## alternative hypothesis: true correlation is greater than 0
## 95 percent confidence interval:
## 0.2092 1.0000
## sample estimates:
## cor
## 0.3545

Correlación parcial
Para hacer una correlación parcial entre x e y, controlando por z, es necesario instalar la librería ppcor, y
ocupar la función pcor.test(). Esta función simplemente no acepta observaciones con NAs, por lo que vamos a
tener que procesar un poco nuestra base de datos. El procedimiento que vamos a ocupar se aplica a
cualquier otra situación en que queramos sacar de una base de datos a las personas que no contestaron
algunas de las variables, así que vale la pena revisarlo de todas formas.

Primero, para simplificar las cosas, vamos a crear una nueva base de datos incluyendo Únicamente las
variables insom, ansev y cinsom; que vamos a llamar corpar.

corpar = with(estudio2012,
data.frame(insom, ansev, cinsom))

Una vez hecho esto, podemos seleccionar Únicamente a las personas que efectivamente tienen puntajes en
estas tres variables, ocupando el argumento “complete.cases”:

corpar = corpar[complete.cases(corpar), ]

Ahora que tenemos una base de datos que no tiene ningún NA,

summary(corpar)
## insom ansev cinsom
## Min. :1.00 Min. :1.00 Min. :1.00
## 1st Qu.:2.00 1st Qu.:3.33 1st Qu.:2.00
## Median :3.00 Median :4.67 Median :4.00
## Mean :3.25 Mean :4.41 Mean :3.97
## 3rd Qu.:4.33 3rd Qu.:5.67 3rd Qu.:5.50
## Max. :7.00 Max. :7.00 Max. :7.00

vamos a revisar la correlación entre insomnio y ansiedad ante evaluaciones, controlando por conductas
negativas del sueño.

install.packages("ppcor") # Primero tenemos que instalar


library(ppcor) # y cargar la librería ppcor

La función pcor.test() ocupa el formato pcor.test(x, y, z), donde z es la variable que queremos controlar.

pcor.test(corpar$insom, corpar$ansev, corpar$cinsom)


## estimate p.value statistic n gp Method
## 1 0.3845 1.647e-05 4.308 110 1 pearson

La correlación se mantiene prácticamente igual al controlar por conductas negativas del sueño, lo que nos da
cierta indicación de que la relación entre insomnio y ansiedad en periodos de evaluaciones no puede ser
explicada por esta variable.

Regresión
Hacer regresión en R es exactamente lo mismo que hacer un ANOVA. De hecho, la función aov() ocupa la
función básica para hacer modelos de regresión: lm(). El formato de esta función es exactamente el mismo:
lm(variable dependiente~predictor1+predictor2).

Una de las escalas que no hemos ocupado es la de estrés universitario, que podemos usar para predecir los
niveles de insomnio. La escala tiene los siguientes ítems:

streu1 Siento que no me alcanza el tiempo para cumplir con todas mis responsabilidades académicas. streu2
Siento molestias físicas (dolor de cabeza, de estómago, náuseas, etc.) debido a la cantidad de actividades
que debo realizar. streu3 Siento que tengo tantas responsabilidades académicas que no logro
“desconectarme” en mi tiempo libre. streu4 Cuando pienso en todas las actividades que tengo que hacer me
pongo irritable. streu5 Siento mucha presión para cumplir con todas mis responsabilidades en la universidad.

La confiabilidad es buena,

alpha(with(estudio2012,
data.frame(streu1, streu2, streu3, streu4, streu5)))
##
## Reliability analysis
## Call: alpha(x = with(estudio2012, data.frame(streu1, streu2, streu3,
## streu4, streu5)))
##
## raw_alpha std.alpha G6(smc) average_r S/N ase mean sd
## 0.83 0.83 0.83 0.5 5 0.053 4.5 1.4
##
## lower alpha upper 95% confidence boundaries
## 0.73 0.83 0.94
##
## Reliability if an item is dropped:
## raw_alpha std.alpha G6(smc) average_r S/N alpha se
## streu1 0.86 0.86 0.85 0.60 6.0 0.059
## streu2 0.79 0.79 0.76 0.48 3.7 0.069
## streu3 0.78 0.78 0.76 0.47 3.6 0.069
## streu4 0.77 0.77 0.75 0.46 3.4 0.070
## streu5 0.79 0.79 0.76 0.48 3.7 0.069
##
## Item statistics
## n r r.cor r.drop mean sd
## streu1 112 0.61 0.44 0.41 5.0 1.7
## streu2 112 0.80 0.76 0.68 3.9 1.9
## streu3 112 0.81 0.77 0.69 4.1 2.0
## streu4 112 0.84 0.80 0.73 4.5 1.8
## streu5 112 0.80 0.76 0.68 4.8 1.8
##
## Non missing response frequency for each item
## 1 2 3 4 5 6 7 miss
## streu1 0.01 0.12 0.07 0.15 0.20 0.18 0.27 0
## streu2 0.12 0.19 0.12 0.15 0.21 0.09 0.12 0
## streu3 0.11 0.21 0.11 0.12 0.13 0.19 0.13 0
## streu4 0.06 0.12 0.11 0.13 0.24 0.17 0.16 0
## streu5 0.05 0.09 0.08 0.19 0.17 0.21 0.21 0

y aunque eliminar el primer ítem mejoraría un poco el alpha, la correlación del ítem con el total es adecuada
(.4), por lo que prefiero incluirlo de todas formas.

estudio2012$streu = with(estudio2012,
rowMeans(data.frame(streu1, streu2, streu3,
streu4, streu5),
na.rm=TRUE))

summary(estudio2012$streu)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.40 3.35 4.50 4.46 5.60 7.00

Noten que el promedio está claramente por sobre el punto medio de la escala.

¿Podemos predecir los niveles de insomnio a partir de los niveles de estrés universitario reportados por los
participantes? La función lm() funciona igual que aov(), y también es necesario asignar el resultado a un
objeto, que ahora vamos a llamar lm.

lm = lm(insom~streu, data=estudio2012)
summary(lm)
##
## Call:
## lm(formula = insom ~ streu, data = estudio2012)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.795 -1.343 -0.378 1.032 3.664
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.710 0.504 3.39 0.00096 ***
## streu 0.347 0.107 3.24 0.00160 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.61 on 109 degrees of freedom
## (1 observation deleted due to missingness)
## Multiple R-squared: 0.0877, Adjusted R-squared: 0.0793
## F-statistic: 10.5 on 1 and 109 DF, p-value: 0.0016

El resultado de este análisis indica que efectivamente los niveles de estrés universitario predicen los niveles
de insomnio de forma significativa. El output entrega los coeficientes no estandarizados: un punto en la escala
de estrés se asocia (en general) a un aumento de .35 puntos en la escala de insomnio.

Como vimos en la sección de descriptivos, el resultado de este análisis puede ser ocupado para dibujar la
línea de regresión sobre un dispersiograma que muestra la relación entre las variables.

plot(estudio2012$streu, estudio2012$insom)
abline(lm(insom~streu, data=estudio2012), col="red")

lm() no entrega los coeficientes estandarizados. Si bien no es complicado hacer esto de forma manual,
probablemente la opción más práctica es ocupar variables estandarizadas (puntajes z) desde un comienzo. La
librería psych incluye una función para convertir a puntaje z, o definir cualquier otro valor para el promedio y la
desviación estándar de una variable.

datosz = with(estudio2012,
rescale(cbind(insom, streu), mean = 0, sd = 1))

lmz = lm(insom~streu, data=datosz) # La misma regresión que hicimos


antes
# pero con puntajes z

summary(lmz) # Ahora los coeficientes son betas estandarizados


##
## Call:
## lm(formula = insom ~ streu, data = datosz)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.664 -0.799 -0.225 0.614 2.181
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.00272 0.09108 -0.03 0.9762
## streu 0.29618 0.09151 3.24 0.0016 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.96 on 109 degrees of freedom
## (1 observation deleted due to missingness)
## Multiple R-squared: 0.0877, Adjusted R-squared: 0.0793
## F-statistic: 10.5 on 1 and 109 DF, p-value: 0.0016

Regesión múltiple
Para hacer una regresión múltiple, simplemente hay que agregar otros predictores ocupando + (a no ser que
quieran evaluar también la interacción entre dos predictores).

lm = lm(insom~streu+ansev+intui, data=estudio2012)
summary(lm)
##
## Call:
## lm(formula = insom ~ streu + ansev + intui, data = estudio2012)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.814 -1.014 -0.257 0.986 3.714
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.9994 0.6544 1.53 0.1297
## streu 0.0675 0.1355 0.50 0.6195
## ansev 0.4295 0.1347 3.19 0.0019 **
## intui 0.0155 0.1271 0.12 0.9029
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.56 on 106 degrees of freedom
## (2 observations deleted due to missingness)
## Multiple R-squared: 0.166, Adjusted R-squared: 0.143
## F-statistic: 7.06 on 3 and 106 DF, p-value: 0.000227

Al incluir ansiedad en periodo de evaluaciones el efecto de estrés universitario deja de ser significativo, y -
como es esperable- los niveles de intuición no predicen los niveles de insomnio. Es perfectamente posible
entender ansiedad en periodo de evaluaciones como un mediador del efecto de estrés universitario en
insomnio. La idea es que las personas pueden tener más o menos estrés universitario (streu), por ejemplo
porque tomaron muchos ramos, y esto genera problemas de sueño (insom) justamente porque disminuye la
capacidad de enfrentar tranquilamente los periodos de evaluaciones (ansev).

Una forma de evaluar mediación es haciendo tres regresiones, mostrando que

1. La variable independiente predice la variable dependiente.

lm1 = lm(insom~streu, data=estudio2012)


summary(lm1)
##
## Call:
## lm(formula = insom ~ streu, data = estudio2012)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.795 -1.343 -0.378 1.032 3.664
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.710 0.504 3.39 0.00096 ***
## streu 0.347 0.107 3.24 0.00160 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.61 on 109 degrees of freedom
## (1 observation deleted due to missingness)
## Multiple R-squared: 0.0877, Adjusted R-squared: 0.0793
## F-statistic: 10.5 on 1 and 109 DF, p-value: 0.0016

1. La variable independiente predice el mediador.

lm2 = lm(ansev~streu, data=estudio2012)


summary(lm2)
##
## Call:
## lm(formula = ansev ~ streu, data = estudio2012)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.638 -0.805 -0.178 0.884 2.570
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.6412 0.3499 4.69 7.9e-06 ***
## streu 0.6242 0.0748 8.34 2.5e-13 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.13 on 109 degrees of freedom
## (1 observation deleted due to missingness)
## Multiple R-squared: 0.39, Adjusted R-squared: 0.384
## F-statistic: 69.6 on 1 and 109 DF, p-value: 2.46e-13

1. El efecto de la variable independiente deja de ser significativo al incluir el mediador.

lm3 = lm(insom~ansev+streu, data=estudio2012)


summary(lm3)
##
## Call:
## lm(formula = insom ~ ansev + streu, data = estudio2012)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.805 -1.024 -0.267 0.975 3.682
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.0463 0.5277 1.98 0.0500 *
## ansev 0.4300 0.1340 3.21 0.0018 **
## streu 0.0692 0.1342 0.52 0.6069
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.55 on 107 degrees of freedom
## (2 observations deleted due to missingness)
## Multiple R-squared: 0.166, Adjusted R-squared: 0.151
## F-statistic: 10.7 on 2 and 107 DF, p-value: 5.91e-05

También es posible que el efecto de la variable independiente siga siendo significativo, pero se observe una
reducción importante. Más abajo vamos a ocupar la librería QuantPsyc, que incluye funciones para análisis
más sofisticados de mediación.
Interacciones entre variables continuas
Incluir interacciones en ecuaciones de regresión es prácticamente igual que en ANOVAs, con la importante
excepción de que los predictores tienen que estar centrados. Es decir, su promedio debe ser 0.

Para hacer esto podemos crear otra variable restando el promedio a la variable original, o simplemente
estandarizar los puntajes con rescale() como hicimos antes.

A modo de ejemplo, vamos a incluir la interacción entre estrés universitario y conductas negativas del sueño.
Quizás el estrés universitario afecta menos a las personas que evitan ver televisión hasta tarde.

estudio2012$streuc = estudio2012$streu - mean(estudio2012$streu, na.rm =


TRUE)
estudio2012$cinsomc = estudio2012$cinsom - mean(estudio2012$cinsom, na.rm
= TRUE)

Ahora el modelo de regresión incluye un * en vez de un +, para incluir la interacción entre los dos predictores
ya centrados.

lm = lm(insom~streuc*cinsomc, data=estudio2012)
summary(lm)
##
## Call:
## lm(formula = insom ~ streuc * cinsomc, data = estudio2012)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.071 -0.987 -0.087 0.826 4.292
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.2821 0.1497 21.92 < 2e-16 ***
## streuc 0.2695 0.1053 2.56 0.01187 *
## cinsomc 0.2586 0.0759 3.41 0.00092 ***
## streuc:cinsomc -0.0349 0.0508 -0.69 0.49390
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.54 on 107 degrees of freedom
## (1 observation deleted due to missingness)
## Multiple R-squared: 0.18, Adjusted R-squared: 0.157
## F-statistic: 7.81 on 3 and 107 DF, p-value: 9.21e-05

Como es esperable, las conductas asociadas a baja calidad del sueño predicen los niveles de insomnio. Pero
la interacción entre estrés universitario y estas conductas no es estadísticamente significativa.

Regresiones y ANOVA
En R, el hecho de que las regresiones lineales y los ANOVA son lo mismo es explícito: aov() simplemente
hace un modelo ocupando lm() y lo reporta como es tradicional en los análisis de varianza. De hecho, tanto
aov() como lm() permiten agregar predictores continuos o categóricos. En el caso de las variables categóricas
R automáticamente crea las variables dicotómicas que sean necesarias. La consecuencia práctica que tiene
esto es que pueden agregar tranquilamente predictores categóricos a lm() y predictores continuos a aov().

Por ejemplo, podemos pedir el siguiente modelo, donde se incluyen genero y situación sentimental como
predictores de insomnio.
lm = lm(insom~streu+ansev+ # Predictores continuos
generof+sitsentf, # Predictores categóricos
data=estudio2012)

El output de

summary(lm)
##
## Call:
## lm(formula = insom ~ streu + ansev + generof + sitsentf, data =
estudio2012)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.681 -1.070 -0.254 1.003 3.643
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.9648 0.5650 1.71 0.0907 .
## streu 0.0386 0.1386 0.28 0.7815
## ansev 0.4502 0.1392 3.23 0.0016 **
## generofHombre 0.1312 0.3582 0.37 0.7150
## sitsentfEs complicado 0.7555 0.6103 1.24 0.2186
## sitsentfSoltero/a 0.0340 0.3160 0.11 0.9145
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.56 on 102 degrees of freedom
## (4 observations deleted due to missingness)
## Multiple R-squared: 0.174, Adjusted R-squared: 0.134
## F-statistic: 4.31 on 5 and 102 DF, p-value: 0.00135

muestra que el único predictor significativo de insomnio es ansiedad en periodos de evaluaciones. También se
observa ser hombre predice mayores niveles de insomnio, pero el efecto no es significativo. Además estar
tener una situación sentimental “complicada” (vs. “En una relación”) predice mayores niveles de insomnio,
pero nuevamente el efecto no es estadísticamente significativo, posiblemente porque hay muy pocos
participantes que reportan su situación sentimental como complicada.

Lo que hemos revisado debiera ser más que suficiente para la mayoría de los análisis que se realizan
típicamente en psicología. Los anexos incluyen un poco más de información en caso de que alguna vez la
necesiten.

ANEXOS
La libreria ggplot2 es un excelente recurso para hacer gráficos más sofisticados o con mejores opciones de
presentación.

install.packages("ggplot2")
library(ggplot2)
qplot(bfext, bfopen, data=personalidad, geom = c("point", "smooth"))
## geom_smooth: method="auto" and size of largest group is <1000, so
using loess. Use 'method = x' to change the smoothing method.

Otras funciones útiles:


Para buscar información.

help(mean) # también puede escribirse como


?mean # y agregar dos ?? permite buscar en la documentación online
de R
# por palabras clave. Por ejemplo,
??mean
??"mean center"

Para combinar bases de datos en base a una variable (identificador) común:

help(merge)

El lugar donde aparecen los gráficos puede dividirse para incluir varios gráficos en la misma imagen

par(mfrow=c(1,2)) # Divide el output gráfico en dos columnas.


hist(estudio2012$intolsex)
boxplot(estudio2012$intolsex)

par(mfrow=c(1,1)) # Quita la división del output gráfico.

Otros análisis estadísticos


Evaluación de supuestos estadísticos en modelos de regresión.

El comando plot() entrega cuatro gráficos útiles para evaluar si los datos cumplen los supuestos estadísticos
asociados a un modelo de regresión. Como aparece en la consola, tienen que apretar enter para ver el
siguiente gráfico.

plot(lm)

El primer gráfico muestra la distribución de los residuos. Esto es equivalente a la idea de homogeneidad de
varianza en ANOVA. La distribución de los residuos debiera ser uniforme, y la línea roja debiera ser horizontal.

El segundo gráfico evalúa si los residuos tienen una distribución normal. Los puntos en el gráfico debieran
ajustarse a la línea diagonal. Los gráficos 2 y 3 son menos importantes.

ANOVA de mediciones repetidas

Requiere transformar la base de datos de forma que cada participante tenga varias líneas, una por cada
medición intra-sujeto. Abajo les copio el ejemplo disponible en http://personality-project.org.

la librería reshape2 tiene excelentes funciones para transformar una base de datos

datafilename="http://personality-project.org/r/datasets/R.appendix3.data"
data.ex3=read.table(datafilename,header=T) #read the data into a
table
data.ex3 #show the data
aov.ex3 = aov(Recall~Valence+Error(Subject/Valence),data.ex3)
summary(aov.ex3)
print(model.tables(aov.ex3,"means"),digits=3) # report the means and the
number of subjects/cell
boxplot(Recall~Valence,data=data.ex3) #graphical output

Para modelos de ecuaciones estructurales (SEM) pueden ocupar la librería lavaan. Ver más información
en http://lavaan.ugent.be

install.packages("lavaan")
??lavaan

Para modelos multinivel pueden ocupar la librería lme4, específicamente la función lmer().

install.packages("lme4")
??lmer

Você também pode gostar