Tutorial de dplyr en R: Combinar y unir datos con ejemplos

โšก Resumen inteligente

dplyr combina y une marcos de datos en R con cuatro verbos: left_join(), right_join(), inner_join() y full_join(). Su paquete complementario tidyr luego remodela el resultado de la uniรณn usando gather(), spread(), separate() y unite().

  • ๐Ÿ”— Mutaciones en las uniones: left_join() conserva todas las filas de la tabla de origen y right_join() conserva todas las filas de la tabla de destino.
  • ๐ŸŽฏ Control del partido: inner_join() elimina las filas que no coinciden, mientras que full_join() mantiene ambos lados y rellena los huecos con NA.
  • ๐Ÿ—๏ธ Claves compuestas: Pass by = c(โ€œIDโ€, โ€œyearโ€) siempre que una sola columna no identifique una fila de forma รบnica.
  • ๐Ÿ”„ reshaping: gather() convierte una tabla ancha en larga y spread() la vuelve a convertir en su posiciรณn original, keeping una variable por columna.
  • โœ‚๏ธ Divisiรณn y uniรณn: La funciรณn separate() divide una columna por un delimitador y la funciรณn unite() concatena las columnas en una sola.
  • โš ๏ธ Nota de la versiรณn: pivot_longer(), pivot_wider() y separate_wider_delim() reemplazan a la versiรณn anterior de tidyr reshaping funciones.

Dplyr en R: Combinar y unir datos

Introducciรณn al anรกlisis de datos

Antes de unirse o reorganizarseping El verbo tiene sentido, ayuda a ver dรณnde encaja la manipulaciรณn de datos. El anรกlisis de datos se puede dividir en tres partes:

  • Extracdisrupciรณn : Primero, necesitamos recopilar datos de muchas fuentes y combinarlas.
  • Transformaciรณn: Este paso implica la manipulaciรณn de datos. Una vez que hayamos consolidado todas las fuentes de datos, podemos comenzar a limpiar los datos.
  • Visualizar las: El รบltimo paso es visualizar nuestros datos para comprobar la irregularidad.

El siguiente diagrama muestra cรณmo se conectan las tres etapas.

Proceso de anรกlisis de datos en tres etapas que muestra extracciรณn, transformaciรณn y visualizaciรณn
Proceso de anรกlisis de datos

Uno de los mayores desafรญos para los cientรญficos de datos es la manipulaciรณn de datos. Los datos nunca estรกn disponibles en el formato deseado. Los cientรญficos de datos deben dedicar al menos la mitad de su tiempo a limpiar y manipular los datos. Esta es una de las tareas mรกs crรญticas de su trabajo. Si el proceso de manipulaciรณn de datos no es completo, preciso y riguroso, el modelo no funcionarรก correctamente.

R dplyr

R cuenta con un paquete llamado dplyr que se encarga de la transformaciรณn de datos. Estรก construido en torno a un pequeรฑo conjunto de verbos bรกsicos โ€”filter(), select(), arrange(), mutate() y summarise()โ€” ademรกs de una familia de funciones de uniรณn. Una vez que los datos estรกn preparados, ggplot2 puede visualizarlos.

Aprenderemos cรณmo usar el paquete dplyr para manipular un Marco de datos. Si R aรบn no estรก instalado, siga las instrucciones Pasos de configuraciรณn de R y RStudio, luego ejecute install.packages(โ€œdplyrโ€).

Combinar datos con dplyr

dplyr proporciona una forma agradable y cรณmoda de combinar conjuntos de datos. Es posible que tengamos muchas fuentes de datos de entrada y, en algรบn momento, necesitemos combinarlas. Una combinaciรณn con dplyr agrega variables a la derecha del conjunto de datos original.

dplyr se une

A continuaciรณn se muestran cuatro tipos importantes de uniones que se utilizan en dplyr para combinar dos conjuntos de datos. Los cuatro aceptan los mismos argumentos (las dos tablas y la clave) y se diferencian รบnicamente en quรฉ filas no coincidentes se conservan:

Funciรณn Objetivo Argumentos Llaves mรบltiples
uniรณn_izquierda() Fusionar dos conjuntos de datos. Mantener todas las observaciones de la tabla de origen. x, y, por = โ€œIDโ€ x, y, por = c(โ€œIDโ€, โ€œID2โ€)
uniรณn_derecha() Fusionar dos conjuntos de datos. Mantener todas las observaciones de la tabla de destino. x, y, por = โ€œIDโ€ x, y, por = c(โ€œIDโ€, โ€œID2โ€)
unir internamente() Combinar dos conjuntos de datos. Excluir todas las filas que no coincidan. x, y, por = โ€œIDโ€ x, y, por = c(โ€œIDโ€, โ€œID2โ€)
uniรณn_completa() Combinar dos conjuntos de datos. Conservar todas las observaciones. x, y, por = โ€œIDโ€ x, y, por = c(โ€œIDโ€, โ€œID2โ€)

Estos cuatro verbos se corresponden con las uniones IZQUIERDA, DERECHA, INTERNA y EXTERNA COMPLETA de SQL. Base R alcanza los mismos resultados a travรฉs de los argumentos all, all.x y all.y de unir().

Estudiaremos todos los tipos de uniones mediante un ejemplo sencillo.

En primer lugar, construimos dos conjuntos de datos. La Tabla 1 contiene dos variables, ID e y, mientras que la Tabla 2 reรบne ID y z. En cada situaciรณn, necesitamos tener una Par de claves variable. En nuestro caso, la identificaciรณn es nuestra clave variable. La funciรณn buscarรก valores idรฉnticos en ambas tablas y vincularรก los valores devueltos a la derecha de la tabla 1. La siguiente figura muestra las dos tablas una al lado de la otra.

Dos tablas de ejemplo que comparten una columna de clave de ID antes de una fusiรณn con dplyr.

library(dplyr)
df_primary <- tribble(
  ~ID, ~y,
   "A", 5,
   "B", 5,
   "C", 8,
   "D", 0,
  "F", 9)
df_secondary <- tribble(
  ~ID, ~z,
   "A", 30,
   "B", 21,
   "C", 22,
   "D", 25,
   "E", 29)

dplyr left_join()

La forma mรกs comรบn de combinar dos conjuntos de datos es mediante la funciรณn left_join(). La imagen a continuaciรณn muestra que el par clave-valor coincide con las filas A, B, C y D, mientras que E y F quedan sin combinar. Con left_join(), conservamos todas las filas de la tabla original e ignoramos las que no tienen un par clave-valor en la tabla de destino. En nuestro ejemplo, el valor E no existe en la tabla 1, por lo que se elimina esa fila. El valor F proviene de la tabla de origen, por lo que se conserva despuรฉs de left_join() y devuelve NA en la columna z.

Ejemplo de dplyr left_join()

El siguiente diagrama reproduce lo que sucede durante una operaciรณn left_join().

Diagrama de dplyr left_join keeping cada fila de la tabla de origen y eliminarping ID E

left_join(df_primary, df_secondary, by ='ID')

Salida:

## 
# A tibble: 5 x 3
##      ID   y.x   y.y
##   <chr> <dbl> <dbl>		
## 1     A     5    30
## 2     B     5    21
## 3     C     8    22
## 4     D     0    25
## 5     F     9    NA

Tenga en cuenta que cuando ambas tablas tienen una columna con el mismo nombre, dplyr las desambigua con los sufijos .x y .y que se muestran arriba.

dplyr right_join()

La funciรณn right_join() funciona exactamente como left_join(). La รบnica diferencia es que se eliminรณ la fila. El valor E, disponible en el marco de datos de destino, existe en la nueva tabla y toma el valor NA para la columna y.

Ejemplo de dplyr right_join()

El diagrama que aparece a continuaciรณn muestra la imagen especular.

Diagrama de dplyr right_join keeping cada fila de la tabla de destino y soltarping Identificaciรณn F

right_join(df_primary, df_secondary, by = 'ID')

Salida:

##
# A tibble: 5 x 3
##      ID   y.x   y.y
##   <chr> <dbl> <dbl>
## 1     A     5    30
## 2     B     5    21
## 3     C     8    22
## 4     D     0    25
## 5     E    NA    29

dplyr inner_join()

Cuando las observaciones no coincidentes no son de ninguna utilidad, podemos devolver รบnico las filas que existen en ambas conjuntos de datos. Esta es la opciรณn correcta cuando necesitamos un conjunto de datos completo y no queremos imputar los valores faltantes con la media o la mediana.

La funciรณn inner_join() resulta รบtil en este caso. Excluye las filas que no coinciden en ambos lados.

