DEV Community

Cover image for Data Quality
Romina Mendez
Romina Mendez

Posted on

Data Quality

Introducción

En el entorno digital actual, la cantidad de datos disponibles es abrumadora. Sin embargo, la verdadera piedra angular para tomar decisiones informadas reside en la calidad de estos datos. En este artículo, exploraremos la importancia crucial de la calidad de datos, analizando los desafíos inherentes que enfrentan las organizaciones en la gestión de la información. Aunque a menudo pasada por alto, la calidad de datos desempeña un papel fundamental en la confiabilidad y utilidad de la información que sustenta nuestras decisiones estratégicas.


Que es Data quality?

Data quality ó calidad de los datos mide qué tan bien un conjunto de datos cumple con los criterios de accuracy, completeness, validity, consistency, uniqueness, timeliness y fitness para el propósito, y es fundamental para todas las iniciativas de gobernanza de datos dentro de una organización. Los estándares de calidad de los datos garantizan que las empresas tomen decisiones basadas en datos para alcanzar sus objetivos comerciales.

source: IBM

DataCamp cheat sheet
source: DataCamp cheat sheet

Data quality dimensions

En la siguiente tabla destaca los distintos dominios de calidad de datos, desde la precisión hasta la aptitud, proporcionando una guía esencial para evaluar y mejorar la robustez de los conjuntos de datos.

Dimensión Descripción
🎯 Precisión (Accuracy) Exactitud de los datos, es decir, qué tan cerca están de la realidad o la verdad. Datos precisos son aquellos que reflejan con precisión la información que intentan representar.
🧩 Integridad (Completeness) Mide la totalidad de los datos. Un conjunto de datos completo es aquel que no tiene valores faltantes o huecos significativos. La integridad de los datos es crucial para obtener una visión completa y precisa.
✅ Validez (Validity) Indica si los datos están en conformidad con las reglas y estándares definidos. Los datos válidos cumplen con las restricciones y criterios establecidos para un conjunto de datos específico.
🔄 Coherencia (Consistency) Se refiere a la uniformidad de los datos a lo largo del tiempo y entre diferentes conjuntos de datos. Datos coherentes no presentan contradicciones o discrepancias cuando se comparan entre sí.
📇 Unicidad (Uniqueness) Evalúa si no hay duplicados en los datos. Los datos únicos garantizan que cada entidad o elemento esté representado solo una vez en un conjunto de datos.
⌛ Oportunidad (Timeliness) Se refiere a la actualidad de los datos. La información oportuna es aquella que está disponible cuando se necesita, sin demoras innecesarias.
🏋️ Aptitud (Fitness) Este aspecto evalúa la relevancia y utilidad de los datos para el propósito previsto. Los datos deben ser adecuados y aplicables a los objetivos específicos de la organización o del análisis que se esté llevando a cabo.

Data quality dimensions- caso de uso

A continuación colocamos un ejemplo en el que se puede observar algunos problemas que tiene un caso de uso basado en eccommerce

ID Transacción ID Cliente Producto Cantidad Precio Unitario Total
⚪ 1 10234 Laptop HP 1 \$800 \$800
🟣 2 Auriculares Inalámbricos 2 \$50 \$100
🔵 3 10235 Teléfono Inteligente -1 \$1000 -\$1000
🟢 4 10236 Ratón Inalámbrico 3 \$30 \$90
🟢 4 10237 Teclado Inalámbrico 2 \$40 \$80
  1. 🟣 Fila 2 (Completeness): La fila 2 no cumple con la integridad de los datos (Completeness) ya que falta el ID del cliente.
    La información sobre el cliente está incompleta, lo que dificulta el seguimiento de la transacción hasta un cliente específico.

  2. 🔵Fila 3 (Accuracy y Consistency): La fila 3 presenta problemas de exactitud (Accuracy) y coherencia (Consistency).
    La cantidad de productos es negativa, lo cual es inexacto y va en contra de la consistencia esperada en un conjunto de datos de transacciones.

  3. 🟢Fila 4 (Unicidad): La introducción de una segunda fila con el mismo ID de transacción (ID Transacción = 4) viola el principio de unicidad.
    Cada transacción debe tener un identificador único, y la presencia de dos filas con el mismo ID Transacción crea duplicados, afectando la unicidad de las transacciones.\


