💡 MATERIALES PARA LA ACTIVIDAD:

Script.

PREPARATIVOS INICIALES

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")

EXTRACCIÓN DE VARIABLES: Función select()

La sintaxis general es la siguiente:

Selección.

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"))

Exclusión

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

CAMBIO DE NOMBRE A VARIABLES: Función 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.

CAMBIAR LAS POSICIONES DE LAS VARIABLES: Función 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

AÑADIR (CALCULAR) UNA NUEVA VARIABLE EN UN DATAFRAME: Función 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

FUSIÓN DE DOS DATAFRAMES CON EL MISMO NÚMERO DE FILAS/CASOS: Función 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)

UNIÓN ENTRE DATAFRAMES CON DIFERENTE NÚMERO DE CASOS/FILAS: Función 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
  1. Selecciona las variables barrio, precio y superficie y cambia el nombre de precio por el de precio_euros y el de superficie por m2.
inmobiliaria %>%
  select(barrio, precio, superficie) %>%
  rename(precio_euros = precio,
         metros2 = superficie)
  1. Cambia el nombre de la variable banos por baños.
inmobiliaria <- inmobiliaria %>% 
  rename(baños = banos)
  1. Coloca la variable precio antes de la variable barrio y selecciona las variables precio, barrio, habitaciones y baños.
inmobiliaria %>%
  relocate(precio, .before = barrio) %>%
  select(precio, barrio, habitaciones, baños)
  1. Selecciona las variables barrio, precio y superficie, y calcula el precio del m2.
inmobiliaria %>%
  select(barrio, precio, superficie) %>%
  mutate(precio_m2 = precio / superficie)
  1. Selecciona las variables barrio, precio y superficie y reubicar superfice tras barrio.
inmobiliaria %>%
  select(barrio, precio, superficie) %>%
  relocate(superficie, .after = barrio)
  1. Cambia el nombre de las variables habitaciones por dormitorios y baños por aseos, y seleccionalas
inmobiliaria %>% 
  rename(aseos = baños, 
         dormitorios = habitaciones)
    select(habitaciones, aseos)
  1. Crea la variable ratio_hab_baños, cambia el nombre de comundad por costes_comunidad y selecciona las variables barrio, ratio_hab_baños y costes_comunidad.
inmobiliaria %>%
  mutate(ratio_hab_baños = habitaciones / baños) %>%
  rename(costes_comunidad = comunidad) %>%
  select(barrio, ratio_hab_baños, costes_comunidad)
  1. Crea un vector denominado ascensores, consistente en 694 casos en los que se informa si la vivienda cuenta o no con ascensor. Únelo posteriormente al dataframe inmobilidaria.
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) 
  1. Calcula el valor del precio en m2 y crea la variable categoría clasificando a las viviendas en función del precio en dos categorías, Alta si superan los 200000€ y Media/baja las restantes.
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")
)
  1. Une el dataframe zonas al dataframe inmobiliaria.
inmobiliaria %>%
  left_join(zonas, by = "barrio") %>%
  select(barrio, distrito, precio, superficie)
  1. Crea la variable nivel de accesibilidad, de tal manera que los valores de esa variable iguales o superiores a 2 tengan la etiqueta Alta, y los demás, baja. Selecciona las variables barrio y nivel_accesibilidad
inmobiliaria %>%
  mutate(nivel_accesibilidad = ifelse(accesibilidad >= 2, "Alta", "Baja")) %>%
  select(barrio, nivel_accesibilidad)