Dataframes en R

La estructura de datos más común en R son los dataframes. La mayoría de los paquetes en R contienen rutinas para manipular dicha estructura de datos. Este artículo explica algunas de sus funcionalidades básicas.

Introducción

Conceptualmente los dataframes son tablas de datos, con columnas, renglones, sus encabezados y números de línea correspondientes. Desde el punto de vista técnico se operan como matrices (arreglos bidimensionales) que contienen diferentes tipos de datos.

Crear un dataframe es muy fácil, sólo hay que pasar como argumentos los datos de cada columna al comando data.frame( ). Veamos un ejemplo sencillo:

> nombre <- c('Sofía', 'Ema', 'Olivia', 'Elizabet', 'María', 'Emilia',
'Guadalupe', 'Karla')
> altura <- c(158, 165, 159, 164, 160, 163, 161, 162)
> peso <- c(55, 65, 117, 72, 60, 59, 73, 66)

> fdatos <- data.frame(nombre, altura, peso)

> print(fdatos)
     nombre altura peso
     1     Sofía    158   55
     2       Ema    165   65
     3    Olivia    159  117
     4  Elizabet    164   72
     5     María    160   60
     6    Emilia    163   59
     7 Guadalupe    161   73
     8     Karla    162   66

El símbolo > representa el prompt de R y no es parte de los comandos.

En este ejemplo se combinan tres arreglos o vectores nombre, altura y peso como columnas por medio del comando data.frame( ) para crear la tabla.

Si el tipo de datos de una columna es una cadena de texto (string), R convertirá ese vector en un factor, un tipo especial de variable categórica, lo cual puede no ser conveniente en varias situaciones. Para prevenir este comportamiento se requiere un parámetro adicional, stringsAsFactors = FALSE.

Si imprimimos la columna nombre en este momento esto es lo que pasa:

> print(fdatos$nombre)
     [1] Sofía     Ema       Olivia    Elizabet  María     Emilia
     [7] Guadalupe Karla
     Levels: Elizabet Ema Emilia Guadalupe Karla María Olivia Sofía

Si ahora usamos la opción mencionada en el párrafo anterior este es el resultado:

> fdatos <- data.frame(nombre, altura, peso, stringsAsFactors=FALSE)
> print(fdatos$nombre)

[1] "Sofía"     "Ema"       "Olivia"    "Elizabet"  "María"
[6] "Emilia"    "Guadalupe" "Karla"

En este caso los nombres no aparecen como Levels.

Nombres de Renglón y Columna

Es posible acceder a los datos guardados en un dataframe usando ya sea los nombres de reglón y columna o la posición correspondiente (índices). El siguiente ejemplo ilustra esta idea:

> print(fdatos[3, 1])
[1] "Olivia"

> print(fdatos[2:5, 'peso'])
[1]  65 117  72  60

> print(fdatos['6', 'nombre'])
[1] "Emilia"
  • El primer comando imprime la entrada en el renglón 3 y la columna 1 del dataframe.
  • El segundo comando imprime las entradas desde el renglón 2 hasta el renglón 5 en la columna cuyo nombre es peso.
  • El último comando usa el nombre del renglón y el nombre de la columna para imprimir la entrada correspondiente.

Hay escenarios en lo que uno no conoce de antemano los nombres de los renglones y las columnas. Si, por ejemplo, los datos fueron cargados desde un archivo el usuario no sabe en principio con qué clase de datos está trabajando. Existen varias funciones para extraer esta información.

> print(dimnames(fdatos))
[[1]]
[1] "1" "2" "3" "4" "5" "6" "7" "8"

[[2]]
[1] "nombre" "altura" "peso"

> print(names(fdatos))
[1] "nombre" "altura" "peso"

El primer comando, dimnames muestra los nombres en la dimensión uno (renglones) y los de la dimensión 2 (columnas). El segundo comando, names solo imprime los nombres de las columnas.

Como ya se mostró en uno de los ejemplos es posible usar los nombres de las columnas para extraer los datos de esa columna en particular como un vector. La sintaxis es muy simple, dataframe$nombredecolumna:

> print(fdatos$nombre)
[1] "Sofía"     "Ema"       "Olivia"    "Elizabet"  "María"
[6] "Emilia"    "Guadalupe" "Karla"