Python Frameworks

Los siguientes son algunas de las implementaciones realizadas en python para poder realizar validaciones de la calidad de los datos

Framework Descripción
Great Expectations Great Expectations es una biblioteca open-source para la validación de datos. Permite definir, documentar y validar expectativas sobre los datos, garantizando la calidad y consistencia en proyectos de ciencia de datos y análisis.
Pandera Pandera es una biblioteca de validación de datos para estructuras de datos en Python, especialmente diseñada para trabajar con DataFrames de pandas. Permite definir esquemas y reglas de validación para asegurar la conformidad de los datos.
Dora Dora es una libreria python diseñada para automatizar exploración de datos y realizar analisis de datos exploratorios

Anlicemos algunas de las metricas que se pueden observar en sus repositorios de github, teniendo en cuenta que las metricas fueron obtenidas el 2023-11-12

Metricas Great Expectations Pandera Dora
👥 Colaboradores 399 109 106
⚠️ Issues abiertos 112 273 1
🟢 Issues Cerrados 1642 419 7
⭐ Stars 9000 2700 623
📺 Watching 78 17 42
🔎 Forks 1400 226 63
📬 Open PR 43 19 0
🐍 Python version >=3.8 >=3.7 No especificada
📄 Nro. Versiones 233 76 3
📄 Ultima Version 0.18.2 0.17.2 0.0.3
📆 Fecha Ultima Version 9 Nov 2023 30 sep 2023 30 jun 2020
📄 Tipo de licencia Apache-2.0 license MIT MIT
📄 Languages Python 95.1%, Jupyter Notebook 4.3%, Jinja 0.4%, JavaScript 0.1%, CSS 0.1%, HTML 0.0% Python 99.9%, Makefile 0.1% Python100%

Diferencias entre Licencia Apache 2.0 y MIT

  • Notificación de Cambios:
    • Apache 2.0: Requiere que se notifiquen los cambios realizados en el código fuente cuando se distribuye el software.
    • MIT: No requiere notificación específica de cambios.
  • Compatibilidad:
    • Apache 2.0: Es conocida por ser compatible con más licencias en comparación con MIT.
    • MIT: También es bastante compatible con diversas licencias, pero la Licencia Apache 2.0 a menudo se elige en proyectos que buscan una mayor interoperabilidad con otras licencias.
  • Atribución:
    • Apache 2.0: Requiere atribución y la inclusión de un aviso de derechos de autor.
    • MIT: Requiere atribución de la autoría original, pero puede tener requisitos menos estrictos en términos de cómo se muestra esa atribución.

Teniendo en cuenta estas metricas actualmente analizadas vamos a realizar un ejemplo de una implementación utilizando Pandera y Great expectations


Dataset

Para el desarrollo de este ejemplo utilizaremos el conjunto de datos denominado Tips, el conjunto de datos se puede descargar del siguiente link.

El conjunto de datos "tips" que contiene información sobre las propinas dadas en un restaurante, junto con detalles sobre la factura total, el sexo de la persona que pagó la factura, si el cliente es fumador, el día de la semana y la hora de la comida.

Columna Descripción
total_bill El monto total de la factura (incluida la propina).
tip La cantidad de propina dada.
sex El género del pagador de la factura (hombre o mujer).
smoker Si el cliente es fumador o no.
day El día de la semana en que se realizó la comida.
time El momento del día (almuerzo o cena).
size El tamaño del grupo que compartió la comida

A continuación una tabla con las primeras 5 filas del conjunto de datos:

total_bill tip sex smoker day time size
16.99 1.01 Female No Sun Dinner 2
10.34 1.66 Male No Sun Dinner 3
21.01 3.50 Male No Sun Dinner 3
23.68 3.31 Male No Sun Dinner 2
24.59 3.61 Female No Sun Dinner 4

🟢 Pandera

A continución vamos a realizar un ejemplo de implementación de Pandera utilizando el conjunto de datos anteriormente descripto.

Instalar pandera

pip install pandas pandera 
Enter fullscreen mode Exit fullscreen mode

Ejemplo de implementación

1️⃣ Importar pandas y pandera

import pandas as pd
import pandera as pa
Enter fullscreen mode Exit fullscreen mode

2️⃣ Importar el archivo del dataframe

path = 'data/tips.csv'
data = pd.read_csv(path)

print(f"Numero de columnas: {data.shape[1]}, Numero de filas: {data.shape[0]}")
print(f"Nombre de columnas: {list(data.columns)}")
Enter fullscreen mode Exit fullscreen mode
data.info()
Enter fullscreen mode Exit fullscreen mode
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 244 entries, 0 to 243
Data columns (total 7 columns):
 #   Column      Non-Null Count  Dtype  
---  ------      --------------  -----  
 0   total_bill  244 non-null    float64
 1   tip         244 non-null    float64
 2   sex         244 non-null    object 
 3   smoker      244 non-null    object 
 4   day         244 non-null    object 
 5   time        244 non-null    object 
 6   size        244 non-null    int64  
dtypes: float64(2), int64(1), object(4)
memory usage: 13.5+ KB
Enter fullscreen mode Exit fullscreen mode

3️⃣ Ahora vamos a crear el objeto schema que tiene todas las validaciones que queremos realizar.

En el siguiente link puede encontrar otras validaciones que se pueden realizar https://pandera.readthedocs.io/en/stable/dtype_validation.html

schema = pa.DataFrameSchema({
  "total_bill": pa.Column(float, checks=pa.Check.le(50)),
  "tip"       : pa.Column(float, checks=pa.Check.between(0,30)),
  "sex"       : pa.Column(str, checks=[pa.Check.isin(['Female','Male'])]),
  "smoker"    : pa.Column(str, checks=[pa.Check.isin(['No','Yes'])]),
  "day"       : pa.Column(str, checks=[pa.Check.isin(['Sun','Sat'])]),
  "time"      : pa.Column(str, checks=[pa.Check.isin(['Dinner','Lunch'])]),
  "size"      : pa.Column(int, checks=[pa.Check.between(1,4)])
})
Enter fullscreen mode Exit fullscreen mode

4️⃣ Para poder obtener el error y posteriormente poder utilizar este output para analizarlo es necesario capturar el mismo con un exception.

try:
    schema(data).validate()
except Exception as e:
    print(e)
    error = e
Enter fullscreen mode Exit fullscreen mode
Schema None: A total of 3 schema errors were found.

Error Counts
------------
- SchemaErrorReason.SCHEMA_COMPONENT_CHECK: 3

Schema Error Summary
--------------------
schema_context column     check                     failure_cases  n_failure_cases

Column         day        isin(['Sun', 'Sat'])      [Thur, Fri]             2
               size       in_range(1, 4)              [5, 6]                2
               total_bill less_than_or_equal_to(50)   [50.81]               1
Enter fullscreen mode Exit fullscreen mode

5️⃣ A continuación tienes una función que te permite transformar el output en un diccionario o en un dataframe de pandas.

def get_errors(error, dtype_dict=True):
    response = []


    for item in range(len(error.schema_errors)):
        error_item = error.schema_errors[item]
        response.append(
        {
            'column'     :error_item.schema.name,
            'check_error':error_item.schema.checks[0].error,
            'num_cases'  :error_item.failure_cases.index.shape[0],
            'check_rows' :error_item.failure_cases.to_dict()
        })

    if dtype_dict:
        return response
    else:
        return pd.DataFrame(response)
Enter fullscreen mode Exit fullscreen mode
get_errors(error,dtype_dict=True)
Enter fullscreen mode Exit fullscreen mode
[{'column': 'total_bill',
  'check_error': 'less_than_or_equal_to(50)',
  'num_cases': 1,
  'check_rows': {'index': {0: 170}, 'failure_case': {0: 50.81}}},
 {'column': 'day',
  'check_error': "isin(['Sun', 'Sat'])",
  'num_cases': 81,
  'check_rows': {'index': {0: 77,
    1: 78,
    2: 79,
    3: 80,
    4: 81,
    5: 82,
    6: 83,
    7: 84,
...
    5: 156,
    6: 185,
    7: 187,
    8: 216},
   'failure_case': {0: 6, 1: 6, 2: 5, 3: 6, 4: 5, 5: 6, 6: 5, 7: 5, 8: 5}}}]
Enter fullscreen mode Exit fullscreen mode

🟠 Great Expectations

Great Expectations es una biblioteca de código abierto basada en Python para validar, documentar y crear perfiles de sus datos.
La cual ayuda a mantener la calidad de los datos y mejorar la comunicación sobre los datos entre equipos.

source : https://docs.greatexpectations.io/docs/

Por lo cual podemos describir a Great Expectations como una herramienta de código abierto diseñada para garantizar la calidad y confiabilidad de los datos en diversas fuentes, como bases de datos, tablas, archivos y dataframes.
Su funcionamiento se basa en la creación de grupos de validaciones que especifican las expectativas o reglas que los datos deben cumplir.

Los siguientes son los pasos que debemos definir cuando utilizamos este framework:

1️⃣ Definición de Expectativas: Se especifican las expectativas que tienen sobre los datos.
Estas expectativas pueden incluir restricciones simples, como rangos de valores, o reglas más complejas sobre la coherencia y calidad de los datos.

2️⃣ Conexión a Fuentes de Datos: En este paso se debe definir cuales son las conexiones que debemos realizar a las diversas fuentes de datos, como bases de datos, tablas, archivos o dataframes.

3️⃣ Generación de Suites de Validaciones: A partir de las expectativas definidas, Great Expectations genera suites de validaciones que son conjuntos organizados de reglas que se aplicarán a los datos.

4️⃣ Ejecución de Validaciones: Las suites de validaciones se aplican a los datos, verificando si cumplen con las expectativas definidas.
Esto puede realizarse automáticamente en un flujo de trabajo programado o de forma interactiva según sea necesario.

5️⃣ Generación de Análisis y Reportes: Great Expectations proporciona capacidades avanzadas de análisis y generación de informes.
Esto incluye perfiles detallados de la calidad de los datos y reportes que resumen la salud general de los datos en función de las expectativas.

6️⃣ Alertas y Notificaciones: En caso de que los datos no cumplan con las expectativas definidas, Great Expectations puede generar alertas o notificaciones, permitiendo a los usuarios tomar medidas inmediatas para abordar problemas de calidad de datos.

En conjunto, Great Expectations ofrece una solución integral para garantizar la calidad de los datos a lo largo del tiempo, facilitando la detección temprana de problemas y brindando confianza en la integridad y utilidad de los datos utilizados en análisis y toma de decisiones.

Instalación de great expectation

!pip install great_expectations==0.17.22 seaborn matplotlib numpy pandas
Enter fullscreen mode Exit fullscreen mode

Ejemplo de implementación

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import os
import re 

import great_expectations as gx
from ruamel.yaml import YAML
from great_expectations.cli.datasource import sanitize_yaml_and_save_datasource
from great_expectations.core.expectation_configuration import ExpectationConfiguration

print(f"* great expectations version:{gx.__version__}")
print(f"* seaborn version:{sns.__version__}")
print(f"* numpy version:{np.__version__}")
print(f"* pandas:{pd.__version__}")
Enter fullscreen mode Exit fullscreen mode
* great expectations version:0.17.22
* seaborn version:0.13.0
* numpy version:1.26.1
* pandas:2.1.3
Enter fullscreen mode Exit fullscreen mode

1️⃣ Importar dataset utilizando great expectation

path = 'data/tips.csv'
data_gx = gx.read_csv(path)
Enter fullscreen mode Exit fullscreen mode

2️⃣ Listar todas las expectation disponibles por tipo

list_expectations = pd.DataFrame([item for item in dir(data_gx) if item.find('expect_')==0],columns=['expectation'])
list_expectations['expectation_type'] = np.select( [
        list_expectations.expectation.str.find('_table_')>0, 
        list_expectations.expectation.str.find('_column_')>0,  
        list_expectations.expectation.str.find('_multicolumn_')>0,
    ],['table','column','multicolumn'],
    default='other'
)

plt.figure(figsize=(20,6))
sns.countplot(x=list_expectations.expectation_type)
plt.show()
Enter fullscreen mode Exit fullscreen mode

En la imagen se observa que las expectations disponibles son principalmente aplicadas a columnas (como por ejemplo: expect_column_max_to_be_between ) y a tablas (como por ejemplo: expect_table_columns_to_match_set) , aunque tambien se pueden aplicar una expectation basada en los valores de varias columnas (como por ejemplo:expect_multicolumn_values_to_be_unique).

Expectations: Tables

# La siguiente lista contiene las colmnas que debe tener el dataframe
columns = ['total_bill', 'tip', 'sex', 'smoker', 'day', 'time', 'size']
data_gx.expect_table_columns_to_match_set(column_set = columns)
Enter fullscreen mode Exit fullscreen mode
{
  "success": true,
  "result": {
    "observed_value": [
      "total_bill",
      "tip",
      "sex",
      "smoker",
      "day",
      "time",
      "size"
    ]
  },
  "meta": {},
  "exception_info": {
    "raised_exception": false,
    "exception_traceback": null,
    "exception_message": null
  }
}
Enter fullscreen mode Exit fullscreen mode
# Ahora borramos dos columnas que son "time" y "size" para validar cual es el resultado.

columns = = ['total_bill', 'tip', 'sex', 'smoker', 'day']
data_gx.expect_table_columns_to_match_set(column_set = columns)
Enter fullscreen mode Exit fullscreen mode

Si observamos el resultado es False y en details nos detallan cuales son las columnas que el dataframe tiene adicionales a las que se esperaban.

{
  "success": false,
  "result": {
    "observed_value": [
      "day",
      "sex",
      "size",
      "smoker",
      "time",
      "tip",
      "total_bill"
    ],
    "details": {
      "mismatched": {
        "unexpected": [
          "size",
          "time"
        ]
      }
    }
  },
  "meta": {},
  "exception_info": {
    "raised_exception": false,
    "exception_traceback": null,
    "exception_message": null
  }
}
Enter fullscreen mode Exit fullscreen mode

Expectations: Columns

1️⃣ Validemos que existe un valor categorico dentro de una columna

data_gx['total_bill_group'] = pd.cut(data_gx['total_bill'],
                              bins=[0,10,20,30,40,50,float('inf')], 
                              labels=['0-10', '10-20', '20-30', '30-40', '40-50', '>50'],
                              right=False, 
                              include_lowest=True)

# Ahora validamos si 3 categorias existen dentro del conjunto de datos

data_gx.expect_column_distinct_values_to_contain_set(column='total_bill_group',
                                                      value_set=['0-10','10-20', '20-30'],
                                                      result_format='BASIC') 
Enter fullscreen mode Exit fullscreen mode
{
  "success": true,
  "result": {
    "observed_value": [
      "0-10",
      "10-20",
      "20-30",
      "30-40",
      "40-50",
      ">50"
    ],
    "element_count": 244,
    "missing_count": null,
    "missing_percent": null
  },
  "meta": {},
  "exception_info": {
    "raised_exception": false,
    "exception_traceback": null,
    "exception_message": null
  }
}
Enter fullscreen mode Exit fullscreen mode

2️⃣ Validemos que la columna no tiene valor nulos

data_gx.expect_column_values_to_not_be_null('sex')
Enter fullscreen mode Exit fullscreen mode
{
  "success": true,
  "result": {
    "element_count": 244,
    "unexpected_count": 0,
    "unexpected_percent": 0.0,
    "unexpected_percent_total": 0.0,
    "partial_unexpected_list": []
  },
  "meta": {},
  "exception_info": {
    "raised_exception": false,
    "exception_traceback": null,
    "exception_message": null
  }
}
Enter fullscreen mode Exit fullscreen mode

Great Expectation Project

Ahora vamos a genera un proyecto de great expectation para poder ejecutar un grupo de validaciones basados en uno o varios conjuntos de datos.

1️⃣ Inicializar el proyecto de great expectation

 !yes Y | great_expectations init
Enter fullscreen mode Exit fullscreen mode
  ___              _     ___                  _        _   _
 / __|_ _ ___ __ _| |_  | __|_ ___ __  ___ __| |_ __ _| |_(_)___ _ _  ___
| (_ | '_/ -_) _` |  _| | _|\ \ / '_ \/ -_) _|  _/ _` |  _| / _ \ ' \(_-<
 \___|_| \___\__,_|\__| |___/_\_\ .__/\___\__|\__\__,_|\__|_\___/_||_/__/
                                |_|
             ~ Always know what to expect from your data ~

Let's create a new Data Context to hold your project configuration.

Great Expectations will create a new directory with the following structure:

    great_expectations
    |-- great_expectations.yml
    |-- expectations
    |-- checkpoints
    |-- plugins
    |-- .gitignore
    |-- uncommitted
        |-- config_variables.yml
        |-- data_docs
        |-- validations

OK to proceed? [Y/n]: 
================================================================================

Congratulations! You are now ready to customize your Great Expectations configuration.

You can customize your configuration in many ways. Here are some examples:

  Use the CLI to:
    - Run `great_expectations datasource new` to connect to your data.
    - Run `great_expectations checkpoint new <checkpoint_name>` to bundle data with Expectation Suite(s) in a Checkpoint for later re-validation.
    - Run `great_expectations suite --help` to create, edit, list, profile Expectation Suites.
    - Run `great_expectations docs --help` to build and manage Data Docs sites.

  Edit your configuration in great_expectations.yml to:
    - Move Stores to the cloud
    - Add Slack notifications, PagerDuty alerts, etc.
    - Customize your Data Docs

Please see our documentation for more configuration options!
Enter fullscreen mode Exit fullscreen mode

2️⃣ Copiar datos dentro de la carpeta de "gx" generada a partir de la inicialización del proyecto

!cp -r data gx
Enter fullscreen mode Exit fullscreen mode
# vamos a imprimir el contenido de la carpeta

def print_directory_structure(directory_path, indent=0):
    current_dir = os.path.basename(directory_path)
    print("    |" + "    " * indent + f"-- {current_dir}")
    indent += 1
    with os.scandir(directory_path) as entries:
        for entry in entries:
            if entry.is_dir():
                print_directory_structure(entry.path, indent)
            else:
                print("    |" + "    " * indent + f"-- {entry.name}")


print_directory_structure('gx')
Enter fullscreen mode Exit fullscreen mode
    |-- gx
    |    -- great_expectations.yml
    |    -- plugins
    |        -- custom_data_docs
    |            -- renderers
    |            -- styles
    |                -- data_docs_custom_styles.css
    |            -- views
    |    -- checkpoints
    |    -- expectations
    |        -- .ge_store_backend_id
    |    -- profilers
    |    -- .gitignore
    |    -- data
    |        -- tips.csv
    |    -- uncommitted
    |        -- data_docs
    |        -- config_variables.yml
    |        -- validations
    |            -- .ge_store_backend_id
Enter fullscreen mode Exit fullscreen mode

Algunas aclaraciones sobre los archivos y carpetas que se generan en esta carpeta:

Archivos/Carpetas Descripción
📄great_expectations.yml Este archivo contiene la configuración principal del proyecto. Aquí se especifican detalles como las ubicaciones de almacenamiento y otros parámetros de configuración.
📂 plugins - 📄 custom_data_docs: Contiene renderizadores personalizados para documentos de datos.
- 📄 renderers: Incluye estilos personalizados para los documentos de datos, como hojas de estilo CSS (data_docs_custom_styles.css).
- 📄 views: Puede contener vistas personalizadas para los documentos de datos.
📂 checkpoints Esta carpeta podría contener definiciones de checkpoints, que son puntos en el flujo de datos donde se pueden realizar validaciones específicas.
📂 expectations Aquí se almacenan las expectativas definidas para los datos. Este directorio puede contener varias subcarpetas y archivos, dependiendo de la organización del proyecto.
📂 profilers Puede contener configuraciones para perfiles de datos, que son análisis detallados de las estadísticas de los datos.
📄 .gitignore Es un archivo de configuración para Git que especifica archivos y carpetas que deben ignorarse al realizar operaciones de seguimiento y compromiso (commit).
📂 data Contiene los datos utilizados en el proyecto, en este caso, el archivo tips.csv.
📂 uncommitted - 📂 data_docs: Carpeta donde se generan documentos de datos.
- 📄 config_variables.yml: Archivo de configuración que puede contener variables específicas del proyecto.
- 📂 validations: Puede contener resultados de validaciones realizadas en los datos.

3️⃣ Configuración de datasource y data conectors

DataSource: Es el origen de datos utilizado (puede ser un archivo, API, base de datos, entre otros.

Data Connectors: Son los conectores que facilitan la conexion a la fuentes de datos y donde se deben definir las credenciales de acceso, ubicación, entre otros.

datasource_name_file = 'tips.csv'
datasource_name = 'datasource_tips'
dataconnector_name = 'connector_tips'
Enter fullscreen mode Exit fullscreen mode
# Creamos la configuración del datasource

context = gx.data_context.DataContext()
my_datasource_config = f"""
    name: {datasource_name}
    class_name: Datasource
    execution_engine:
      class_name: PandasExecutionEngine
    data_connectors:
      {dataconnector_name}:
        class_name: InferredAssetFilesystemDataConnector
        base_directory: data
        default_regex:
          group_names:
            - data_asset_name
          pattern: (.*)
      default_runtime_data_connector_name:
        class_name: RuntimeDataConnector
        assets:
          my_runtime_asset_name:
            batch_identifiers:
              - runtime_batch_identifier_name
"""

yaml = YAML()
context.add_datasource(**yaml.load(my_datasource_config))
sanitize_yaml_and_save_datasource(context, my_datasource_config, overwrite_existing=True)
Enter fullscreen mode Exit fullscreen mode

4️⃣ Configuración de las expectations

En el siguiente fragmento de código, se presenta la configuración de tres expectativas (expectations).

En particular, la última de ellas incluye un parámetro denominado "mostly" con un valor de 0.75.
Este parámetro indica que la expectativa puede fallar en hasta un 25% de los casos, ya que, por defecto, se espera un cumplimiento del 100% a menos que se especifique lo contrario.

Adicionalmente se puede especificar un mensaje de error en formato markdown, tal como se visualiza en la ultima expectation.

expectation_configuration_table =  ExpectationConfiguration(
   expectation_type="expect_table_columns_to_match_set",
      kwargs= {
        "column_set": ['total_bill', 'tip', 'sex', 'smoker', 'day', 'time', 'size']
      },
      meta= {}
)

expectation_configuration_total_bill = ExpectationConfiguration(
      expectation_type= "expect_column_values_to_be_between",
      kwargs= {
        "column": "total_bill",
        "min_value": 0,
        "max_value": 100
      },
      meta= {}
)


expectation_configuration_size = ExpectationConfiguration(
   expectation_type="expect_column_values_to_not_be_null",
   kwargs={
      "column": "size",
      "mostly": 0.75,
   },
   meta={
      "notes": {
         "format": "markdown",
         "content": "Expectation to validate column `size` does not have null values."
      }
   }
)
Enter fullscreen mode Exit fullscreen mode

5️⃣ Creación de la suite expectation

expectation_suite_name = "tips_expectation_suite"
expectation_suite = context.create_expectation_suite(
    expectation_suite_name=expectation_suite_name, 
    overwrite_existing=True
)

# Add expectations
expectation_suite.add_expectation(expectation_configuration=expectation_configuration_table)
expectation_suite.add_expectation(expectation_configuration=expectation_configuration_total_bill)
expectation_suite.add_expectation(expectation_configuration=expectation_configuration_size)

# save expectation_suite
context.save_expectation_suite(expectation_suite=expectation_suite, 
                               expectation_suite_name=expectation_suite_name)
Enter fullscreen mode Exit fullscreen mode
data-quality/gx/expectations/tips_expectation_suite.json
Enter fullscreen mode Exit fullscreen mode

Dentro de la carpeta expectations se crea un archivo json con todas las expectations generadas anteriormente.

6️⃣ Configuración de los checkpoints

checkpoint_name ='tips_checkpoint'

config_checkpoint = f"""
    name: {checkpoint_name}
    config_version: 1
    class_name: SimpleCheckpoint
    expectation_suite_name: {expectation_suite_name}
    validations:
      - batch_request:
          datasource_name: {datasource_name}
          data_connector_name: {dataconnector_name}
          data_asset_name: {datasource_name_file}
          batch_spec_passthrough:
            reader_method: read_csv
            reader_options: 
              sep: ","
          data_connector_query:
            index: -1
        expectation_suite_name: {expectation_suite_name}
"""

# Validar si la estructura del yaml es correcta
context.test_yaml_config(config_checkpoint)

# Agregar el checkpoint al contexto generado
context.add_checkpoint(**yaml.load(config_checkpoint)) 
Enter fullscreen mode Exit fullscreen mode

7️⃣ Ejecutar el checkpoint para validar todas las expectations configuradas sobre el conjunto de datos

response = context.run_checkpoint(checkpoint_name=checkpoint_name)
Enter fullscreen mode Exit fullscreen mode

8️⃣ Para observar el resultado obtenido de las validaciones se puede convertir a json

 response.to_json_dict()
Enter fullscreen mode Exit fullscreen mode
{'run_id': {'run_name': None, 'run_time': '2023-11-12T20:39:23.346946+01:00'},
 'run_results': {'ValidationResultIdentifier::tips_expectation_suite/__none__/20231112T193923.346946Z/722b2e93e32fd7222c8ad9339f3e0e1d': {'validation_result': {'success': True,
    'results': [{'success': True,
      'expectation_config': {'expectation_type': 'expect_table_columns_to_match_set',
       'kwargs': {'column_set': ['total_bill',
         'tip',
         'sex',
         'smoker',
         'day',
         'time',
         'size'],
        'batch_id': '722b2e93e32fd7222c8ad9339f3e0e1d'},
       'meta': {}},
      'result': {'observed_value': ['total_bill',
        'tip',
        'sex',
        'smoker',
        'day',
        'time',
        'size']},
      'meta': {},
      'exception_info': {'raised_exception': False,
       'exception_traceback': None,
       'exception_message': None}},
     {'success': True,
...
  'notify_on': None,
  'default_validation_id': None,
  'site_names': None,
  'profilers': []},
 'success': True}
Enter fullscreen mode Exit fullscreen mode

Obtener los resultados

 context.open_data_docs()
Enter fullscreen mode Exit fullscreen mode

Al ejecutar este chunck de codigo se va abrir un archivo html con el resultado de las validaciones que esta en gx/uncommitted/data_docs/local_site/validations/tips_expectation_suite/__none__/20231112T192529.002401Z/722b2e93e32fd7222c8ad9339f3e0e1d.html

Si quieres aprender...

  1. Pandera Documentación Oficial
  2. Pandera: Statistical Data Validation of Pandas Dataframes - Researchgate
  3. Great Expectation Documentación Oficial
  4. Data Quality Fundamentals Book O'relly
  5. Great Expectation Yoututbe Channel

Top comments (0)