Tarea 7 - Joins, Tidy Data y Relaciones entre Tablas

Author

Ramyeissi Montilla

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.2.1     ✔ readr     2.2.0
✔ forcats   1.0.1     ✔ stringr   1.6.0
✔ ggplot2   4.0.3     ✔ tibble    3.3.1
✔ lubridate 1.9.5     ✔ tidyr     1.3.2
✔ purrr     1.2.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

Dataset de práctica

clientes <- tibble(
  id_cliente = c("C001", "C002", "C003", "C004", "C005", "C006"),
  nombre     = c("Ana Torres", "Pedro Méndez", "María López", "Luis García", "Carmen Díaz", "Jorge Reyes"),
  ciudad     = c("Santo Domingo", "Santiago", "Santo Domingo", "La Vega", "San Pedro", "Santo Domingo"),
  tipo       = c("Premium", "Regular", "Premium", "Regular", "Regular", "Premium")
)

facturas <- tibble(
  id_factura = c("F001", "F002", "F003", "F004", "F005", "F006", "F007", "F008"),
  id_cliente = c("C001", "C001", "C002", "C003", "C005", "C007", "C002", "C001"),
  mes        = c("Ene", "Feb", "Ene", "Feb", "Ene", "Feb", "Mar", "Ene"),
  monto      = c(15000, 22000, 8500, 31000, 4500, 12000, 9800, 15000)
)

pagos <- tibble(
  id_factura   = c("F001", "F002", "F004", "F006", "F007"),
  monto_pagado = c(15000, 22000, 31000, 12000, 9800)
)

Parte 1 — Diagnóstico Relacional

1.1 Facturas con clientes inexistentes

anti_join(facturas, clientes, by = "id_cliente")
# A tibble: 1 × 4
  id_factura id_cliente mes   monto
  <chr>      <chr>      <chr> <dbl>
1 F006       C007       Feb   12000

La factura F006 pertenece al cliente C007, que no existe en la tabla clientes.

1.2 Clientes sin facturas

clientes_sin_facturas <- anti_join(clientes, facturas, by = "id_cliente")

clientes_sin_facturas
# A tibble: 2 × 4
  id_cliente nombre      ciudad        tipo   
  <chr>      <chr>       <chr>         <chr>  
1 C004       Luis García La Vega       Regular
2 C006       Jorge Reyes Santo Domingo Premium
nrow(clientes_sin_facturas)
[1] 2

Hay 2 clientes sin facturas: Luis García y Jorge Reyes.

1.3 Facturas sin pago

facturas_sin_pago <- anti_join(facturas, pagos, by = "id_factura")

facturas_sin_pago |> select(id_factura)
# A tibble: 3 × 1
  id_factura
  <chr>     
1 F003      
2 F005      
3 F008      

Las facturas sin pago son F003, F005 y F008.

1.4 Verificar duplicados

facturas |>
  count(id_cliente, id_factura, mes, monto) |>
  filter(n > 1)
# A tibble: 0 × 5
# ℹ 5 variables: id_cliente <chr>, id_factura <chr>, mes <chr>, monto <dbl>,
#   n <int>

No se encontraron duplicados exactos.

Parte 2 — Aplicando los 4 Joins

2.1 left_join

nrow(clientes)
[1] 6
clientes_con_facturas <- clientes |>
  left_join(facturas, by = "id_cliente")

nrow(clientes_con_facturas)
[1] 9
clientes_con_facturas
# A tibble: 9 × 7
  id_cliente nombre       ciudad        tipo    id_factura mes   monto
  <chr>      <chr>        <chr>         <chr>   <chr>      <chr> <dbl>
1 C001       Ana Torres   Santo Domingo Premium F001       Ene   15000
2 C001       Ana Torres   Santo Domingo Premium F002       Feb   22000
3 C001       Ana Torres   Santo Domingo Premium F008       Ene   15000
4 C002       Pedro Méndez Santiago      Regular F003       Ene    8500
5 C002       Pedro Méndez Santiago      Regular F007       Mar    9800
6 C003       María López  Santo Domingo Premium F004       Feb   31000
7 C004       Luis García  La Vega       Regular <NA>       <NA>     NA
8 C005       Carmen Díaz  San Pedro     Regular F005       Ene    4500
9 C006       Jorge Reyes  Santo Domingo Premium <NA>       <NA>     NA

El resultado tiene más filas porque algunos clientes tienen varias facturas.

2.2 inner_join

clientes_inner <- clientes |>
  inner_join(facturas, by = "id_cliente")

