diff --git a/benchmark/README.md b/benchmark/README.md
new file mode 100644
index 0000000..d8a3bd2
--- /dev/null
+++ b/benchmark/README.md
@@ -0,0 +1,55 @@
+# Benchmarking DataTracer
+This directory contains code for benchmarking the performance of `DataTracer`
+on user-supplied datasets. The datasets for benchmarking can be found in the
+`s3://tracer-data` bucket.
+
+
+
+
+
+Each benchmark - `primary`, `foreign`, and `column` - can be executed by
+running the following command
+
+> datatracer-benchmark --csv /path/to/results.csv
+
+which will (optionally) generate a CSV file with the benchmark results.
+
+## Primary Key
+Primary key detection is evaluated by:
+
+ - Accuracy. The percent of tables where the primary key was correctly identified.
+ - Inference time. The amount of time to infer the primary key for all tables.
+
+We will use leave-one-out validation and report the test performance on each dataset
+in the S3 bucket.
+
+## Foreign Key
+Foreign key detection is evaluated by:
+
+ - F1.
+ - Recall.
+ - Precision.
+ - Inference time.
+
+Note that this assumes that the foreign key primitive returns a set of foreign keys;
+in other words, for models that return a score for each candidate foreign key, this
+assumes that thresholding is done.
+
+We will use leave-one-out validation and report the test performance on each dataset
+in the S3 bucket.
+
+## Column Map
+Column map detection is evaluated by:
+
+ - F1.
+ - Recall.
+ - Precision.
+ - Inference time.
+
+Note that this assumes that the column map primitive returns a set of columns that it
+thinks contributed to the target derived column. Since each dataset can have multiple
+derived columns, this will report a F1/recall/precision/time tuple for each derived
+column in the dataset.
+
+We will use leave-one-out validation and report the test performance on each dataset
+in the S3 bucket.
diff --git a/benchmark/benchmark.gif b/benchmark/benchmark.gif
new file mode 100644
index 0000000..578f0a9
Binary files /dev/null and b/benchmark/benchmark.gif differ
diff --git a/benchmark/benchmark.py b/benchmark/benchmark.py
new file mode 100644
index 0000000..2b869d9
--- /dev/null
+++ b/benchmark/benchmark.py
@@ -0,0 +1,345 @@
+import argparse
+import os
+from io import BytesIO
+from time import time
+from urllib.parse import urljoin
+from urllib.request import urlopen
+from zipfile import ZipFile
+
+import boto3
+import dask
+import pandas as pd
+from dask.diagnostics import ProgressBar
+
+from datatracer import DataTracer, load_datasets
+
+BUCKET_NAME = 'tracer-data'
+DATA_URL = 'http://{}.s3.amazonaws.com/'.format(BUCKET_NAME)
+
+
+def download(data_dir):
+ """Download benchmark datasets from S3.
+
+ This downloads the benchmark datasets from S3 into the target folder in an
+ uncompressed format. It skips datasets that have already been downloaded.
+
+ Args:
+ data_dir: The directory to download the datasets to.
+
+ Returns:
+ A DataFrame describing the downloaded datasets.
+
+ Raises:
+ NoCredentialsError: If AWS S3 credentials are not found.
+ """
+ rows = []
+ client = boto3.client('s3')
+ for dataset in client.list_objects(Bucket=BUCKET_NAME)['Contents']:
+ rows.append(dataset)
+ dataset_name = dataset['Key'].replace(".zip", "")
+ dataset_path = os.path.join(data_dir, dataset_name)
+ if os.path.exists(dataset_path):
+ dataset["Status"] = "Skipped"
+ print("Skipping %s" % dataset_name)
+ else:
+ dataset["Status"] = "Downloaded"
+ print("Downloading %s" % dataset_name)
+ with urlopen(urljoin(DATA_URL, dataset['Key'])) as fp:
+ with ZipFile(BytesIO(fp.read())) as zipfile:
+ zipfile.extractall(dataset_path)
+ return pd.DataFrame(rows)
+
+
+@dask.delayed
+def primary_key(solver, target, datasets):
+ """Benchmark the primary key solver on the target dataset.
+
+ Args:
+ solver: The name of the primary key pipeline.
+ target: The name of the target dataset.
+ datases: A dictionary mapping dataset names to (metadata, tables) tuples.
+
+ Returns:
+ A dictionary mapping metric names to values.
+ """
+ datasets = datasets.copy()
+ metadata, tables = datasets.pop(target)
+
+ tracer = DataTracer(solver)
+ tracer.fit(datasets)
+
+ y_true = {}
+ for table in metadata.get_tables():
+ if "primary_key" not in table:
+ continue # Skip tables without primary keys
+ if not isinstance(table["primary_key"], str):
+ continue # Skip tables with composite primary keys
+ y_true[table["name"]] = table["primary_key"]
+
+ if len(y_true) == 0:
+ return {} # Skip dataset, no primary keys found.
+
+ correct, total = 0, 0
+ start = time()
+ y_pred = tracer.solve(tables)
+ end = time()
+ for table_name, primary_key in y_true.items():
+ if y_pred.get(table_name) == primary_key:
+ correct += 1
+ total += 1
+ accuracy = correct / total
+
+ return {
+ "accuracy": accuracy,
+ "inference_time": end - start
+ }
+
+
+def benchmark_primary_key(data_dir, solver="datatracer.primary_key.basic"):
+ """Benchmark the primary key solver.
+
+ This uses leave-one-out validation and evaluates the performance of the
+ solver on the specified datasets.
+
+ Args:
+ data_dir: The directory containing the datasets.
+ solver: The name of the primary key pipeline.
+
+ Returns:
+ A DataFrame containing the benchmark resuls.
+ """
+ datasets = load_datasets(data_dir)
+ dataset_names = list(datasets.keys())
+ datasets = dask.delayed(datasets)
+ dataset_to_metrics = {}
+ for dataset_name in dataset_names:
+ dataset_to_metrics[dataset_name] = primary_key(
+ solver=solver, target=dataset_name, datasets=datasets)
+
+ with ProgressBar():
+ results = dask.compute(dataset_to_metrics)[0]
+ for dataset_name, metrics in results.items():
+ metrics["dataset"] = dataset_name
+ return pd.DataFrame(list(results.values()))
+
+
+@dask.delayed
+def foreign_key(solver, target, datasets):
+ """Benchmark the foreign key solver on the target dataset.
+
+ Args:
+ solver: The name of the foreign key pipeline.
+ target: The name of the target dataset.
+ datasets: A dictionary mapping dataset names to (metadata, tables) tuples.
+
+ Returns:
+ A dictionary mapping metric names to values.
+ """
+ datasets = datasets.copy()
+ metadata, tables = datasets.pop(target)
+
+ tracer = DataTracer(solver)
+ tracer.fit(datasets)
+
+ y_true = set()
+ for fk in metadata.get_foreign_keys():
+ if not isinstance(fk["field"], str):
+ continue # Skip composite foreign keys
+ y_true.add((fk["table"], fk["field"], fk["ref_table"], fk["ref_field"]))
+
+ start = time()
+ fk_pred = tracer.solve(tables)
+ end = time()
+
+ y_pred = set()
+ for fk in fk_pred:
+ y_pred.add((fk["table"], fk["field"], fk["ref_table"], fk["ref_field"]))
+
+ if len(y_pred) == 0 or len(y_true) == 0 or \
+ len(y_true.intersection(y_pred)) == 0:
+ return {
+ "precision": 0.0,
+ "recall": 0.0,
+ "f1": 0.0,
+ "inference_time": end - start
+ }
+
+ precision = len(y_true.intersection(y_pred)) / len(y_pred)
+ recall = len(y_true.intersection(y_pred)) / len(y_true)
+ f1 = 2.0 * precision * recall / (precision + recall)
+
+ return {
+ "precision": precision,
+ "recall": recall,
+ "f1": f1,
+ "inference_time": end - start
+ }
+
+
+def benchmark_foreign_key(data_dir, solver="datatracer.foreign_key.standard"):
+ """Benchmark the foreign key solver.
+
+ This uses leave-one-out validation and evaluates the performance of the
+ solver on the specified datasets.
+
+ Args:
+ data_dir: The directory containing the datasets.
+ solver: The name of the foreign key pipeline.
+
+ Returns:
+ A DataFrame containing the benchmark resuls.
+ """
+ datasets = load_datasets(data_dir)
+ dataset_names = list(datasets.keys())
+ datasets = dask.delayed(datasets)
+ dataset_to_metrics = {}
+ for dataset_name in dataset_names:
+ dataset_to_metrics[dataset_name] = foreign_key(
+ solver=solver, target=dataset_name, datasets=datasets)
+
+ with ProgressBar():
+ results = dask.compute(dataset_to_metrics)[0]
+ for dataset_name, metrics in results.items():
+ metrics["dataset"] = dataset_name
+ return pd.DataFrame(list(results.values()))
+
+
+@dask.delayed
+def column_map(solver, target, datasets):
+ """Benchmark the column map solver on the target dataset.
+
+ Args:
+ solver: The name of the column map pipeline.
+ target: The name of the target dataset.
+ datases: A dictionary mapping dataset names to (metadata, tables) tuples.
+
+ Returns:
+ A list of dictionaries mapping metric names to values for each deived column.
+ """
+ datasets = datasets.copy()
+ metadata, tables = datasets.pop(target)
+ if not metadata.data.get("constraints"):
+ return {} # Skip dataset, no constraints found.
+
+ tracer = DataTracer(solver)
+ tracer.fit(datasets)
+
+ list_of_metrics = []
+ for constraint in metadata.data["constraints"]:
+ field = constraint["fields_under_consideration"][0]
+ related_fields = constraint["related_fields"]
+
+ y_true = set()
+ for related_field in related_fields:
+ y_true.add((related_field["table"], related_field["field"]))
+
+ start = time()
+ y_pred = tracer.solve(tables, target_table=field["table"], target_field=field["field"])
+ y_pred = {field for field, score in y_pred.items() if score > 0.0}
+ end = time()
+
+ precision = len(y_true.intersection(y_pred)) / len(y_pred)
+ recall = len(y_true.intersection(y_pred)) / len(y_true)
+ f1 = 2.0 * precision * recall / (precision + recall)
+
+ list_of_metrics.append({
+ "table": field["table"],
+ "field": field["field"],
+ "precision": precision,
+ "recall": recall,
+ "f1": f1,
+ "inference_time": end - start
+ })
+
+ return list_of_metrics
+
+
+def benchmark_column_map(data_dir, solver="datatracer.column_map.basic"):
+ """Benchmark the column map solver.
+
+ This uses leave-one-out validation and evaluates the performance of the
+ solver on the specified datasets.
+
+ Args:
+ data_dir: The directory containing the datasets.
+ solver: The name of the column map pipeline.
+
+ Returns:
+ A DataFrame containing the benchmark resuls.
+ """
+ datasets = load_datasets(data_dir)
+ dataset_names = list(datasets.keys())
+ datasets = dask.delayed(datasets)
+ dataset_to_metrics = {}
+ for dataset_name in dataset_names:
+ dataset_to_metrics[dataset_name] = column_map(
+ solver=solver, target=dataset_name, datasets=datasets)
+
+ rows = []
+ with ProgressBar():
+ results = dask.compute(dataset_to_metrics)[0]
+ for dataset_name, list_of_metrics in results.items():
+ for metrics in list_of_metrics:
+ metrics["dataset"] = dataset_name
+ rows.append(metrics)
+ return pd.DataFrame(rows)
+
+
+def _get_parser():
+ shared_args = argparse.ArgumentParser(add_help=False)
+ shared_args.add_argument('--data_dir', type=str,
+ default=os.path.expanduser("~/tracer_data"), required=False,
+ help='Path to the benchmark datasets.')
+ shared_args.add_argument('--csv', type=str, required=False,
+ help='Path to the CSV file where the report will be written.')
+
+ parser = argparse.ArgumentParser(
+ prog='datatracer-benchmark',
+ description='DataTracer Benchmark CLI'
+ )
+
+ command = parser.add_subparsers(title='command', help='Command to execute')
+ parser.set_defaults(benchmark=None)
+
+ subparser = command.add_parser(
+ 'download',
+ parents=[shared_args],
+ help='Download datasets from S3.'
+ )
+ subparser.set_defaults(command=download)
+
+ subparser = command.add_parser(
+ 'primary',
+ parents=[shared_args],
+ help='Primary key benchmark.'
+ )
+ subparser.set_defaults(command=benchmark_primary_key)
+
+ subparser = command.add_parser(
+ 'foreign',
+ parents=[shared_args],
+ help='Foreign key benchmark.'
+ )
+ subparser.set_defaults(command=benchmark_foreign_key)
+
+ subparser = command.add_parser(
+ 'column',
+ parents=[shared_args],
+ help='Column map benchmark.'
+ )
+ subparser.set_defaults(command=benchmark_column_map)
+
+ return parser
+
+
+def main():
+ parser = _get_parser()
+ args = parser.parse_args()
+ df = args.command(args.data_dir)
+ if args.csv:
+ df.to_csv(args.csv, index=False)
+ print(df)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/datatracer/column_map/base.py b/datatracer/column_map/base.py
index 435bbf3..a257ce5 100644
--- a/datatracer/column_map/base.py
+++ b/datatracer/column_map/base.py
@@ -4,15 +4,15 @@
class ColumnMapSolver:
"""Base Solver for the data lineage problem of column dependency."""
- def fit(self, list_of_databases):
+ def fit(self, dict_of_databases):
"""Fit this solver.
Args:
- list_of_databases (list):
- List of tuples containing ``MetaData`` instnces and table dictinaries,
- which contain table names as input and ``pandas.DataFrames`` as values.
+ dict_of_databases (dict):
+ Map from database names to tuples containing ``MetaData``
+ instances and table dictionaries, which contain table names
+ as input and ``pandas.DataFrames`` as values.
"""
- pass
def solve(self, tables, foreign_keys, target_table, target_field):
"""Find the fields which contributed to the target_field the most.
diff --git a/datatracer/core.py b/datatracer/core.py
index 58c2f7b..fcc4104 100644
--- a/datatracer/core.py
+++ b/datatracer/core.py
@@ -52,15 +52,13 @@ def fit(self, datasets):
"""Fit the pipeline to the given data.
Args:
- datasets (list or dict):
- List or dict of tuples containing a MetaData instance and a dict
- with the tables of the dataset loaded as DataFrames.
+ datasets (dict):
+ Dict mapping dataset names to tuples containing a MetaData
+ instance and a dict with the tables of the dataset loaded
+ as DataFrames.
"""
- if isinstance(datasets, dict):
- datasets = list(datasets.values())
-
self._mlpipeline = self._get_mlpipeline()
- self._mlpipeline.fit(list_of_databases=datasets, tables={})
+ self._mlpipeline.fit(dict_of_databases=datasets, tables={})
def solve(self, tables, **kwargs):
"""Solve the data lineage problem.
diff --git a/datatracer/foreign_key/base.py b/datatracer/foreign_key/base.py
index d31a96e..82a336e 100644
--- a/datatracer/foreign_key/base.py
+++ b/datatracer/foreign_key/base.py
@@ -3,15 +3,15 @@
class ForeignKeySolver():
- def fit(self, list_of_databases):
+ def fit(self, dict_of_databases):
"""Fit this solver.
Args:
- list_of_databases (list):
- List of tuples containing ``MetaData`` instnces and table dictinaries,
- which contain table names as input and ``pandas.DataFrames`` as values.
+ dict_of_databases (dict):
+ Map from database names to tuples containing ``MetaData``
+ instances and table dictionaries, which contain table names
+ as input and ``pandas.DataFrames`` as values.
"""
- pass
def solve(self, tables, primary_keys=None):
"""Solve the foreign key detection problem.
diff --git a/datatracer/foreign_key/standard.py b/datatracer/foreign_key/standard.py
index 1210d59..adb5690 100644
--- a/datatracer/foreign_key/standard.py
+++ b/datatracer/foreign_key/standard.py
@@ -50,20 +50,24 @@ def _feature_vector(self, parent_col, child_col):
1.0 if child_col.dtype == "object" else 0.0,
]
- def fit(self, list_of_databases):
+ def fit(self, dict_of_databases):
"""Fit this solver.
Args:
- list_of_databases (list):
- List of tuples containing ``MetaData`` instnces and table dictinaries,
- which contain table names as input and ``pandas.DataFrames`` as values.
+ dict_of_databases (dict):
+ Map from database names to tuples containing ``MetaData``
+ instances and table dictionaries, which contain table names
+ as input and ``pandas.DataFrames`` as values.
"""
X, y = [], []
- for metadata, tables in tqdm(list_of_databases, "extracting features"):
- fks = set()
- for fk in metadata.get_foreign_keys():
- if isinstance(fk["field"], str):
- fks.add((fk["table"], fk["field"], fk["ref_table"], fk["ref_field"]))
+ iterator = tqdm(dict_of_databases.items())
+ for database_name, (metadata, tables) in iterator:
+ iterator.set_description("Extracting features from %s" % database_name)
+ fks = metadata.get_foreign_keys()
+ fks = set([
+ (fk["table"], fk["field"], fk["ref_table"], fk["ref_field"])
+ for fk in fks
+ ])
for t1, t2 in permutations(tables.keys(), r=2):
for c1 in tables[t1].columns:
diff --git a/datatracer/jsons/primitives/datatracer.foreign_key.StandardForeignKeySolver.json b/datatracer/jsons/primitives/datatracer.foreign_key.StandardForeignKeySolver.json
index 51d9518..87ae0a7 100644
--- a/datatracer/jsons/primitives/datatracer.foreign_key.StandardForeignKeySolver.json
+++ b/datatracer/jsons/primitives/datatracer.foreign_key.StandardForeignKeySolver.json
@@ -6,7 +6,7 @@
"method": "fit",
"args": [
{
- "name": "list_of_databases",
+ "name": "dict_of_databases",
"type": "list"
}
]
diff --git a/datatracer/jsons/primitives/datatracer.primary_key.BasicPrimaryKeySolver.json b/datatracer/jsons/primitives/datatracer.primary_key.BasicPrimaryKeySolver.json
index ff81725..c387f9f 100644
--- a/datatracer/jsons/primitives/datatracer.primary_key.BasicPrimaryKeySolver.json
+++ b/datatracer/jsons/primitives/datatracer.primary_key.BasicPrimaryKeySolver.json
@@ -6,7 +6,7 @@
"method": "fit",
"args": [
{
- "name": "list_of_databases",
+ "name": "dict_of_databases",
"type": "list"
}
]
diff --git a/datatracer/primary_key/base.py b/datatracer/primary_key/base.py
index f033f8f..df316d2 100644
--- a/datatracer/primary_key/base.py
+++ b/datatracer/primary_key/base.py
@@ -3,15 +3,15 @@
class PrimaryKeySolver():
- def fit(self, list_of_databases):
+ def fit(self, dict_of_databases):
"""Fit this solver.
Args:
- list_of_databases (list):
- List of tuples containing ``MetaData`` instnces and table dictinaries,
- which contain table names as input and ``pandas.DataFrames`` as values.
+ dict_of_databases (dict):
+ Map from database names to tuples containing ``MetaData``
+ instances and table dictionaries, which contain table names
+ as input and ``pandas.DataFrames`` as values.
"""
- pass
def solve(self, tables):
"""Solve the primary key detection problem.
diff --git a/datatracer/primary_key/basic.py b/datatracer/primary_key/basic.py
index ea46aaf..b0c657a 100644
--- a/datatracer/primary_key/basic.py
+++ b/datatracer/primary_key/basic.py
@@ -2,6 +2,7 @@
import numpy as np
from sklearn.ensemble import RandomForestClassifier
+from tqdm import tqdm
from datatracer.primary_key.base import PrimaryKeySolver
@@ -27,16 +28,19 @@ def _feature_vector(self, table, column_name):
1.0 if column.dtype == "object" else 0.0,
]
- def fit(self, list_of_databases):
+ def fit(self, dict_of_databases):
"""Fit this solver.
Args:
- list_of_databases (list):
- List of tuples containing ``MetaData`` instnces and table dictinaries,
- which contain table names as input and ``pandas.DataFrames`` as values.
+ dict_of_databases (dict):
+ Map from database names to tuples containing ``MetaData``
+ instances and table dictionaries, which contain table names
+ as input and ``pandas.DataFrames`` as values.
"""
X, y = [], []
- for metadata, tables in list_of_databases:
+ iterator = tqdm(dict_of_databases.items())
+ for database_name, (metadata, tables) in iterator:
+ iterator.set_description("Extracting features from %s" % database_name)
for table in metadata.get_tables():
if "primary_key" not in table:
continue
diff --git a/setup.py b/setup.py
index 691ae45..9385f01 100644
--- a/setup.py
+++ b/setup.py
@@ -12,6 +12,7 @@
history = history_file.read()
install_requires = [
+ 'boto3>=1.13,<2',
'pandas>=0.23.4,<0.25',
'scikit-learn>=0.20.0,<0.21',
'numpy<1.17,>=1.15.2',
@@ -20,7 +21,7 @@
'falcon>=2.0.0,<3',
'hug>=2.6.1,<3',
'pyyaml>=5.3.1,<6',
- 'tqdm>=4.46.1,<5',
+ 'tqdm>=4,<5',
]
setup_requires = [
@@ -62,6 +63,10 @@
# Advanced testing
'coverage>=4.5.1,<6',
'tox>=2.9.1,<4',
+
+ # benchmarking
+ 'dask>=2.15,<3',
+ 'distributed>=2.15,<3',
]
setup(
@@ -84,7 +89,8 @@
'pipelines=datatracer:MLBLOCKS_PIPELINES'
],
'console_scripts': [
- 'datatracer=datatracer.__main__:main'
+ 'datatracer=datatracer.__main__:main',
+ 'datatracer-benchmark=benchmark.benchmark:main'
],
},
extras_require={
@@ -100,11 +106,11 @@
keywords='datatracer data-tracer Data Tracer',
name='datatracer',
packages=find_packages(include=['datatracer', 'datatracer.*']),
- python_requires='>=3.5,<3.8',
+ python_requires='>=3.5',
setup_requires=setup_requires,
test_suite='tests',
tests_require=tests_require,
- url='https://github.com/HDI-Project/DataTracer',
+ url='https://github.com/data-dev/DataTracer',
version='0.0.6.dev0',
zip_safe=False,
)
diff --git a/tutorials/DataTracer Quickstart.ipynb b/tutorials/DataTracer Quickstart.ipynb
index 26a1840..fb5037f 100644
--- a/tutorials/DataTracer Quickstart.ipynb
+++ b/tutorials/DataTracer Quickstart.ipynb
@@ -33,7 +33,9 @@
{
"cell_type": "code",
"execution_count": 1,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [
{
"name": "stdout",
@@ -83,7 +85,7 @@
{
"data": {
"text/plain": [
- "dict_keys(['mutagenesis', 'Chess', 'classicmodels', 'university', 'Bupa', 'trains', 'SameGen', 'NBA', 'pubs'])"
+ "dict_keys(['posts', 'NBA', 'university', 'pubs', 'Chess', 'classicmodels', 'mutagenesis', 'Bupa', 'trains', 'SameGen'])"
]
},
"execution_count": 3,
@@ -395,15 +397,6 @@
"the dataset that we just explored, using the rest of the datasets as our training data."
]
},
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [],
- "source": [
- "training_datasets = list(datasets.values())"
- ]
- },
{
"cell_type": "markdown",
"metadata": {},
@@ -423,7 +416,7 @@
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": 10,
"metadata": {},
"outputs": [
{
@@ -435,7 +428,7 @@
" 'datatracer.primary_key.basic']"
]
},
- "execution_count": 11,
+ "execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
@@ -467,7 +460,7 @@
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
@@ -486,11 +479,19 @@
},
{
"cell_type": "code",
- "execution_count": 13,
+ "execution_count": 12,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Extracting features from SameGen: 100%|██████████| 9/9 [00:00<00:00, 145.54it/s]\n"
+ ]
+ }
+ ],
"source": [
- "dtr.fit(training_datasets)"
+ "dtr.fit(datasets)"
]
},
{
@@ -503,7 +504,7 @@
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
@@ -519,7 +520,7 @@
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": 14,
"metadata": {},
"outputs": [
{
@@ -535,7 +536,7 @@
" 'products': 'productCode'}"
]
},
- "execution_count": 15,
+ "execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
@@ -557,14 +558,14 @@
},
{
"cell_type": "code",
- "execution_count": 16,
+ "execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
- "extracting features: 100%|██████████| 8/8 [00:00<00:00, 19.07it/s]\n"
+ "Extracting features from SameGen: 100%|██████████| 9/9 [00:01<00:00, 8.46it/s] \n"
]
}
],
@@ -572,7 +573,7 @@
"from datatracer import DataTracer\n",
"\n",
"dtr = DataTracer('datatracer.foreign_key.standard')\n",
- "dtr.fit(training_datasets)\n",
+ "dtr.fit(datasets)\n",
"foreign_keys = dtr.solve(tables)"
]
},
@@ -586,7 +587,7 @@
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": 16,
"metadata": {},
"outputs": [
{
@@ -618,7 +619,7 @@
" 'ref_field': 'officeCode'}]"
]
},
- "execution_count": 17,
+ "execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
@@ -649,14 +650,14 @@
},
{
"cell_type": "code",
- "execution_count": 18,
+ "execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
- "extracting features: 100%|██████████| 8/8 [00:00<00:00, 18.00it/s]\n"
+ "Extracting features from SameGen: 100%|██████████| 9/9 [00:01<00:00, 8.10it/s] \n"
]
}
],
@@ -664,7 +665,7 @@
"from datatracer import DataTracer\n",
"\n",
"dtr = DataTracer('datatracer.column_map.basic')\n",
- "dtr.fit(training_datasets)\n",
+ "dtr.fit(datasets)\n",
"column_map = dtr.solve(\n",
" tables,\n",
" target_table='orderdetails',\n",
@@ -682,18 +683,18 @@
},
{
"cell_type": "code",
- "execution_count": 19,
+ "execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "{('orderdetails', 'orderNumber'): 0.3854540808399761,\n",
- " ('orderdetails', 'priceEach'): 0.43313416486749556,\n",
- " ('orderdetails', 'orderLineNumber'): 0.18141175429252837}"
+ "{('orderdetails', 'orderNumber'): 0.3831749750863929,\n",
+ " ('orderdetails', 'priceEach'): 0.4397562935716433,\n",
+ " ('orderdetails', 'orderLineNumber'): 0.1770687313419638}"
]
},
- "execution_count": 19,
+ "execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
@@ -719,7 +720,7 @@
},
{
"cell_type": "code",
- "execution_count": 20,
+ "execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
@@ -735,7 +736,7 @@
},
{
"cell_type": "code",
- "execution_count": 21,
+ "execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
@@ -748,19 +749,19 @@
},
{
"cell_type": "code",
- "execution_count": 22,
+ "execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "{('orderdetails', 'orderNumber'): 0.00022471076974350297,\n",
- " ('orderdetails', 'priceEach'): 0.00015177917546761553,\n",
- " ('orderdetails', 'orderLineNumber'): 0.00014925873321498974,\n",
- " ('orderdetails', 'quantityOrdered_x2'): 0.9994742513215739}"
+ "{('orderdetails', 'orderNumber'): 0.00019290156505023432,\n",
+ " ('orderdetails', 'priceEach'): 0.00014624354192835704,\n",
+ " ('orderdetails', 'orderLineNumber'): 9.105599151739842e-05,\n",
+ " ('orderdetails', 'quantityOrdered_x2'): 0.9995697989015039}"
]
},
- "execution_count": 22,
+ "execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
diff --git a/tutorials/Introducing DataTracer.ipynb b/tutorials/Introducing DataTracer.ipynb
index 9555b19..2598548 100644
--- a/tutorials/Introducing DataTracer.ipynb
+++ b/tutorials/Introducing DataTracer.ipynb
@@ -338,12 +338,12 @@
{
"data": {
"text/plain": [
- "{('users', 'id'): 0.0,\n",
- " ('users', 'birthyear'): 0.9999980097244106,\n",
- " ('users', 'height'): 5.180246597799326e-07,\n",
+ "{('users', 'id'): 5.046102180418218e-07,\n",
+ " ('users', 'birthyear'): 0.9999978458447893,\n",
+ " ('users', 'height'): 0.0,\n",
" ('users', 'nb_posts'): 0.0,\n",
- " ('posts', 'uid'): 6.40004263964262e-07,\n",
- " ('posts', 'id'): 2.8343526963126543e-07}"
+ " ('posts', 'uid'): 0.0,\n",
+ " ('posts', 'id'): 7.225373384175289e-07}"
]
},
"execution_count": 7,
@@ -383,8 +383,8 @@
" ('users', 'age'): 0.0,\n",
" ('users', 'birthyear'): 0.0,\n",
" ('users', 'height'): 0.0,\n",
- " ('posts', 'uid'): 0.4785790560832036,\n",
- " ('posts', 'id'): 0.5136442420361127}"
+ " ('posts', 'uid'): 0.5263822157542845,\n",
+ " ('posts', 'id'): 0.46999603701224835}"
]
},
"execution_count": 8,