💡 MATERIALES PARA LA ACTIVIDAD:
► Script.
Para no tener que cargar los paquetes dplyr y
tidyr, se procede a activar el paquete
tidyverse ya que incluye los dos anteriores como
dependencias
library(tidyverse)
Establecer la carpeta de trabajo
setwd("D:/G2040/TEMA_1_Introduccion/TEMA_1_ejercicios")
Cargar el fichero
load("zonas_verdes.RData")
select()La sintaxis general es la siguiente:
Seleccionar determinadas columnas por el nombre de la variable, pe parques y superficie.
zonas_verdes %>%
select(parques, superficie)
También es posible seleccionar un rango de columnas, pe. todas las columnas entre parques y fecha de inauguración.
zonas_verdes %>%
select(parques:fecha_inauguracion)
En tercer lugar, seleccionar todas las columnas exceptuando algunas, por ejemplo, dejando fuera barrio y superficie.
zonas_verdes %>%
select(-c(barrio, superficie))
También es posible seleccionar las columnas utilizando un índice de su posición (su ubicación de izquierda a derecha en el fichero)
zonas_verdes %>%
select(1, 3)
Igualmente, es posible seleccionar las columnas cuyos nombres
contienen un conjunto determinado de caracteres, en
este caso pa**rq**ues o supe**rfi**cie.
zonas_verdes %>%
select(matches("rq|rfi"))
El operador ^ sirve también para seleccionar columnas que comienzan
con un conjunto determinado de caracteres, por ejemplo,
^fech equivale a comenzar por “fech”.
zonas_verdes %>%
select(matches("^fech|ob"))
También es posible excluir determinadas columnas, tanto por su nombre…
zonas_verdes %>%
select(-ID)
… su posición
zonas_verdes %>%
select(-c(1,3))
Similar a la anterior
zonas_verdes %>%
select(-1, -4)
Las variables a excluir se pueden enumerar como una lista concatenada…
zonas_verdes %>%
select(-one_of("barrio", "fecha_inauguracion"))
… como un rango de variables.
zonas_verdes %>%
select(-(barrio:obras))
Es posible eliminar todas las columnas que contienen una frase…
zonas_verdes %>%
select(-contains("obras"))
… o cuyo nombre comienza por ciertos caracteres…
zonas_verdes %>%
select(-starts_with("Bar"))
…o que finaliza con ciertos caracteres.
zonas_verdes %>% select(-ends_with("ion"))
A continuación mostramos un resumen de las funciones para select() que nos serán muy útiles:
| Función | Acción |
|---|---|
| - | Selecciona todas las variables excepto |
| : | Selecciona un rango |
| contains() | Selecciona variables cuyo nombre contiene la cadena de texto |
| ends_with() | Selecciona variables cuyo nombre termina con la cadena de caracteres |
| everything() | Selecciona todas las columnas |
| matches() | Selecciona las variables cuyos nombres coinciden con una expresión regular |
| num_range() | Selecciona las variables por posición |
| one_of() | Selecciona variables cuyos nombres están en un grupo de nombres |
| start_with() | Selecciona variables cuyos nombres empiezan con la cadena de caracteres |
rename()La función rename() esta diseñada para modificar el
nombre de variables. La sintaxis original e
rename(dataframe, nombre_nuevo = nombre_antiguo).
Ya sabemos que para conocer los nombres originales de las variables
de un dataframe se debe aplicar la función names().
names(zonas_verdes)
Para no destruir el dataframe original en este proce se creará uno
nuevo, denominado borrame, en el que se cambiará el nombre
de la variable “fecha_inauguracion” a “fecha”.
borrame <- zonas_verdes %>%
rename(fecha = fecha_inauguracion)
Es posible cambiar el nombre de varias variables simultáneamente…
borrame <- borrame %>%
rename(distrito = barrio,
zona_verde = parques)
… o de todas las variables de un dataframe (aunque la sintaxis es algo diferente).
borrame <- borrame %>%
`colnames<-`(c("v1", "v2", "v3", "v4", "v5", "v6"))
borrame
El número de nuevos nombres usando la función colnames()
debe ser el mismo que el de las variables en el dataframe anterior.
relocate()Si el orden de las variables no conviene a nuestros intereses, es
posible mover una variable de posición, por ejemplo al
inicio (mueve fecha_inauguracion a la
primera posición del dataframe)…
zonas_verdes %>%
relocate(fecha_inauguracion)
… al final (mueve ID a la última
posición)
zonas_verdes %>%
relocate(ID, .after = last_col())
Igualmente, es posible mover una columna después de
otra (mueve parques justo después de
barrio)
zonas_verdes %>%
relocate(parques, .after = barrio)
… o moverla antes de otra (ueve obras
antes de superficie)
zonas_verdes %>%
relocate(obras, .before = superficie)
Esta función permite mover varias columnas
simultáneamente (mueve parques y
obras después de ID)…
zonas_verdes %>%
relocate(parques, obras, .after = ID)
… o mover columnas tras definir una condición (em este caso, por tipo; mueve todas las columnas de tipo Date al final)
zonas_verdes %>%
relocate(where(is.Date), .after = last_col())
Finalmente, mueve columnas cuyo nombre contiene un
texto (superficie antes de obras)
zonas_verdes %>%
relocate(contains("superficie"), .before = obras)
| Argumento | Qué hace |
|---|---|
| .before = col | Mueve la(s) columna(s) antes de col |
| .after = col | Mueve la(s) columna(s) después de col |
| Sin .before/.after | Mueve al principio |
mutate()La función mutate() crea nuevas variables, modifica las
existentes (sobreescribe la antigua si le proporcionas el mismo nombre)
o agrega múltiples variables nuevas a la vez. Normalmente, se añaden al
final del dataframe.
📝 Actividad de clase:
Crea dos nuevas variables en el dataframe zonas_verdes.
La primera, denominada ratio_superficie_arbolada, está
constituida de una secuencia de 100 números racionales entre 23 y 75
La segunda, denominada ratio_supeficie_dura, estará constituida de una secuencia de 100 números racionales entre 5 y 17,
Una vez creadas estas nuevas variables, se calculará la variable *ratio_superficie_ajardinada” como el resultado de sustraer a 100 el ratio de la superficie arbolada y el ratio de la superficie ajardinada
zonas_verdes <- zonas_verdes %>%
mutate(ratio_superficie_ajardinada = 100 - (ratio_superficie_arbolada + ratio_superficie_dura))
Las nuevas variables añaden antes de una variable concreta
borrame <- borrame %>%
mutate(tarari = sample(1:10, 100, replace = TRUE),
.before = v5)
borrame
… o después de una variable concreta.
borrame %>%
mutate(nueva_variable=sample(75:95, 100, replace = TRUE),
.after=v6)
O añadir otra columna con los valores reclasificados de una variable preexistente
borrame <- borrame %>%
mutate(clasificado = if_else(.$v4 < 10, "Normal", "Grande"))
También se puede añadir una columna vacía, que puede rellenarse con otros datos.
borrame <- zonas_verdes %>%
mutate(columna_vacia = NA)
borrame
bind_cols()Si quiere añadir a un dataframe los datos correspondientes a otro
dataframe con su misma estructura, hay que recurrir a la función
bind_cols().
df1 <- data.frame(a = 1:3)
df2 <- data.frame(b = c("x", "y", "z"))
df_combinado <- bind_cols(df1, df2)
Con este ejemplo se crea un dataframe con una estructura “ancha” (wide).
🚫️ ¡CUIDADO!:
Si ambos dataframes no tienen la misma estructura (por ejemplo, número de variables), R devuelve un mensaje de error.
rm(df1,df2, df_combinado)
join()Sin embargo, lo más habitual es que nuestros dataframes tengan una estructura diferente, ya que pueden provenir de varias fuentes de información.
La función join() fusiona o uni dos data frames siempre
que posean columnas comunes (nombres de fila). Esta función ofrece
diferentes combinaciones (SQL), como unión izquierda
(left_join()), unión interna (inner_join()),
unión derecha (right_join()) o unión completa
(full_join()).
| Función | ¿Qué filas conserva? |
|---|---|
inner_join() |
Solo las filas que coinciden en ambas tablas |
left_join() |
Todas las filas de la tabla de la izquierda (x), y datos coincidentes de la derecha (y) |
right_join() |
Todas las filas de la tabla de la derecha (y), y datos coincidentes de la izquierda (x) |
full_join() |
Todas las filas de ambas tablas. Coincidencias se unen; no coincidencias tienen NA |
La función habitual es left_join(), en la que unimos un
dataframe “básico” (zonas_verdes), cuyos valores queremos mantener
intactos, a otro “secundario” (zonas_verdes), según esta sintaxis
dplyr::left_join(fichero1, fichero).
Vamos a crear un nuevo dataframe. Este fichero debe poseer una primera variable denominada ID
ID <- 1:100
La segunda, denominada especie_dominante, está constituida por una secuencia aleatoria de 100 elementos (cadenas de texto) que se pueden repetir con los siguientes elementos (platano, cipres, tilo, pino, castaño_indias) y una probabilidad de 0.45, 0.25, 0.15, 0.12 y 0.08
especie_dominante <- sample(c("platano", "cipres", "tilo", "pino", "castaño_indias"),
size = 100, # Número de caracteres
replace = TRUE, # Se pueden repetir
prob=c(0.45,0.25,0.15,0.12, 0.08)) # Probabilidades de aparición
A continuación, uniremos ambas vectores en un único dataframe, tras lo cual serán eliminados
zonas_verdes2 <- data.frame(ID, especie_dominante)
zonas_verdes2
rm(ID, especie_dominante)
Simularemos que el 10 % de los datos se han perdido.
set.seed(123) # Para reproducibilidad (opcional)
zonas_verdes2 <- zonas_verdes2 %>%
slice_sample(prop = 0.90)
zonas_verdes2
Como los dos dataframes tienen diferentes dimensiones, no se puede
utilizar la función bind_cols(), sino la función
left_join()con el argumento by=ID que
identifica la columna común en ambos dataframes.
left_join(zonas_verdes, zonas_verdes2,
by="ID")
Si elegimos inner_join() sólo se conservan los elementos
comunes a ambos dataframes (se pierde información del fichero que hemos
considerado básico).
inner_join(zonas_verdes, zonas_verdes2,
by="ID")
📝 ACTIVIDAD EN EL AULA :
Supongamos que poseemos un fichero denominado inmobiliaria. Lo importaremos desde el servidor de la UC.
url <- "https://personales.unican.es/rasillad/docencia/g2040/tema_1/datos/inmobiliaria.csv"
inmobiliaria <- read.csv(url, sep = ";", dec = ",", header = TRUE)
head(inmobiliaria)
## barrio precio superficie accesibilidad habitaciones banos terraza garaje
## 1 San Agustin 173800 43.2 2 3 1 2 2
## 2 San Agustin 204600 56.9 1 2 1 2 2
## 3 San Agustin 220000 66.4 2 2 2 1 1
## 4 San Agustin 270600 61.9 1 3 2 2 2
## 5 San Agustin 297000 89.8 3 3 2 2 1
## 6 San Agustin 308000 71.0 2 3 2 1 2
## comunidad valor disponible
## 1 110.0 32830.6 1
## 2 151.8 59400.0 2
## 3 0.0 34624.5 1
## 4 286.0 59400.0 1
## 5 0.0 87047.4 2
## 6 264.0 68520.1 2
inmobiliaria %>%
select(barrio, precio, superficie) %>%
rename(precio_euros = precio,
metros2 = superficie)
inmobiliaria <- inmobiliaria %>%
rename(baños = banos)
inmobiliaria %>%
relocate(precio, .before = barrio) %>%
select(precio, barrio, habitaciones, baños)
inmobiliaria %>%
select(barrio, precio, superficie) %>%
mutate(precio_m2 = precio / superficie)
inmobiliaria %>%
select(barrio, precio, superficie) %>%
relocate(superficie, .after = barrio)
inmobiliaria %>%
rename(aseos = baños,
dormitorios = habitaciones)
select(habitaciones, aseos)
inmobiliaria %>%
mutate(ratio_hab_baños = habitaciones / baños) %>%
rename(costes_comunidad = comunidad) %>%
select(barrio, ratio_hab_baños, costes_comunidad)
ascensor <- as.data.frame(sample(c("Si", "No"), # Caracteres a reproducir
size = 694, # Número de caracteres
replace = TRUE, # Se pueden repetir
prob=c(0.8,0.2))) # Probabilidades de aparición
inmobiliaria %>%
bind_cols(ascensor)
inmobiliaria %>%
mutate(precio_m2 = precio / superficie,
categoria = ifelse(precio > 200000, "Alta", "Media/Baja")) %>%
relocate(categoria, .before = precio)
Crea un dataframe denominado zonas con las siguientes
características
zonas <- data.frame(
barrio = c("San Agustin","El Robledo","Canizal","La Llama","Pingarron","Monsanto","Castillo"),
distrito = c("Sur","Centro", "Centro", "Norte", "Norte","Sur", "Sur")
)
zonas al dataframe
inmobiliaria.inmobiliaria %>%
left_join(zonas, by = "barrio") %>%
select(barrio, distrito, precio, superficie)
inmobiliaria %>%
mutate(nivel_accesibilidad = ifelse(accesibilidad >= 2, "Alta", "Baja")) %>%
select(barrio, nivel_accesibilidad)