clientes_inner
# A tibble: 7 × 7
  id_cliente nombre       ciudad        tipo    id_factura mes   monto
  <chr>      <chr>        <chr>         <chr>   <chr>      <chr> <dbl>
1 C001       Ana Torres   Santo Domingo Premium F001       Ene   15000
2 C001       Ana Torres   Santo Domingo Premium F002       Feb   22000
3 C001       Ana Torres   Santo Domingo Premium F008       Ene   15000
4 C002       Pedro Méndez Santiago      Regular F003       Ene    8500
5 C002       Pedro Méndez Santiago      Regular F007       Mar    9800
6 C003       María López  Santo Domingo Premium F004       Feb   31000
7 C005       Carmen Díaz  San Pedro     Regular F005       Ene    4500

Los clientes Luis García y Jorge Reyes desaparecen porque no tienen facturas.

2.3 full_join

clientes_full <- clientes |>
  full_join(facturas, by = "id_cliente")

clientes_full
# A tibble: 10 × 7
   id_cliente nombre       ciudad        tipo    id_factura mes   monto
   <chr>      <chr>        <chr>         <chr>   <chr>      <chr> <dbl>
 1 C001       Ana Torres   Santo Domingo Premium F001       Ene   15000
 2 C001       Ana Torres   Santo Domingo Premium F002       Feb   22000
 3 C001       Ana Torres   Santo Domingo Premium F008       Ene   15000
 4 C002       Pedro Méndez Santiago      Regular F003       Ene    8500
 5 C002       Pedro Méndez Santiago      Regular F007       Mar    9800
 6 C003       María López  Santo Domingo Premium F004       Feb   31000
 7 C004       Luis García  La Vega       Regular <NA>       <NA>     NA
 8 C005       Carmen Díaz  San Pedro     Regular F005       Ene    4500
 9 C006       Jorge Reyes  Santo Domingo Premium <NA>       <NA>     NA
10 C007       <NA>         <NA>          <NA>    F006       Feb   12000

Aparece el cliente C007 porque existe en facturas pero no en clientes.

2.4 Tabla maestra

tabla_maestra <- clientes |>
  left_join(facturas, by = "id_cliente") |>
  left_join(pagos, by = "id_factura")

tabla_maestra
# A tibble: 9 × 8
  id_cliente nombre       ciudad       tipo  id_factura mes   monto monto_pagado
  <chr>      <chr>        <chr>        <chr> <chr>      <chr> <dbl>        <dbl>
1 C001       Ana Torres   Santo Domin… Prem… F001       Ene   15000        15000
2 C001       Ana Torres   Santo Domin… Prem… F002       Feb   22000        22000
3 C001       Ana Torres   Santo Domin… Prem… F008       Ene   15000           NA
4 C002       Pedro Méndez Santiago     Regu… F003       Ene    8500           NA
5 C002       Pedro Méndez Santiago     Regu… F007       Mar    9800         9800
6 C003       María López  Santo Domin… Prem… F004       Feb   31000        31000
7 C004       Luis García  La Vega      Regu… <NA>       <NA>     NA           NA
8 C005       Carmen Díaz  San Pedro    Regu… F005       Ene    4500           NA
9 C006       Jorge Reyes  Santo Domin… Prem… <NA>       <NA>     NA           NA
nrow(tabla_maestra)
[1] 9

Algunos valores de monto_pagado son NA porque esas facturas no tienen pago registrado.

Parte 3 — Joins de Filtro

3.1 Clientes con al menos una factura

clientes_con_factura <- clientes |>
  semi_join(facturas, by = "id_cliente")

clientes_con_factura
# A tibble: 4 × 4
  id_cliente nombre       ciudad        tipo   
  <chr>      <chr>        <chr>         <chr>  
1 C001       Ana Torres   Santo Domingo Premium
2 C002       Pedro Méndez Santiago      Regular
3 C003       María López  Santo Domingo Premium
4 C005       Carmen Díaz  San Pedro     Regular
nrow(clientes_con_factura)
[1] 4

Hay 4 clientes con al menos una factura.

3.2 Clientes que nunca han facturado

clientes |>
  anti_join(facturas, by = "id_cliente") |>
  select(nombre, ciudad)
# A tibble: 2 × 2
  nombre      ciudad       
  <chr>       <chr>        
1 Luis García La Vega      
2 Jorge Reyes Santo Domingo

3.3 Facturas de clientes no registrados

facturas |>
  anti_join(clientes, by = "id_cliente") |>
  select(id_factura, id_cliente, monto)
# A tibble: 1 × 3
  id_factura id_cliente monto
  <chr>      <chr>      <dbl>
1 F006       C007       12000

