Code
#| echo: true
library (tidyverse)#| echo: true
library (tidyverse)# 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)
)
clientes# A tibble: 6 × 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 C004 Luis García La Vega Regular
5 C005 Carmen Díaz San Pedro Regular
6 C006 Jorge Reyes Santo Domingo Premium
facturas# 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
pagos# A tibble: 5 × 2
id_factura monto_pagado
<chr> <dbl>
1 F001 15000
2 F002 22000
3 F004 31000
4 F006 12000
5 F007 9800
facturas %>%
anti_join(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" aparece con un id_cliente "C007", el cual no esta en la tabla de clientes.clientes %>%
anti_join(facturas, by = "id_cliente")# 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
# Hay dos clientes sin factura registrada, Luis García C004 Y Jorge Reyes C006.cat("Facturas sin pago registrado:",
facturas %>%
anti_join(pagos, by = "id_factura") %>%
pull(id_factura),
"\n"
)Facturas sin pago registrado: F003 F005 F008
# Facturas sin pago registrado: F003 F005 F008 # Verifica si hay duplicados en la tabla facturas usando count() + filter(n > 1). ¿Cuál es el id_cliente que tiene una factura duplicada? Documenta en un comentario qué decisión tomarías.
facturas %>%
count(id_factura) %>%
filter(n > 1)# A tibble: 0 × 2
# ℹ 2 variables: id_factura <chr>, n <int>
# No hay facturas duplicadas y no hay id_cliente con factura duplicada, ya que todos tienen un id_factura diferente.
# En el caso de C001, existen dos facturas con el mismo monto y mes, pero con id_factura diferentes. Antes de eliminarlas, verificaría si se trata de una duplicación por error o de dos transacciones diferentes.
# Si fuese un error del sistema, seria mas probable que aparezca una factura debajo de la otra, ejemplo ficticio 007 y 008, ya que en bases de datos el campo ID suele ser autoincremental. Al parecer, aqui se inserta manual, ya que los meses y facturas estan "sorteados". En este caso, solo puedo guiarme del id_factura para decidir y al no ser iguales, lo tomaría como valido.#left_join: Une clientes con facturas por id_cliente. Llama al resultado clientes_con_facturas. ¿Cuántas filas tiene el resultado y por qué tiene más filas que la tabla clientes?
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 9 filas. Esto pasa porque algunos clientes tienen más de una factura. Por ejemplo, C001 tiene 3 facturas y C002 tiene 2, por eso sus registros se repiten al hacer el join.# inner_join:Une clientes con facturas usando inner_join. ¿Qué clientes desaparecen del resultado comparado con el left_join? Documenta en un comentario.
ccf_inner <- clientes %>%
inner_join(facturas, by = "id_cliente")
ccf_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
clientes %>%
anti_join(facturas, by = "id_cliente")# 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
# Desaparecen Luis G. C004 y Jorge R. C006 porque no tienen facturas (aparecian NA en el left) y el inner_join solo muestra las coincidencias entre ambas tablas.# Une clientes con facturas usando full_join. ¿Qué fila extra aparece que no estaba en ninguna de las dos tablas originales? Explica en un comentario por qué aparece esa fila.
ccf_full <- clientes %>%
full_join(facturas, by = "id_cliente")
ccf_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 una fila para el cliente C007, porque hay una factura con ese id_cliente, pero el cliente no está registrado en la tabla clientes. Al usar full join se muestra todo de ambas tablas.# Joins encadenados: Construye una tabla maestra uniendo las **tres tablas** en un solo pipeline:
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
# La tabla_maestra tiene 9 filas. Algunos monto_pagado son NA porque esas facturas no tienen un pago registrado en la tabla pagos.# Usa semi_join() para obtener solo los clientes que sí tienen al menos una factura.
clientes_con_una_factura <- clientes %>%
semi_join(facturas, by = "id_cliente")
clientes_con_una_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_una_factura)[1] 4
# Hay 4 clientes con al menos una factura.# Usa anti_join() para obtener los clientes que nunca han facturado. Muestra su nombre y ciudad.
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
# Luis García de La Vega y Jorge Reyes de Santo Domingo, nunca han facturado.# Usa anti_join() al revés: ¿qué facturas pertenecen a clientes que no están registrados? Muestra el id_factura, id_cliente y monto.
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
# La factura F006 del id_cliente C007 que no está registrado.facturas_sin_dup <- facturas %>%
filter(!duplicated(.))
nrow(facturas_sin_dup)[1] 8
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
# En este caso, quedan las mismas 8 filas de facturas, porque no hay duplicados.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
# Se conserva la factura de mayor monto para cada cliente, hay 5 filas.#Vuelve a construir la tabla_maestra del Parte 2.4 pero esta vez usando facturas_sin_dup en lugar de facturas. ¿Cambió el número de filas?
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
# La tabla tiene 9 filas porque algunos clientes tienen varias facturas y se repiten en el join. Además, se mantienen los clientes sin compras (C004 y C006), y la factura de C007 no aparece porque ese cliente no está registrado. En total, se muestran 7 facturas asociadas a clientes registrados y 2 clientes sin facturas.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
ventas_largo <- ventas_por_mes |>
pivot_longer(
cols = -nombre, # Todo excepto la columna 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
# Con ventas_largo, usa group_by() + summarise() para calcular el total vendido por mes y ordena de mayor a menor.
ventas_largo %>%
group_by(mes) %>%
summarise(
total_vendido = sum(total),
.groups = "drop"
) %>%
arrange(desc(total_vendido))# A tibble: 3 × 2
mes total_vendido
<chr> <dbl>
1 Feb 53000
2 Ene 43000
3 Mar 9800