4.2 Manipulación de datos
Una vez cargada una (o varias) bases de datos hay una serie de operaciones que serán de interés para el tratamiento de datos:
- Operaciones con variables:
- crear
- recodificar (e.g. categorizar)
- …
- Operaciones con casos:
- ordenar
- filtrar
- …
A continuación se tratan algunas operaciones básicas.
4.2.1 Operaciones con variables
4.2.1.1 Creación (y eliminación) de variables
Consideremos de nuevo la
base de datos cars
incluida en el paquete datasets
:
data(cars)
# str(cars)
head(cars)
## speed dist
## 1 4 2
## 2 4 10
## 3 7 4
## 4 7 22
## 5 8 16
## 6 9 10
Utilizando el comando help(cars)
se obtiene que cars
es un data.frame con 50 observaciones y dos
variables:
speed
: Velocidad (millas por hora)dist
: tiempo hasta detenerse (pies)
Recordemos que, para acceder a la variable speed
se puede
hacer directamente con su nombre o bien utilizando notación
“matricial.”
$speed cars
## [1] 4 4 7 7 8 9 10 10 10 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15
## [26] 15 16 16 17 17 17 18 18 18 18 19 19 19 20 20 20 20 20 22 23 24 24 24 24 25
1] # Equivalente cars[,
## [1] 4 4 7 7 8 9 10 10 10 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15
## [26] 15 16 16 17 17 17 18 18 18 18 19 19 19 20 20 20 20 20 22 23 24 24 24 24 25
Supongamos ahora que queremos transformar la variable original speed
(millas por hora) en una nueva variable velocidad
(kilómetros por
hora) y añadir esta nueva variable al data.frame cars
.
La transformación que permite pasar millas a kilómetros es
kilómetros=millas/0.62137
que en R se hace directamente con:
$speed/0.62137 cars
Finalmente, incluimos la nueva variable que llamaremos
velocidad
en cars
:
$velocidad <- cars$speed / 0.62137
carshead(cars)
## speed dist velocidad
## 1 4 2 6.437388
## 2 4 10 6.437388
## 3 7 4 11.265430
## 4 7 22 11.265430
## 5 8 16 12.874777
## 6 9 10 14.484124
También transformaremos la variable dist
(en pies) en una nueva
variable distancia
(en metros). Ahora la transformación deseada es
metros=pies/3.2808
:
$distancia <- cars$dis / 3.2808
carshead(cars)
## speed dist velocidad distancia
## 1 4 2 6.437388 0.6096074
## 2 4 10 6.437388 3.0480371
## 3 7 4 11.265430 1.2192148
## 4 7 22 11.265430 6.7056815
## 5 8 16 12.874777 4.8768593
## 6 9 10 14.484124 3.0480371
Ahora, eliminaremos las variables originales speed
y
dist
, y guardaremos el data.frame resultante con el nombre coches
.
En primer lugar, veamos varias formas de acceder a las variables de
interés:
c(3, 4)]
cars[, c("velocidad", "distancia")]
cars[, -c(1, 2)] cars[,
Utilizando alguna de las opciones anteriores se obtiene el data.frame
deseado:
<- cars[, c("velocidad", "distancia")]
coches # head(coches)
str(coches)
## 'data.frame': 50 obs. of 2 variables:
## $ velocidad: num 6.44 6.44 11.27 11.27 12.87 ...
## $ distancia: num 0.61 3.05 1.22 6.71 4.88 ...
Finalmente los datos anteriores podrían ser guardados en un fichero exportable a Excel con el siguiente comando:
write.csv2(coches, file = "coches.csv")
4.2.1.2 Recodificación de variables
Con el comando cut()
podemos crear variables categóricas a partir de variables numéricas.
El parámetro breaks
permite especificar los intervalos para la discretización, puede ser un vector con los extremos de los intervalos o un entero con el número de intervalos.
Por ejemplo, para categorizar la variable cars$speed
en tres intervalos equidistantes podemos emplear3:
<- cut(cars$speed, 3, labels = c("Baja", "Media", "Alta"))
fspeed table(fspeed)
## fspeed
## Baja Media Alta
## 11 24 15
Para categorizar esta variable en tres niveles con aproximadamente el mismo número de observaciones podríamos combinar esta función con quantile()
:
<- quantile(cars$speed, probs = seq(0, 1, len = 4))
breaks <- cut(cars$speed, breaks, labels = c("Baja", "Media", "Alta"))
fspeed table(fspeed)
## fspeed
## Baja Media Alta
## 17 16 15
Para otro tipo de recodificaciones podríamos emplear la función ifelse()
vectorial:
<- ifelse(cars$speed < 15, "Baja", "Alta")
fspeed <- factor(fspeed, levels = c("Baja", "Alta"))
fspeed table(fspeed)
## fspeed
## Baja Alta
## 23 27
Alternativamente en el caso de dos niveles podríamos emplear directamente la función factor()
:
<- factor(cars$speed >= 15, labels = c("Baja", "Alta")) # levels = c("FALSE", "TRUE")
fspeed table(fspeed)
## fspeed
## Baja Alta
## 23 27
En el caso de múltiples niveles se podría emplear ifelse()
anidados o la función recode()
del paquete car
.
Para acceder directamente a las variables de un data.frame podríamos emplear la función attach()
para añadirlo a la ruta de búsqueda y detach()
al finalizar.
Sin embargo esta forma de proceder puede causar numerosos inconvenientes, especialmente al modificar la base de datos, por lo que la recomendación sería emplear with()
.
Por ejemplo:
<- with(cars, ifelse(speed < 10, "Baja",
fspeed ifelse(speed < 20, "Media", "Alta")))
<- factor(fspeed, levels = c("Baja", "Media", "Alta"))
fspeed table(fspeed)
## fspeed
## Baja Media Alta
## 6 32 12
Para manipular factores (variables cualitativas) pueden resultar de interés las herramientas en el paquete forcats
de la colección tidyverse
.
4.2.2 Operaciones con casos
4.2.2.1 Ordenación
Continuemos con el data.frame cars
.
Se puede comprobar que los datos disponibles están ordenados por
los valores de speed
. A continuación haremos la ordenación utilizando
los valores de dist
. Para ello utilizaremos el conocido como vector de
índices de ordenación.
Este vector establece el orden en que tienen que ser elegidos los
elementos para obtener la ordenación deseada.
Veamos un ejemplo sencillo:
<- c(2.5, 4.3, 1.2, 3.1, 5.0) # valores originales
x <- order(x)
ii # vector de ordenación ii
## [1] 3 1 4 2 5
# valores ordenados x[ii]
## [1] 1.2 2.5 3.1 4.3 5.0
En el caso de vectores, el procedimiento anterior se podría hacer directamente con:
sort(x)
Sin embargo, para ordenar data.frames será necesario la utilización del
vector de índices de ordenación. A continuación, los datos de cars
ordenados por dist
:
<- order(cars$dist) # Vector de índices de ordenación
ii <- cars[ii, ] # Datos ordenados por dist
cars2 head(cars2)
## speed dist velocidad distancia
## 1 4 2 6.437388 0.6096074
## 3 7 4 11.265430 1.2192148
## 2 4 10 6.437388 3.0480371
## 6 9 10 14.484124 3.0480371
## 12 12 14 19.312165 4.2672519
## 5 8 16 12.874777 4.8768593
4.2.2.2 Filtrado
El filtrado de datos consiste en elegir un subconjunto que cumpla determinadas condiciones.
Para ello se puede utilizar la función subset()
(que además permite seleccionar variables).
A continuación se muestran un par de ejemplos:
subset(cars, dist > 85) # datos con dis>85
## speed dist velocidad distancia
## 47 24 92 38.62433 28.04194
## 48 24 93 38.62433 28.34674
## 49 24 120 38.62433 36.57644
subset(cars, speed > 10 & speed < 15 & dist > 45) # speed en (10,15) y dist>45
## speed dist velocidad distancia
## 19 13 46 20.92151 14.02097
## 22 14 60 22.53086 18.28822
## 23 14 80 22.53086 24.38430
También se pueden hacer el filtrado empleando directamente los correspondientes vectores de índices:
<- cars$dist > 85
ii # dis>85 cars[ii, ]
## speed dist velocidad distancia
## 47 24 92 38.62433 28.04194
## 48 24 93 38.62433 28.34674
## 49 24 120 38.62433 36.57644
<- cars$speed > 10 & cars$speed < 15 & cars$dist > 45
ii # speed en (10,15) y dist>45 cars[ii, ]
## speed dist velocidad distancia
## 19 13 46 20.92151 14.02097
## 22 14 60 22.53086 18.28822
## 23 14 80 22.53086 24.38430
En este caso también puede ser de utilidad la función which()
:
<- which(ii)
it str(it)
## int [1:3] 19 22 23
1:2] cars[it,
## speed dist
## 19 13 46
## 22 14 60
## 23 14 80
# rownames(cars[it, 1:2])
<- which(!ii)
id str(cars[id, 1:2])
## 'data.frame': 47 obs. of 2 variables:
## $ speed: num 4 4 7 7 8 9 10 10 10 11 ...
## $ dist : num 2 10 4 22 16 10 18 26 34 17 ...
# Se podría p.e. emplear cars[id, ] para predecir cars[it, ]$speed
# ?which.min
4.2.3 Operaciones con tablas de datos
El paquete base de R dispone de diversas herramientas para realizar distintos tipos de operaciones, como:
Añadir casos o variables:
Combinar tablas:
match(x, table)
devuelve un vector (de la misma longitud quex
) con las (primeras) posiciones de coincidencia dex
entable
(oNA
, por defecto, si no hay coincidencia).pmatch(x, table, ...)
: similar al anterior pero con coincidencias parciales de cadenas de texto.
Estos operadores devuelven un índice con el que se pueden añadir variables de una segunda tabla. Para realizar consultas combinando tablas puede ser más cómodo el operador
%in%
(?'%in%'
).
Sin embargo, como se muestra en el Apéndice B puede resultar más cómodo emplear los paquetes dplyr
y tidyr
de la colección tidyverse
.
Aunque si el objetivo es obtener las frecuencias de cada intervalo puede ser más eficiente emplear
hist()
conplot = FALSE
.↩︎