Empezemos con la la carga de la librería de tidyverse. En este modulo se trabajará con la libreria “tidyr” dentro del grupo de librerías “tidyverse”
library(tidyverse)
## -- Attaching packages ----------------------------------------------------------------------------------------------- tidyverse 1.2.1 --
## v ggplot2 3.1.0 v purrr 0.2.5
## v tibble 1.4.2 v dplyr 0.7.8
## v tidyr 0.8.2 v stringr 1.3.1
## v readr 1.1.1 v forcats 0.3.0
## -- Conflicts -------------------------------------------------------------------------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
Diferencia entre uno limpio y uno no:
Cada variable debe estar en una columna diferente, no pueden estar mezclados los valores
Cada una de las observaciones han de tener su propia fila
Cada valor debe estar en su propia celda.
Problemas que podemos encontrar a la hora de trabajar con una nueva base de datos:
Para limpiar correctamente un nuevo dataset haremos uso de las funciones de gather() y spread()
Gather nos permitirá unificar diferentes variables en una sola columna. Necesita 3 parámetros:
Conjunto de valores que representan valores (no variables)
La clave (key) donde pondremos el nombre de las variables
El valor que usaremos
Este es e dataset que transformaremos:
table4a
Usaremos gather para unificar year en una sola variable:
table4a %>%
gather("1999","2000",key = "year", value = "cases") -> tidy4a
tidy4a
Hemos creado un diccionario o array asociativo. Otro ejemplo de limpieza de datos:
table4b
Usamos la función gather:
table4b %>%
gather("1999","2000", key = "year", value = "population") -> tidy4b
tidy4b
Unificación de los dos data fraes que hemos creados con left_join():
left_join(tidy4a,tidy4b)
## Joining, by = c("country", "year")
La función spread nos sirve para juntar observaciones que estan en diferentes líneas, en una sola. Ejemplo:
table2
Para spread solo necesitamos dos valores, la clave (corresponderá la columna que contemplará el nombre de la variable que quiero separar) y el valor (nombre de la columna que contiene los diferentes valores que quiero separar).
table2 %>%
spread(key = type, value = count)
Análisis de un nuevo data frame:
table3
La columna rate tiene dos variables dentro de ella, y además esta en character. ¿Cómo podemos tratar estos datos? Haremos uso de:
separate() -> separa una columna a partir de un valore especificado
unite() -> unificación de diferentes valores
table3 %>%
separate(rate, into = c("cases","population"),
sep = "/", convert = TRUE) # no me hace falta determinar el separador, ya esta de forma interna en separate. Con convert igual a true, le pedimos que mire el tipo de dato que es para que le de el formato correcto
También podemos separar especificando por la posición para todoas las observaciones. Imaginemos que queremos separar siglo y año:
table3 %>%
separate(rate, into = c("cases","population"),
sep = "/", convert = TRUE) %>%
separate(year, sep = 2, into = c("century","year"), convert = TRUE)
Usando la tabla5 para rejuntar siglo con año, usaremos la función unite():
table5
Usamos la función unite():
table5 %>%
unite(new_year, century, year)
El separador por defecto es una “_“, si queremos especificarlo:
table5 %>%
unite(new_year, century, year, sep = "")
Los NAs solo pueden aparecer en dos formas:
de forma explícita: el dato falta y es “NA”
de forma implícita: el dato no aparecía en el dataset original, antes de ser transformado, o podría ser que en el orginal no hubiera un NA pero al tranformarse fuera un NA.
Primero creamos el dataset con el que vamos a trabajar:
roi <- tibble(
year = c(rep(2016,4), rep(2017,4), 2018),
quarter = c(rep(c(1,2,3,4),2),1),
return = rnorm(9, mean = 0.5, sd = 1)
)
roi
Vamos a hacer aparecer algun NA de forma explícita, no podemos saber que valor debería ir en esta posición, porqué el dato no existe:
roi$return[7] = NA
roi
En cambio, si eliminamos una fila, podemos decir que hay un NA de algo que debería estar pero no está:
roi %>%
spread(year, return)
Aquí podemos ver que nos faltan más datos de los localizados a primera vista. ¿Cómo tratarlos?
roi %>%
spread(year, return) %>%
gather(year, return, "2016":"2018", na.rm = TRUE)
Aquí hemos tratado los NAs implícitos y explícitos con el parametro na.rm().
La función complete(), completará el conjunto de columnas que hayamos indicado y rellenara de forma explícita con NAs allí donde haga falta.
roi %>%
complete(year,quarter)
Complete() nos ha mostrado tres NA al final que no estavan introducidos. También se puede hacer uso de la función fill() para rellenar datos.
Base de datos relacionales -> bases de datos relacionadas a partir de ciertas variables.
Para ver la relación entre diferentas tablas, haremos uso de los datos relacionales de los dataset de la libreria(flights). Los datos relacionados son los siguientes:
datos NYCflights13 relacionados
library(nycflights13)
Una claves es una variable o un conjunto de variables per que de forma unívoca identifica la observación. Existen dos tipos de clave:
clave primaria: identifica de forma unívoca un observación de su propia tabla
clave foranea: identifica únicament la observación en otra tabla.
Una variable puede ser primaria y foranea.
¿Cómo se que tailnum es la clave primaria del data set planes?
nycflights13::planes %>%
count(tailnum) %>%
filter(n>1)
Al ser 0, nos muestra que no hay ningún avión que tenga un número de cola repetido.
¿Cómo se que year, month, day, hour y origin conjuntamente son claves primarias?
weather %>%
count(year, month, day, hour, origin) %>%
filter(n>1)
Por lo tanto, son variables foraneas.
En el caso que no tengamos una clave primaria, podríamos añadir una a mano con mutate() o usando el número de la linea.
Nos permite combinar variables de dos tablas. Primero buscará observaciones que coincidan por clave, y luego hacer copas a través de las variables de una tabla a la otra.
flights_new <- flights %>%
select(year:day, hour, origin, dest, tailnum, carrier)
head(flights_new)
Principalmente nos hemos quedado con las claves primarias:
flights_new %>%
left_join(airlines, by = "carrier") %>%
head(10)
Podríamos haber obtenido el mismo resultado usando mutate() para crear una primary key:
head(flights_new) %>%
mutate(name = airlines$name[match(carrier, airlines$carrier)])
Metodología de los joins
Ejemplo para entender los joins:
x <- tribble(
~key, ~value_x,
1, "x1",
2, "x2",
3, "x3"
)
y <- tribble(
~key, ~value_y,
1, "y1",
2, "y2",
4, "y3"
)
Se esperan que las claves coincidan a la perfeccion entre las claves del primer y el segundo dataframe.
Los inner join
Como realizamos el join a partir de la clave comuna:
x %>%
inner_join(y, by = "key")
La propiedad más importante de un inner join es que solo es capaz de mantener los resultados que aparecen en ambas tablas.
Outer join
El outer join conserva las observaciones que aparecen al menos en una de las dos tablas. Diferentes tipos de outer join:
Left join: se queda con todas las observaciones que aparecen en el primer data set independientemente del segundo
Right join: se queda con todas las observaciones que aparecen en el segundo data set independientemente del primero
Full join: se queda con las observaciones tanto del primero como del segundo data frame.
Existen también otra forma de ver los joins a través de los diagramas de conjuntos:
Diagramas de conjunntos
Vamos a ver diferentes ejemplos:
x %>% inner_join(y, by = "key")
x %>% left_join(y, by = "key")
x %>% right_join(y, by = "key")
x %>% full_join(y, by = "key")
¿Qué ocurre cuando las claves estan duplicadas?
Claves duplicadas
Creamos la tribble del ejemplo:
x <- tribble(
~key, ~value_x,
1, "x1",
2, "x2",
2, "x3",
1, "x4"
)
y <- tribble(
~key, ~value_y,
1, "y1",
2, "y2"
)
Una vez los datasets creados vamos a ver como podemos aplicar el join:
x %>% left_join(y, by = "key")
También puede pasar que hayan claves duplicadas en las dos tablas. Cuando se combinan los dos se juntan todas las posibles combinaciones, creando un producto cartesiano.
claves duplicadas ambas tablas
Creación de los tribbles con los que trabajaremos:
x <- tribble(
~key, ~value_x,
1, "x1",
2, "x2",
2, "x3",
3, "x4"
)
y <- tribble(
~key, ~value,
1, "y1",
2, "y2",
2, "y3",
3, "y4"
)
Creemos el left join para este caso,
left_join(x,y, by = "key")
Si no se especifican las variables clave par a la unificación de dos datasets, joing cogerá el parametro “NULL” por defecto. Esto quiere decir que buscará todas las variables que coincidan el los dos datasets. Ejemplo:
head(flights_new) %>% left_join(weather)
## Joining, by = c("year", "month", "day", "hour", "origin")
En pantalla mostrará el natural join, como se llama cuando no se especifica el parametro by().
Podemos también hacer un join donde le damos a entender que hay alguna variable que es la misma en dos datasets distintos, pero tienen un nombre diferente:
flights_new %>%
left_join(airports, by = c("dest" = "faa")) %>%
head(10)
La función merge() tiene la misma función que los join. Ahora mostraremos primero la relación enrte DPLYR y el paquete base de R, y también con SQL(standard query location)
dplyr <-> base R
inner_join(x,y) <-> merge(x,y)
left_join(x,y) <-> merge(x, y, all.x = TRUE)
right_join(x,y) <-> merge(x, y, all.y = TRUE)
full_join(x,y) <-> merge(x, y, all.x = TRUE, all.y = TRUE)
dplyr <-> SQL
left_join(x, y, by = “z”)
SELECT * FROM x INNER JOIN y USING (z)
SELECT * FROM x INNER JOIN y ON x.key = y.key
left_join(x,y, by = “z”)
SELECT * FROM x LEFT OUTER JOIN y USING(z)
SELECT * FROM x LEFT OUTER JOIN y ON x.key = y.key
right_join(x,y, by = “z”)
SELECT * FROM x RIGHT OUTER JOIN y USING (z)
SELECT * FROM x RIGHT OUTER JOIN y ON x.key = y.key
full_join(x,y, by = “z”)
SELECT * FROM x FULL OUTER JOIN y USING (z)
SELECT + FROM x FULL OUTER JOIN y ON x.key = y.key
Junta dataframes afectando a las observaciones no a las variables. Existen dos tipos de filtering joins:
semi_join(x,y) -> se queda con las observaciones de x que tienen correspondencia con y
anti_join(x,y) -> eliminan todas las observaciones de x que tienen correspondencia en y
Ejemplo del que podemos hacer con filter_join():
flights %>%
count(dest, sort = TRUE) %>%
head(10) -> top_dest
Ahora haremos un filtrado de la información, para saber la lista total de los vuelos que volaron en alguno del top 10 destinos:
flights %>%
filter(dest %in% top_dest$dest)
Hacer el filtrado con semi_join():
flights %>% semi_join(top_dest) %>%
head(10)
## Joining, by = "dest"
Gráfico de como quedaría un semi_join():
semi_join()
Un anti_join hace el proceso contrario:
anti_join()
Como hacer un anti_join(), encontrar correspondencias o no con diferentes datasets:
flights %>% anti_join(planes, by = "tailnum") %>%
count(tailnum, sort = TRUE) %>%
head(10)
Principalmente son 3:
intersect(x,y): observaciones comunes a “x” e “y”
union(x,y): observaciones únicas en “x” e “y”
setdiff(x,y): observaciones en “x” pero no en “y” (x - y)
Ejemplo:
x <- tribble(
~a, ~b,
1, 1,
2, 1
)
y <- tribble(
~a, ~b,
1, 1,
1, 2
)
Operaciones que puedo realizar:
intersect(x,y)
union(x,y)
setdiff(x,y)