Octava sesión con Rcmdr. Datos cualitativos. Matrices y dataframes.

Manejando variables cualitativas en R.

En la anterior sesión con Rcmdr aprendimos a utilizar (de forma básica) las matrices de R. Para refrescar la memoria puedes empezar ejecutando este código, en el que la única novedad es la última fila.

library("gtools") #recuerda que has debido instalar este paquete (ver septima sesion del blog)
combinaciones=combinations(4,3)
combinaciones
# de que tipo es el objeto combinaciones que hemos creado?
class(combinaciones)

Cuando lo ejecutes obtendrás como última linea de la salida:

> class(combinaciones)
[1] "matrix"

Es decir, que el objeto combinaciones es de tipo matrix. Puedes utilizar la función class de R para averiguar el tipo de cualquiera de los objetos que aparecen en una sesión de trabajo con R. Por ejemplo, prueba a usarla con un vector de números:

datos=c(2,5,17,21,9,7)
class(datos)

y observa el resultado. Verás que el vector datos es de tipo numeric.

Todo nuestro trabajo, en las anteriores sesiones del blog se ha centrado en números, en valores de variables cuantitativas. Pero sabemos que a veces es necesario trabajar con variables cualitativas.Recuerda que una variable cualitativa se usa para establecer clasificaciones nominales en los datos. Por ejemplo, la clasificación en hombre o mujer entre los pacientes que siguen un cierto tratamiento. O la clasificación taxonómica por especies.

Es cierto que siempre podríamos codificarlas mediante números.  Pero no es menos cierto que lo más cómodo es poder utilizar nombres como valores de las variables. Para hacer esto posible, R nos permite crear un cierto tipo de valores, que  son simplemente palabras o frases entrecomilladas (en general las llamamos cadenas de texto).  Por ejemplo, este vector podría representar el género de los diez pacientes que se han sometido a un cierto tratamiento:

pacientesPorGenero=c("mujer","mujer","hombre","mujer","hombre","hombre","hombre","mujer","mujer","mujer")
class(pacientesPorGenero)

Cuando ejecutes este código,obtendrás como último resultado

> class(pacientesPorGenero)
[1] "character"

Es decir, que los elementos del vector pacientesPorGenero son, para R, de tipo character. Ese es el tipo de dato que se utiliza en R para representar los valores de una variable cualitativa. Naturalmente, sin intentas  realizar operaciones numéricas con ese vector, como estas,

pacientesPorGenero^2
mean(pacientesPorGenero)

R te obsequiará con un surtido de insultos más o menos ofensivos en la ventana de mensajes de Rcmdr. En el segundo caso (el intento fallido de calcular la media), el valor que devuelve R es interesante: se obtiene NA, que es el valor que R devuelve cuando un resultado numérico es imposible de calcular, o no está disponible (Not Available, de ahí el nombre).

Una última observación: los vectores de tipo character se pueden ordenar, alfabéticamente, pero es muy posible que esa ordenación no tenga sentido en nuestro problema. Volveremos sobre esto en otra entrada, cuando tratemos el tema de los factores en R, que nos permitirán una gestión mucho más eficiente de la información que contienen las variables cualitativas.

Matrices a partir de un vector

En la sétima sesión obtuvimos varias matrices como resultado de las operaciones combinatorias que hacíamos. Pero ¿y si yo quiero rellenar una matriz con mis datos, escribiéndolos directamente?

Podemos hacer esto usando la función matrix de R. Como argumentos de esta función escribiremos los elementos de la matriz como un vector, y el número de filas mediante la opción nrow. Por ejemplo:

unaMatriz=matrix(c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),nrow=3)
unaMatriz
class(unaMatriz)

producirá este (seguramente sorprendente) resultado:

> unaMatriz=matrix(c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),nrow=3)
> unaMatriz
[,1] [,2] [,3] [,4] [,5]
[1,]    1    4    7   10   13
[2,]    2    5    8   11   14
[3,]    3    6    9   12   15
> class(unaMatriz)
[1] "matrix"

Obsérvese que R ha ido colocando los elementos por columnas, hasta formar una matriz de tres filas y cinco columnas (de acuerdo con el argumento nrow=3 que hemos usado).

Naturalmente también podríamos haber fabricado el vector usando cualquiera de los métodos que vimos en la sexta sesión, escribiendo por ejemplo:

unaMatriz=matrix(1:15,nrow=3)

y el resultado sería el mismo. Asimismo podemos emplear un vector guardado previamente mediante su nombre (y de esa manera puedes, por ejemplo, con lo que ya sabes de anteriores sesiones, fabricar una matriz a partir de los datos de un fichero csv).

¿.Y si quiero rellenar por filas (porque me resulta más natural, probablemente)? Pues basta con añadir una opción byrow=T a la  función matrix:

unaMatriz=matrix(1:15,nrow=3,byrow=T)
unaMatriz

Y ahora se obtiene

> unaMatriz=matrix(1:15,nrow=3,byrow=T)
> unaMatriz
[,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10
[3,]   11   12   13   14   15

como queríamos.

Otra opción es usar la función t (simplemente la letra t), que traspone una matriz. Prueba a ejecutar este código para ver como funciona:

unaMatriz=matrix(1:15,nrow=3)
unaMatriz
matrizTranspuesta=t(unaMatriz)
matrizTranspuesta

Una pregunta natural cuando se usa la función matrix es ¿y qué pasa si las dimensiones de la matriz no casan con la longitud del vector? Por ejemplo, si tratamos de meter 13 datos en una matriz de  3 filas:

unaMatriz=matrix(1:13,nrow=3)
unaMatriz

El resultado es que se obtiene:

> unaMatriz
[,1] [,2] [,3] [,4] [,5]
[1,]    1    4    7   10   13
[2,]    2    5    8   11    1
[3,]    3    6    9   12    2

y una advertencia en la ventana de mensajes. R nos avisa de que el vector no era suficiente para rellenar la matriz y por esa razón ha vuelto al principio del vector, utilizando 1 y 2 para rellenar la parte restante de la matriz. Esta forma de trabajar de R nos puede resultar más o menos conveniente o convincente, pero en cualquier caso hay que conocerla.

Matrices por filas y columnas: cbind y rbind.

Otra manera de fabricar matrices a partir de vectores es utilizar las funciones rbind y cbind (donde r y c proceden de row, fila y column, columna, respectivamente) para escribir las filas o columnas directamente como vectores. Por ejemplo, el código

vectorFila1=2:5
vectorFila2=1:4
vectorFila3=c(-2,1,4,7)
matrizPorFilas=rbind(vectorFila1,vectorFila2,vectorFila3)
matrizPorFilas

produce este resultado:

> matrizPorFilas
[,1] [,2] [,3] [,4]
vectorFila1    2    3    4    5
vectorFila2    1    2    3    4
vectorFila3   -2    1    4    7

Y para ilustrar la función cbind vamos a añadirle una columna más a esta matriz, escribiendo:

quintaColumna=c(11,17,-4)
matrizModificada=cbind(matrizPorFilas,quintaColumna)
matrizModificada

que produce:

> matrizModificada
                          quintaColumna
vectorFila1  2 3 4 5            11
vectorFila2  1 2 3 4            17
vectorFila3 -2 1 4 7            -4

Obsérvese que cuando construimos la matriz mediante cbind y rbind, R usa los nombres de los vectores como nombres de las filas y columnas correspondientes. Volveremos pronto sobre esto (en una próxima entrada).

Dataframes

Después de conocer la forma en que R maneja las variables cualitativas, y de aprender un poco más sobre matrices, podemos estar tentados de combinar ambas ideas. Por ejemplo, puede resultar útil disponer de una tabla en la que guardamos, para cada uno de los pacientes ingresados en una planta de un hospital, su género (hombre o mujer),  su edad y el número de días que llevan ingresados. Algo como el contenido de este fichero pacientes.csv .

Puesto que cada columna contiene unos datos, podemos introducir los datos mediante vectores por columnas (usando cbind). El código sería:

vectorColumna1=c("hombre","mujer","mujer","mujer","hombre","hombre","mujer","mujer","hombre")
vectorColumna2=c(53,67,31,56,25,43,41,76,17)
vectorColumna3=c(3,1,4,2,1,7,2,4,8)
matrizPorColumnas=cbind(vectorColumna1,vectorColumna2,vectorColumna3)
matrizPorColumnas

y el resultado es:

> matrizPorColumnas
vectorColumna1 vectorColumna2 vectorColumna3
[1,] "hombre"       "53"           "3"
[2,] "mujer"        "67"           "1"
[3,] "mujer"        "31"           "4"
[4,] "mujer"        "56"           "2"
[5,] "hombre"       "25"           "1"
[6,] "hombre"       "43"           "7"
[7,] "mujer"        "41"           "2"
[8,] "mujer"        "76"           "4"
[9,] "hombre"       "17"           "8"

¿Perfecto, verdad? Espera un momento, algo va mal; esas comillas en las columnas de números no deberían estar ahí…

Para comprobar que en efecto tenemos un problema, tratemos de calcular la media de esa columna. Primero vemos el contenido de la columna (con matrizPorColumnas[,2]):

matrizPorColumnas[,2]
mean(matrizPorColumnas[,2])

Y al tratar de calcular la media obtenemos NA y un mensaje de advertencia en la ventana de mensajes.:

[18] NOTA: Aviso en mean.default(matrizPorColumnas[, 2]) :
argument is not numeric or logical: returning NA

¿Qué ha sucedido? Pues que nos hemos topado con la principal limitación de las matrices de R (que afecta también a los vectores, aunque hasta ahora no se nos había planteado el problema). Una matriz está formada por elementos que son todos del mismo tipo. Todos numeric, o todos de tipo character, pero no se admiten mezclas. Por eso, cuando le hemos pedido a R que usara los tres vectores columna para hacer una matriz, ha hecho lo que ha podido: ha convertido las columnas de números a tipo character, y las ha usado como tales (la conversión contraria, convertir character a numeric casi nunca tiene sentido, por eso R ha hecho lo que ha hecho).

Vaya decepción. Entonces, ¿en R no puedo escribir una tabla en la que se mezclen números y nombres? ¡Los dataframes al rescate! Un dataframe está pensado exactamente para eso, para albergar una tabla con tipos mixtos de datos. Veamos como funcionaría en este ejemplo:

pacientes=data.frame(vectorColumna1,vectorColumna2,vectorColumna3)
pacientes

Como puede verse, ahora no hay problema, el resultado es:

> pacientes
vectorColumna1 vectorColumna2 vectorColumna3
1         hombre             53              3
2          mujer             67              1
3          mujer             31              4
4          mujer             56              2
5         hombre             25              1
6         hombre             43              7
7          mujer             41              2
8          mujer             76              4
9         hombre             17              8

y si queremos calcular la media de la segunda columna, podemos hacer:

mean(pacientes[,2])

y se obtiene el resultado deseado.

> mean(pacientes[,2])
[1] 45.44444

Puesto que la columna dos tiene nombre (vectorColumna2), podemos conseguir lo mismo con esta otra notación  con el símbolo $ (volveremos a encontrarla en futuras entradas):

mean(pacientes$vectorColumna2)

Y ya que estamos en ello, es el momento de darse cuenta de que los nombres de las columnas en nuestro flamante data.frame no son especialmente afortunados. Podríamos haber sido más cuidadosos al elegir los nombres de los vectores, pero incluso si no lo hemos sido, todavía tiene remedio. Podemos hacer:

colnames(pacientes)=c("genero","edad","diasHospital")
pacientes

Y ahora se obtiene:

> pacientes
genero edad diasHospital
1 hombre   53            3
2  mujer   67            1
3  mujer   31            4
4  mujer   56            2
5 hombre   25            1
6 hombre   43            7
7  mujer   41            2
8  mujer   76            4
9 hombre   17            8

como queríamos.

En estos primeros ejemplos ya hemos visto que los dataframes se pueden manejar de manera muy parecida a como se hace con las matrices. En próximas entradas iremos aprendiendo más sobre ellos, por el procedimiento de usarlos. De momento, si quieres ver más ejemplos, te conviene saber que R incorpora una buena cantidad de dataframes de ejemplo. Para ver la lista escribe el comando

data()

y aparecerá (en otra ventana). Uno de los ejemplos es el dataframe llamado crabs. Puedes ver su contenido tecleando en R simplemente

crabs

y verás aparecer una tabla de datos (de 200 filas), con datos morfológicos de cangrejos (crabs, en inglés) del género Leptograpsus. Naturalmente, sin más información se hace difícil interpretar esta tabla. Para averiguar más sobre el fichero (o sobre casi cualquier otra cosa en R) puedes escribir su nombre precedido de una interrogación y ejecutar esa línea:

?crabs

Cuando lo hagas se abrirá una ventana de tu navegador (no te preocupes, aunque se abra el navegador no se necesita estar conectado a internet para esto), con información sobre el fichero, como en esta figura:

Finalmente, dataframes y ficheros csv. Funciones write.table y read.table

De la misma forma que hemos aprendido a usar scan y cat para leer y escribir vectores en ficheros csv, podemos leer y escribir dataframes a esos ficheros. Por ejemplo, para escribir el dataframe crabs a un fichero crabs.csv (que puedes abrir en Calc, por ejemplo), usaríamos la función write.table así (acuérdate de fijar el directorio de trabajo primero):

write.table(crabs,"crabs.csv",sep=" ",dec=",")

Un par de comentarios para explicar las opciones:

  1. la opción dec=”,” sirve para pedirle a R que al escribir el fichero reemplace los puntos decimales que emplea por comas. Esto es necesario si vas a usar el fichero en una versión española de Calc, que usa comas para los decimales.
  2. la opción sep=” ” le dice  a R que use espacios para separar los valores dentro de una línea del fichero csv. En este caso es necesario usar espacios, y no comas,  porque ya hemos usado comas para los decimales.

Si lo que queremos es leer un fichero de datos como el fichero pacientes.csv que vimos antes en esta misma entrada, podemos utilizar la función read.table así (¡recuerda fijar el directorio de trabajo!)

datosPacientes=read.table("pacientes.csv")
datosPacientes

Estos comandos producen esta salida:

> datosPacientes=read.table("pacientes.csv")
> datosPacientes
V1    V2
1 hombre ,53,3
2  mujer ,67,1
3  mujer ,31,4
4  mujer ,56,2
5 hombre ,25,1
6 hombre ,43,7
7  mujer ,41,2
8  mujer ,76,4
9 hombre ,17,8

donde vemos que, en efecto, R ha creado un nuevo data.frame datosPacientes, y le ha asignado automáticamente nombres V1 y V2 a las variables columna. En futuros encuentros con la función read.table aprenderemos más detalles sobre su funcionamiento.

Muchas gracias por la atención, especialmente en esta entrada tan extensa.

Un pensamiento en “Octava sesión con Rcmdr. Datos cualitativos. Matrices y dataframes.

  1. Pingback: 15ª sesión con Rcmdr: Factores y ANOVA unifactorial en R. | PostData

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s