python/examples/integrations/Dask_Profiling.ipynb
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
">### 🚩 *Create a free WhyLabs account to get more value out of whylogs!*<br> \n",
">*Did you know you can store, visualize, and monitor whylogs profiles with the [WhyLabs Observability Platform](https://whylabs.ai/whylogs-free-signup?utm_source=whylogs-Github&utm_medium=whylogs-example&utm_campaign=Dask_Profiling)? Sign up for a [free WhyLabs account](https://whylabs.ai/whylogs-free-signup?utm_source=whylogs-Github&utm_medium=whylogs-example&utm_campaign=Dask_Profiling) to leverage the power of whylogs and WhyLabs together!*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Dask Profiling\n",
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/whylabs/whylogs/blob/mainline/python/examples/integrations/Dask_Profiling.ipynb)\n",
"\n",
"\n",
"Hi! If you have a Dask available on your processing and modeling environment, you can leverage its delayed API to profile data with `whylogs` in a distributed way, and this is what we are going to cover in this example notebook 😃 "
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Note: you may need to restart the kernel to use updated packages.\n"
]
}
],
"source": [
"# Note: you may need to restart the kernel to use updated packages.\n",
"%pip install dask 'whylogs[viz]'"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from glob import glob\n",
"from typing import List\n",
"from functools import reduce\n",
"\n",
"import dask\n",
"import pandas as pd\n",
"import whylogs as why\n",
"from whylogs.core import DatasetProfileView"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Read data\n",
"We will use a functional programming approach to read the data and profile it in parallel and then merge them back to a single profile, that can be further used to investigate important information, such as with a Constraints validation, a drift report, and much more. First, we will use the pandas library to read parquet files, assuming you have a directory with some parquet files available."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"@dask.delayed\n",
"def read_data(parquet_file):\n",
" df = pd.read_parquet(parquet_file)\n",
" return df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Profile data\n",
"\n",
"The with pandas DataFrames in place, it is straight forward to profile your data with whylogs. To do so, let's also define a delayed function."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"@dask.delayed\n",
"def log_data(df: pd.DataFrame):\n",
" return why.log(df).view()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Merge profiles\n",
"\n",
"The last step in the pipeline is to merge the profiles we have created in the previous delayed steps, where we will take in a list of `DatasetProfileView` objects and turn them into a single profile that will contain the summary of relevant metrics that represent our data. "
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def reduce_list(profile_list: List[DatasetProfileView]):\n",
" result = reduce(lambda x, y: x.merge(y), profile_list)\n",
" return result"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"data_list = [f\"https://whylabs-public.s3.us-west-2.amazonaws.com/whylogs_examples/dask_example/example_{number}.parquet\" for number in range(5)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Chaining execution\n",
"\n",
"Now we will chain together the logic of our code execution, by creating the output list with the profiles from the read data. With it, we can create a Dask delayed task, and this will make sure to create our task graph properly."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"output = []\n",
"\n",
"for file in data_list:\n",
" df = read_data(parquet_file=file)\n",
" profile_view = log_data(df=df)\n",
" output.append(profile_view)\n",
"\n",
"task = dask.delayed(reduce_list)(output)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Visualizing the execution plan\n",
"\n",
"To view what the task graph looks like, we need the `graphviz` library available. Then we can call Dask's visualize method and check what are the planned steps for our computations."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Note: you may need to restart the kernel to use updated packages.\n"
]
}
],
"source": [
"%pip install -q graphviz"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
"<IPython.core.display.Image object>"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"task.visualize()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Triggering execution\n",
"\n",
"Up until now, we only have planned what to execute using the delayed decorator in our simple processes. When we want to trigger the execution, we need to call the action, and that can be done with the compute method. This will return us a single merged `DatasetProfileView` object. "
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"merged_profile_view = task.compute()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And now we can investigate important metric in our entire dataset! Let's use whylogs' extra visualization package to see some metrics from our data."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div></div><iframe srcdoc=\"<!DOCTYPE html>\n",
"<html lang="en">\n",
" <head>\n",
" <meta charset="UTF-8" />\n",
" <meta http-equiv="X-UA-Compatible" content="IE=edge" />\n",
" <meta name="viewport" content="width=device-width, initial-scale=1.0" />\n",
" <meta name="description" content="" />\n",
" <meta name="author" content="" />\n",
"\n",
" <title>Profile Visualizer | whylogs</title>\n",
"\n",
" <link rel="icon" href="images/whylabs-favicon.png" type="image/png" sizes="16x16" />\n",
" <link rel="preconnect" href="https://fonts.googleapis.com" />\n",
" <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />\n",
" <link href="https://fonts.googleapis.com/css2?family=Asap:wght@400;500;600;700&display=swap" rel="stylesheet" />\n",
" <link rel="preconnect" href="https://fonts.gstatic.com" />\n",
" <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" />\n",
"\n",
" <script\n",
" src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.7/handlebars.min.js"\n",
" integrity="sha512-RNLkV3d+aLtfcpEyFG8jRbnWHxUqVZozacROI4J2F1sTaDqo1dPQYs01OMi1t1w9Y2FdbSCDSQ2ZVdAC8bzgAg=="\n",
" crossorigin="anonymous"\n",
" referrerpolicy="no-referrer"\n",
" ></script>\n",
"\n",
" <style type="text/css">\n",
" :root {\n",
" /* CONSTANTS */\n",
" --SIDE-PANEL-WIDTH: 320px;\n",
" --PROPERTY-PANEL-WIDTH: 420px;\n",
"\n",
" /* COLOR VARIABLES */\n",
" /** Standard colors */\n",
" --red: #d11010;\n",
" --orange: #f07028;\n",
" --yellow: #faaf40;\n",
" --olive: #b5cc18;\n",
" --green: #1dbb42;\n",
" --teal: #00b5ad;\n",
" --blue: #2683c9;\n",
" --violet: #6435c9;\n",
" --purple: #a333c8;\n",
" --pink: #ed45a4;\n",
" --brown: #ac724d;\n",
" --grey: #778183;\n",
" --black: #1b1c1d;\n",
" --white: #ffffff;\n",
"\n",
" /** Branded colors */\n",
" --brandPrimary900: #0e7384;\n",
" --brandPrimary800: #228798;\n",
" --brandPrimary700: #369bac;\n",
" --brandPrimary600: #4aafc0;\n",
" --brandPrimary500: #5ec3d4;\n",
" --brandPrimary400: #72d7e8;\n",
" --brandPrimary300: #86ebfc;\n",
" --brandPrimary200: #a6f2ff;\n",
" --brandPrimary100: #cdf8ff;\n",
" --brandSecondary900: #4f595b;\n",
" --brandSecondary800: #636d6f;\n",
" --brandSecondary700: #778183;\n",
" --brandSecondary600: #8b9597;\n",
" --brandSecondary500: #9fa9ab;\n",
" --brandSecondary400: #b3bdbf;\n",
" --brandSecondary300: #c7d1d3;\n",
" --brandSecondary200: #dbe5e7;\n",
" --brandSecondary100: #ebf2f3;\n",
" --secondaryLight1000: #313b3d;\n",
" --brandRed4: #b30000;\n",
" --brandRed3: #d72424;\n",
" --brandRed2: #eb5656;\n",
" --brandRed1: #ff8282;\n",
" --night1: #021826;\n",
" /** Purpose colors */\n",
" --textColor: #4f595b;\n",
" --linkColor: #369bac;\n",
" --infoColor: #2683c9;\n",
" --warningColor: #faaf40;\n",
" --tealBackground: #eaf2f3;\n",
" --pageBackground: #e5e5e5;\n",
" --contrastTableRow: #fafafa;\n",
" --whiteBackground: #ffffff;\n",
" --primaryBackground: #e5e5e5;\n",
" }\n",
"\n",
" /* RESET STYLE */\n",
" *,\n",
" *::after,\n",
" *::before {\n",
" margin: 0;\n",
" padding: 0;\n",
" box-sizing: border-box;\n",
" font-family: "Asap", Arial, Helvetica, sans-serif;\n",
" }\n",
"\n",
" /*\n",
" * Main content\n",
" */\n",
" .main {\n",
" position: relative;\n",
" background: #FFFFFF;\n",
" border: 1px solid #DBE5E7;\n",
" box-sizing: border-box;\n",
" border-radius: 4px;\n",
" }\n",
" .main .page-header {\n",
" margin-top: 0;\n",
" }\n",
"\n",
" /* CSS DIV TABLE BASIC STYLE */\n",
"\n",
" .wl-table-row .wl-table-head:first-child {\n",
" min-width: 360px;\n",
" z-index: 2;\n",
" }\n",
"\n",
" .wl-table-wrap {\n",
" position: relative;\n",
" }\n",
"\n",
" .wl-table {\n",
" display: table;\n",
" width: 100%;\n",
" }\n",
"\n",
" .row>* {\n",
" padding-right: 0 !important;\n",
" padding-left: 0 !important;\n",
" }\n",
"\n",
" .wl-table-row {\n",
" display: table-row;\n",
" }\n",
"\n",
" .wl-table-row:hover,\n",
" .wl-table-row:hover .wl-table-cell:first-child {\n",
" background-color: var(--brandSecondary100);\n",
" }\n",
" .wl-table-row--clickable:hover .wl-table-cell__title-button {\n",
" visibility: visible;\n",
" }\n",
"\n",
" .wl-table-heading {\n",
" position: sticky;\n",
" top: 0;\n",
" z-index: 900;\n",
" display: table-header-group;\n",
" font-weight: 700;\n",
" }\n",
"\n",
" .wl-table-cell,\n",
" .wl-table-head {\n",
" border-bottom: 1px solid var(--brandSecondary200);\n",
" display: table-cell;\n",
" padding: 12px 18px;\n",
" }\n",
"\n",
" .wl-table-cell {\n",
" font-size: 14px;\n",
" }\n",
"\n",
" .wl-table-cell--top-spacing {\n",
" padding-top: 35px; /* cell-top-padding + cell-title-height */\n",
" }\n",
"\n",
" .wl-table-head-wraper {\n",
" background-color: var(--white);\n",
" }\n",
"\n",
" .wl-table-head {\n",
" position: sticky;\n",
" left: 0;\n",
" min-width: 100px;\n",
" border-bottom: 2px solid var(--brandSecondary100);\n",
" font-size: 12px;\n",
" line-height: 1.67;\n",
" white-space: nowrap;\n",
" }\n",
"\n",
" .wl-sub-table-head {\n",
" position: relative;\n",
" }\n",
"\n",
" .wl-table-body {\n",
" display: table-row-group;\n",
" }\n",
"\n",
" .wl-table-row .wl-table-cell:first-child{\n",
" position: sticky;\n",
" left: 0;\n",
" background-color: var(--white);\n",
" border-right-width: 2px;\n",
" }\n",
"\n",
" /* Table custom style */\n",
"\n",
" .wl-table-cell__title-wrap {\n",
" display: flex;\n",
" justify-content: space-between;\n",
" }\n",
"\n",
" .wl-table-cell__title {\n",
" height: 25px;\n",
" margin: 0;\n",
" font-size: 14px;\n",
" font-weight: 700;\n",
" overflow: hidden;\n",
" white-space: nowrap;\n",
" text-overflow: ellipsis;\n",
" }\n",
"\n",
" .wl-table-cell__bedge-wrap {\n",
" padding: 2px 0;\n",
" white-space: nowrap;\n",
" overflow: hidden;\n",
" font-style: italic;\n",
" text-align: center;\n",
" color: var(--brandSecondary400);\n",
" }\n",
" .wl-table-cell__bedge {\n",
" height: 24px;\n",
" margin: 1px;\n",
" padding: 2px 8px;\n",
" border: 1px solid var(--brandSecondary400);\n",
" font-style: normal;\n",
" color: var(--brandSecondary900);\n",
" border-radius: 20px;\n",
" white-space: nowrap;\n",
" }\n",
"\n",
" /* Property side panel */\n",
"\n",
" .wl-compare-profile {\n",
" z-index: 999;\n",
" position: absolute;\n",
" right: 0;\n",
" background: var(--white);;\n",
" border-bottom: 1px solid var(--brandSecondary200);\n",
" }\n",
"\n",
" /* Screen on smaller screens */\n",
" .no-responsive {\n",
" display: none;\n",
" position: fixed;\n",
" top: 0;\n",
" left: 0;\n",
" z-index: 1031;\n",
" width: 100vw;\n",
" height: 100vh;\n",
" background-color: var(--tealBackground);\n",
" display: flex;\n",
" align-items: center;\n",
" justify-content: center;\n",
" }\n",
"\n",
" .no-responsive__content {\n",
" max-width: 600px;\n",
" width: 100%;\n",
" padding: 0 24px;\n",
" }\n",
"\n",
" .no-responsive__title {\n",
" font-size: 96px;\n",
" font-weight: 300;\n",
" color: var(--brandSecondary900);\n",
" line-height: 1.167;\n",
" }\n",
"\n",
" .no-responsive__text {\n",
" margin: 0;\n",
" font-size: 16px;\n",
" font-weight: 400;\n",
" color: var(--brandSecondary900);\n",
" line-height: 1.5;\n",
" }\n",
"\n",
" .space-between {\n",
" display: flex;\n",
" justify-content: space-between;\n",
" }\n",
"\n",
" .align-items {\n",
" display: flex;\n",
" align-items: center;\n",
" }\n",
"\n",
" .display-flex{\n",
" display: flex;\n",
" }\n",
"\n",
" .table-border-none {\n",
" padding: 0;\n",
" border: none;\n",
" }\n",
"\n",
" .flex-direction-colum {\n",
" display: flex;\n",
" flex-direction: column;\n",
" }\n",
"\n",
" .align-items {\n",
" align-items: center;\n",
" }\n",
"\n",
" .search-input{\n",
" padding-top: 0 !important;\n",
" padding-bottom: 0 !important;\n",
" }\n",
"\n",
" .search-input input{\n",
" border: none;\n",
" background: none;\n",
" outline: none;\n",
" height: 40px;\n",
" width: 100%;\n",
" font-size: 14px;\n",
" }\n",
"\n",
" .search-input img{\n",
" height: 19px;\n",
" pointer-events: none;\n",
" }\n",
"\n",
" input::placeholder {\n",
" color: var(--secondaryLight1000);\n",
" }\n",
"\n",
" .text-align-center {\n",
" text-align: center;\n",
" }\n",
"\n",
" .text-align-end {\n",
" text-align: end;\n",
" }\n",
"\n",
" .drift-detection {\n",
" justify-content: space-between;\n",
" align-items: center;\n",
" }\n",
"\n",
" .drift-detection-info-circle {\n",
" width: 15px;\n",
" height: 15px;\n",
" border-radius: 50px;\n",
" display: inline-block;\n",
" margin-right: 8px;\n",
" }\n",
"\n",
" .severe-drift-circle-color {\n",
" background: #D40D00;\n",
" }\n",
"\n",
" .moderate-drift-circle-color {\n",
" background: #F5843C;\n",
" }\n",
"\n",
" .mild-drift-circle-color {\n",
" background: #F2C142;\n",
" }\n",
"\n",
" .minimal-drift-circle-color {\n",
" background: #ABCA52;\n",
" }\n",
"\n",
" .drift-detection-info-drifts-item {\n",
" padding-right: 20px;\n",
" }\n",
"\n",
" .drift-detection-info-title {\n",
" font-family: Arial;\n",
" font-weight: bold;\n",
" font-size: 16px;\n",
" line-height: 130%;\n",
" color: #313B3D;\n",
" }\n",
"\n",
" .drift-detection-info-drifts-item-count {\n",
" font-family: Arial;\n",
" font-weight: bold;\n",
" font-size: 14px;\n",
" line-height: 16px;\n",
" color: #000000;\n",
" padding-right: 8px;\n",
" }\n",
"\n",
" .drift-detection-info-drifts-item-name {\n",
" font-family: Arial;\n",
" font-style: normal;\n",
" font-weight: normal;\n",
" font-size: 12px;\n",
" line-height: 14px;\n",
" color: #000000;\n",
" }\n",
"\n",
" .drift-detection-info-drifts-item-range {\n",
" font-family: Arial;\n",
" font-style: normal;\n",
" font-weight: normal;\n",
" font-size: 11px;\n",
" line-height: 13px;\n",
" color: #6C757D;\n",
" }\n",
"\n",
" .drift-detection-search-input {\n",
" display: flex;\n",
" align-items: center;\n",
" background: rgba(255, 255, 255, 0.7);\n",
" border: 1px solid #DBE5E7;\n",
" box-sizing: border-box;\n",
" border-radius: 4px;\n",
" width: 170px;\n",
" padding-left: 10px;\n",
" }\n",
"\n",
" .drift-detection-search-input img{\n",
" margin-right: 5px;\n",
" }\n",
"\n",
" .drift-detection-search-input input::placeholder {\n",
" font-family: Arial;\n",
" font-weight: normal;\n",
" font-size: 13px;\n",
" line-height: 16px;\n",
" color: #313B3D;\n",
" }\n",
"\n",
" .close-filter-button {\n",
" display: flex;\n",
" justify-content: center;\n",
" align-items: center;\n",
" background: rgba(255, 255, 255, 0.7);\n",
" border: 1px solid #369BAC;\n",
" box-sizing: border-box;\n",
" border-radius: 4px;\n",
" width: 40px;\n",
" height: 40px;\n",
" cursor: pointer;\n",
" margin-left: 10px;\n",
" }\n",
"\n",
" .filter-options-title {\n",
" width: 240px;\n",
" }\n",
"\n",
" .filter-options-title p {\n",
" margin: 0;\n",
" }\n",
"\n",
" .dropdown-container {\n",
" position: absolute;\n",
" right: 18px;\n",
" z-index: 999;\n",
" background: #FFFFFF;\n",
" border: 1px solid #DBE5E7;\n",
" box-sizing: border-box;\n",
" box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.05);\n",
" border-radius: 4px;\n",
" padding: 10px !important;\n",
" border: none !important;\n",
" }\n",
"\n",
" .form-check-input:checked {\n",
" background-color: #0E7384;\n",
" border-color: #0E7384;\n",
" }\n",
"\n",
" .form-check-input[type=checkbox] {\n",
" border-radius: 2px;\n",
" }\n",
"\n",
" .justify-content-center {\n",
" justify-content: center;\n",
" }\n",
"\n",
" .wl-table-cell__graph-wrap {\n",
" width: 0;\n",
" }\n",
"\n",
" .svg-container {\n",
" display: inline-block;\n",
" position: relative;\n",
" width: 85%;\n",
" padding-bottom: 17%;\n",
" vertical-align: top;\n",
" overflow: hidden;\n",
" }\n",
"\n",
" .svg-content-responsive {\n",
" display: inline-block;\n",
" position: absolute;\n",
" left: 0;\n",
" }\n",
"\n",
" .reference-table-head {\n",
" min-width: 250px;\n",
" }\n",
"\n",
" .wl__dropdown_arrow-icon {\n",
" position: relative;\n",
" }\n",
"\n",
" .notif-circle-container{\n",
" position: absolute;\n",
" top: -4px;\n",
" right: -4px;\n",
" padding: 5.3px;\n",
" border-radius: 50%;\n",
" background-color: white;\n",
" cursor: pointer;\n",
" }\n",
"\n",
" .notif-circle {\n",
" position: absolute;\n",
" top: 2px;\n",
" right: 2px;\n",
" padding: 3.3px;\n",
" border-radius: 50%;\n",
" background-color: #F2994A;\n",
" }\n",
"\n",
"\n",
" .header-title {\n",
" font-size: 26px;\n",
" font-weight: 700;\n",
" color: #444444;\n",
" }\n",
"\n",
" .statistic-number-title {\n",
" font-family: Arial;\n",
" font-weight: normal;\n",
" font-size: 14px;\n",
" line-height: 20px;\n",
" color: #6C757D;\n",
" }\n",
"\n",
" .statistic-number {\n",
" font-family: Arial;\n",
" font-weight: bold;\n",
" font-size: 20px;\n",
" line-height: 140%;\n",
" display: flex;\n",
" align-items: center;\n",
" color: #0E7384;\n",
" }\n",
"\n",
" .statistic-measurement {\n",
" font-size: 15px !important;\n",
" margin-left: 3px;\n",
" }\n",
"\n",
" .statistic-measurement-percent {\n",
" font-size: 15px !important;\n",
" }\n",
"\n",
" .question-mark {\n",
" font-size: 10px;\n",
" font-weight: 900;\n",
" color: #0E7384;\n",
" border-radius: 50px;\n",
" border: 2px solid #0E7384;\n",
" padding: 0px 4px;\n",
" transition: 0.5s;\n",
" cursor: pointer;\n",
" }\n",
"\n",
" .question-mark:hover {\n",
" color: white;\n",
" background: #0E7384;\n",
" border: 2px solid none;\n",
" transition: 0.5s;\n",
" }\n",
"\n",
" .tooltip-full-number {\n",
" position: relative;\n",
" display: inline-block;\n",
" }\n",
"\n",
" .tooltip-full-number .tooltiptext {\n",
" visibility: hidden;\n",
" background: black;\n",
" color: white;\n",
" border: 1px solid black;\n",
" text-align: start;\n",
" padding: 3px;\n",
" position: absolute;\n",
" z-index: 1;\n",
" top: 0;\n",
" left: 100%;\n",
" margin-left: 5px;\n",
" opacity: 0;\n",
" transition: opacity 0.5s;\n",
" font-size: 13px;\n",
" font-weight: normal;\n",
" line-height: 100%;\n",
" }\n",
"\n",
" .tooltip-full-number:hover .tooltiptext {\n",
" visibility: visible;\n",
" opacity: 1;\n",
" }\n",
"\n",
" .display-flex {\n",
" display: flex;\n",
" }\n",
"\n",
" .flex-direction-column {\n",
" flex-direction: column;\n",
" }\n",
"\n",
" .justify-content-space-between {\n",
" justify-content: space-between;\n",
" }\n",
"\n",
" .justify-content-center {\n",
" justify-content: center;\n",
" }\n",
"\n",
" .align-items-center {\n",
" align-items: center;\n",
" }\n",
"\n",
" .padding-right-30 {\n",
" padding-right: 30px;\n",
" }\n",
"\n",
" .padding-5 {\n",
" padding: 5px;\n",
" }\n",
"\n",
" .text-color {\n",
" color: var(--secondaryLight1000);\n",
" }\n",
"\n",
" .error-message {\n",
" display: flex;\n",
" justify-content: center;\n",
" align-items: center;\n",
" color: rgb(255, 114, 71);\n",
" font-size: 30px;\n",
" font-weight: 900;\n",
" }\n",
"\n",
" @media screen and (min-width: 500px) {\n",
" .desktop-content {\n",
" display: block;\n",
" }\n",
" .no-responsive {\n",
" display: none;\n",
" }\n",
" }\n",
" </style>\n",
" </head>\n",
"\n",
" <body id="generated-html"></body>\n",
"\n",
" <script id="entry-template" type="text/x-handlebars-template">\n",
" \n",
" <div class="desktop-content">\n",
" <div class="container-fluid">\n",
" <div class="feature-summary-statistics-wrap">\n",
" <div class="feature-summary-statistics">\n",
" <div class="mb-4">\n",
" <strong class="header-title">Profile Summary</strong>\n",
" </div>\n",
" <div class="display-flex statistics">\n",
" <div class="padding-right-30">\n",
" <div class="statistic-number-title">Observations</div>\n",
" <div class="statistic-number">{{{observations this}}}</div>\n",
" </div>\n",
" <div class="padding-right-30">\n",
" <div class="statistic-number-title">Missing Cells</div>\n",
" <div class="statistic-number">\n",
" {{{missingCells this}}}\n",
" <div>{{{missingCellsPercentage this}}}</div>\n",
" </div>\n",
" </div>\n",
" <div class="wl-compare-profile" id="compare-profile" style="display: flex; justify-content: space-around">\n",
" <div class="drift-detection-wrap">\n",
" <div class="drift-detection display-flex">\n",
" <div class="drift-detection-search-input-wrap display-flex">\n",
" <div class="drift-detection-search-input search-input ">\n",
" <input type="text" id="wl__feature-search" placeholder="Quick search..."/>\n",
" <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAGdSURBVHgBpZK7TkJBEIZnZoVocdTYyQNALxpNKPQBMEaNJsbCRMKhl8ISWwt6AaksCF5iTHgAGhJD4AHkAaAzGiwUsjvOQnO4SYh/cXbPzO43OxcEj9Zy92EiFSXNIfvPyE1kKFfdoxJMENpP6DrvLC0vJoEwCgwto7DWcxoIIHBYbA3NmKwnDltjAeuZhyul1DaTTlfPB6Nt5Z53DOgky4P875+nlctY2+unjZviLklkJhi5bPUa3y/7qJuQUM7PinMy7CdQc1Gh16vnBxPzrMROmlKQEgKNASAHLQCmSIGpS75O+O5pdQAgVXaIqTkNwDDXHmcnW3VmHZoGMLoTsOt88+NrAMCIZdu+iLTyTwKRa1Md6YKfOgXbzO7K8sWku5u5RxcRV5EpPezrzcHGbXEXWaUkgkweZ/UC9YrK3zqggFw5FBZfm8EUavHj7AjAKpIvBDrGn+pNnlcyhYgqbcC41idr1gvB4SdZkDbzQa21gwv0Vj07aPTtL07XdDOyDXohCDNoHIRmAVRie20f+RKybRDQDvxHkXy/7b/DrayncLbMwQAAAABJRU5ErkJggg=="/>\n",
" </div>\n",
" <div class="wl__dropdown_arrow-icon" >\n",
" <div onclick="openFilter()" class="close-filter-button">\n",
" <div class="display-flex close-filter-icon d-none">\n",
" <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADFSURBVHgBfY+xDcIwEEXvnLQBZQkYAEhDwwKpEEK0CCZgAEjJCEmgjYSAygxAHTZgFRSOsyUjY5mcZFnn/+78PwBXf3+MoKWUPuYjVBPFnTwpr9t/oNJfcTfXsAhRAlDqDhhQIPYgpAqNMDqcUqSAYZT1epr9gAHt6uXshvYme4DYHQJNDKh0dD0m5WXB10Y3Fqjtuh7fROn3oREDWxfeMLyRsMnc0OgDzdduaA0Pi3Plgr7Q2kaAePeBqh6rueSNBVt6fgCwBV1JLF3rlAAAAABJRU5ErkJggg=="/>\n",
" </div>\n",
" <div class="display-flex filter-icon">\n",
" <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACSSURBVHgBrZLBCYAwDEWTUjw7igcdwI1cxkNXUJzBEVzFAbSVKoKmaVrEB6GHJv/w+AACtRk7P9IONv1QOYUl96k0zv61m2tjARoLtSDI3EFsgIJ4uoXrMLazO72CRG2mzg/8BSdVlEjhpGZJjAWdAZJECpWalEhJSs1pHuUlMad5FFai1Lwg4Ckx1TxKIPFL8w55mEWd8VjPGAAAAABJRU5ErkJggg=="/>\n",
" </div>\n",
" </div>\n",
" <span class="notif-circle-container">\n",
" <span class="notif-circle"></span>\n",
" </span>\n",
" </div>\n",
" </div>\n",
" </div>\n",
" </div>\n",
" <div class="dropdown-container flex-direction-colum mb-2 d-none" id="dropdown-container">\n",
" <div class="filter-options">\n",
" <div class="filter-options-title space-between dropdown">\n",
" <p>Filter by type</p>\n",
" </div>\n",
" <div class="form-check mb-1 mt-2">\n",
" <input\n",
" class="form-check-input wl__feature-filter-input"\n",
" type="checkbox"\n",
" name="checkbox"\n",
" value="Discrete"\n",
" id="inferredDiscrete"\n",
" onclick="changeDiscreteValue()"\n",
" checked\n",
" />\n",
" <label class="form-check-label" for="inferredDiscrete">\n",
" Inferred discrete (<span class="wl__feature-count--discrete">{{getDiscreteTypeCount}}</span>)\n",
" </label>\n",
" </div>\n",
" <div class="form-check mb-1">\n",
" <input\n",
" class="form-check-input wl__feature-filter-input"\n",
" type="checkbox"\n",
" name="checkbox"\n",
" value="Non-discrete"\n",
" id="inferredNonDiscrete"\n",
" onclick="changeNonDiscreteValue()"\n",
" checked\n",
" />\n",
" <label class="form-check-label" for="inferredNonDiscrete">\n",
" Inferred non-discrete (<span\n",
" class="wl__feature-count--non-discrete"\n",
" >{{getNonDiscreteTypeCount}}</span>)\n",
" </label>\n",
" </div>\n",
" <div class="form-check mb-1">\n",
" <input\n",
" class="form-check-input wl__feature-filter-input"\n",
" type="checkbox"\n",
" name="checkbox"\n",
" value="Unknown"\n",
" id="inferredUnknown"\n",
" onclick="changeUnknwonValue()"\n",
" checked\n",
" />\n",
" <label class="form-check-label" for="inferredUnknown">\n",
" Unknown (<span class="wl__feature-count--unknown">{{getUnknownTypeCount}}</span>)\n",
" </label>\n",
" </div>\n",
" </div>\n",
" </div>\n",
" </div>\n",
" </div>\n",
" </div>\n",
" <div class="row">\n",
" <div class="main">\n",
" <div class="wl-table-wrap" id="table-content">\n",
" <div class="wl-table">\n",
" <div class="wl-table-heading">\n",
" <div class="wl-table-row wl-table-row--bottom-shadow">\n",
" <div class="wl-table-head wl-table-head-wraper">\n",
" <div class="wl-table-head table-border-none graph-table-head">Target</div>\n",
" </div>\n",
" <div class="wl-table-head wl-table-head-wraper text-align-end">Total count</div>\n",
" <div class="wl-table-head wl-table-head-wraper text-align-end">Missing</div>\n",
" <div class="wl-table-head wl-table-head-wraper text-align-end">Mean</div>\n",
" <div class="wl-table-head wl-table-head-wraper text-align-end">Min</div>\n",
" <div class="wl-table-head wl-table-head-wraper text-align-end">Max</div>\n",
"\n",
" </div>\n",
" </div>\n",
" <ul class="wl-table-body wl__table-body" id="table-body">\n",
"{{#each this.columns}} <li\n",
" {{#if this.numberSummary}} class="wl-table-row wl-table-row--clickable" {{else}} class="wl-table-row" {{/if}}\n",
" data-feature-name={{@key}}\n",
" data-inferred-type={{inferredType this}}\n",
" data-scroll-to-feature-name={{@key}}\n",
" >\n",
" <div class="wl-table-cell wl-table-cell__graph-wrap">\n",
" <div class="wl-table-cell__title-wrap">\n",
" <h4 class="wl-table-cell__title">{{@key}}</h4>\n",
" <div></div>\n",
" </div>\n",
" <div class="display-flex">\n",
" {{{getGraphHtml this}}}\n",
" </div>\n",
" </div>\n",
" <div\n",
" class="wl-table-cell wl-table-cell--top-spacing align-middle"\n",
" ><div class="text-align-end">{{totalCount this}}</div></div>\n",
" <div\n",
" class="wl-table-cell wl-table-cell--top-spacing align-middle"\n",
" ><div class="text-align-end">{{missing this}}</div></div>\n",
" <div\n",
" class="wl-table-cell wl-table-cell--top-spacing align-middle"\n",
" ><div class="text-align-end">{{mean this}}</div></div>\n",
" <div\n",
" class="wl-table-cell wl-table-cell--top-spacing align-middle"\n",
" ><div class="text-align-end">{{minimumValue this}}</div></div>\n",
" <div\n",
" class="wl-table-cell wl-table-cell--top-spacing align-middle"\n",
" ><div class="text-align-end">{{maximumValue this}}</div></div>\n",
"\n",
" </li>\n",
"{{/each}} </ul>\n",
" </div>\n",
" </div>\n",
" </div>\n",
" </div>\n",
" </div>\n",
" </div>\n",
" <div class="no-responsive">\n",
" <div class="no-responsive__content">\n",
" <h1 class="no-responsive__title">Hold on! :)</h1>\n",
" <p class="no-responsive__text">\n",
" It looks like your current screen size or device is not yet supported by the WhyLabs Sandbox. The Sandbox is\n",
" best experienced on a desktop computer. Please try maximizing this window or switching to another device. We\n",
" are working on adding support for a larger variety of devices.\n",
" </p>\n",
" </div>\n",
" </div>\n",
" \n",
" </script>\n",
"\n",
" <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>\n",
"\n",
" <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js" integrity="sha512-cd6CHE+XWDQ33ElJqsi0MdNte3S+bQY819f7p3NUHgwQQLXSKjE4cPZTeGNI+vaxZynk1wVU3hoHmow3m089wA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>\n",
"\n",
" <script>\n",
" const getTargetProfile = () => { return {"columns": {"c": {"histogram": null, "frequentItems": [{"value": "123", "estimate": 1251675}, {"value": "Short one", "estimate": 1251395}, {"value": "This is a very long string", "estimate": 1250270}, {"value": "345", "estimate": 1246660}], "drift_from_ref": null, "isDiscrete": true, "featureStats": {"total_count": 5000000, "missing": 0, "distinct": 8.000000059604647e-05, "min": NaN, "max": NaN, "range": NaN, "quantile_statistics": null, "descriptive_statistics": {"stddev": 0.0, "coefficient_of_variation": null, "sum": 0, "variance": 0.0, "mean": 0}}}, "b": {"histogram": {"start": 7.414007036077308e-07, "end": 1.000000046668008, "width": 0, "counts": [168768, 163840, 163840, 166912, 167936, 167936, 164864, 167936, 167936, 163840, 166912, 166912, 164864, 168960, 168960, 166912, 164864, 167936, 166912, 164864, 164864, 168960, 164864, 167936, 166912, 166912, 165888, 167936, 166912, 166912], "max": 0.9999999466680132, "min": 7.414007036077308e-07, "bins": [7.414007036077308e-07, 0.033334051576280416, 0.06666736175185722, 0.10000067192743403, 0.13333398210301084, 0.16666729227858765, 0.20000060245416446, 0.23333391262974126, 0.26666722280531807, 0.3000005329808949, 0.3333338431564717, 0.36666715333204847, 0.4000004635076253, 0.43333377368320214, 0.4666670838587789, 0.5000003940343557, 0.5333337042099325, 0.5666670143855094, 0.6000003245610862, 0.6333336347366629, 0.6666669449122398, 0.7000002550878166, 0.7333335652633933, 0.7666668754389702, 0.800000185614547, 0.8333334957901238, 0.8666668059657007, 0.9000001161412774, 0.9333334263168542, 0.9666667364924311, 1.0000000466680077], "n": 5000000}, "frequentItems": null, "drift_from_ref": null, "isDiscrete": false, "featureStats": {"total_count": 5000000, "missing": 0, "distinct": 20.217218558952247, "min": 7.414007036077308e-07, "max": 0.9999999466680132, "range": 0.9999992052673096, "quantile_statistics": {"fifth_percentile": 0.0502584621297707, "iqr": 0.5001548774867743, "q1": 0.25065417768277176, "median": 0.5001518463071901, "q3": 0.7508090551695461, "ninety_fifth_percentile": 0.9507353929096598}, "descriptive_statistics": {"stddev": 0.28869003587451164, "coefficient_of_variation": 0.5770905248799041, "sum": 2501254.3390362347, "variance": 0.08334193681322682, "mean": 0.5002508678072469}}}, "a": {"histogram": {"start": 5.063938359750608e-07, "end": 1.0000000799625974, "width": 0, "counts": [166720, 165888, 167936, 166912, 166912, 164864, 168960, 165888, 165888, 165888, 164864, 168960, 163840, 166912, 165888, 167936, 166912, 166912, 167936, 166912, 165888, 166912, 168960, 168960, 163840, 166912, 165888, 171008, 163840, 164864], "max": 0.9999999799625994, "min": 5.063938359750608e-07, "bins": [5.063938359750608e-07, 0.03333382551279469, 0.06666714463175341, 0.10000046375071213, 0.13333378286967085, 0.16666710198862955, 0.20000042110758828, 0.23333374022654702, 0.2666670593455057, 0.3000003784644644, 0.3333336975834231, 0.3666670167023819, 0.4000003358213406, 0.4333336549402993, 0.46666697405925806, 0.5000002931782168, 0.5333336122971755, 0.5666669314161342, 0.6000002505350929, 0.6333335696540516, 0.6666668887730103, 0.700000207891969, 0.7333335270109278, 0.7666668461298864, 0.8000001652488452, 0.833333484367804, 0.8666668034867626, 0.9000001226057214, 0.9333334417246801, 0.9666667608436388, 1.0000000799625974], "n": 5000000}, "frequentItems": null, "drift_from_ref": null, "isDiscrete": false, "featureStats": {"total_count": 5000000, "missing": 0, "distinct": 19.45193948017024, "min": 5.063938359750608e-07, "max": 0.9999999799625994, "range": 0.9999994735687634, "quantile_statistics": {"fifth_percentile": 0.0501805682421963, "iqr": 0.5001355010780355, "q1": 0.25014118037227795, "median": 0.5013827253414714, "q3": 0.7502766814503135, "ninety_fifth_percentile": 0.9500272156390741}, "descriptive_statistics": {"stddev": 0.28865174898169144, "coefficient_of_variation": 0.5770437708744107, "sum": 2501125.24864699, "variance": 0.08331983219018942, "mean": 0.500225049729398}}}, "d": {"histogram": {"start": 1.9049971800022547e-07, "end": 1.0000000223239445, "width": 0, "counts": [164672, 168960, 164864, 166912, 166912, 167936, 166912, 164864, 166912, 162816, 168960, 166912, 167936, 166912, 165888, 166912, 166912, 167936, 163840, 168960, 165888, 166912, 166912, 163840, 168960, 165888, 168960, 168960, 161792, 168960], "max": 0.9999999223239522, "min": 1.9049971800022547e-07, "bins": [1.9049971800022547e-07, 0.033333518227192216, 0.06666684595466643, 0.10000017368214065, 0.13333350140961486, 0.16666682913708908, 0.2000001568645633, 0.2333334845920375, 0.2666668123195117, 0.30000014004698594, 0.33333346777446016, 0.3666667955019344, 0.4000001232294086, 0.4333334509568828, 0.466666778684357, 0.5000001064118312, 0.5333334341393055, 0.5666667618667797, 0.6000000895942539, 0.6333334173217281, 0.6666667450492023, 0.7000000727766765, 0.7333334005041507, 0.766666728231625, 0.8000000559590992, 0.8333333836865734, 0.8666667114140476, 0.9000000391415218, 0.933333366868996, 0.9666666945964703, 1.0000000223239445], "n": 5000000}, "frequentItems": null, "drift_from_ref": null, "isDiscrete": false, "featureStats": {"total_count": 5000000, "missing": 0, "distinct": 19.803930018610956, "min": 1.9049971800022547e-07, "max": 0.9999999223239522, "range": 0.9999997318242342, "quantile_statistics": {"fifth_percentile": 0.05041648293378931, "iqr": 0.5003680806909643, "q1": 0.25055342136166703, "median": 0.5002699005106862, "q3": 0.7509215020526313, "ninety_fifth_percentile": 0.9505069112957704}, "descriptive_statistics": {"stddev": 0.28868787751190866, "coefficient_of_variation": 0.5771613654002292, "sum": 2500928.638143682, "variance": 0.08334069062233077, "mean": 0.5001857276287364}}}}, "properties": {"observations": 20000000, "missing_cells": 0, "missing_percentage": 0.0}} }\n",
" const targetProfile = getTargetProfile()\n",
"\n",
" function fixNumberTo(number, decimals = 3) {\n",
" const fractionalDigits = String(number % 1).split('').slice(2, 2 + decimals).join('')\n",
" return `${Math.trunc(number)}.${fractionalDigits}`\n",
" }\n",
"\n",
" function registerHandlebarHelperFunctions() {\n",
" //helper fun\n",
"\n",
" class GenerateChartParams {\n",
" constructor(height, width, data, bottomMargin=20, topMargin=5) {\n",
" this.MARGIN = {\n",
" TOP: topMargin,\n",
" RIGHT: 5,\n",
" BOTTOM: bottomMargin,\n",
" LEFT: 55,\n",
" };\n",
" this.SVG_WIDTH = width;\n",
" this.SVG_HEIGHT = height;\n",
" this.CHART_WIDTH = this.SVG_WIDTH - this.MARGIN.LEFT - this.MARGIN.RIGHT;\n",
" this.CHART_HEIGHT = this.SVG_HEIGHT - this.MARGIN.TOP - this.MARGIN.BOTTOM;\n",
" this.svgEl = d3.create("svg")\n",
" .attr("preserveAspectRatio", "xMinYMin meet")\n",
" .attr("viewBox", "30 0 240 400")\n",
" .classed("svg-content-responsive", true)\n",
" this.maxYValue = d3.max(data, (d) => Math.abs(d.axisY));\n",
" this.xScale = d3\n",
" .scaleBand()\n",
" .domain(data.map((d) => d.axisX))\n",
" .range([this.MARGIN.LEFT, this.MARGIN.LEFT + this.CHART_WIDTH]);\n",
" this.yScale = d3\n",
" .scaleLinear()\n",
" .domain([0, this.maxYValue * 1.02])\n",
" .range([this.CHART_HEIGHT, 0]);\n",
" }\n",
" }\n",
"\n",
" function generateChart(data, height = 70, width = 250, index = 0, referenceProfileExist = false) {\n",
" const sizes = new GenerateChartParams(height, width, data, 5)\n",
" const {\n",
" MARGIN,\n",
" SVG_WIDTH,\n",
" SVG_HEIGHT,\n",
" CHART_WIDTH,\n",
" CHART_HEIGHT,\n",
" svgEl,\n",
" maxYValue,\n",
" xScale,\n",
" yScale\n",
" } = sizes\n",
" const rectColors = ["#44C0E7", "#F5843C"]\n",
"\n",
" // Add the y Axis\n",
" if (!referenceProfileExist) {\n",
" svgEl\n",
" .append("g")\n",
" .attr("transform", "translate(" + MARGIN.LEFT + ", " + MARGIN.TOP + ")")\n",
" .call(d3.axisLeft(yScale).tickValues([0, maxYValue/2, maxYValue]))\n",
" .selectAll("text")\n",
" .style("font-size", "8")\n",
" }\n",
"\n",
" const gChart = svgEl.append("g");\n",
" gChart\n",
" .attr("transform", "translate(" + 20 + ", " + 0 + ")")\n",
" .selectAll(".bar")\n",
" .data(data)\n",
" .enter()\n",
" .append("rect")\n",
" .classed("bar", true)\n",
" .attr("width", xScale.bandwidth() - 1)\n",
" .attr("height", (d) => CHART_HEIGHT - yScale(d.axisY))\n",
" .attr("x", (d) => xScale(d.axisX))\n",
" .attr("y", (d) => yScale(d.axisY) + MARGIN.TOP)\n",
" .attr("fill", rectColors[index]);\n",
"\n",
" return svgEl._groups[0][0].outerHTML;\n",
" }\n",
"\n",
" function chartData(column) {\n",
" const data = [];\n",
" if (column.histogram) {\n",
" column.histogram.counts.slice(0, 30).forEach((count, index) => {\n",
" data.push({\n",
" axisY: count,\n",
" axisX: index,\n",
" });\n",
" });\n",
" } else if (column.frequentItems) {\n",
" Object.entries(column.frequentItems).forEach(([key, {value, estimate}], index) => {\n",
" data.push({\n",
" axisY: estimate,\n",
" axisX: value,\n",
" });\n",
" });\n",
" }\n",
"\n",
" return data\n",
" }\n",
"\n",
" function graph(column, key, referenceColumn) {\n",
" let data = [];\n",
" const columnKey = key.data.key\n",
" let chartValue = false\n",
" let chartColor = undefined\n",
" if(!!referenceColumn){\n",
" column = referenceColumn.columns[columnKey]\n",
" chartValue = true\n",
" chartColor = 1\n",
" } else if (referenceColumn === undefined) {\n",
" column = ""\n",
" }\n",
"\n",
" if (column.histogram || column.frequentItems) {\n",
" data = chartData(column)\n",
" } else if (referenceColumn === null ) {\n",
" $(".svg-container").css("padding-bottom", "0")\n",
" return '<span class="wl-table-cell__bedge-wrap">No data to show the chart</span>';\n",
" } else if (referenceColumn === undefined) {\n",
" $(document).ready(function() {\n",
" $(".reference-table-head").addClass("d-none")\n",
" });\n",
" return ''\n",
" } else if (referenceColumn.frequentItems === undefined){\n",
" return '';\n",
" }\n",
" return `\n",
" <div class="svg-container">\n",
" ${generateChart(data, ...[,,], chartColor, chartValue)}\n",
" </div>\n",
" `;\n",
" }\n",
"\n",
" function formatLabelDate(timestamp) {\n",
" const date = new Date(timestamp);\n",
" const format = d3.timeFormat("%Y-%m-%d %I:%M:%S %p %Z");\n",
" return format(date);\n",
" }\n",
"\n",
" abbreviate_number = function(value, fixed = 0) {\n",
" value = +value\n",
" if (value === null) { return null; } // terminate early\n",
" if (value === 0) { return '0'; } // terminate early\n",
" fixed = (!fixed || fixed < 0) ? 0 : fixed; // number of decimal places to show\n",
" var b = (value).toPrecision(2).split("e"), // get power\n",
" k = b.length === 1 ? 0 : Math.floor(Math.min(b[1].slice(1), 14) / 3), // floor at decimals, ceiling at trillions\n",
" c = k < 1 ? value.toFixed(0 + fixed) : (value / Math.pow(10, k * 3) ).toFixed(1 + fixed), // divide by power\n",
" d = c < 0 ? c : Math.abs(c), // enforce -0 is 0\n",
" newValue = d,\n",
" suffixe = ['', 'K', 'M', 'B', 'T'][k]; // append power\n",
" return {value, newValue, suffixe};\n",
" }\n",
"\n",
" function formatBytes(bytes, decimals = 2) {\n",
" let newValue,\n",
" suffixe = ""\n",
" if (bytes === 0) return '0 Bytes';\n",
"\n",
" const k = 1024;\n",
" const dm = decimals < 0 ? 0 : decimals;\n",
" const sizes = ['Bytes', 'KiB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n",
"\n",
" const i = Math.floor(Math.log(bytes) / Math.log(k));\n",
" newValue = parseFloat((bytes / Math.pow(k, i)).toFixed(dm));\n",
" suffixe = sizes[i]\n",
" return {bytes, newValue, suffixe};\n",
" }\n",
"\n",
" const valueSuffixe = (newNumber) => `\n",
" <div class="statistic-measurement">\n",
" ${newNumber}\n",
" </div>`\n",
" const valueNumber = (newNumber) => `\n",
" <div class="statistic-number">\n",
" ${newNumber}\n",
" </div>`\n",
"\n",
" const numberWithSuffixe = (number, newNumber, suffixe) =>\n",
" `<div class="tooltip-full-number">\n",
" <div class="statistic-number">\n",
" ${newNumber}\n",
" <div class="statistic-measurement">${suffixe}</div>\n",
" </div>\n",
" <span class="tooltiptext">${number}</span>\n",
" </div>`\n",
"\n",
" Handlebars.registerHelper("observations", function (properties) {\n",
" const {value, newValue, suffixe} = abbreviate_number(targetProfile.properties.observations)\n",
" return numberWithSuffixe(value, valueNumber(newValue), valueNumber(suffixe));\n",
" });\n",
"\n",
" Handlebars.registerHelper("missingCells", function (properties) {\n",
" const {value, newValue, suffixe} = abbreviate_number(targetProfile.properties.missing_cells)\n",
" if (typeof value !== 'undefined' && typeof newValue !== 'undefined' && typeof suffixe !== 'undefined' ) {\n",
" return numberWithSuffixe(value, valueSuffixe(`${newValue}`), suffixe);\n",
" }\n",
" return numberWithSuffixe(0, valueNumber(0), valueNumber(''));\n",
" });\n",
"\n",
" Handlebars.registerHelper("missingCellsPercentage", function (properties) {\n",
" const {value, newValue, suffixe} = abbreviate_number(targetProfile.properties.missing_percentage)\n",
" if (typeof value !== 'undefined' && typeof newValue !== 'undefined' && typeof suffixe !== 'undefined' ) {\n",
" return numberWithSuffixe(value, valueSuffixe(`(${newValue}%)`), suffixe);\n",
" }\n",
" return numberWithSuffixe(0, valueSuffixe(`(${0}%)`), '');\n",
" });\n",
"\n",
" Handlebars.registerHelper("getProfileTimeStamp", function (properties) {\n",
" return formatLabelDate(+properties.properties.dataTimestamp)\n",
" });\n",
"\n",
" Handlebars.registerHelper("getProfileName", function (properties) {\n",
" return properties.properties.tags.name\n",
" });\n",
"\n",
" const cheqValueTypeNumber = (profile, profileValue) => {\n",
" let validValue;\n",
" if (profile && profileValue !== undefined && typeof profileValue === "number") {\n",
" return true\n",
" } else if (profileValue !== undefined && typeof profileValue !== "number") {\n",
" return false\n",
" }\n",
" }\n",
"\n",
"\n",
" Handlebars.registerHelper("inferredType", function (column) {\n",
" let infferedType = "";\n",
"\n",
" if (column.isDiscrete) {\n",
" infferedType = "Discrete";\n",
" } else {\n",
" infferedType = "Non-discrete";\n",
" }\n",
" return infferedType;\n",
" });\n",
"\n",
" Handlebars.registerHelper("frequentItems", function (column) {\n",
" frequentItemsElemString = "";\n",
" if (column.isDiscrete) {\n",
" const slicedFrequentItems = column.frequentItems.items.slice(0, 5);\n",
" for (let fi = 0; fi < slicedFrequentItems.length; fi++) {\n",
" frequentItemsElemString +=\n",
" '<span class="wl-table-cell__bedge">' + slicedFrequentItems[fi].jsonValue + "</span>";\n",
" }\n",
" } else {\n",
" frequentItemsElemString += "No data to show";\n",
" }\n",
" return frequentItemsElemString;\n",
" });\n",
"\n",
" Handlebars.registerHelper("totalCount", function (column) {\n",
" if (column.featureStats) {\n",
" return column.featureStats.total_count;\n",
" }\n",
"\n",
" return "-";\n",
" });\n",
"\n",
" Handlebars.registerHelper("missing", function (column) {\n",
" if (column.featureStats) {\n",
" return column.featureStats.missing;\n",
" }\n",
"\n",
" return "-";\n",
" });\n",
"\n",
" Handlebars.registerHelper("minimumValue", function (column) {\n",
" if (column.featureStats) {\n",
" if (isNaN(column.featureStats.min)){return "-"}\n",
" return fixNumberTo(column.featureStats.min);\n",
" }\n",
"\n",
" return "-";\n",
" });\n",
"\n",
" Handlebars.registerHelper("maximumValue", function (column) {\n",
" if (column.featureStats) {\n",
" if (isNaN(column.featureStats.max)){return "-"}\n",
" return fixNumberTo(column.featureStats.max);\n",
" }\n",
"\n",
" return "-";\n",
" });\n",
"\n",
"\n",
" Handlebars.registerHelper("mean", function (column) {\n",
" if (column.featureStats?.descriptive_statistics) {\n",
" if (isNaN(column.featureStats.descriptive_statistics.mean)){return "-"}\n",
" return fixNumberTo(column.featureStats.descriptive_statistics.mean);\n",
" }\n",
" return "-";\n",
" });\n",
"\n",
" Handlebars.registerHelper("getGraphHtml",(column,key) => graph(column, key, null));\n",
"\n",
" Handlebars.registerHelper("getDiscreteTypeCount", function () {\n",
" let count = 0;\n",
"\n",
" Object.entries(this.columns).forEach((feature) => {\n",
" if (feature[1].isDiscrete === true) {\n",
" count++;\n",
" }\n",
" });\n",
" return count.toString();\n",
" });\n",
"\n",
" Handlebars.registerHelper("getNonDiscreteTypeCount", function () {\n",
" let count = 0;\n",
"\n",
" Object.entries(this.columns).forEach((feature) => {\n",
" if (feature[1].isDiscrete === false) {\n",
" count++;\n",
" }\n",
" });\n",
" return count;\n",
" });\n",
"\n",
" Handlebars.registerHelper("getUnknownTypeCount", function () {\n",
" let count = 0;\n",
" return count;\n",
" Object.entries(this.columns).forEach((feature) => {\n",
" if (!feature[1].isDiscrete) {\n",
" count++;\n",
" }\n",
" });\n",
" return count;\n",
" });\n",
" }\n",
"\n",
" function initHandlebarsTemplate() {\n",
" // Replace this context with JSON from .py file\n",
" const context = {"columns": {"c": {"histogram": null, "frequentItems": [{"value": "123", "estimate": 1251675}, {"value": "Short one", "estimate": 1251395}, {"value": "This is a very long string", "estimate": 1250270}, {"value": "345", "estimate": 1246660}], "drift_from_ref": null, "isDiscrete": true, "featureStats": {"total_count": 5000000, "missing": 0, "distinct": 8.000000059604647e-05, "min": NaN, "max": NaN, "range": NaN, "quantile_statistics": null, "descriptive_statistics": {"stddev": 0.0, "coefficient_of_variation": null, "sum": 0, "variance": 0.0, "mean": 0}}}, "b": {"histogram": {"start": 7.414007036077308e-07, "end": 1.000000046668008, "width": 0, "counts": [168768, 163840, 163840, 166912, 167936, 167936, 164864, 167936, 167936, 163840, 166912, 166912, 164864, 168960, 168960, 166912, 164864, 167936, 166912, 164864, 164864, 168960, 164864, 167936, 166912, 166912, 165888, 167936, 166912, 166912], "max": 0.9999999466680132, "min": 7.414007036077308e-07, "bins": [7.414007036077308e-07, 0.033334051576280416, 0.06666736175185722, 0.10000067192743403, 0.13333398210301084, 0.16666729227858765, 0.20000060245416446, 0.23333391262974126, 0.26666722280531807, 0.3000005329808949, 0.3333338431564717, 0.36666715333204847, 0.4000004635076253, 0.43333377368320214, 0.4666670838587789, 0.5000003940343557, 0.5333337042099325, 0.5666670143855094, 0.6000003245610862, 0.6333336347366629, 0.6666669449122398, 0.7000002550878166, 0.7333335652633933, 0.7666668754389702, 0.800000185614547, 0.8333334957901238, 0.8666668059657007, 0.9000001161412774, 0.9333334263168542, 0.9666667364924311, 1.0000000466680077], "n": 5000000}, "frequentItems": null, "drift_from_ref": null, "isDiscrete": false, "featureStats": {"total_count": 5000000, "missing": 0, "distinct": 20.217218558952247, "min": 7.414007036077308e-07, "max": 0.9999999466680132, "range": 0.9999992052673096, "quantile_statistics": {"fifth_percentile": 0.0502584621297707, "iqr": 0.5001548774867743, "q1": 0.25065417768277176, "median": 0.5001518463071901, "q3": 0.7508090551695461, "ninety_fifth_percentile": 0.9507353929096598}, "descriptive_statistics": {"stddev": 0.28869003587451164, "coefficient_of_variation": 0.5770905248799041, "sum": 2501254.3390362347, "variance": 0.08334193681322682, "mean": 0.5002508678072469}}}, "a": {"histogram": {"start": 5.063938359750608e-07, "end": 1.0000000799625974, "width": 0, "counts": [166720, 165888, 167936, 166912, 166912, 164864, 168960, 165888, 165888, 165888, 164864, 168960, 163840, 166912, 165888, 167936, 166912, 166912, 167936, 166912, 165888, 166912, 168960, 168960, 163840, 166912, 165888, 171008, 163840, 164864], "max": 0.9999999799625994, "min": 5.063938359750608e-07, "bins": [5.063938359750608e-07, 0.03333382551279469, 0.06666714463175341, 0.10000046375071213, 0.13333378286967085, 0.16666710198862955, 0.20000042110758828, 0.23333374022654702, 0.2666670593455057, 0.3000003784644644, 0.3333336975834231, 0.3666670167023819, 0.4000003358213406, 0.4333336549402993, 0.46666697405925806, 0.5000002931782168, 0.5333336122971755, 0.5666669314161342, 0.6000002505350929, 0.6333335696540516, 0.6666668887730103, 0.700000207891969, 0.7333335270109278, 0.7666668461298864, 0.8000001652488452, 0.833333484367804, 0.8666668034867626, 0.9000001226057214, 0.9333334417246801, 0.9666667608436388, 1.0000000799625974], "n": 5000000}, "frequentItems": null, "drift_from_ref": null, "isDiscrete": false, "featureStats": {"total_count": 5000000, "missing": 0, "distinct": 19.45193948017024, "min": 5.063938359750608e-07, "max": 0.9999999799625994, "range": 0.9999994735687634, "quantile_statistics": {"fifth_percentile": 0.0501805682421963, "iqr": 0.5001355010780355, "q1": 0.25014118037227795, "median": 0.5013827253414714, "q3": 0.7502766814503135, "ninety_fifth_percentile": 0.9500272156390741}, "descriptive_statistics": {"stddev": 0.28865174898169144, "coefficient_of_variation": 0.5770437708744107, "sum": 2501125.24864699, "variance": 0.08331983219018942, "mean": 0.500225049729398}}}, "d": {"histogram": {"start": 1.9049971800022547e-07, "end": 1.0000000223239445, "width": 0, "counts": [164672, 168960, 164864, 166912, 166912, 167936, 166912, 164864, 166912, 162816, 168960, 166912, 167936, 166912, 165888, 166912, 166912, 167936, 163840, 168960, 165888, 166912, 166912, 163840, 168960, 165888, 168960, 168960, 161792, 168960], "max": 0.9999999223239522, "min": 1.9049971800022547e-07, "bins": [1.9049971800022547e-07, 0.033333518227192216, 0.06666684595466643, 0.10000017368214065, 0.13333350140961486, 0.16666682913708908, 0.2000001568645633, 0.2333334845920375, 0.2666668123195117, 0.30000014004698594, 0.33333346777446016, 0.3666667955019344, 0.4000001232294086, 0.4333334509568828, 0.466666778684357, 0.5000001064118312, 0.5333334341393055, 0.5666667618667797, 0.6000000895942539, 0.6333334173217281, 0.6666667450492023, 0.7000000727766765, 0.7333334005041507, 0.766666728231625, 0.8000000559590992, 0.8333333836865734, 0.8666667114140476, 0.9000000391415218, 0.933333366868996, 0.9666666945964703, 1.0000000223239445], "n": 5000000}, "frequentItems": null, "drift_from_ref": null, "isDiscrete": false, "featureStats": {"total_count": 5000000, "missing": 0, "distinct": 19.803930018610956, "min": 1.9049971800022547e-07, "max": 0.9999999223239522, "range": 0.9999997318242342, "quantile_statistics": {"fifth_percentile": 0.05041648293378931, "iqr": 0.5003680806909643, "q1": 0.25055342136166703, "median": 0.5002699005106862, "q3": 0.7509215020526313, "ninety_fifth_percentile": 0.9505069112957704}, "descriptive_statistics": {"stddev": 0.28868787751190866, "coefficient_of_variation": 0.5771613654002292, "sum": 2500928.638143682, "variance": 0.08334069062233077, "mean": 0.5001857276287364}}}}, "properties": {"observations": 20000000, "missing_cells": 0, "missing_percentage": 0.0}};\n",
" // Config handlebars and pass data to HBS template\n",
" const source = document.getElementById("entry-template").innerHTML;\n",
" const template = Handlebars.compile(source);\n",
" const html = template(context);\n",
" const target = document.getElementById("generated-html");\n",
" target.innerHTML = html;\n",
" }\n",
"\n",
" function initWebsiteScripts() {\n",
" const $featureSearch = document.getElementById("wl__feature-search");\n",
" const $tableBody = document.getElementById("table-body");\n",
" const $discrete = document.getElementById("inferredDiscrete");\n",
" const $nonDiscrete = document.getElementById("inferredNonDiscrete");\n",
" const $unknown = document.getElementById("inferredUnknown");\n",
"\n",
" const activeTypes = {\n",
" discrete: true,\n",
" "non-discrete": true,\n",
" unknown: true,\n",
" };\n",
"\n",
" let searchString = "";\n",
"\n",
" function debounce(func, wait, immediate) {\n",
" let timeout;\n",
"\n",
" return function () {\n",
" const context = this;\n",
" const args = arguments;\n",
" const later = function () {\n",
" timeout = null;\n",
" if (!immediate) func.apply(context, args);\n",
" };\n",
"\n",
" const callNow = immediate && !timeout;\n",
" clearTimeout(timeout);\n",
" timeout = setTimeout(later, wait);\n",
" if (callNow) func.apply(context, args);\n",
" };\n",
" }\n",
"\n",
" function filterNotification() {\n",
" const $notifCircleContainer = $(".notif-circle-container")\n",
" const $boxes = $('.wl_filter-options>.form-check>input[name=checkbox]:checked');\n",
" const item = Object.values($boxes).find(function(value) { return $(value)[0] === undefined});\n",
" if (item === undefined) {\n",
" $notifCircleContainer.removeClass("d-none")\n",
" } else {\n",
" $notifCircleContainer.addClass("d-none")\n",
" }\n",
" }\n",
"\n",
" function handleSearch() {\n",
" const tableBodyChildren = $tableBody.children;\n",
"\n",
" for (let i = 0; i < tableBodyChildren.length; i++) {\n",
" const type = tableBodyChildren[i].dataset.inferredType.toLowerCase();\n",
" const name = tableBodyChildren[i].dataset.featureName.toLowerCase();\n",
"\n",
" if (activeTypes[type] && name.startsWith(searchString)) {\n",
" tableBodyChildren[i].style.display = "";\n",
" } else {\n",
" tableBodyChildren[i].style.display = "none";\n",
" }\n",
" }\n",
" }\n",
"\n",
" $featureSearch.addEventListener(\n",
" "keyup",\n",
" debounce((event) => {\n",
" searchString = event.target.value.toLowerCase();\n",
" handleSearch();\n",
" }, 100),\n",
" );\n",
"\n",
" $discrete.addEventListener("change", (event) => {\n",
" if (event.currentTarget.checked) {\n",
" activeTypes["discrete"] = true;\n",
" } else {\n",
" activeTypes["discrete"] = false;\n",
" }\n",
" handleSearch();\n",
" filterNotification()\n",
" });\n",
"\n",
" $nonDiscrete.addEventListener("change", (event) => {\n",
" if (event.currentTarget.checked) {\n",
" activeTypes["non-discrete"] = true;\n",
" } else {\n",
" activeTypes["non-discrete"] = false;\n",
" }\n",
" handleSearch();\n",
" filterNotification()\n",
" });\n",
"\n",
" $unknown.addEventListener("change", (event) => {\n",
" if (event.currentTarget.checked) {\n",
" activeTypes["unknown"] = true;\n",
" } else {\n",
" activeTypes["unknown"] = false;\n",
" }\n",
" handleSearch();\n",
" filterNotification()\n",
" });\n",
"\n",
"\n",
" $(".svg-container").css("padding-bottom", "27%")\n",
" }\n",
"\n",
" function checkedBoxes() {\n",
" const $boxes = $('input[name=checkbox]:checked');\n",
" const $notifCircleContainer = $(".notif-circle-container")\n",
"\n",
" if ($boxes.length) {\n",
" $notifCircleContainer.removeClass("d-none")\n",
" }\n",
" }\n",
"\n",
" function openFilter() {\n",
" const $filterOptions = $(".dropdown-container");\n",
" const $notifCircleContainer = $(".notif-circle-container")\n",
" const filterClass = $filterOptions.attr("class");\n",
"\n",
" if (filterClass.indexOf("d-none") > 0) {\n",
" $notifCircleContainer.addClass("d-none")\n",
" $filterOptions.removeClass("d-none");\n",
" $(".filter-icon").addClass("d-none")\n",
" $(".close-filter-icon").removeClass("d-none")\n",
" } else {\n",
" $filterOptions.addClass("d-none");\n",
" $(".close-filter-icon").addClass("d-none")\n",
" $(".filter-icon").removeClass("d-none")\n",
" checkedBoxes()\n",
" }\n",
" }\n",
"\n",
" // Invoke functions -- keep in mind invokation order\n",
" registerHandlebarHelperFunctions();\n",
" initHandlebarsTemplate();\n",
" initWebsiteScripts();\n",
" </script>\n",
"</html>\n",
"\" width=100% height=1000px\n",
" frameBorder=0></iframe>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from whylogs.viz import NotebookProfileVisualizer\n",
"\n",
"visualization = NotebookProfileVisualizer()\n",
"visualization.set_profiles(target_profile_view=merged_profile_view)\n",
"\n",
"visualization.profile_summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And that's it, you have successfully created a DatasetProfileView with whylogs in a distributed manner with Dask! 😄\n",
"If you wish to have other insights on how to use whylogs, feel free to check our [other existing examples](https://github.com/whylabs/whylogs/tree/mainline/python/examples), as they might be extremely useful. Happy coding!"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
},
"vscode": {
"interpreter": {
"hash": "5dd5901cadfd4b29c2aaf95ecd29c0c3b10829ad94dcfe59437dbee391154aea"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}