Saltar al contenido

Indice / Practicas / EJ-6.3

EJ-6.3 · Anti-join: lo que esta en un solo sistema

Practica de: 6.3 merge avanzadoDificultad: B

Los productos que tiene un catálogo y el otro no. Es la operación más chica de la unidad y la que más se usa: casi todo control de calidad entre dos sistemas empieza acá.

Qué hay que hacer

A partir de los dos catálogos, producir catalogo_solo_a.csv (14 productos) y catalogo_solo_b.csv (10 productos).

ELI5Explicado facil

Dos listas de asistencia de la misma clase. La pregunta no es quién está en las dos: es quién falta en cada una.

Y hay que contestarla dos veces, porque «los que están en A y no en B» y «los que están en B y no en A» son dos preguntas distintas con dos respuestas distintas.

Archivos

No existe how="anti"

El anti-join se arma con dos cosas que ya conocés: un left con indicator=True, filtrado por left_only. Tres líneas y funciona para cualquier par de tablas.

Un detalle que ahorra trabajo: cruzá contra derecha[["sku"]] y no contra la tabla entera. Así el resultado no trae columnas con sufijos que después hay que sacar.

Cómo saber si te salió

python comparar.py mi_solo_a.csv catalogo_solo_a.csv
python comparar.py mi_solo_b.csv catalogo_solo_b.csv

Antes de arrancar, mirá los datos

catalogo_sistema_a.csv (entrada) · 62 filas, se muestran 5
skunombrepreciostockactualizado
SKU001Artículo 001205.25222026-07-23
SKU002Artículo 002695.67842026-08-06
SKU003Artículo 00331.891512026-08-09
SKU004Artículo 004vacio1952026-07-15
SKU005Artículo 005174.261262026-08-07

El contrato de salida

catalogo_solo_a.csv · 14 filas

ColumnaTipoQue lleva
skutextoLa clave del producto
nombretextoTal cual viene de A
preciodecimalTal cual viene, redondeado a 2 decimales. Puede quedar vacio
stockenteroTal cual viene. Puede quedar vacio
actualizadotextoTal cual viene

Orden de las filas: sku ascendente. Es unico en la salida. Indice: no se escribe: to_csv(index=False)

catalogo_solo_b.csv · 10 filas

ColumnaTipoQue lleva
skutextoLa clave del producto
nombretextoTal cual viene de B
preciodecimalTal cual viene, redondeado a 2 decimales
stockenteroTal cual viene
actualizadotextoTal cual viene

Orden de las filas: sku ascendente. Es unico en la salida. Indice: no se escribe: to_csv(index=False)

Que hacer con cada defecto

DefectoDondeAccionAdonde va
SKU repetidos dentro de cada catalogoSKU002 y SKU007 en A, SKU020 en Bdeduplicar deduplicar por recencia antes de cruzaruna fila por sku en cada salida
precio y stock ausentes en ASKU004 (precio) y SKU010 (stock, token NaN)NO NO se corrigen: el ejercicio compara claves, no valida datoscatalogo_solo_a.csv, con el campo vacio
precios negativos en BBNO NO se validan. Ninguno cae en los 10 que estan solo en B, pero la politica va escrita igualcatalogo_solo_b.csv
Orden de comprobacion

Una fila puede tener mas de un problema. Se informa solo el primero de esta lista:

  1. deduplicar A y B por recencia
  2. left merge de A contra las claves de B, con indicator
  3. quedarse con left_only
  4. repetir dando vuelta las tablas

El anti-join no es un how: es un left con indicator filtrado por left_only. Cruzar contra df[['sku']] en vez de contra la tabla entera evita que aparezcan columnas con sufijos que despues hay que sacar.

Conteos clave

Si estos numeros no te dan, algo se desvio antes de que llegues a comparar los archivos.

sku unicos en A60
sku unicos en B56
en las dos fuentes46
catalogo_solo_a.csv14
catalogo_solo_b.csv10
union de las dos70
por motivo

Invariantes

Comprobaciones que tu resultado tiene que cumplir. Corrilas vos mismo antes de comparar los archivos:

len(solo_a) == 14
len(solo_b) == 10
46 + 14 + 10 == 70
solo_a['sku'].is_unique
solo_b['sku'].is_unique
set(solo_a['sku']) & set(solo_b['sku']) == set()
set(solo_a['sku']) <= set(a['sku'])
set(solo_b['sku']) & set(a['sku']) == set()
PISTASSi te trabas, abri esto
  • No existe how='anti'. Se arma con left + indicator + filtrar por left_only.
  • Cruza contra derecha[['sku']] y no contra la tabla entera: asi no aparecen columnas con sufijos.
  • Los dos archivos no pueden compartir ningun sku: si comparten alguno, algo salio mal.
  • La comprobacion final es 46 + 14 + 10 = 70, que es la cantidad de sku distintos entre las dos fuentes.

Así tiene que quedar

catalogo_solo_a.csv (objetivo) · 14 filas, se muestran 5
skunombrepreciostockactualizado
SKU001Artículo 001205.25222026-07-23
SKU002Artículo 00231.5122026-08-20
SKU003Artículo 00331.891512026-08-09
SKU004Artículo 004vacio1952026-07-15
SKU005Artículo 005174.261262026-08-07
catalogo_solo_b.csv (objetivo) · 10 filas, se muestran 5
skunombrepreciostockactualizado
SKU061Artículo 06173.2632026-07-17
SKU062Artículo 062498.991302026-08-16
SKU063Artículo 063455.531042026-08-17
SKU064Artículo 064671.1642026-08-14
SKU065Artículo 06531.4562026-08-17
La cuenta que tiene que cerrar

46 + 14 + 10 = 70: los que están en las dos, más los de cada lado, dan la cantidad de SKU distintos entre los dos catálogos. Es la misma cuenta que produce el outer de EJ-6.1, y sirve como comprobación cruzada entre los dos ejercicios.

Y los dos archivos no pueden compartir ningún SKU: si comparten alguno, algo salió mal.

Deduplicar sigue yendo primero

SKU002 y SKU007 aparecen dos veces en A, y los dos están entre los 14 que faltan en B. Sin deduplicar, salen dos veces cada uno en el informe y el archivo tiene 16 filas en vez de 14.