Código
# Cargar las librerías necesarias
library(dplyr)
library(tidyr)# Cargar las librerías necesarias
library(dplyr)
library(tidyr)# Tabla 1: Clientes
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")
)
# Tabla 2: Facturas
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)
)
# Tabla 3: Pagos
pagos <- tibble(
id_factura = c("F001", "F002", "F004", "F006", "F007"),
monto_pagado = c(15000, 22000, 31000, 12000, 9800)
)# 1.1 Facturas con id_cliente inexistente en clientes
facturas_sin_cliente <- facturas |> anti_join(clientes, by = "id_cliente")
facturas_sin_cliente# A tibble: 1 × 4
id_factura id_cliente mes monto
<chr> <chr> <chr> <dbl>
1 F006 C007 Feb 12000
# 1.2 Clientes sin ninguna factura registrada
clientes_sin_factura <- clientes |> anti_join(facturas, by = "id_cliente")
clientes_sin_factura# 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
# 1.3 Facturas sin pago registrado
facturas_sin_pago <- facturas |> anti_join(pagos, by = "id_factura")
facturas_sin_pago# A tibble: 3 × 4
id_factura id_cliente mes monto
<chr> <chr> <chr> <dbl>
1 F003 C002 Ene 8500
2 F005 C005 Ene 4500
3 F008 C001 Ene 15000
# 1.4 Verificar duplicados en la tabla facturas
duplicados_facturas <- facturas |> count(id_factura, id_cliente, mes, monto) |> filter(n > 1)
duplicados_facturas# A tibble: 0 × 5
# ℹ 5 variables: id_factura <chr>, id_cliente <chr>, mes <chr>, monto <dbl>,
# n <int>
1.1 Factura huérfana: se identificó que la factura F006 está asignada al cliente C007, el cual no existe en nuestra base de datos de clientes.
1.2 Clientes inactivos: hay 2 clientes (C004 - Luis García y C006 - Jorge Reyes) que no registran ninguna factura.
1.3 Facturas impagadas: hay 3 facturas sin registro de pago. Sus IDs son: F003, F005 y F008.
1.4 Registro duplicado: la factura F001 del cliente C001 (Ana Torres) está cargada dos veces exactamente idéntica en el dataset de facturas.
Decisión sugerida: para corregir este problema, se debe aplicar una limpieza de duplicados exactos en la tabla facturas utilizando la función distinct() o un filtro de unicidad antes de proceder con el análisis financiero o la integración de datos, evitando así inflar las métricas de venta.
# 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
# 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
# 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
# 2.4 — Joins encadenados (Tabla maestra con duplicados)
tabla_maestra <- clientes |>
left_join(facturas, by = "id_cliente") |>
left_join(pagos, by = "id_factura")
print(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
2.1 Filas en left_join: el resultado tiene 9 filas, superando las 6 iniciales de clientes. Esto ocurre porque los clientes que tienen múltiples compras (como C001 y C002) duplican sus filas de datos base para combinarse con cada una de sus facturas correspondientes.
2.2 Desaparición en inner_join: en el inner_join desaparecen C004 (Luis García) y C006 (Jorge Reyes), debido a que esta unión solo conserva aquellos registros cuyas llaves coinciden estrictamente en ambas tablas (es decir, clientes que sí poseen facturas).
2.3 Fila extra en full_join: aparece una fila con id_cliente = C007 y nombre NA. Surge porque el full_join mantiene absolutamente todas las filas de ambas tablas. Al haber una factura (F006) vinculada al cliente no registrado C007, R crea el registro llenando con nulos los datos demográficos que le faltan.
2.4 Evaluación de la Tabla Maestra:
Número de filas: tiene 9 filas.
Presencia de NAs en monto_pagado: los campos monto_pagado son NA debido a que hay clientes que no poseen facturas (por lo que no hay ID de factura para asociar un pago) y a que existen facturas específicas (F003, F005 y la duplicada F008) que no cuentan con un registro de transacción dentro de la tabla de pagos.
# 3.1 Clientes con al menos una factura registrada
clientes_activos <- clientes |> semi_join(facturas, by = "id_cliente")
nrow(clientes_activos)[1] 4
clientes_activos# 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
# 3.2 Clientes que nunca han facturado (Nombre y ciudad)
clientes_sin_compra <- clientes |> anti_join(facturas, by = "id_cliente") |> select(nombre, ciudad)
clientes_sin_compra# A tibble: 2 × 2
nombre ciudad
<chr> <chr>
1 Luis García La Vega
2 Jorge Reyes Santo Domingo
# 3.3 Facturas que pertenecen a clientes no registrados
facturas_sin_registro <- facturas |> anti_join(clientes, by = "id_cliente") |> select(id_factura, id_cliente, monto)
facturas_sin_registro# A tibble: 1 × 3
id_factura id_cliente monto
<chr> <chr> <dbl>
1 F006 C007 12000
3.1 Conteo: hay 4 clientes que registran al menos una factura.
3.2 Inactivos: los clientes que nunca han facturado son Luis García (La Vega) y Jorge Reyes (Santo Domingo).
3.3 Huérfanos: la factura F006 por un monto de 12000 pertenece al cliente no registrado C007.
# 4.1 — Eliminar duplicados exactos
facturas_sin_dup <- facturas |> filter(!duplicated(facturas))
nrow(facturas_sin_dup)[1] 8
# 4.2 — Quedarte con la factura de mayor monto por cliente
facturas_max <- facturas |>
group_by(id_cliente) |>
slice_max(order_by = monto, n = 1, with_ties = FALSE) |>
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 Reconstrucción de la tabla maestra sin duplicados
tabla_maestra_limpia <- clientes |>
left_join(facturas_sin_dup, by = "id_cliente") |>
left_join(pagos, by = "id_factura")
nrow(tabla_maestra_limpia)[1] 9
4.1 Filas resultantes: quedan 7 filas en la tabla facturas_sin_dup (se eliminó exitosamente una de las dos filas repetidas de la factura F001).
4.3 Impacto en las filas totales: sí cambió. El número de filas de la tabla maestra se redujo de 9 a 8 filas, ya que al remover el duplicado exacto del origen, R ya no expande innecesariamente los registros del cliente C001.
# 5.1 — Formato ancho: Facturación por cliente y mes
ventas_por_mes <- tabla_maestra_limpia |>
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 ordenado de mayor a menor
resumen_mensual <- ventas_largo |>
group_by(mes) |>
summarise(total_vendido = sum(total, na.rm = TRUE), .groups = "drop") |>
arrange(desc(total_vendido))
resumen_mensual# A tibble: 3 × 2
mes total_vendido
<chr> <dbl>
1 Feb 53000
2 Ene 43000
3 Mar 9800