Parte 4 — Manejo de Duplicados

4.1 Eliminar duplicados exactos

facturas_sin_dup <- facturas |>
  distinct()

facturas_sin_dup
# A tibble: 8 × 4
  id_factura id_cliente mes   monto
  <chr>      <chr>      <chr> <dbl>
1 F001       C001       Ene   15000
2 F002       C001       Feb   22000
3 F003       C002       Ene    8500
4 F004       C003       Feb   31000
5 F005       C005       Ene    4500
6 F006       C007       Feb   12000
7 F007       C002       Mar    9800
8 F008       C001       Ene   15000
nrow(facturas_sin_dup)
[1] 8

Quedan 8 filas porque no existen duplicados exactos.

4.2 Factura de mayor monto por cliente

facturas_max <- facturas |>
  group_by(id_cliente) |>
  slice_max(order_by = monto, n = 1) |>
  ungroup()

facturas_max
# A tibble: 5 × 4
  id_factura id_cliente mes   monto
  <chr>      <chr>      <chr> <dbl>
1 F002       C001       Feb   22000
2 F007       C002       Mar    9800
3 F004       C003       Feb   31000
4 F005       C005       Ene    4500
5 F006       C007       Feb   12000

4.3 Nueva tabla maestra

tabla_maestra <- clientes |>
  left_join(facturas_sin_dup, by = "id_cliente") |>
  left_join(pagos, by = "id_factura")

tabla_maestra
# A tibble: 9 × 8
  id_cliente nombre       ciudad       tipo  id_factura mes   monto monto_pagado
  <chr>      <chr>        <chr>        <chr> <chr>      <chr> <dbl>        <dbl>
1 C001       Ana Torres   Santo Domin… Prem… F001       Ene   15000        15000
2 C001       Ana Torres   Santo Domin… Prem… F002       Feb   22000        22000
3 C001       Ana Torres   Santo Domin… Prem… F008       Ene   15000           NA
4 C002       Pedro Méndez Santiago     Regu… F003       Ene    8500           NA
5 C002       Pedro Méndez Santiago     Regu… F007       Mar    9800         9800
6 C003       María López  Santo Domin… Prem… F004       Feb   31000        31000
7 C004       Luis García  La Vega      Regu… <NA>       <NA>     NA           NA
8 C005       Carmen Díaz  San Pedro    Regu… F005       Ene    4500           NA
9 C006       Jorge Reyes  Santo Domin… Prem… <NA>       <NA>     NA           NA
nrow(tabla_maestra)
[1] 9

El número de filas no cambia porque no había duplicados exactos.

Parte 5 — Tidy Data con pivot

5.1 Formato ancho

ventas_por_mes <- tabla_maestra |>
  filter(!is.na(mes)) |>
  group_by(nombre, mes) |>
  summarise(total = sum(monto, na.rm = TRUE), .groups = "drop") |>
  pivot_wider(
    names_from = mes,
    values_from = total,
    values_fill = 0
  )

ventas_por_mes
# A tibble: 4 × 4
  nombre         Ene   Feb   Mar
  <chr>        <dbl> <dbl> <dbl>
1 Ana Torres   30000 22000     0
2 Carmen Díaz   4500     0     0
3 María López      0 31000     0
4 Pedro Méndez  8500     0  9800

5.2 Volver a formato largo

ventas_largo <- ventas_por_mes |>
  pivot_longer(
    cols = -nombre,
    names_to = "mes",
    values_to = "total"
  )

ventas_largo
# A tibble: 12 × 3
   nombre       mes   total
   <chr>        <chr> <dbl>
 1 Ana Torres   Ene   30000
 2 Ana Torres   Feb   22000
 3 Ana Torres   Mar       0
 4 Carmen Díaz  Ene    4500
 5 Carmen Díaz  Feb       0
 6 Carmen Díaz  Mar       0
 7 María López  Ene       0
 8 María López  Feb   31000
 9 María López  Mar       0
10 Pedro Méndez Ene    8500
11 Pedro Méndez Feb       0
12 Pedro Méndez Mar    9800

5.3 Total vendido por mes

ventas_largo |>
  group_by(mes) |>
  summarise(total_vendido = sum(total)) |>
  arrange(desc(total_vendido))
# A tibble: 3 × 2
  mes   total_vendido
  <chr>         <dbl>
1 Feb           53000
2 Ene           43000
3 Mar            9800

Conclusión

Se utilizaron distintos tipos de joins para analizar la relación entre clientes, facturas y pagos. Además, se aplicaron técnicas de tidy data usando pivot_wider() y pivot_longer() para transformar los datos entre formato ancho y largo.