Ejemplo de dplyr internal_join()

El diagrama que aparece a continuaciรณn resalta los cuatro identificadores que sobreviven a la uniรณn.

Diagrama de dplyr inner_join que devuelve solo los cuatro ID presentes en ambas tablas.

inner_join(df_primary, df_secondary, by ='ID')

Salida:

## 
# A tibble: 4 x 3
##      ID   y.x   y.y
##   <chr> <dbl> <dbl>
## 1     A     5    30
## 2     B     5    21
## 3     C     8    22
## 4     D     0    25

dplyr full_join()

Finalmente, la funciรณn full_join() conserva todas las observaciones y reemplaza los valores faltantes con NA.

Ejemplo de dplyr full_join()

El diagrama que aparece a continuaciรณn muestra todos los ID de ambas tablas que se conservan tras la uniรณn.

Diagrama de dplyr full_join keeping Los seis identificadores y rellenar los valores faltantes con NA.

full_join(df_primary, df_secondary, by = 'ID')

Salida:

## # A tibble: 6 x 3
##      ID   y.x   y.y
##   <chr> <dbl> <dbl>
## 1     A     5    30
## 2     B     5    21
## 3     C     8    22
## 4     D     0    25
## 5     F     9    NA
## 6     E    NA    29

Mรบltiples pares de claves

Por รบltimo, pero no menos importante, podemos tener varias claves en nuestro conjunto de datos. Consideremos el siguiente conjunto de datos, donde tenemos los aรฑos y una lista de productos comprados por el cliente. La captura de pantalla a continuaciรณn muestra las dos tablas y las columnas ID y aรฑo que, en conjunto, identifican una fila.

Dos marcos de datos que comparten una clave compuesta formada por las columnas ID y aรฑo.

Si unimos ambas tablas solo por ID, cada aรฑo se compara con todos los demรกs y el nรบmero de filas se dispara. Para solucionar esto, podemos pasar dos variables clave-valor: ID y aรฑo, que aparecen en ambos conjuntos de datos. Podemos usar el siguiente cรณdigo para fusionar la tabla 1 y la tabla 2:

df_primary <- tribble(
  ~ID, ~year, ~items,
  "A", 2015,3,
  "A", 2016,7,
  "A", 2017,6,
  "B", 2015,4,
  "B", 2016,8,
  "B", 2017,7,
  "C", 2015,4,
  "C", 2016,6,
  "C", 2017,6)
df_secondary <- tribble(
  ~ID, ~year, ~prices,
  "A", 2015,9,
  "A", 2016,8,
  "A", 2017,12,
  "B", 2015,13,
  "B", 2016,14,
  "B", 2017,6,
  "C", 2015,15,
  "C", 2016,15,
  "C", 2017,13)
left_join(df_primary, df_secondary, by = c('ID', 'year'))

Salida:

## # A tibble: 9 x 4
##      ID  year items prices
##   <chr> <dbl> <dbl>  <dbl>
## 1     A  2015     3      9
## 2     A  2016     7      8
## 3     A  2017     6     12
## 4     B  2015     4     13
## 5     B  2016     8     14
## 6     B  2017     7      6
## 7     C  2015     4     15
## 8     C  2016     6     15
## 9     C  2017     6     13

Desde dplyr 1.1.0 (enero de 2023), la misma clave se puede escribir como join_by(ID, aรฑo), y dplyr ahora advierte sobre coincidencias inesperadas de muchos a muchos, ya que dplyr 1.1.0 se une al anuncio explica.

Funciones de limpieza de datos en R

La fusiรณn solo resuelve la mitad del problema, ya que la tabla combinada aรบn debe ser remodelada. A continuaciรณn se presentan las cuatro funciones importantes para ordenar (limpiar) los datos:

Funciรณn Objetivo Argumentos
recolectar() Transforma los datos de ancho a largo (datos, clave, valor, na.rm = FALSO)
desparramar() Transforme los datos de largo a ancho (datos, clave, valor)
separado() Dividir una variable en dos (datos, columna, en, separador = โ€œโ€, eliminar = VERDADERO)
unir() Unir dos variables en una sola (datos, columna, conc, sep = โ€œโ€, eliminar = VERDADERO)

