(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo detectar datos duplicados en Machine Learning: paso a paso

João Barros 21 de September de 2026 4 min de lectura

Este tutorial muestra cómo detectar y tratar datos duplicados en Machine Learning para mejorar la calidad del entrenamiento y reducir el sesgo. Explicaré por qué las duplicaciones son problemáticas y presentaré un paso a paso práctico con Python, pandas y scikit-learn.

Requisitos previos

  • Python 3.8+ con pandas y scikit-learn instalados
  • Un archivo CSV o DataFrame con registros que puedan repetirse
  • Conocimientos básicos de manipulación de DataFrame (pandas)

Paso 1: Entender qué tipo de duplicados existen

Los duplicados pueden ser filas exactamente idénticas, registros con claves repetidas (ID) o registros casi iguales (pequeñas diferencias en los valores). Identificar el tipo orienta la estrategia: eliminar, agregar o marcar.

Paso 2: Cargar los datos

Carga el CSV en un DataFrame y mira las primeras filas. Esto ayuda a identificar columnas clave y la existencia de NaNs.

import pandas as pd

df = pd.read_csv('dados.csv')
print(df.head())
print(df.shape)

Paso 3: Duplicados exactos (filas idénticas)

Usa pandas para contar filas exactamente iguales y, si tiene sentido, eliminarlas. Antes de eliminar, guarda el recuento para auditoría.

# contar duplicados exactos (mantiene la primera ocurrencia)
num_dup = df.duplicated(keep='first').sum()
print(f'Duplicados exactos: {num_dup}')

# eliminar duplicados exactos
df_no_exact_dup = df.drop_duplicates(keep='first')
print(df_no_exact_dup.shape)

Paso 4: Duplicados por clave (ID) — localizar y decidir

Si existe una columna ID que debería ser única, identifica IDs repetidos. Después decide: mantener la primera, la última, o agregar (por ejemplo la media).

# encontrar IDs duplicados
id_col = 'customer_id'  # ajusta para tu columna
dups = df[df.duplicated(subset=[id_col], keep=False)].sort_values(id_col)
print(dups.head())

# ejemplo: mantener el registro más reciente por fecha
df[id_col] = df[id_col].astype(str)
df['date'] = pd.to_datetime(df['date'])
# ordenar por date y eliminar duplicados manteniendo el más reciente
df_latest = df.sort_values('date').drop_duplicates(subset=[id_col], keep='last')
print(df_latest.shape)

Paso 5: Duplicados casi iguales (fuzzy duplicates)

Para registros con pequeñas diferencias (errores tipográficos o variaciones) usa técnicas de fuzzy matching. Un enfoque simple: crear hashes de columnas normalizadas o usar la distancia de Levenshtein. Aquí muestro una versión con normalización y comparación por similitud usando scikit-learn y fingerprints.

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

# ejemplo para columnas nombre + dirección
df['name_addr'] = (df['name'].fillna('').str.lower().str.replace(r'\W+', ' ', regex=True)
                   + ' ' + df['address'].fillna('').str.lower().str.replace(r'\W+', ' ', regex=True))

vec = TfidfVectorizer().fit_transform(df['name_addr'])
sim = cosine_similarity(vec[:1000], vec[:1000])  # limita para evitar OOM

# encuentra pares con similitud alta
threshold = 0.85
pairs = []
for i in range(sim.shape[0]):
    for j in range(i+1, sim.shape[1]):
        if sim[i, j] > threshold:
            pairs.append((i, j, sim[i, j]))
print('pares fuzzy semejantes:', len(pairs))

Paso 6: Agregar o marcar duplicados para entrenamiento

Decide si vas a eliminar, agregar (por ejemplo media de métricas) o marcar con una flag. Para modelos, a veces es preferible mantener y añadir una columna is_duplicate para que el modelo aprenda patrones.

# ejemplo: añadir flag de duplicado por clave
df['is_duplicate_by_id'] = df.duplicated(subset=[id_col], keep='first')

# ejemplo: agregar métricas por ID
agg = df.groupby(id_col).agg({'value': 'mean', 'is_active': 'max'}).reset_index()
print(agg.head())

Paso 7: Integrar en el pipeline de Machine Learning

Incluye la limpieza de duplicados antes del split train/test. Si eliminas duplicados después del split, corres el riesgo de tener registros iguales en ambos conjuntos (data leakage).

# limpieza antes del split
from sklearn.model_selection import train_test_split

df_clean = df_no_exact_dup.copy()
X = df_clean.drop('target', axis=1)
y = df_clean['target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

Verificar el resultado

Confirma que ya no existen duplicados problemáticos: cuenta duplicados exactos y por clave, verifica pares fuzzy sospechosos y asegura que no hay leakage entre entrenamiento y prueba (IDs en común).

# verificar duplicados exactos y por ID
print('exact dup after:', X_train.duplicated().sum() + X_test.duplicated().sum())
print('IDs comunes entre entrenamiento y prueba:', set(X_train[id_col]).intersection(set(X_test[id_col])))

Conclusión

Tratar duplicados mejora la calidad del conjunto de entrenamiento y reduce sesgo y leakage. Próximos pasos: automatizar la detección con funciones reutilizables, experimentar con thresholds para fuzzy matching y registrar los cambios en un pipeline ETL. Consejo: haz siempre una copia de seguridad de los datos originales antes de eliminar o agregar — ¿prefieres marcar o eliminar?