1/7
CLASE 2: TRATAMIENTO Y LIMPIEZA DE BASES DE DATOS
1.- TODOS LOS DATOS DEBEN TIENER UN “ID”
# Cargamos el fichero de formato .csv
Data_set <- read.csv("data/arrowheads_limpieza.csv", sep = ";")
#Hacemos un preview de la base con un head()
head(data_set)
#Para hacer unas tablas más bonitas usamos kableExtra
#install.packages("kableExtra") #Instalamos este paquete para ayudarnos a mejorar tablas
library(kableExtra) #Cargamos la librería, Revisar documentación
head(data_set) %>% kbl() %>% kable_classic_2(full_width = F, position = "left") %>%
kable_styling(fixed_thead = T, bootstrap_options = "responsive", font_size = 11) %>%
row_spec(0, font_size = 11)
#Aunque esta base tiene una columna de “record” como identificador, vamos a crear otro desde
cero, lo llamaremos ID
#Primero contamos la cantidad de filas y lo asignamos a un objeto
n <- nrow(data_set)
cat("La Base tiene: ", n, " filas") #lo imprimimos en la consola
#Creamos una nueva variable en la base y le generamos una secuencia de números del 1 al 1079
data_set$ID <- seq(from=1, to=n, by=1)
head(data_set,8) %>% kbl() %>% kable_classic_2(full_width = F, position = "left") %>%
kable_styling(fixed_thead = T, bootstrap_options = "responsive", font_size = 11) %>%
row_spec(0, font_size = 11)
2.- IDENTIFICAR VALORES DUPLICADOS
#Revisamos si en la columna record de la base de datos tiene valores repetidos.
duplicated(data_set$record)
duplicados <- duplicated(data_set$record) #Los guardamos en un objeto
sum(duplicados==TRUE) #Contamos cuantos TRUE existen
2/7
#Es decir, hay 3 datos que estan duplicados. Ahora queremos saber quienes son.
data_set[duplicados, ] %>% kbl() %>% kable_classic_2(full_width = F, position = "left") %>%
kable_styling(fixed_thead = T, bootstrap_options = "responsive", font_size = 11) %>%
row_spec(0, font_size = 11)
#Como ya sabemos quienes son, agregamos un indentificador a los valores repetidos por medio de
un condicional
data_set$record <- ifelse(duplicados == TRUE, "999", data_set$record)
sum(data_set$record == "999") #Contamos para verificar los valores repetidos
#verificamos que son los mismos:
data_set[data_set$record == "999", ]
# Como vemos que son las misma cantidad, procedemos a eliminar los valores repetidos
data_set <- data_set[data_set$record != "999", ]
nrow(data_set) #Volvemos a contar la cantidad de filas de nuestra base para verificar que hubo un
cambio
sum(duplicated(data_set$record) == TRUE) #verificamos que no existan duplicados en "record"
3.- IDENTIFICAR/ELIMINAR DATOS FALTANTES
#Lo primero es saber si todas nuestras columnas tienen el formato que les corresponde. Para ello
usaremos la función str()
str(data_set)
#Podemos ver que la columna “width” está en formato “chr” (character), es decir, en formato
texto, lo cual no corresponde, pues debería ser numérico. Para eso usamos la función as.numeric()
data_set$width <- as.numeric(data_set$width)
str(data_set) #comprobamos que se ha realizado el cambio
#Ahora comprobamos si existen valores perdidos en nuestra base con la función is.na()
sum(is.na(data_set)) #Cuenta todos los valores perdidos en la base en variables numéricas
# Si queremos conocer los valores perdidos de cada variable, hay que usar una función vectorizada
llamada sapply
sapply(data_set, function(x) length(which(is.na(x))))
3/7
# Si queremos verlo en un forma más “presentable”, usaremos el kableExtra
t(sapply(data_set,function(x) length(which(is.na(x))))) %>% kbl() %>%
kable_classic_2(full_width = F, position = "center") %>%
kable_styling(fixed_thead = T, bootstrap_options = "responsive", font_size = 11) %>%
row_spec(0, font_size = 11)
#Podemos identificar que hay una columna que tienen muy poca información como es:
“diameter”, que es la que más aporta a los vacíos. Por tanto vamos a proceder a eliminar esa
columna de la base de datos
data_set <- data_set[, -7] #Eliminamos la columna donde tienen mayor cantidad de valores vacíos
"diameter"
# data_set$diameter = NULL #alternativamente podemos eliminarlo así
data_set[, c("classification","subClassification")] <- list(NULL) #aprovechamos y eliminamos estas
dos que nada aportan y hacen que la base sea muy “larga”
#Volvemos a revisar
sum(is.na(data_set))
t(sapply(data_set,function(x) length(which(is.na(x))))) %>% kbl() %>%
kable_classic_2(full_width = F, position = "center") %>%
kable_styling(fixed_thead = T, bootstrap_options = "responsive", font_size = 12) %>%
row_spec(0, font_size = 12)
# Una vez que ya sabemos cuantos y donde está los datos vacíos o perdidos, los eliminamos con la
función na.omit()
data_set <- na.omit(data_set)
sum(is.na(data_set)) # Volvemos a revisar si existen datos vacíos.
# Buscar y eliminar otros vacíos que no fueron detectados con el is.na(), porque esta función solo
busca en variables numéricas.
sum(data_set$broadperiod == "")
sum(data_set$location == "")
# Los inputamos como NA para poder eliminarlos
data_set$broadperiod[data_set$broadperiod == ""] <- NA
data_set$location[data_set$location == ""] <- NA
4/7
sum(is.na(data_set)) #contamos los NA
# Finalmente los eliminamos
data_set <- na.omit(data_set) # Los eliminamos
sum(is.na(data_set)) #Volvemos a verificar la existencia de NA
# Al constatar que ya no hay valores vacíos, podemos revisar cuanto es el “n” de cada columna de
nuestro data frame. Nos apoyamos con la función kableExtra para que se vea mejor.
t(sapply(data_set, length)) %>% kbl() %>% kable_classic_2(full_width = F, position = "center") %>%
kable_styling(fixed_thead = T, bootstrap_options = "responsive", font_size = 12) %>%
row_spec(0, font_size = 12)
# Observamos que ahora nuestra base tiene 694 filas.
4.- SEPARAR COLUMNAS QUE TIENEN MÁS DE UN DATO
#Para separar columnas que tienen más de un dato usaremos como ejemplo la columna “location”,
que observamos que tiene el nombre de la district y la county
head(data_set$location, 12) #al hacer un head sobre location en los 12 primeros datos, podemos
observar que podemos usar la coma(“,”) como separador de las dos instancias. Para ello podemos
usar la función strsplit()
district_county <- strsplit(data_set$location, ",") #Usando la "," como separador, genera un lista
# Convertimos la lista “district_county” a una matriz en dos columnas leido en filas, esto para
poder identificar o separar en dos columnas: ditrict y county
m <- matrix(unlist(district_county), ncol = 2, byrow=T) #aquí creamos la matriz m
data_set$ditrict <- m[,1] #Agregamos la columna 1 a una nueva columna en la base llamada ditrict
data_set$county <- m[,2] #Agregamos la columna 2 a una nueva columna en la base llamada
county
head(data_set, 12) #vemos los resultados
# Observamos que ha separado correctamente en dos columnas
5.- INCONSISTENCIA/ERRORES EN VALORES CONTINUOS
#Identificamos si hay datos con incosistencia o errores en valores contínuos por ejemplo: length,
width, thickness y weight entre otras variables numéricas.
5/7
#Empezamos por length
#Hacemos una descriptiva básica de length para identificar valores
summary(data_set$length)
# Observamos que el valor mínimo es de -47.62 mm y un valor máximo de 48000 mm. Que son
claramente datos erróneos. Por tanto, vamos a explorar con más detalle:
#Identificamos los individuos con valores menores o iguales a 0
data_set[ifelse(data_set$length <= 0, TRUE,FALSE), ]
#Vemos que en realidad hay 2 individuos con valores “negativos”. Como no tenemos posibilidad de
corregir esos datos. Procedemos a eliminarlos.
#Para eliminar esos valores, usamos el siguiente código:
data_set <- data_set[data_set$length >0, ] #Aquí le decimos que nos deje solamente los valores
#cuya length sea mayor a 0. Por tanto, esos valores
#negativos ya no aparecen en la base
sum(ifelse(data_set$length <= 0, TRUE,FALSE)) #Confirmados que se hayan eliminados de la base
# Ahora identificamos los mayores de 1000 mm
data_set[ifelse(data_set$length > 1000, TRUE,FALSE), ]
#Igualmente que el caso anterior, no tenemos la posibilidad de corregir esos datos, por tanto
procedemos a eliminarlos.
data_set <- data_set[data_set$length <=1000, ] #Conservamos los valores menores o iguales a
1000
sum(ifelse(data_set$length > 1000, TRUE,FALSE)) #Confirmados que se hayan eliminados de la
base
#Si hacemos un nrow(data_set) observaremos que nuestra base ahora tiene 691 filas
6.- COLOCAR LOS DATOS EN EL FORMATO O UNIDAD CORRECTOS
#La variable “weather” está en grados farenheit y necesitamos transformarla en grados Celsius
summary(data_set$weather) #hacemos un summary para ver si hay valores extremos inusuales o
extraños.
#Creamos una nueva columna en la base de datos llamada weather_m
data_set$weather_m <- (data_set$weather-32)*5/9 #En esta nueva columna hacemos la
transformación
6/7
summary(data_set$weather_m) #Verificamos con un summary
#Vemos que se ha transformado correctamente
7.- TODAS LAS CATEGÓRICAS DEBEN ESTAR CODIFICADAS
#Para que el programa r reconozca las variables categóricas, hay que usar la función factor()
#Empezaremos con la variable "broadperiod"
data_set$broadperiod <- factor(data_set$broadperiod) #Aqui hemos factorizado la variable
table(data_set$broadperiod) #Podemos ver una frecuencia simple son table()
Si queremos darle un mejor formato a la tabla, usaremos el kableExtra
t(table(data_set$broadperiod)) %>% kbl() %>% kable_classic_2(full_width = F, position =
"float_left") %>% kable_styling(fixed_thead = T, bootstrap_options = "responsive", font_size = 11)
%>% row_spec(0, font_size = 11)
#Hay que hacer lo mismo con el resto de variables categóricas.
#En caso de querer unir dos o más categorías hay que usar la función ifelse junto con la condición |
(OR). Por ejemplo, supongamos que deseamos unir las categorías EARLY MEDIEVAL y MEDIEVAL
data_set$broadperiod_m <- ifelse(data_set$broadperiod == "EARLY MEDIEVAL" |
data_set$broadperiod == "MEDIEVAL", "MEDIEVAL_full", data_set$broadperiod)
data_set$broadperiod_m <- factor(data_set$broadperiod_m, labels=c("BRONZE AGE","IRON
AGE","MESOLITHIC","NEOLITHIC", "POST MEDIEVAL","ROMAN","UNKNOWN","MEDIEVAL_full"))
table(data_set$broadperiod_m)
8.- AJUSTAR VALORES FECHAS
# transformar el campo “date” de un formato numérico a un formato de tipo fecha.
# vamos a usar la función as.Date()
#Transformar el campo date a tipo fecha
library(dplyr) # Cargamos esta librería para poder usar la función mutate
fecha <- data_set['date'] %>%
mutate(date_m = as.Date(date, # transformamos en date_m
origin = "1900-01-01", # Fecha de origen para el conteo
tz = "UTC")) # Huso horario
7/7
data_set$date_m <- fecha$date_m #Integramos la nueva fecha a la base
#Observamos el cambio en nuestra base de datos
head(data_set,6) %>% kbl() %>%
kable_classic_2(full_width = F, position = "left") %>%
kable_styling(fixed_thead = T, bootstrap_options = "responsive", font_size = 9) %>%
row_spec(0, font_size = 9)
# …y de esta forma ya podemos hacer uso de la fecha para diferentes operaciones:
as.numeric(format(data_set$date_m,'%Y')) #Extrae solo los años
#as.numeric(format(data_set$date_m,'%d')) #Extrae solo los días
#as.numeric(format(data_set$date_m,'%m')) #Extrae solo los meses
9.- GUARDAR Y LEER BASES EN FORMATO R
Para guardar la base (data frame) ya lista y limpia, tenemos dos opciones:
1. Guardar el fichero con formato .xlsx o .csv por ejemplo:
a. write.csv(data_set, “data_set.csv”) | openxlsx::write.xlsx(data_set,
file=“data_set.xlsx”)
2. Lo recomendable, guardarlo con el formato interno de R (.RData), lo que permite mayor
rápidez al momento de cargarlo y usarlo nuevamente
a. Para esta última opción, usaremos la función save():
b. save(data_set, file="data_set.RData") #Lo guarda en la mima carpeta que estemos
trabajando
Para cargarlo nuevamente, ya sea en la misma carpeta u otra, debemos asegurarnos que tener el
fichero .RData y usamos la función load()
load("data_set.RData")