Nota de versiรณn: gather() y spread() fueron reemplazados por pivot_longer() y pivot_wider() en tidyr 1.0.0, y separate() por la familia separate_wider_delim() en tidyr 1.3.0. Las funciones reemplazadas aรบn se ejecutan, por lo que todos los ejemplos a continuaciรณn funcionan, pero el cรณdigo nuevo deberรญa preferir las familias mรกs nuevas que se muestran en el viรฑeta pivotante mรกs ordenada. unite() sigue vigente.

Utilizamos el paquete tidyr, parte de la colecciรณn tidyverse para manipular, limpiar y visualizar datos. Si R se instalรณ con Anaconda, el paquete ya estรก disponible desde https://anaconda.org/r/r-tidyr.

Si aรบn no estรก instalado, ingrese el siguiente comando para instalar tidyr:

install.packages("tidyr")

recolectar()

El objetivo de la funciรณn gather() es transformar los datos de formato ancho a formato largo.

Sintaxis

gather(data, key, value, na.rm = FALSE)
Arguments:
-data: The data frame used to reshape the dataset 
-key: Name of the new column created
-value: Select the columns used to fill the key column
-na.rm: Remove missing values. FALSE by default

Ejemplo

A continuaciรณn, podemos visualizar el concepto de reshaping De ancho a largo. Queremos crear una sola columna llamada "crecimiento", que se rellenarรก con las filas de las variables trimestrales. La siguiente figura muestra la tabla ancha a la izquierda y la tabla larga redimensionada a la derecha.

reshaping una tabla trimestral ancha en formato largo con la funciรณn tidyr gather

library(tidyr)
# Create a messy dataset
messy <- data.frame(
  country = c("A", "B", "C"),
  q1_2017 = c(0.03, 0.05, 0.01),
  q2_2017 = c(0.05, 0.07, 0.02),
  q3_2017 = c(0.04, 0.05, 0.01),
  q4_2017 = c(0.03, 0.02, 0.04))
messy

Salida:

##   country q1_2017 q2_2017 q3_2017 q4_2017
## 1       A    0.03    0.05    0.04    0.03
## 2       B    0.05    0.07    0.05    0.02
## 3       C    0.01    0.02    0.01    0.04
# Reshape the data
tidier <-messy %>%
gather(quarter, growth, q1_2017:q4_2017)
tidier

Salida:

##    country quarter growth
## 1        A q1_2017   0.03
## 2        B q1_2017   0.05
## 3        C q1_2017   0.01
## 4        A q2_2017   0.05
## 5        B q2_2017   0.07
## 6        C q2_2017   0.02
## 7        A q3_2017   0.04
## 8        B q3_2017   0.05
## 9        C q3_2017   0.01
## 10       A q4_2017   0.03
## 11       B q4_2017   0.02
## 12       C q4_2017   0.04

En la funciรณn gather(), creamos dos nuevas variables, quarter y growth, porque nuestro conjunto de datos original tiene una variable de grupo, country, y los pares clave-valor. En tidyr 1.0.0 y posteriores, la misma remodelaciรณn se escribe como pivot_longer(messy, cols = q1_2017:q4_2017, names_to = โ€œquarterโ€, values_to = โ€œgrowthโ€).

desparramar()

La funciรณn spread() hace lo contrario que gather().

Sintaxis

spread(data, key, value)
arguments: 
data: The data frame used to reshape the dataset
key: Column to reshape long to wide
value: Rows used to fill the new column

Ejemplo

Podemos volver a convertir el conjunto de datos ordenado en uno desordenado con spread().

# Reshape the data
messy_1 <- tidier %>%
  spread(quarter, growth) 
messy_1

Salida:

##   country q1_2017 q2_2017 q3_2017 q4_2017
## 1       A    0.03    0.05    0.04    0.03
## 2       B    0.05    0.07    0.05    0.02
## 3       C    0.01    0.02    0.01    0.04

El equivalente moderno es pivot_wider(tidier, names_from = quarter, values_from = growth).

separado()

La funciรณn `separate()` divide una columna en dos segรบn un separador. Esta funciรณn es รบtil cuando la variable es una fecha. Nuestro anรกlisis puede requerir que nos centremos en el mes y el aรฑo, y queremos separar la columna en dos nuevas variables.

Sintaxis

separate(data, col, into, sep= "", remove = TRUE)
arguments:
-data: The data frame used to reshape the dataset 
-col: The column to split
-into: The name of the new variables
-sep: Indicates the symbol used that separates the variable, i.e.:  "-", "_", "&"
-remove: Remove the old column. By default sets to TRUE.