> print(fdatos$altura[c(1, 8)])
[1] 158 162

El primer comando imprime los datos correspondientes a la columna nombres, el segundo comando imprime la primera y octava entradas de la columna altura.

Nombres de Renglones

Es importante apreciar que los índices y los nombres de renglón no son la misma cosa.

> print(fdatos)
     nombre altura peso
1     Sofía    158   55
2       Ema    165   65
3    Olivia    159  117
4  Elizabet    164   72
5     María    160   60
6    Emilia    163   59
7 Guadalupe    161   73
8     Karla    162   66

> fdatos <- fdatos[order(fdatos$peso),]

> print(fdatos)
     nombre altura peso
1     Sofía    158   55
6    Emilia    163   59
5     María    160   60
2       Ema    165   65
8     Karla    162   66
4  Elizabet    164   72
7 Guadalupe    161   73
3    Olivia    159  117

Los números en la primera columna son los nombres de cada renglón. Para hacer esto evidente el comando order ordena ascendentemente la tabla usando la columna peso, lo que obviamente cambia la posición de los nombres de cada renglón.

Por supuesto esta confusión puede evitarse si en vez de usar números como nombres de renglón usamos otra cosa. Por ejemplo podemos usar los elementos en la columna nombre como nombres de cada renglón. Regresemos al comando básico data.frame( ) que usamos para crear el fdatos.

> fdatos <- data.frame(nombre, altura, peso, stringsAsFactors=FALSE, row.names = nombre)

> print(fdatos)
             nombre altura peso
Sofía         Sofía    158   55
Ema             Ema    165   65
Olivia       Olivia    159  117
Elizabet   Elizabet    164   72
María         María    160   60
Emilia       Emilia    163   59
Guadalupe Guadalupe    161   73
Karla         Karla    162   66

Así que ahora de una forma más intuitiva podemos, por ejemplo, leer la información completa de Sofía o conocer la altura de Karla.

> print(fdatos['Sofía',])
      nombre altura peso
Sofía  Sofía    158   55

> print(fdatos['Karla', 'altura'])
[1] 162

Modificar la información en un Dataframe

Los Dataframes son estructuras flexibles, la información puede ser modificada y es posible añadir nuevos renglones y columnas.

Añadir nuevas columnas

Supongamos que queremos añadir una nueva columna que muestre la estatura de cada quien en pulgadas. Para esto hay que dividir la altura en centímetros por 2.54:

> fdatos$alt_in = fdatos$altura/2.54

> print(fdatos)

                  nombre altura peso   alt_in
     Sofía         Sofía    158   55 62.20472
     Ema             Ema    165   65 64.96063
     Olivia       Olivia    159  117 62.59843
     Elizabet   Elizabet    164   72 64.56693
     María         María    160   60 62.99213
     Emilia       Emilia    163   59 64.17323
     Guadalupe Guadalupe    161   73 63.38583
     Karla         Karla    162   66 63.77953

Como se puede ver la sintaxis para añadir una nueva columna requiere escribir dataframe$nuevacolumna = vector, en el ejemplo anterior el vector se generó a partir de información existente pero se puede ingresar información arbitraria a la nueva columna. Ésta no es la única forma de añadir columnas, también se puede hacer por medio de la función cbind( ) cuya sintaxis es la misma que la de la función rbind( ) descrita más abajo.

Modificar un dataframe

Como se dijo al inicio también es posible modificar información existente. Supongamos que en nuestro dataframe al que acabamos de añadir la altura en pulgadas queremos redondear la información de la última columna a sólo un dígito:

> fdatos$alt_in <- round(fdatos$alt_in, digits=1)

> print(fdatos)
             nombre altura peso alt_in
Sofía         Sofía    158   55   62.2
Ema             Ema    165   65   65.0
Olivia       Olivia    159  117   62.6
Elizabet   Elizabet    164   72   64.6
María         María    160   60   63.0
Emilia       Emilia    163   59   64.2
Guadalupe Guadalupe    161   73   63.4
Karla         Karla    162   66   63.8

La función round( ) usa dos argumentos, un vector numérico y el número de dígitos a usar para la operación de redondeo. Es una función vectorizada, es decir produce un vector de la misma longitud que el que se pasó como primer argumento. El vector resultante se asignó a la columna fdatos$alt_in

Añadir nuevos renglones

Para añadir nuevos renglones la función a usar es rbind( ). Añadiremos los datos de una persona más a nuestro dataframe

> fdatos <- rbind(fdatos, c('Alejandra', 161, 68, 63.4))

> print(fdatos)
             nombre altura peso alt_in
Sofía         Sofía    158   55   62.2
Ema             Ema    170   65     65
Olivia       Olivia    159  117   62.6
Elizabet   Elizabet    164   72   64.6
María         María    160   60     63
Emilia       Emilia    163   59   64.2
Guadalupe Guadalupe    161   73   63.4
Karla         Karla    162   66   63.8
9         Alejandra    161   68   63.4

Ésta función toma dos argumentos: el dataframe al que añadiremos un nuevo renglón, el nuevo renglón ya sea en forma de vector, lista o dataframe. Hay que notar que el nuevo renglón usa el nombre por defecto 9. Si queremos que use el nombre de la persona como nombre del renglón podemos hacer algo como esto:

> fdatos = data.frame(fdatos, row.names = fdatos$nombre)

> print(fdatos)
             nombre altura peso alt_in
Sofía         Sofía    158   55   62.2
Ema             Ema    165   65     65
Olivia       Olivia    159  117   62.6
Elizabet   Elizabet    164   72   64.6
María         María    160   60     63
Emilia       Emilia    163   59   64.2
Guadalupe Guadalupe    161   73   63.4
Karla         Karla    162   66   63.8
Alejandra Alejandra    161   68   63.4

Modificar entradas individuales en un dataframe

También es posible modificar valores individuales en un dataframe. Por ejemplo, para modificar la altura de Ema sólo hay que acceder a la entrada correspondiente y usar el operador de asignación <- para establecer el nuevo valor.

> fdatos['Ema', 'altura'] <- 170

> print(head(fdatos))
           nombre altura peso alt_in
Sofía       Sofía    158   55   62.2
Ema           Ema    170   65   65.0
Olivia     Olivia    159  117   62.6
Elizabet Elizabet    164   72   64.6
María       María    160   60   63.0
Emilia     Emilia    163   59   64.2

Todas las operaciones anteriores lo que en realidad hacen es crear una copia del dataframe, llevar a cabo la operación que pedimos y asignar el resultado a nuestro dataframe original. En el caso de que se estén manejando grandes cantidades de datos esto no es recomendable porque incremente notablemente el consumo de recursos.

Combinar Dataframes

Es posible combinar dataframes que tienen columnas en común por medio de la rutina merge( ). Supongamos que tenemos las siguientes dos tablas:

> print(datos1)
     nombre altura peso
1     Sofía    158   55
2       Ema    165   65
3    Olivia    159  117
4  Elizabet    164   72
5     María    160   60
6    Emilia    163   59
7 Guadalupe    161   73
8     Karla    162   66

> print(datos2)
   personas edades
1 Guadalupe     19
2       Ema     21
3     Karla     28
4  Elizabet     18
5     María     22
6    Emilia     25
7     Sofía     24
8    Olivia     26

Ambas tablas contienen información complementaria sobre las mismas personas, así que sería deseable tener toda esa información en una sola tabla.

> datos <- merge(datos1, datos2, by.x = 'nombre', by.y = 'personas')

> print(datos)
     nombre altura peso edades
1  Elizabet    164   72     18
2       Ema    165   65     21
3    Emilia    163   59     25
4 Guadalupe    161   73     19
5     Karla    162   66     28
6     María    160   60     22
7    Olivia    159  117     26
8     Sofía    158   55     24

La función merge( ) combina ambas tablas y toma 4 argumentos:

  • el nombre del primer dataframe
  • el nombre del segundo dataframe
  • el nombre de la columna en el primer dataframe que se usará como identificador para combinarlos
  • el nombre de la columna en el segundo dataframe que contiene los identificadores

En este caso funciona porque las entradas de la columna en común son únicas, no hay nombres repetidos. El dataframe final muestra los nombres ordenados alfabéticamente.