Ejemplo

Podemos dividir el trimestre del aรฑo en el conjunto de datos mรกs ordenado aplicando la funciรณn separa().

separate_tidier <-tidier %>%
separate(quarter, c("Qrt", "year"), sep ="_")
head(separate_tidier)

Salida:

##   country Qrt year growth
## 1       A  q1 2017   0.03
## 2       B  q1 2017   0.05
## 3       C  q1 2017   0.01
## 4       A  q2 2017   0.05
## 5       B  q2 2017   0.07
## 6       C  q2 2017   0.02

unir()

La funciรณn unite() concatena dos columnas en una sola.

Sintaxis

unite(data, col, conc ,sep= "", remove = TRUE)
arguments:
-data: The data frame used to reshape the dataset 
-col: Name of the new column
-conc: Name of the columns to concatenate
-sep: Indicates the symbol used that unites the variable, i.e:  "-", "_", "&"
-remove: Remove the old columns. By default, sets to TRUE

Ejemplo

En el ejemplo anterior, separamos el trimestre del aรฑo. ยฟQuรฉ sucede si queremos combinarlos? Usamos el siguiente cรณdigo:

unit_tidier <- separate_tidier %>%
  unite(Quarter, Qrt, year, sep ="_")
head(unit_tidier)

Salida:

##   country Quarter growth
## 1       A q1_2017   0.03
## 2       B q1_2017   0.05
## 3       C q1_2017   0.01
## 4       A q2_2017   0.05
## 5       B q2_2017   0.07
## 6       C q2_2017   0.02

El marco de datos reformateado ya estรก listo para los pasos de modelado que se describen en el resto del documento. Serie de tutoriales de R.

Preguntas Frecuentes

merge() expresa cada uniรณn a travรฉs de las banderas all, all.x y all.y, mientras que dplyr nombra el comportamiento en el verbo mismo. dplyr tambiรฉn conserva el orden de fila original y devuelve un tibble. La ruta base de R se cubre en el combinar marcos de datos guรญa.

Se trata de uniones filtradas, por lo que nunca aรฑaden columnas. `semi_join(x, y)` conserva las filas de `x` que coinciden con `y`, y `anti_join(x, y)` conserva las filas que no coinciden. Ambas son รบtiles para auditar las claves antes de una uniรณn que modifica las propiedades.

Asigne explรญcitamente con by = c(โ€œIDโ€ = โ€œcustomer_idโ€), o utilice el nuevo asistente join_by(ID == customer_id). Sin un mapeopingdplyr realiza coincidencias en cada nombre de columna compartida, lo que puede reducir silenciosamente el resultado o ampliarlo drรกsticamente.

Un valor clave se repite en ambos lados, por lo que se generan todas las combinaciones posibles. Primero, compruebe si cada clave es duplicada, agregue el lado de muchos o pase relationship = โ€œmany-to-manyโ€ para indicar la intenciรณn. dplyr advierte sobre coincidencias inesperadas de muchos a muchos.

filter() selecciona filas, select() selecciona columnas, arrange() hechizos, mutate() agrega columnas y summarise() colapsa los grupos creados por group_by(). La tuberรญa pasa un resultado al siguiente verbo; %>% viene con dplyr y |> es nativo de R.

Los asistentes de IA pueden perfilar un marco de datos, marcar claves duplicadas o mal escritas antes de una uniรณn, sugerir la reorganizaciรณnping Utilice un verbo que se ajuste al diseรฑo y explique en lenguaje sencillo cualquier cambio repentino en el nรบmero de filas. Siempre vuelva a ejecutar el cรณdigo y verifique las dimensiones usted mismo.

Sรญ. Copiloto de GitHub Funciona en RStudio Desktop 2023.09.0 y versiones posteriores, y completa pipelines de uniรณn y pivote a partir de un comentario. Posit advierte que las sugerencias no son deterministas, por lo que se recomienda revisar cada lรญnea generada antes de ejecutarla.

Encadena las uniones o pliega una lista con Reduce(function(x, y) left_join(x, y, by = โ€œIDโ€), list(df1, df2, df3)). purrr::reduce() hace lo mismo. Comprueba nrow() despuรฉs de cada paso, ya que las claves duplicadas se acumulan en las uniones.

Resumir este post con: