From e4137f882301907e25c78564e14f71f9adfd5c51 Mon Sep 17 00:00:00 2001 From: taylorfturner Date: Mon, 25 Sep 2023 11:12:22 -0400 Subject: [PATCH] update docs 0.10.3 --- docs/0.10.5/doctrees/API.doctree | Bin 0 -> 3786 bytes .../add_new_model_to_data_labeler.doctree | Bin 0 -> 40597 bytes .../column_name_labeler_example.doctree | Bin 0 -> 35573 bytes docs/0.10.5/doctrees/data_labeling.doctree | Bin 0 -> 51622 bytes docs/0.10.5/doctrees/data_reader.doctree | Bin 0 -> 65267 bytes docs/0.10.5/doctrees/data_readers.doctree | Bin 0 -> 32135 bytes ...ataprofiler.data_readers.avro_data.doctree | Bin 0 -> 53055 bytes ...ataprofiler.data_readers.base_data.doctree | Bin 0 -> 38025 bytes ...dataprofiler.data_readers.csv_data.doctree | Bin 0 -> 59710 bytes .../dataprofiler.data_readers.data.doctree | Bin 0 -> 16955 bytes ...taprofiler.data_readers.data_utils.doctree | Bin 0 -> 165862 bytes .../dataprofiler.data_readers.doctree | Bin 0 -> 4691 bytes ...er.data_readers.filepath_or_buffer.doctree | Bin 0 -> 23191 bytes ...taprofiler.data_readers.graph_data.doctree | Bin 0 -> 54323 bytes ...ataprofiler.data_readers.json_data.doctree | Bin 0 -> 55846 bytes ...profiler.data_readers.parquet_data.doctree | Bin 0 -> 52314 bytes ...ler.data_readers.structured_mixins.doctree | Bin 0 -> 11992 bytes ...ataprofiler.data_readers.text_data.doctree | Bin 0 -> 51266 bytes docs/0.10.5/doctrees/dataprofiler.doctree | Bin 0 -> 5904 bytes .../doctrees/dataprofiler.dp_logging.doctree | Bin 0 -> 11220 bytes ...rofiler.labelers.base_data_labeler.doctree | Bin 0 -> 220960 bytes .../dataprofiler.labelers.base_model.doctree | Bin 0 -> 153576 bytes ...ofiler.labelers.char_load_tf_model.doctree | Bin 0 -> 89493 bytes ...labelers.character_level_cnn_model.doctree | Bin 0 -> 99846 bytes ...belers.classification_report_utils.doctree | Bin 0 -> 83964 bytes ...rofiler.labelers.column_name_model.doctree | Bin 0 -> 65857 bytes ...ataprofiler.labelers.data_labelers.doctree | Bin 0 -> 248623 bytes ...aprofiler.labelers.data_processing.doctree | Bin 0 -> 555299 bytes .../doctrees/dataprofiler.labelers.doctree | Bin 0 -> 11173 bytes ...ataprofiler.labelers.labeler_utils.doctree | Bin 0 -> 541413 bytes .../dataprofiler.labelers.regex_model.doctree | Bin 0 -> 72344 bytes .../dataprofiler.labelers.utils.doctree | Bin 0 -> 12860 bytes ...er.profilers.base_column_profilers.doctree | Bin 0 -> 75639 bytes ...ofilers.categorical_column_profile.doctree | Bin 0 -> 60550 bytes ...profilers.column_profile_compilers.doctree | Bin 0 -> 177148 bytes ...filers.data_labeler_column_profile.doctree | Bin 0 -> 65527 bytes ....profilers.datetime_column_profile.doctree | Bin 0 -> 47589 bytes .../doctrees/dataprofiler.profilers.doctree | Bin 0 -> 5178 bytes ...ler.profilers.float_column_profile.doctree | Bin 0 -> 83126 bytes ...aprofiler.profilers.graph_profiler.doctree | Bin 0 -> 36831 bytes .../dataprofiler.profilers.helpers.doctree | Bin 0 -> 11844 bytes ...r.profilers.helpers.report_helpers.doctree | Bin 0 -> 18709 bytes ...profiler.profilers.histogram_utils.doctree | Bin 0 -> 4301 bytes ...filer.profilers.int_column_profile.doctree | Bin 0 -> 80738 bytes ...ataprofiler.profilers.json_decoder.doctree | Bin 0 -> 84834 bytes ...ataprofiler.profilers.json_encoder.doctree | Bin 0 -> 25266 bytes ...r.profilers.numerical_column_stats.doctree | Bin 0 -> 83126 bytes ...ler.profilers.order_column_profile.doctree | Bin 0 -> 46938 bytes ...profiler.profilers.profile_builder.doctree | Bin 0 -> 267594 bytes ...rofiler.profilers.profiler_options.doctree | Bin 0 -> 727399 bytes ...aprofiler.profilers.profiler_utils.doctree | Bin 0 -> 220324 bytes ...iler.profilers.text_column_profile.doctree | Bin 0 -> 104808 bytes ...ilers.unstructured_labeler_profile.doctree | Bin 0 -> 30250 bytes ...rofilers.unstructured_text_profile.doctree | Bin 0 -> 28111 bytes .../dataprofiler.profilers.utils.doctree | Bin 0 -> 2328 bytes .../doctrees/dataprofiler.reports.doctree | Bin 0 -> 4138 bytes .../dataprofiler.reports.graphs.doctree | Bin 0 -> 3176 bytes .../dataprofiler.reports.utils.doctree | Bin 0 -> 13824 bytes .../doctrees/dataprofiler.rng_utils.doctree | Bin 0 -> 5252 bytes .../doctrees/dataprofiler.settings.doctree | Bin 0 -> 3098 bytes ...rofiler.validators.base_validators.doctree | Bin 0 -> 26522 bytes .../doctrees/dataprofiler.validators.doctree | Bin 0 -> 4155 bytes .../doctrees/dataprofiler.version.doctree | Bin 0 -> 3111 bytes docs/0.10.5/doctrees/environment.pickle | Bin 0 -> 650218 bytes docs/0.10.5/doctrees/examples.doctree | Bin 0 -> 4707 bytes docs/0.10.5/doctrees/graph_data_demo.doctree | Bin 0 -> 26328 bytes docs/0.10.5/doctrees/graphs.doctree | Bin 0 -> 25584 bytes docs/0.10.5/doctrees/index.doctree | Bin 0 -> 64408 bytes docs/0.10.5/doctrees/install.doctree | Bin 0 -> 12450 bytes docs/0.10.5/doctrees/labeler.doctree | Bin 0 -> 46397 bytes .../doctrees/merge_profile_list.doctree | Bin 0 -> 11848 bytes docs/0.10.5/doctrees/modules.doctree | Bin 0 -> 2668 bytes .../add_new_model_to_data_labeler.ipynb | 488 + .../column_name_labeler_example.ipynb | 364 + .../doctrees/nbsphinx/data_reader.ipynb | 689 + .../doctrees/nbsphinx/graph_data_demo.ipynb | 271 + docs/0.10.5/doctrees/nbsphinx/labeler.ipynb | 650 + .../nbsphinx/merge_profile_list.ipynb | 159 + docs/0.10.5/doctrees/nbsphinx/overview.ipynb | 470 + .../nbsphinx/popmon_dp_loader_example.ipynb | 416 + .../doctrees/nbsphinx/profiler_example.ipynb | 577 + .../nbsphinx/regex_labeler_from_scratch.ipynb | 444 + .../unstructured_profiler_example.ipynb | 436 + docs/0.10.5/doctrees/overview.doctree | Bin 0 -> 39414 bytes .../doctrees/popmon_dp_loader_example.doctree | Bin 0 -> 27518 bytes docs/0.10.5/doctrees/profiler.doctree | Bin 0 -> 215481 bytes docs/0.10.5/doctrees/profiler_example.doctree | Bin 0 -> 47446 bytes .../regex_labeler_from_scratch.doctree | Bin 0 -> 42399 bytes docs/0.10.5/doctrees/roadmap.doctree | Bin 0 -> 19890 bytes .../unstructured_profiler_example.doctree | Bin 0 -> 36875 bytes docs/0.10.5/html/.buildinfo | 4 + docs/0.10.5/html/API.html | 294 + docs/0.10.5/html/_images/DL-Flowchart.png | Bin 0 -> 7609 bytes .../html/_images/histogram_example_0.png | Bin 0 -> 14056 bytes .../html/_images/histogram_example_1.png | Bin 0 -> 11387 bytes .../html/_images/histogram_example_2.png | Bin 0 -> 12592 bytes .../missing_value_barchart_example_0.png | Bin 0 -> 24758 bytes .../missing_value_matrix_example_0.png | Bin 0 -> 37730 bytes docs/0.10.5/html/_sources/API.rst.txt | 16 + .../add_new_model_to_data_labeler.nblink.txt | 3 + .../column_name_labeler_example.nblink.txt | 3 + .../html/_sources/data_labeling.rst.txt | 365 + .../html/_sources/data_reader.nblink.txt | 3 + .../0.10.5/html/_sources/data_readers.rst.txt | 164 + ...ataprofiler.data_readers.avro_data.rst.txt | 7 + ...ataprofiler.data_readers.base_data.rst.txt | 7 + ...dataprofiler.data_readers.csv_data.rst.txt | 7 + .../dataprofiler.data_readers.data.rst.txt | 7 + ...taprofiler.data_readers.data_utils.rst.txt | 7 + ...er.data_readers.filepath_or_buffer.rst.txt | 7 + ...taprofiler.data_readers.graph_data.rst.txt | 7 + ...ataprofiler.data_readers.json_data.rst.txt | 7 + ...profiler.data_readers.parquet_data.rst.txt | 7 + .../dataprofiler.data_readers.rst.txt | 30 + ...ler.data_readers.structured_mixins.rst.txt | 7 + ...ataprofiler.data_readers.text_data.rst.txt | 7 + .../_sources/dataprofiler.dp_logging.rst.txt | 7 + ...rofiler.labelers.base_data_labeler.rst.txt | 7 + .../dataprofiler.labelers.base_model.rst.txt | 7 + ...ofiler.labelers.char_load_tf_model.rst.txt | 7 + ...labelers.character_level_cnn_model.rst.txt | 7 + ...belers.classification_report_utils.rst.txt | 7 + ...rofiler.labelers.column_name_model.rst.txt | 7 + ...ataprofiler.labelers.data_labelers.rst.txt | 7 + ...aprofiler.labelers.data_processing.rst.txt | 7 + ...ataprofiler.labelers.labeler_utils.rst.txt | 7 + .../dataprofiler.labelers.regex_model.rst.txt | 7 + .../_sources/dataprofiler.labelers.rst.txt | 30 + .../dataprofiler.labelers.utils.rst.txt | 7 + ...er.profilers.base_column_profilers.rst.txt | 7 + ...ofilers.categorical_column_profile.rst.txt | 7 + ...profilers.column_profile_compilers.rst.txt | 7 + ...filers.data_labeler_column_profile.rst.txt | 7 + ....profilers.datetime_column_profile.rst.txt | 7 + ...ler.profilers.float_column_profile.rst.txt | 7 + ...aprofiler.profilers.graph_profiler.rst.txt | 7 + ...r.profilers.helpers.report_helpers.rst.txt | 7 + .../dataprofiler.profilers.helpers.rst.txt | 20 + ...profiler.profilers.histogram_utils.rst.txt | 7 + ...filer.profilers.int_column_profile.rst.txt | 7 + ...ataprofiler.profilers.json_decoder.rst.txt | 7 + ...ataprofiler.profilers.json_encoder.rst.txt | 7 + ...r.profilers.numerical_column_stats.rst.txt | 7 + ...ler.profilers.order_column_profile.rst.txt | 7 + ...profiler.profilers.profile_builder.rst.txt | 7 + ...rofiler.profilers.profiler_options.rst.txt | 7 + ...aprofiler.profilers.profiler_utils.rst.txt | 7 + .../_sources/dataprofiler.profilers.rst.txt | 39 + ...iler.profilers.text_column_profile.rst.txt | 7 + ...ilers.unstructured_labeler_profile.rst.txt | 7 + ...rofilers.unstructured_text_profile.rst.txt | 7 + .../dataprofiler.profilers.utils.rst.txt | 7 + .../dataprofiler.reports.graphs.rst.txt | 7 + .../_sources/dataprofiler.reports.rst.txt | 21 + .../dataprofiler.reports.utils.rst.txt | 7 + .../_sources/dataprofiler.rng_utils.rst.txt | 7 + .../0.10.5/html/_sources/dataprofiler.rst.txt | 28 + .../_sources/dataprofiler.settings.rst.txt | 7 + ...rofiler.validators.base_validators.rst.txt | 7 + .../_sources/dataprofiler.validators.rst.txt | 20 + .../_sources/dataprofiler.version.rst.txt | 7 + docs/0.10.5/html/_sources/examples.rst.txt | 24 + .../html/_sources/graph_data_demo.nblink.txt | 3 + docs/0.10.5/html/_sources/graphs.rst.txt | 196 + docs/0.10.5/html/_sources/index.rst.txt | 587 + docs/0.10.5/html/_sources/install.rst.txt | 145 + docs/0.10.5/html/_sources/labeler.nblink.txt | 6 + .../_sources/merge_profile_list.nblink.txt | 3 + docs/0.10.5/html/_sources/modules.rst.txt | 7 + docs/0.10.5/html/_sources/overview.nblink.txt | 3 + .../popmon_dp_loader_example.nblink.txt | 3 + docs/0.10.5/html/_sources/profiler.rst.txt | 962 ++ .../html/_sources/profiler_example.nblink.txt | 3 + .../regex_labeler_from_scratch.nblink.txt | 3 + docs/0.10.5/html/_sources/roadmap.rst.txt | 58 + .../unstructured_profiler_example.nblink.txt | 3 + .../_static/DataProfilerLogoLightTheme.png | Bin 0 -> 118089 bytes docs/0.10.5/html/_static/basic.css | 904 ++ docs/0.10.5/html/_static/custom.css | 50 + docs/0.10.5/html/_static/doctools.js | 323 + .../html/_static/documentation_options.js | 12 + docs/0.10.5/html/_static/file.png | Bin 0 -> 286 bytes .../images/DataProfilerDarkLogoLong.png | Bin 0 -> 20019 bytes .../images/DataProfilerLogoLightTheme.png | Bin 0 -> 118089 bytes .../images/DataProfilerLogoLightThemeLong.png | Bin 0 -> 177437 bytes .../images/branching_workflow_diagram.png | Bin 0 -> 131890 bytes .../_static/images/histogram_example_0.png | Bin 0 -> 14056 bytes .../_static/images/histogram_example_1.png | Bin 0 -> 11387 bytes .../_static/images/histogram_example_2.png | Bin 0 -> 12592 bytes .../missing_value_barchart_example_0.png | Bin 0 -> 24758 bytes .../images/missing_value_matrix_example_0.png | Bin 0 -> 37730 bytes docs/0.10.5/html/_static/jquery-3.5.1.js | 10872 ++++++++++++++++ docs/0.10.5/html/_static/jquery.js | 2 + docs/0.10.5/html/_static/language_data.js | 297 + docs/0.10.5/html/_static/minus.png | Bin 0 -> 90 bytes docs/0.10.5/html/_static/plus.png | Bin 0 -> 90 bytes docs/0.10.5/html/_static/pygments.css | 74 + docs/0.10.5/html/_static/pygments_dark.css | 84 + docs/0.10.5/html/_static/scripts/main.js | 2 + docs/0.10.5/html/_static/scripts/main.js.map | 1 + docs/0.10.5/html/_static/searchtools.js | 522 + .../html/_static/styles/furo-extensions.css | 2 + .../_static/styles/furo-extensions.css.map | 1 + docs/0.10.5/html/_static/styles/furo.css | 2 + docs/0.10.5/html/_static/styles/furo.css.map | 1 + docs/0.10.5/html/_static/underscore-1.13.1.js | 2042 +++ docs/0.10.5/html/_static/underscore.js | 6 + .../html/add_new_model_to_data_labeler.html | 936 ++ .../html/add_new_model_to_data_labeler.ipynb | 488 + .../html/column_name_labeler_example.html | 821 ++ .../html/column_name_labeler_example.ipynb | 364 + docs/0.10.5/html/data_labeling.html | 616 + docs/0.10.5/html/data_reader.html | 1102 ++ docs/0.10.5/html/data_reader.ipynb | 689 + docs/0.10.5/html/data_readers.html | 453 + .../dataprofiler.data_readers.avro_data.html | 410 + .../dataprofiler.data_readers.base_data.html | 372 + .../dataprofiler.data_readers.csv_data.html | 439 + .../html/dataprofiler.data_readers.data.html | 311 + .../dataprofiler.data_readers.data_utils.html | 657 + ...filer.data_readers.filepath_or_buffer.html | 322 + .../dataprofiler.data_readers.graph_data.html | 416 + .../html/dataprofiler.data_readers.html | 325 + .../dataprofiler.data_readers.json_data.html | 421 + ...ataprofiler.data_readers.parquet_data.html | 406 + ...ofiler.data_readers.structured_mixins.html | 305 + .../dataprofiler.data_readers.text_data.html | 411 + docs/0.10.5/html/dataprofiler.dp_logging.html | 299 + docs/0.10.5/html/dataprofiler.html | 384 + ...taprofiler.labelers.base_data_labeler.html | 910 ++ .../dataprofiler.labelers.base_model.html | 676 + ...aprofiler.labelers.char_load_tf_model.html | 492 + ...er.labelers.character_level_cnn_model.html | 513 + ....labelers.classification_report_utils.html | 452 + ...taprofiler.labelers.column_name_model.html | 452 + .../dataprofiler.labelers.data_labelers.html | 981 ++ ...dataprofiler.labelers.data_processing.html | 1413 ++ docs/0.10.5/html/dataprofiler.labelers.html | 361 + .../dataprofiler.labelers.labeler_utils.html | 2642 ++++ .../dataprofiler.labelers.regex_model.html | 487 + .../html/dataprofiler.labelers.utils.html | 309 + ...filer.profilers.base_column_profilers.html | 458 + ....profilers.categorical_column_profile.html | 450 + ...er.profilers.column_profile_compilers.html | 678 + ...profilers.data_labeler_column_profile.html | 447 + ...ler.profilers.datetime_column_profile.html | 406 + ...ofiler.profilers.float_column_profile.html | 547 + ...dataprofiler.profilers.graph_profiler.html | 383 + .../html/dataprofiler.profilers.helpers.html | 334 + ...iler.profilers.helpers.report_helpers.html | 325 + ...ataprofiler.profilers.histogram_utils.html | 288 + docs/0.10.5/html/dataprofiler.profilers.html | 342 + ...profiler.profilers.int_column_profile.html | 540 + .../dataprofiler.profilers.json_decoder.html | 547 + .../dataprofiler.profilers.json_encoder.html | 364 + ...iler.profilers.numerical_column_stats.html | 536 + ...ofiler.profilers.order_column_profile.html | 402 + ...ataprofiler.profilers.profile_builder.html | 892 ++ ...taprofiler.profilers.profiler_options.html | 2396 ++++ ...dataprofiler.profilers.profiler_utils.html | 825 ++ ...rofiler.profilers.text_column_profile.html | 588 + ...rofilers.unstructured_labeler_profile.html | 348 + ...r.profilers.unstructured_text_profile.html | 356 + .../html/dataprofiler.profilers.utils.html | 265 + .../html/dataprofiler.reports.graphs.html | 266 + docs/0.10.5/html/dataprofiler.reports.html | 298 + .../html/dataprofiler.reports.utils.html | 291 + docs/0.10.5/html/dataprofiler.rng_utils.html | 271 + docs/0.10.5/html/dataprofiler.settings.html | 266 + ...taprofiler.validators.base_validators.html | 362 + docs/0.10.5/html/dataprofiler.validators.html | 315 + docs/0.10.5/html/dataprofiler.version.html | 266 + docs/0.10.5/html/examples.html | 427 + docs/0.10.5/html/genindex.html | 3431 +++++ docs/0.10.5/html/graph_data_demo.html | 709 + docs/0.10.5/html/graph_data_demo.ipynb | 271 + docs/0.10.5/html/graphs.html | 488 + docs/0.10.5/html/index.html | 746 ++ docs/0.10.5/html/install.html | 392 + docs/0.10.5/html/labeler.html | 957 ++ docs/0.10.5/html/labeler.ipynb | 650 + docs/0.10.5/html/merge_profile_list.html | 638 + docs/0.10.5/html/merge_profile_list.ipynb | 159 + docs/0.10.5/html/modules.html | 299 + docs/0.10.5/html/objects.inv | Bin 0 -> 29194 bytes docs/0.10.5/html/overview.html | 849 ++ docs/0.10.5/html/overview.ipynb | 470 + .../0.10.5/html/popmon_dp_loader_example.html | 804 ++ .../html/popmon_dp_loader_example.ipynb | 416 + docs/0.10.5/html/profiler.html | 1410 ++ docs/0.10.5/html/profiler_example.html | 949 ++ docs/0.10.5/html/profiler_example.ipynb | 577 + docs/0.10.5/html/py-modindex.html | 605 + .../html/regex_labeler_from_scratch.html | 858 ++ .../html/regex_labeler_from_scratch.ipynb | 444 + docs/0.10.5/html/roadmap.html | 388 + docs/0.10.5/html/search.html | 267 + docs/0.10.5/html/searchindex.js | 1 + .../html/unstructured_profiler_example.html | 836 ++ .../html/unstructured_profiler_example.ipynb | 436 + docs/source/index.rst | 3 + index.html | 2 +- profiler_options.html | 2 +- 303 files changed, 77726 insertions(+), 2 deletions(-) create mode 100644 docs/0.10.5/doctrees/API.doctree create mode 100644 docs/0.10.5/doctrees/add_new_model_to_data_labeler.doctree create mode 100644 docs/0.10.5/doctrees/column_name_labeler_example.doctree create mode 100644 docs/0.10.5/doctrees/data_labeling.doctree create mode 100644 docs/0.10.5/doctrees/data_reader.doctree create mode 100644 docs/0.10.5/doctrees/data_readers.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.data_readers.avro_data.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.data_readers.base_data.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.data_readers.csv_data.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.data_readers.data.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.data_readers.data_utils.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.data_readers.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.data_readers.filepath_or_buffer.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.data_readers.graph_data.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.data_readers.json_data.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.data_readers.parquet_data.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.data_readers.structured_mixins.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.data_readers.text_data.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.dp_logging.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.labelers.base_data_labeler.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.labelers.base_model.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.labelers.char_load_tf_model.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.labelers.character_level_cnn_model.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.labelers.classification_report_utils.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.labelers.column_name_model.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.labelers.data_labelers.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.labelers.data_processing.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.labelers.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.labelers.labeler_utils.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.labelers.regex_model.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.labelers.utils.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.base_column_profilers.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.categorical_column_profile.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.column_profile_compilers.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.data_labeler_column_profile.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.datetime_column_profile.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.float_column_profile.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.graph_profiler.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.helpers.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.helpers.report_helpers.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.histogram_utils.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.int_column_profile.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.json_decoder.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.json_encoder.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.numerical_column_stats.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.order_column_profile.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.profile_builder.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.profiler_options.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.profiler_utils.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.text_column_profile.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.unstructured_labeler_profile.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.unstructured_text_profile.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.profilers.utils.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.reports.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.reports.graphs.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.reports.utils.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.rng_utils.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.settings.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.validators.base_validators.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.validators.doctree create mode 100644 docs/0.10.5/doctrees/dataprofiler.version.doctree create mode 100644 docs/0.10.5/doctrees/environment.pickle create mode 100644 docs/0.10.5/doctrees/examples.doctree create mode 100644 docs/0.10.5/doctrees/graph_data_demo.doctree create mode 100644 docs/0.10.5/doctrees/graphs.doctree create mode 100644 docs/0.10.5/doctrees/index.doctree create mode 100644 docs/0.10.5/doctrees/install.doctree create mode 100644 docs/0.10.5/doctrees/labeler.doctree create mode 100644 docs/0.10.5/doctrees/merge_profile_list.doctree create mode 100644 docs/0.10.5/doctrees/modules.doctree create mode 100644 docs/0.10.5/doctrees/nbsphinx/add_new_model_to_data_labeler.ipynb create mode 100644 docs/0.10.5/doctrees/nbsphinx/column_name_labeler_example.ipynb create mode 100644 docs/0.10.5/doctrees/nbsphinx/data_reader.ipynb create mode 100644 docs/0.10.5/doctrees/nbsphinx/graph_data_demo.ipynb create mode 100644 docs/0.10.5/doctrees/nbsphinx/labeler.ipynb create mode 100644 docs/0.10.5/doctrees/nbsphinx/merge_profile_list.ipynb create mode 100644 docs/0.10.5/doctrees/nbsphinx/overview.ipynb create mode 100644 docs/0.10.5/doctrees/nbsphinx/popmon_dp_loader_example.ipynb create mode 100644 docs/0.10.5/doctrees/nbsphinx/profiler_example.ipynb create mode 100644 docs/0.10.5/doctrees/nbsphinx/regex_labeler_from_scratch.ipynb create mode 100644 docs/0.10.5/doctrees/nbsphinx/unstructured_profiler_example.ipynb create mode 100644 docs/0.10.5/doctrees/overview.doctree create mode 100644 docs/0.10.5/doctrees/popmon_dp_loader_example.doctree create mode 100644 docs/0.10.5/doctrees/profiler.doctree create mode 100644 docs/0.10.5/doctrees/profiler_example.doctree create mode 100644 docs/0.10.5/doctrees/regex_labeler_from_scratch.doctree create mode 100644 docs/0.10.5/doctrees/roadmap.doctree create mode 100644 docs/0.10.5/doctrees/unstructured_profiler_example.doctree create mode 100644 docs/0.10.5/html/.buildinfo create mode 100644 docs/0.10.5/html/API.html create mode 100644 docs/0.10.5/html/_images/DL-Flowchart.png create mode 100644 docs/0.10.5/html/_images/histogram_example_0.png create mode 100644 docs/0.10.5/html/_images/histogram_example_1.png create mode 100644 docs/0.10.5/html/_images/histogram_example_2.png create mode 100644 docs/0.10.5/html/_images/missing_value_barchart_example_0.png create mode 100644 docs/0.10.5/html/_images/missing_value_matrix_example_0.png create mode 100644 docs/0.10.5/html/_sources/API.rst.txt create mode 100644 docs/0.10.5/html/_sources/add_new_model_to_data_labeler.nblink.txt create mode 100644 docs/0.10.5/html/_sources/column_name_labeler_example.nblink.txt create mode 100644 docs/0.10.5/html/_sources/data_labeling.rst.txt create mode 100644 docs/0.10.5/html/_sources/data_reader.nblink.txt create mode 100644 docs/0.10.5/html/_sources/data_readers.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.data_readers.avro_data.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.data_readers.base_data.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.data_readers.csv_data.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.data_readers.data.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.data_readers.data_utils.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.data_readers.filepath_or_buffer.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.data_readers.graph_data.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.data_readers.json_data.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.data_readers.parquet_data.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.data_readers.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.data_readers.structured_mixins.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.data_readers.text_data.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.dp_logging.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.labelers.base_data_labeler.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.labelers.base_model.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.labelers.char_load_tf_model.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.labelers.character_level_cnn_model.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.labelers.classification_report_utils.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.labelers.column_name_model.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.labelers.data_labelers.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.labelers.data_processing.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.labelers.labeler_utils.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.labelers.regex_model.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.labelers.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.labelers.utils.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.base_column_profilers.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.categorical_column_profile.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.column_profile_compilers.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.data_labeler_column_profile.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.datetime_column_profile.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.float_column_profile.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.graph_profiler.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.helpers.report_helpers.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.helpers.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.histogram_utils.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.int_column_profile.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.json_decoder.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.json_encoder.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.numerical_column_stats.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.order_column_profile.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.profile_builder.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.profiler_options.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.profiler_utils.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.text_column_profile.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.unstructured_labeler_profile.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.unstructured_text_profile.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.profilers.utils.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.reports.graphs.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.reports.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.reports.utils.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.rng_utils.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.settings.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.validators.base_validators.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.validators.rst.txt create mode 100644 docs/0.10.5/html/_sources/dataprofiler.version.rst.txt create mode 100644 docs/0.10.5/html/_sources/examples.rst.txt create mode 100644 docs/0.10.5/html/_sources/graph_data_demo.nblink.txt create mode 100644 docs/0.10.5/html/_sources/graphs.rst.txt create mode 100644 docs/0.10.5/html/_sources/index.rst.txt create mode 100644 docs/0.10.5/html/_sources/install.rst.txt create mode 100644 docs/0.10.5/html/_sources/labeler.nblink.txt create mode 100644 docs/0.10.5/html/_sources/merge_profile_list.nblink.txt create mode 100644 docs/0.10.5/html/_sources/modules.rst.txt create mode 100644 docs/0.10.5/html/_sources/overview.nblink.txt create mode 100644 docs/0.10.5/html/_sources/popmon_dp_loader_example.nblink.txt create mode 100644 docs/0.10.5/html/_sources/profiler.rst.txt create mode 100644 docs/0.10.5/html/_sources/profiler_example.nblink.txt create mode 100644 docs/0.10.5/html/_sources/regex_labeler_from_scratch.nblink.txt create mode 100644 docs/0.10.5/html/_sources/roadmap.rst.txt create mode 100644 docs/0.10.5/html/_sources/unstructured_profiler_example.nblink.txt create mode 100644 docs/0.10.5/html/_static/DataProfilerLogoLightTheme.png create mode 100644 docs/0.10.5/html/_static/basic.css create mode 100644 docs/0.10.5/html/_static/custom.css create mode 100644 docs/0.10.5/html/_static/doctools.js create mode 100644 docs/0.10.5/html/_static/documentation_options.js create mode 100644 docs/0.10.5/html/_static/file.png create mode 100644 docs/0.10.5/html/_static/images/DataProfilerDarkLogoLong.png create mode 100644 docs/0.10.5/html/_static/images/DataProfilerLogoLightTheme.png create mode 100644 docs/0.10.5/html/_static/images/DataProfilerLogoLightThemeLong.png create mode 100644 docs/0.10.5/html/_static/images/branching_workflow_diagram.png create mode 100644 docs/0.10.5/html/_static/images/histogram_example_0.png create mode 100644 docs/0.10.5/html/_static/images/histogram_example_1.png create mode 100644 docs/0.10.5/html/_static/images/histogram_example_2.png create mode 100644 docs/0.10.5/html/_static/images/missing_value_barchart_example_0.png create mode 100644 docs/0.10.5/html/_static/images/missing_value_matrix_example_0.png create mode 100644 docs/0.10.5/html/_static/jquery-3.5.1.js create mode 100644 docs/0.10.5/html/_static/jquery.js create mode 100644 docs/0.10.5/html/_static/language_data.js create mode 100644 docs/0.10.5/html/_static/minus.png create mode 100644 docs/0.10.5/html/_static/plus.png create mode 100644 docs/0.10.5/html/_static/pygments.css create mode 100644 docs/0.10.5/html/_static/pygments_dark.css create mode 100644 docs/0.10.5/html/_static/scripts/main.js create mode 100644 docs/0.10.5/html/_static/scripts/main.js.map create mode 100644 docs/0.10.5/html/_static/searchtools.js create mode 100644 docs/0.10.5/html/_static/styles/furo-extensions.css create mode 100644 docs/0.10.5/html/_static/styles/furo-extensions.css.map create mode 100644 docs/0.10.5/html/_static/styles/furo.css create mode 100644 docs/0.10.5/html/_static/styles/furo.css.map create mode 100644 docs/0.10.5/html/_static/underscore-1.13.1.js create mode 100644 docs/0.10.5/html/_static/underscore.js create mode 100644 docs/0.10.5/html/add_new_model_to_data_labeler.html create mode 100644 docs/0.10.5/html/add_new_model_to_data_labeler.ipynb create mode 100644 docs/0.10.5/html/column_name_labeler_example.html create mode 100644 docs/0.10.5/html/column_name_labeler_example.ipynb create mode 100644 docs/0.10.5/html/data_labeling.html create mode 100644 docs/0.10.5/html/data_reader.html create mode 100644 docs/0.10.5/html/data_reader.ipynb create mode 100644 docs/0.10.5/html/data_readers.html create mode 100644 docs/0.10.5/html/dataprofiler.data_readers.avro_data.html create mode 100644 docs/0.10.5/html/dataprofiler.data_readers.base_data.html create mode 100644 docs/0.10.5/html/dataprofiler.data_readers.csv_data.html create mode 100644 docs/0.10.5/html/dataprofiler.data_readers.data.html create mode 100644 docs/0.10.5/html/dataprofiler.data_readers.data_utils.html create mode 100644 docs/0.10.5/html/dataprofiler.data_readers.filepath_or_buffer.html create mode 100644 docs/0.10.5/html/dataprofiler.data_readers.graph_data.html create mode 100644 docs/0.10.5/html/dataprofiler.data_readers.html create mode 100644 docs/0.10.5/html/dataprofiler.data_readers.json_data.html create mode 100644 docs/0.10.5/html/dataprofiler.data_readers.parquet_data.html create mode 100644 docs/0.10.5/html/dataprofiler.data_readers.structured_mixins.html create mode 100644 docs/0.10.5/html/dataprofiler.data_readers.text_data.html create mode 100644 docs/0.10.5/html/dataprofiler.dp_logging.html create mode 100644 docs/0.10.5/html/dataprofiler.html create mode 100644 docs/0.10.5/html/dataprofiler.labelers.base_data_labeler.html create mode 100644 docs/0.10.5/html/dataprofiler.labelers.base_model.html create mode 100644 docs/0.10.5/html/dataprofiler.labelers.char_load_tf_model.html create mode 100644 docs/0.10.5/html/dataprofiler.labelers.character_level_cnn_model.html create mode 100644 docs/0.10.5/html/dataprofiler.labelers.classification_report_utils.html create mode 100644 docs/0.10.5/html/dataprofiler.labelers.column_name_model.html create mode 100644 docs/0.10.5/html/dataprofiler.labelers.data_labelers.html create mode 100644 docs/0.10.5/html/dataprofiler.labelers.data_processing.html create mode 100644 docs/0.10.5/html/dataprofiler.labelers.html create mode 100644 docs/0.10.5/html/dataprofiler.labelers.labeler_utils.html create mode 100644 docs/0.10.5/html/dataprofiler.labelers.regex_model.html create mode 100644 docs/0.10.5/html/dataprofiler.labelers.utils.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.base_column_profilers.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.categorical_column_profile.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.column_profile_compilers.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.data_labeler_column_profile.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.datetime_column_profile.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.float_column_profile.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.graph_profiler.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.helpers.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.helpers.report_helpers.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.histogram_utils.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.int_column_profile.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.json_decoder.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.json_encoder.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.numerical_column_stats.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.order_column_profile.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.profile_builder.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.profiler_options.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.profiler_utils.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.text_column_profile.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.unstructured_labeler_profile.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.unstructured_text_profile.html create mode 100644 docs/0.10.5/html/dataprofiler.profilers.utils.html create mode 100644 docs/0.10.5/html/dataprofiler.reports.graphs.html create mode 100644 docs/0.10.5/html/dataprofiler.reports.html create mode 100644 docs/0.10.5/html/dataprofiler.reports.utils.html create mode 100644 docs/0.10.5/html/dataprofiler.rng_utils.html create mode 100644 docs/0.10.5/html/dataprofiler.settings.html create mode 100644 docs/0.10.5/html/dataprofiler.validators.base_validators.html create mode 100644 docs/0.10.5/html/dataprofiler.validators.html create mode 100644 docs/0.10.5/html/dataprofiler.version.html create mode 100644 docs/0.10.5/html/examples.html create mode 100644 docs/0.10.5/html/genindex.html create mode 100644 docs/0.10.5/html/graph_data_demo.html create mode 100644 docs/0.10.5/html/graph_data_demo.ipynb create mode 100644 docs/0.10.5/html/graphs.html create mode 100644 docs/0.10.5/html/index.html create mode 100644 docs/0.10.5/html/install.html create mode 100644 docs/0.10.5/html/labeler.html create mode 100644 docs/0.10.5/html/labeler.ipynb create mode 100644 docs/0.10.5/html/merge_profile_list.html create mode 100644 docs/0.10.5/html/merge_profile_list.ipynb create mode 100644 docs/0.10.5/html/modules.html create mode 100644 docs/0.10.5/html/objects.inv create mode 100644 docs/0.10.5/html/overview.html create mode 100644 docs/0.10.5/html/overview.ipynb create mode 100644 docs/0.10.5/html/popmon_dp_loader_example.html create mode 100644 docs/0.10.5/html/popmon_dp_loader_example.ipynb create mode 100644 docs/0.10.5/html/profiler.html create mode 100644 docs/0.10.5/html/profiler_example.html create mode 100644 docs/0.10.5/html/profiler_example.ipynb create mode 100644 docs/0.10.5/html/py-modindex.html create mode 100644 docs/0.10.5/html/regex_labeler_from_scratch.html create mode 100644 docs/0.10.5/html/regex_labeler_from_scratch.ipynb create mode 100644 docs/0.10.5/html/roadmap.html create mode 100644 docs/0.10.5/html/search.html create mode 100644 docs/0.10.5/html/searchindex.js create mode 100644 docs/0.10.5/html/unstructured_profiler_example.html create mode 100644 docs/0.10.5/html/unstructured_profiler_example.ipynb diff --git a/docs/0.10.5/doctrees/API.doctree b/docs/0.10.5/doctrees/API.doctree new file mode 100644 index 0000000000000000000000000000000000000000..bb9b715c1c484b739c659c75709afe2bc40bcab5 GIT binary patch literal 3786 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/column_name_labeler_example.doctree b/docs/0.10.5/doctrees/column_name_labeler_example.doctree new file mode 100644 index 0000000000000000000000000000000000000000..b9747a6774a8427f8e3c64d1cc28f4bdff24df37 GIT binary patch literal 35573 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 eyKwP)xn9D$-d&; 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 AqyPW_ literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.data_readers.avro_data.doctree b/docs/0.10.5/doctrees/dataprofiler.data_readers.avro_data.doctree new file mode 100644 index 0000000000000000000000000000000000000000..6f0a3da411cd9ef812218b7e089a9a247fbb89ca GIT binary patch literal 53055 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 Kx2UXLr~e;{uA*rG literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.data_readers.base_data.doctree b/docs/0.10.5/doctrees/dataprofiler.data_readers.base_data.doctree new file mode 100644 index 0000000000000000000000000000000000000000..814e8c1243de5c14e058896a5410d0a4058471ec GIT binary patch literal 38025 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 MKVquDU6#532Z2%AmH+?% literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.data_readers.data.doctree b/docs/0.10.5/doctrees/dataprofiler.data_readers.data.doctree new file mode 100644 index 0000000000000000000000000000000000000000..207083797d172e8a0eb890d9f150cb53bde52bcc GIT binary patch literal 16955 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.data_readers.graph_data.doctree b/docs/0.10.5/doctrees/dataprofiler.data_readers.graph_data.doctree new file mode 100644 index 0000000000000000000000000000000000000000..b3c4c96d5e2843cd568d1b37e529ab4e873c6156 GIT binary patch literal 54323 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 Xw!!#Ct7tRfLz^&AaGT2db@BfLGy4^w literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.data_readers.json_data.doctree b/docs/0.10.5/doctrees/dataprofiler.data_readers.json_data.doctree new file mode 100644 index 0000000000000000000000000000000000000000..f47f304930effb05512cf3c0a4a5badc3484642c GIT binary patch literal 55846 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.data_readers.parquet_data.doctree b/docs/0.10.5/doctrees/dataprofiler.data_readers.parquet_data.doctree new file mode 100644 index 0000000000000000000000000000000000000000..57c4c9e3d11717cce50c3e20d024d31c783dc64e GIT binary patch literal 52314 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 kheH11c7 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.doctree b/docs/0.10.5/doctrees/dataprofiler.doctree new file mode 100644 index 0000000000000000000000000000000000000000..fa9b6a9cbd14bea373f84dc0e20359be75a4936c GIT binary patch literal 5904 zcmcgw%Wot{8TVtJ_V~505Oy6Vi6X|z+7ks1WYGdrA_Q2O03k$xmZqk=W~#?M-A#A3 zABdoENVGK0s`nC;ER2GQ>+vWhIDj?2 z#ZQTT?ewiw^82kP zl{^oAo-_Q6#1ka7_!LAHPeP+ls@tSyDe21&f zoSiy6lp;NBz-w5jT^v3(^@4GFu3Ex%97M#q+Q`r>HadPXAM=Pi>EV)E(*Y0%zIO)L zH3U|n5Hib)Vpp4^18aV%ZbP+|Sz!MpVqu7QVRf^90ryH~g&T-3=3bN;>!sTIa^s1S zcm;YGsjA+b(DH)m)b*#@N>x)t{?yX>-~kqlxsHbIJ$KogA zO)l;oHpKTw!a5f}I2Y_(j1QNDeJ&j1#<{+BAoskkFX29le!8k9Sv2KE!pkFY5kTtd zT*u#j*?*w?T3o578v`)CPnP@{^1}Ed^TLEPnMB+gN6fcHB{d8!%k^DpSqI_S9m*dF z9DmvmCjAN*h~4Gf=&<$@nD8BbdNF`6vvVaTRU>3>l&Wh+;Lq1+y(3y9nKF{^mpRdo zQBIwsy2$)&iU1HL8P(%oN1A3+-k$_fh3SJlXFdd?$fCc4RKI=nEc)KZD15GODB)L+ z7{XQ4wqp1Xs;_z)foR2?JA=Lc!1epa))lSorM2vvUr8V60jA=>`5NdU?2=vb(!Yd8 z0Vh`MqI{CamtfS@9QlBlx;qMdzNf7=0LGraNBs$v-Ml9eO|?-DgN2oAyM<+2(BGdg zx9mWzgSY(J)I)Vck&0MpZ-qe3*thq#>i84w1R28Sz)~H%bowDAXYSp0jpE zvqsT7=aNUBi`J)P&+fwbCSr4!SzLGsFgc307&(|#m%c%m^E6-<6{%<4<)x*|1y{@d zg+e=P)0LaERs7R>-_gPm^#FyLx{5Np%Xf3~_*JF-$&a8NT%`Sp3T@Oc*VnCXNtq1_ zqMW8#RLMU3aI#S5ge9J|&?F_i$^zmw38|^F;yH`t50ik}>T}qAwpZqiFY0H#P-bp2 zTh`#>!wZGG)U4(%^`8qaRl@(iuEprscL_Rrjj#SSKJeJ3gxtAWUs5QY5$Jw%} zcK9ipN=PG1_Fk!DQM2^6#eF40(w8eS%rn zx3$W8v@>Slp29=*g_L1@XE;1LIl)jPMc^L<(RAqW;~^m9A(~FQp;^HVOY%7kC3Tm@ z!~JKT`z$oO8BOdO8QLkx+{($wAi%qn%jHCq5pwQGlXGhko(uLZ z)83t{?fA@>?9>wORCxHne;ZyvuHVz;&&ulGeU!zb9AZMYnR!Q0yS6~jW5awV-k@cz zLO>rSA)W!~4NbobWO)FO2-tD`349<=3|A;s#L2h{x6Sdi;2>7dKud7Uu;=Q!?FH<} z;;0dxg}xc>DZOyrSF7AVrspu#F)0Eu3HL&EaN+RMGDEO_3flo8xQoOf4_81dK(A)% zN@bU7q}~R$$zsu>u)y0Iz}vKGeh+3R2;7;ZuYkThd?l(&5LB!5qnw5r>GM${o_r%6 z=nJB!p;5Bl5lXx-K1kF?*<6~|hV3Gu5woCgb|@-yI3rYf$H3v$59XbZ18?C08uVIi za{=A0VC?2p^`$En{7A5oq>O&Ojw?ICTM%-FjmI`PMyl5B!1G`R$bh=helgpB7n*!4 z{U*E~Z7|{pI**aA48cX}C~xBxZ!o3B@IjFU>D=X9xUtYecX1|BV`M=}=4}nw7tYR&zhHht6yI2q5x>{o-QLS*CvhU|b2bE%HSz6*B#OXTN{kc0TyhQ%J# zVIKA!!r+8N*rF2&JbVH^Btan|NQi%ckD!QzKY%DwK>Ps+l<)kid!Bo@dv_LjSUT@a zPd}=DT~%FGT~}+rc>CTF`A_T%eQvoME!{L-&tzdDrcKX?d(4fJ8_BWfk}FA5)C2u; z=*5A-5;1}v2DcnDU~Y0D5ew8kvYfD$j-Lvd5m}y_59c*L$)_$POS{W*y&B*~|n91g3#+cW{ z9fJ_c#CLFqLKY{n$-Tj{*c7uMb=ilVrPake5hD$zd}kH&Q{U)0CqiGR^I;l8U=J^` zghcovR_UgO^3$+Ab%|*|pfd&j8HDAgDrnCS18tf>Q;1E|Qd_~|SNIPJnX3gd{72Fl zV9O6k^2p5f7_66L;Z!JX{8%a-1GO-l{O4OHXT_KcI-MUl2SF>&Sfbc#+c>n7>aI>I zRZYb01LO_Irj!V%qnPf*jw89{FA#f-FA-a-qoAZsh)L~GB5inXRQ4}&)mxOcJYs(=?{Zz;8bhhfxE%)v%&QIOojv!|W9N=%@kr~@$G&?0>&5GtwXdB$p7|gj;R?mpoK{t*VYMu(CE3V{|7*dvH{G-L@pB#27B@Gk8C zOS@)M%uNuiELLJA-SrW%m~qQ`KG#DlEOkQGiV|K*0pxRay*K;T8|tCjzg6`AM$$jH zD-wUKlX{~<`mBT#+wdLBu%hI;n8K@aN#BrtBRxPUmDq1#V*8i)@0$H9dL#_(U*kWC z-m7?k6z1rS9@_~#9Po{QUcJ%Sx!>Kp5w9FNv8(PWt>x`3o!fo6I68_S#)ucdcD zuKM{~e{hnz`ZpV!JVar-%suZhrPLf0p7c+6vk}U{{)w7opFg@7#jcN4%}Z5>hlVM3 zEgvhce%z5tKTcbMmBp<+l+D}vA=hGgrrnWqwViL-r_Pir8gBi@pWD72M}z8ArL{GbR{IW2HYhUr0)`GVD}9m4=XckgB9m=VD2#?Zf~jsg zM6o|Zgs8kwim~*p$I!fUta5anA!X{O(TI#v$j$Crmzdk2I~HG$c%Ba0W$%1T>~loK zA$vWgg)eOLX!1o5N^ZB}q)ZM%&${EiAQ(va6W-80DrMDyeDRz2KC2 zk0uRT%C;UNZ2!1KKjo|nT*gcawse^#q}v{OETjUW z+(%oK7AWcJ0G<57uDL2ZHftDFI5w$UxPit2ZXtat`w{kQB_b6H_8X-pBx$1{cl+qM zx)(p|o3DBf^vP`I_Ps3W8{GA#-M$-`crZGt+n1xW#qH|{2RpT`+qX@>)*dA!M^Wr` zBn(CW`h}6~znIOO!FUJ6DW*uBK~j`mI)l3Gy0dmqDf5{JhWUGrg4FAGFkM+T2MY+1 zn?{9i)1ck!^^wPM-^~K(a2Vlom{KJ{$&P1|zEiiHaIsTQY}fmH;Y<4Nf0w`x=Re&p z;(t%uHB?ya)OXM9d3F>H9mL_g+u1>y@5MGA{Oh1~hzC!f;lWRhsmY(ZP??*io@y!~xZQ zXnCc_T-Ks0KEyOqauJRMl(Ov4Yg3S9pgSis5tC2Llw1*7?^_e~E_10?zzY(*AXs3K z&Yq8#S+xujHSR^c&ZMt#;NWdO@(hhCMCdD)t5FpOE_M!dJTG#Q{wjT39i@!B5xH?s z+knvb60|J9pj*CXcs;7O2{Gj%)xsPmTQn+9(6Txete6f+3s=^}T)=!Uz!f`{H6*KJ zVuqvcA$zTf{cOVmRuQh8!=kljvUc3XatoLBz@?M~=4E;hE%hkCH7+rQG{}PG`f;Q& z*YGHDk%)R6b(X)hEH4fZS3hbj2)sb!x@)551vnF_xKkASyf~`PQj@bJVyW*--xT&k zkVLVd<}GN*Mjx(z=o>5+iH8tCaX{qAtLb@1ce}CPWkB4-RrMGun8YmsGrYjmOh)M$ zEJI~9Yhn_YlpWlU0ujs9aHrj|Ht3#nL60L(E1JZZ1)-WZ?`asZ1gG zaWMyGLa2Z&e!-;kX*Z4BCt2=vke;vzF6!w55<5(@nb`7KlzQc_5YhdlRgfIF3qf?O z9@0MF9QntGHL>6`U!!agv=LXeSO)nm9}*AhNj*e^N0A?%SXsGz`EtwOjJW5vyr8>c zvP&!I8LlMaHX0#G!3Zrv+RK6NQ4Im}myh1}Adp=MI!50z)KV;SI9n$2JQSf>Eb7Q* zc+_*SL_N~m&>}P9$?CLNf=u?bTs?F0HC4QDT`Y#1ZlrH$-0E@%e~{k^hcb_1F6`-0 zG?~^80n{z>UA-b5VdyEeO9n?K*1*OqeFMr8LX5r``^cG5!JMpuOYOjQNRMY&ZU-`u z8HNL7D#Ey3?YGE!ZDvAOH?bCHNVHuSw;7J7U(^_Gj2#WNA}GF~lD2DNoVk~%{!L6P z69Jusc;V96g1|?b%G60=*pG!EE)lBuAPOc`yIp}1tF)4PC7Ur@Cx4kFwLmc)x=&G~ zdbSs#xAr{#3q_rpDMLt|-F7NRVWTY&k=~&E{WlaJ#kIbo5Op=qWYo8 z53<>7drmICvg@sVjd|~SWyX58svLBnGCxj-Afn^ww*I-&FC$_G2G8(fGG~dHHE_KJ z8G^Ln(3?7)w%@=GznH8;WpS?yBLIO3VQXnY?D0al8A8Fc*5de0i$hBn2DhJgVFj@O zVmvBxfI`w*d3-ialI59GF{F~0^{oxn=sKz<%%z{vfX&6}mx&RVYF#3szJ*QH|B8Iz8z)VdRk Hal7?D7nRSG literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.labelers.base_data_labeler.doctree b/docs/0.10.5/doctrees/dataprofiler.labelers.base_data_labeler.doctree new file mode 100644 index 0000000000000000000000000000000000000000..8befbbb137a7344688fa38a4386a000ec8f45280 GIT binary patch literal 220960 zcmdpf37lm`bvLumGy}*sicP~~?}45M0a06!Z5*~?kwuYlY+iT2nfET;?=|ne9%c|! zV&ZxYQJNSNHwY0oh<+b2E}x29)aV!e+%=n96cUXw8u#Tp=hSkm>Q>dQy6?Toboj;0 z>s#BYf1Pvc)TyddFI;u^x%(~K5C2OK>de<0&E4bGnVDv5rq)?Z*Uq%27v^fs?&4jG z8}C@WeQ`8h*RI~uX)Uy;Ym4cAkYl>un4M|Ynv2^P(*rSkw=vrp=jGRQYSZ0Dt0{}u zSJhY7*KA)Lt*=X0bsOE;nv#?rd_lESt8A`ztCg+QsoHF3uSi$UHk!4?D;B1z=}@)XZ8xSCy3kkb+lt0a z2m7&RdbZl>z(@GKs#%?5zt+wy%x8a0Ri|%i*LGl@g>+4~x)YNY>j%|`>+9=B)>qU= z((6yXu2XAwPQCnDH=O>IGftgvx024OGtfKuwW9&OI~6GGoXRNE62@m)_dDZLfXF14 zndG0w+a2iMQI{=Wn5yrWu4*)AYP%H-8NBtQp*!_s0J`Jge<#5IPJ;h!#I6B4?FMyd zG+jAgZL}BDQ|DSU3$wMSR#e(NBrK-mti-0!0`=8bbQh}&^;7Db6nyS1#AipX+FfYZ zCa2of=5$?y=u`pGsdzN(9!13N^3`OzW~-{0PDJR9k5Y#XS+IISD;NVxUkji zRvXPur8)(bSEsub&M1`~?bcl7mU?5lUg31fq+1%Zvz11(UTZhH&_8vDHTePw}8yS$g+aP$?cVMDp$0cwXw=vqr0PITt0IC-p{Z`VLQ?y4;!PbN^y4z4%f zxR2?D{P?1b0dDIVZZKVe2&{SQ!_Dz7Y{NRQuHMET_^ZeK7!XG!Hn9q*r=P(J8gs> zLWH8~o~w0h?b!y*l**u7(7VV;iD8l|n^Kz@@irrCpy5DSpEQwO!z&Po%D;6a|I&?Q zx~#caRmT^{_5pzGt;Dv65l-0j{6cfOyO5LlWfP)p_@%e{u&>qme5)Vit!_w{Rg9|M zs#aBhP$>NL08OJwz}C;#nlqr@CwGI{r2x(?o(<_*QO;=RYic|0nGr18+K!pl98BGJtKU@O6g?w)zjRjWvD7AZ@&+TK~~g8q`tfw{0}f>}h1=}Cd2j|yfd;(RxL>duKM>ftm=CMj>Y!&`y1LP%m5id{R^r?*=wN?n(wm&?Ck1rU zj_Sf}cXC&CcA=(|l^)tzn4fR8yOW){YP);$LJL<-F9Xg^&XLp_C@btDW|;e-TYnCC zzD2NNdR&01LVX%lbi{hKkm#}gQSbS)y*;m6`60Ou3h5H*RE)_^e*;#=6bV?L9a7#v9*&iW zmLZyN@V5{T1#6@X3~rV8EH-zTn}ewo+z$6&*L=kOCuZF&#p) zxHXl4FKtmX+tbz2R!9BO`s#G;j)mD-GCS*cq3JPGA3+)}TLv^$QR~oz$5uDf;PX%& zfMP{HT0c+n#0Fdoz%rAWGZQy5T5sfF!XhW;i(r{_%NQ z($!>7PRE#picOVNp#IFPk|yZ>P-|`X{A^>o(OrBQWw@o(ZeejoR$Yq~RCfYa!T=pkzg(2*;c(X|B|VfRC83 zp(AWi^^@!hR5YCIi0MZ%!#ZEZf0%McOH@)a)tcFpqZE?&p90NZ>)QK>n=b3H_miMJ z=kmof0XdqxAS#9#Zx;hG&hmRt`{!aB0m+^N)=O1A~q$?|UqlO zlseLROKM$3%4s-xA+zwEETY6EwHakDMu@dZ3Hyqg& za30rNGqC@2cAzWI+#eW63iM4NIT6Y3-Kb0SXuT#rq(>PPQGL*(O;4lE9j<);NakP3 z+GD0K`$MuT3E|2Wx@hRkGg^OL{q>raD;6{0Wl#2#Wz+li@qHPNJ8jO~E74g#$~L-m z2cTu?1}ie9x5**cac!fgU4vb@W=Eaml$EH(<3R2>eJGBTa2Dx9m-8iE0rsixie^;! z7XZxGA5M-20({FBKK9875^4t|Qz*%=KzP|&HTeZBIg($(|I=70`7N$Qf}P^9JiRN~ z4=PO$vk3uh6~bzj4-PE~euMghEc|3S{1oHPCQ5acdemmvQi9_iwMums7mri3H85_3 z0VnO#qHJ&y7Y7e1U!N=)K_Yyg&btRQZ)SB|eo1qFq04MSFdycs-42-+u-lj! z5aUBvE_ChLTAi+vPZ-aAt~DE}XS0!dR_sV6&%_dJDUsojY|HUka%1k(Xi`(YrE9L{ z+C!Mb;%`YMsp^|zNEEAtIu?>b0pgu3C`~g-PzFy?S{qXKha`gk4U&Ib3?;Da9!~Z^ z37={~1D)FtNO7PIQ46S*+Yn-i#3Y+3D)Sr^lClgi0;+}nkO0EozFu&YxrA0T!@zXG z@h!vT%|K_m26QuR87BARpR|ju{Jo~xVh6Tx-=scC<|<#Lau-2qv*#*0cQiRyou9{3 zPo=FN5KGwJ>h1yi=jmnbAB~hA451No4lpVPi)XZclhF7u|8d$YLZK*MB!`ojeGEoN zT`cGpk-8icwh$apNgkG^(g*f+TgZTl44KSiJith1wxjV?hwKZo^ES)HZ$xImC7;J? zh?;ER*sh82-A+_2J2l_*wq877S-Y8RC+~+!2V=bya4t$em@!L_i^wAQ03QpOXZ#k| z2+VPC*mPH|(yiB+d$m$)PPgzFN9JBF$R)Wj`3<%^oct=76%b}T?6~BFm0oJF)r2@_a<}9GSZIXH)MbSR#~2DU9#U-YAuACMSGT4caO?;sDpEw;MFmHh;YLhOmhD2=K40Mk2aiv*CwpKm^YV~HE*mW^!B3472BOM>b~uI8vo*A$r49dUGx!H+F1;%TRbehYh=oSD%=cz45x3OHUSgJ0h`E$6 zB)P?FF6GMsUwtG70Wz091SJB^B}6LFTzY#zt=wD^tPy1{32~MKSIS)aK2XWbr61rg zGMDJrV9cdUxH;Vq_s`SH+DC#h)k}X-8(?&vY;$&di`_-!8`9+*KC4%iv4ED#Qt6xb zbqh$KZkRl)#dl`oh(DzQAfx7R+0S^RCc`K>468AX8ai&1`F7|}z4ha~t-FjGTf2%; z^BWMi!5B3z?i5zc(%}>`TYd*X1?`_5s+ldsR?*`APH|NOW~D3C9@R%5Py-SK)(iKDO{;;)%L}ovbn6ipiiM9D-7&%4dN}W~zJ+f03y|zXoHfTs5zrmhX$J zru4~Pjg%ftm)!YCqvG-=%%dhADG^k<8pR##gBr$h7&n?0mdw zlL43f4689rn=z;7MdNARVKeS=*w~8cy;;4cHwMW1p_n({fW8gJyeW_bVdm`fM_3KE zW6>AB#W|~txuaF+Gk1)Pk{gm^krRfKN-#qRb7yISJ;M7r*v+RW#-J(8p3||=2$!s4 zv*%dV?9qldXa0m_l^l_VB}we3p}fDn!WhCOKvr6Wg&&fGdg-OgibSk zI9aWutds0IjQjTYP*y^C2h>lJ`DvLfoS_+y*#?a2)Z*8H-miF~pQPM9fD; zHab*+|I{tQbLjK<`1r;#N+b81`B5`Yv&110TOVF7flw1_tgUp!OO=?y3vy*FavEci z@fa3K#xVCtQo(Ai@A{o1r|Yi*poO7z9dah4cE-Vc3JR zRP?PEz8P3iL5_W}AcqNAtj%N_>;JQ3`VXrb$senr^UtKt8i~Lzr`2IH zS{%|vjrGV6xT~Kev9$7fAcj)mH+dTt8sWBNq2J{CS3#^Lt{mZgnCUJo8aL7G#_wKZ zEMIuu04Kp}1$cyA#;)va?5Z^-XADU@rc!M}oIr@|BkpV0W-7#0WcJ9&NswIWEKJuY zmd>JZ;t6L?R7RhE_0?Bied-w-E7vt4qAo;NhW_D|Cjbczk8v^p915KUOw4Bdu_22d zM&p570(uxlv2qmGBG{m1Dw{awBf%V_hE6;HO63D$eh|Kbve=L=uZ$YaV3MjHv*^ow zcH1v~jEM4Co13p!I}JSq8p0$dVYXh=Isa=$1Abli70f-He31xtXI0maEIf}TFfv8n z(N~no-$TW2yl5dQ!BS@v8j>7VjtHZy3H~W6dT0E@=MoK#?20k&No`HpeCsYv( zjqRa2Bc)vwLkR)A8A=q59tRjHjsnt9pjq?_-inm1zX`QQx-a;FM9>&m)$FnWc09Au+{W%$x26Qi(;YzLAb{% z9f(LiSydnXQyvC%ZzHUewTWp%`69JC&4Mq7@p3D!f=vWjHht^9ZZ9f`7<&jCg8?Tn zN0sM}hO(kOE%UdpqBMa&|4YaI9*JMf?gA8oDKu<%!QX&mcY!rv+g&iKQ+5~VX)v;Y z^PX@@(|i7Lqoy$1(DQ5&wGkFH_rugbqeaKo0%dh8VQp)H@+!trLBWLf&cNlF!Jo8h319qO_4On;vQ&jz;@Qn3sz&!h8FH-49tRK>AHbzwOXQ}H8 z4-aJxg)!1vAV8Ny_w!dr`-!!q${WZ-Vv(p#{s!XFh>)l}5bg)C&hyjh1HzC)FRME^ z5xhg84`5yICDi)>mR}lxhPVf?58J*8h9!!lGkg+c`@Spi>0t9e}X^zux0u( zZ|Btu4lXJ0ZOilzpnacp&!LiArWOP;?2q}2Y{!&_gzcDeGJzNUQ9mo^ z&&+^-k!%^y~)q$*s8%>Jym$|4<6*@Zeh!m{hvl< zZUY8=G~Ac^Ln6+dRn>w~zSN&U#cpiKmnwnD`BHPZIDDy=d>g}ALu!yTq7Wz=v(-!? zTedUFr}O0klyN}#yG~!AtbS>j=C*xB%7av>^(v33j9FyBK-#+4jhiv_o)bLd+t@@! zhVa-52oOAXA%ZWnyi5@rFFeUL1ZP6|w?vYB0H^G)bG4hh+zcXK>pBVQatIG5^-Xxr zGb(e_tO(CJM4UUTDm=*=$V|_a880;2HX<&7yl!krcqA}6;mP6R5FSgus|UbGk~h*p z)DGfk_M=!Fk1rUvoH%-`6whRREVfvt7Z-~4Yx~>Y1n|Tog9@6_o zSg2r5S2kIcbBvxhL|zj^32D*AfMMeRBgIhw`$w32#)b72=Nad=u>{cK8D9hB`aI*9 z&OGBE#$R-do_-C+Gfv0oNfqn^$LJXyJ^03-WG-d!066a*`)8s;0m^Qp^AK(~I31lA z`=Wkk9M|RG{8W&$Ep00 z1TDh*{R1eZ``p}T>wo8O!0u||4Osj~n4&U>;>p}!VMn%r$sN1^#fq7X^BRY**Xwj^ zchxlU_%K-`VgAd5p>Z3|98OiRRWb9>RRj5-vZ;ukM8z@@xqUSBsK*=M>r+x6e?d%!S z-aK#9(0+vH&4xgRbMpTHmBD!4td|wI0tA~3-v;7iLLQ+na5YlsdOQ9axSk;2+F>g} zr~54|vz+mgSK{CfC$9(|W9$h&zq2GRBZ%pTU0i-C@8n+b!M!O4QDLvY9t%k>0j{_B z;1qlPLe{^^C=1gHFW!suq0*Pq!GpfF2JlNea}=oA*)*m5*~C08PBL;BCD)Lh^jEYa!&!hy+7x8W1G=Y;O?#Yf+eG`fMs;qjipwbOYx@L|=gz85B~iY% z&p^d)bjV%6pfP%hZ+eUAcP0IykIlEs^pX#PA77dc1-|r$-tte%wEUw8e3O5M%%Sd> zpF-Xse8HN?xnpvi=WxeZ@|_$Ze-ghmrWELGv)ycxb9pl#EWjCAp0C4E69ulr|CF-! z?Fiub0lL7u#SY2kj*e5XP`Kg@b99^=LkT%L&V~{`Q$+z7DUJfzJG>&+qnP5N938?E zkpNm89VB(0BY>FB932hl7;|*cufaGvE`<~PsD1i!0Px(h2LL${J-9d?FtW&_839=EB_ko^eQS zx2t=$k5#7dI?!aNacgY?tb#6Fl04&dsDL3k*_y`_?CKFi1b92-!VAn}m0G*qYEQz| z&ACR0E*4Exrdq98NZ(SO?LY>2(rv2Mfx7wUYugJo^2x|KW3-+bN- z%J@C64Ent>&zEJ>`}g%@i4qON74wPzA&kJiA({W^>i&0(w~-yaT#0Q+JBj|#x$Cu( zLn2&HcSE62*VFy}2JEg7-hjpRgejUaob`2UKXnC1(l7y z%8&d#h=lG46*_I&GMfFJzu9=;JS`6bwnGloCDxFQNZ1b0rgQ_UiodCNsEpQ1!n4eM z2J{R+#XfKhYuN5&Ws20us^FkHSziT=23kFvpboQ{OSvg#D9a@#8ugPdL(lN{*WQWC zp-|{_GwE-@4k&NHGTmT`W4c)Z1|;inUN2Ib-tz^cCPNIAF$vUv)J7Ob-b?@*Eqbwb zKmqQ!&_lzo_V(9%XxKj-K!bK@c=;Kp3%Afue< zaPGU_`ww_~?}*v;USgK8TQ#5dH(-}G-hhS0FvTHl2VO~wv+C?NT9a{v@{*U`T+pHT zrct#a4DsTZH54X;|Coc-ZKVCgPplnQ-asA_+a}@igLI^Oh9f4TSsn`a1bMihP#+YA zjN0{`pBW?c-6k)gUVT?cgQo9%o;z|Foa?8ggwA6G8h9!q_WvGum}~V^h>B7G3qinT+xAnRyz~xFroSmVQ4gI z7b-s*5kj@t3NMq(Kv^mFOH7oX7sq+3vA^N=k?nBQQp!iu2-$qs+^m{1G~9 zEGLfS20-8;uCu(I54r27#|Ppk#lraRbZFeShi6>$vvofMF4+T+4Cc7eV;x&Z@|qtT z4LWP|JnlsUQSe{$JNGKK8^m7-#+YD@=KMmJ-SwNQcHpwsEpVD7cmI#Y%#pVMd#*=H zL-HJChT-IfV4i?YRyv`yg!X)Bkesm2zie2_uEHuK!+!47h{)*rg zxG_^1<@*;i+UDj=wwXCEcQWZBAr*p4P*XLrg9)s;0I_=6M6VxcD%=Qqc`zL6agytx zRQ@p2i{UF+)V8o}n50e4hH*b9`h5Cf0YDzqMz>hP%jtF#TRVVYP z<4pHJ#cq7)I1>X$@8>eNFW^08`o{;ri|zV(h0(-Btbdd$h}M;#DnrTNL?E3!1erq* zHhmiMmO$FO!}HBDJq*Em9bnDQBnY6DFFMNqS%!umLLuLbt@3je%0C$Z%0mb1D!?s< zio}MXJk*pLQoyW!(s3RxL&f8u&_Hk=fr?9Tvu|gqO#e8_u&7c3`;qWtil(<6M*%JQ zj&M&@a!687CNO=>S~K&~bDkh1!(EstfJT$NGS_@N1yzQG;jTWb_K zmf4MPg2*=is#{`wI#WMMAPDSg@YuO|M%+T)PAqGki!n(XQ}29{?RRZRE&E%$jLL$f zxO`XO9we>aANQ zA!_rE21F&Eu653#gK{>p$!&0P*~xvE@R9&M7|e`rCJ_SkHp15`K$sLRKr0bQF)^_} zbgDmUROglpWnz4o$a7~cEkYlMirwgt2r+0hQ#N@YP894wBUrV12miiI2RZ(J-Q*81 z@^59@ePmF;{-6}Fsn>E{afr@|ZhlZ$Cj?n#8v?EyTDBbyE7S79P-q}_)CQ=y1k*kd z8H6+Kc7tih%5;!JYcZrSMbjCM$;FcI+JR_YDWd6M>W4|q>`U>ac7K8JMNVor=C%|o zqsYrNmo;`&y5NiE=ezN`Sf^X7&Y(?qOSRqXR9f(gfOr;QNSyty(Y-S9?u2dbvg}rJ z9U#6ejgirrvK< z=N1%YVt)^j=gwMMrak}_yU`(;lF;O2Du;|irY!kRi{_I|e&Wl5te7+u%gP%IFwe<~ zw@MM1>Gl9O2EVU}TN8oT=^D)A(XYTv%MR69-pzOj0>7{LTV(8lofPGw_x^lAi5IlQ z8cO??4Y>9h#`2ID^5_!dK~TbHo?e!7wqrU&uweCV2p7+}`FE_}wZ?daoE1VY7 zJ%RovEEJBuvUD{}1ki!DrR>v#i7Km$c(VoC==|c5q!E8waXvBP2wl{O`vslH=Mr0= zQP)<*rnVeO%e7V7Q}J9|#dLOUbvJa3U0bDJgSobP4LxDpuFbbw;P~mZ+I_jddNI0~ zp~@YNSqQ{S!5ZMPw{hI9pTr~*t5rLuL0a;fw&`5v)#Z9YL)Bd>zdSM3&EiTkgazEYM=-?^_}GtJ{;+&8^c z9e`H5mtkTPRd%7K-&L!D#tziU7IUQeSs(Pb$bpNv{dpf03Oz6TZhr&zqkX&q%h5he zQJGW;JT_5Yniy93iLI9^b(}wA(5(xXdPqT?4n6lndm%0C5ZEValnp}dhY#6!xu-ex zc=(%a)hfp*MP58tm#LNHjR>ISTphhEPF|J#@EH$Vk+Jk&Jr6{0k-UBs)_oB}--bYj zbMjKCZ7@gcDn*l-JY&a3hK_H&oP%3<#_rT>cswtZS==g;6B`A2c82zfE+?fh89odc zXgE0n|A~2=Zb?pPG#VRtSNFe}TnD3w1*cP@N&9Hhe}m6Oeb z#oDf1dc2CA3oBtWgk{!yeZ4`BF>xpwUhz|1N8NL0RVTx!V|X_}#cp)TPbHzv`KfZq zI{Z|Ye8)?6@^P9(E)B~MddqApn*>}3V9qYUR`Fq=90smvM=5LHB3<1D)u~MEW(CD_ z^ha1ITy6O7%ZZmThm-qaC?S`@Jp_fHV(uhDilYGb4zGxGB@}#=%RtQ05DORf23v8-HrJY|&GyAtQ2Mb;Nk$J&f@^Jd73&-Qf7fbr3OyN= zgZu%PBN}cez&eFgw)$7TNbN(j)%Rco-4f_u_J3QJ-S;28R1h)N`%j1lp3Rflvc6;u z>gs(J5g{gE{+B*dzm;f5tkr)Bg+kZr>ks#_LfyVr=M7la>X@Q(maW9NMKwP>Yw;LT!q(nL0g1W&2m9Ka;qRU=#CrOEFd}|R%;27}L|$Bb zXR@9A7Y<|}*4~%(418~E?~81xD#OjYFV@~R1TvhHe*#nnv-ZxtUzh1Fu!1OvHX9OJ z=6!>US>dAlxNG>Ln^cW|p&gW0idAwmj_h#K3LaqW2Zqqz=U=hQps%wC+Oxcmdu3Jq z`!RruRrMWMXoO2`@v3?=V~0_j@}=WZEFF$xEOg*>2HbpvaN4GahP1SCEF)k_du?$4 z)Wuu^rSePVyWy*2sf_g~DY$Y$^Q97)od<{4;{WPca7=DUJfzJG^2k zEVOdeQdrEK5TUxQf+UyJk6e5=!yex|-Gi7)ZkzD7CNV*^s%XJh4K@)%;dlwfW_29ar<2a!D>j1pBa> zzo+Ms=xsIs`mpYc)w~UX4CmxbsBJK-`C|&FHMy0}hK5%4XK{23SM{e|qivoEw6MZs6F z&_AStJ6&$hbCT;v+a3W0k7%qG0;OZ)0-PMdF_)GYhMU@+A6?!!I8YkO!yO)L7|)rS&>L}dW`ZXtcHr+ z_>wY7cu^Vy7rbAjtbOw+ zoEybA+@o+d77AA$VIGC6VkjYx!sSrH$G(co1}TmL*gL$!qaf70nA`k?mMsU=h7&Ps zO8_k%g(HAmpGN`HnMdJP{6(AV^lLC4g=b9HYtuJPihHbmaVKoCuOY~lxhcg9G)ZgyY!!EcFzr_`6`J)j3DkEPltq zow98D;J)rSFtIVV;?M7ST$r(;I14I8Rq_(qGeU>tONc?VCFukCHaQp(o`5$)p-@l2 zd;AU9JpsG{izfh6RK`<00m^l6!vexPUzSJ^e`nOCGjWMS?yQlpMfTqkhDMY2MYbOe zSaF3uaq(~74trze7Sf=_$_)rW{Tn|mC8Fgr65aEj>WjFS&{xE6Zw7te@Hm}^gP7nD zC=@Dl$NL+w%N%dOB6FD1FPWP#>N5K7F!(+Guo#&;i!d~rw9A|yjR={0mbb%RnJc6r zR^}RhT1v)|_E6sXG;jwbranci~X_ zP8MAQ&vCRMs5P0n6at-aYu?7*vIO z@Pk-rgzEu^doVtP_2qf1Sqbxki4`*bVVAF>ZD3a#oyxB2Y-0xEE)9ugC^O3S%Q!aU zoA1uqk|Yb#0_z`wky3qI_d}_?@9?Ye)!{qDByDOpEN9(!s94x`i~2`Kb;eYyXglmiGMp7%Fz7L!LhgP0sU|L&o9xv*bH1ntSBfr}1S$S(!9s^MuPE_@x5O zad>#N+0Ro}f3(@97Ow2%BXqWRGoPD(L};ZGp)QAXVNxHZ>s+HcH`R)ColWGqv#QdS ztcJ{?@yySMyl!+zx+F9?>B=GFkSt7Az`h5ME&V2n3<1g~{)33q!`fr$RRc9u5v|DqN zvyG{CwY{eocmMQkwbQB0!Fr-KvvDykeTFbcR1bdto#tXISNUkOI#-*3pn`33;g{U0 z;7;S40U&lf@r=^`DCi+he0dC~P|lfl1mFY)rShGclW$t+Vi78kM;xFI*sUSK>Q}ICoZc!j3vb_%5i} zjSV?FBrrK=M-CT^BDD11B)GFHoMGz={R24yavPU?6tsj9w6 zJ_Z;EI!E&q6ey3Afux+>uh@cY#vV>iD$XZF6S0kA3BMF`*OQodqg+qIxROI{aXk^b zp0LlD&RkDb=ooW7(XYX{o}QJN9y5*3O?~t`l|F2$Q`CdgDK*4sT(5a_rqQ0ScI)JH z8mmwud&s9VQMq!y3lZ(Bv)k~AwC$C1D5&#)uV?C3;D@l8KrD07Gqp>W+V@YP>f@7h zOC4yYGoO_CSyzHDll_l(NM+b1FU4vMhtw0I8Hg15sB#={y;=oN%}%_o;i+OamVfJA ze51FE4j0y+L7`9=)&u?q>@F0F4&yE-VIx zd)^W9iY~0zP_+t+92cONa-6eXEhN}S|ETlOcl}7(`}HkG>xZPrY}tfp3x4Sh{KVgY zorib>79PSB2M-;n>u!!s-g;Uq@)?v49jRAs46$OZ1Tt0DP?*DPH4vbSru!B05kIkZ zSa}0^NLJ!(XTWiazlC@>SR-YjfQSQ3?ZXqxI)^>YPpA(HLo~hI?qEjn(1adOf2NmE z?@?L5KmZNeQCZ){FfC^4eo9Illw|}Ocq%-SS9QgC(OYkuikF19{v}?BLyqItA0<80 zt+wHe=wkU@gfNMF5zy;fp&8zK+qh&Sn%oR(dNAJl-0@w*IK-7Cy6X4&-gzKYg{*sqU)Hz|v;Aipv>%FcVjK(m7wQuvELrgUH-)h&Y(X+4_FTj>=nk zNB4?5{=+e-3eVpMvCs%#t~lKB@rQ`V_(CLe+~dNT-iO48BKWn@3dW}CSY7vW<-#X# z`M2aHb{aUi%c`I0%}^@u!2c?IbvW=bNi!Y|ODM{L|0AO^x4DQ8T5%Sbh;wIEEz2ke z{*R$zH#Y1nFtrWt!<+*@hl|63Z^<|8V+c9OsW%&F60_!PDsegSzf^!Ef-X+@Qr3bK zzUsmWLT-RPOc6DhW2ib?fmwKAuGZ{AKn>jUoSt2nsZl@|ELdrb*T$I#eP{I zoNH9)rdpAdvxz)+R#j4x)sQ*Rb)B3KdEMx+bG_8IO;U2mI3&fA?~?wpl4OdskClQH znp77{;c*3{l#@blmGXpdfNYBszLeEpE8n1dKT`vJJK+mmS0@uUt0D;EgfA8uV+dvkfdfWYY?M;gzK(;o8OPO&_Dyz}bmK!Y-4o;SE-Vy2 z9=VM-BFnHMiZ|#!6-;VbE$82$(+ww5c^{|o^YSpU#7Bzri48i$HgJQEiKd@>#My9= zVpZ(?g?Jnov8s|oZP}osImEL;hv{sC?$`K>&W6*k!EDfNCxZm9g-%Yl=H^>Xv_1N` zO}Dk=AxE~EX3$lBv+nv)2w~OO-m#&o$_Fs~gqO@$A#~LRy#~{016jgHZd% z5F0PI0U}f=ZttE>)hgS&d*_X+JNyG+@7L{&)}Za(JN*sV8J#y^VRTG!FnY|ZP7cP7 zsX}MuzcA=B_(R#~3S{IMQo|mfbVh7tcF4>4C>w$9yvx9wn$Z}VN zp<1#FF1mGgAXgcMyV+-K_3dUiVAlnsnZt#l%oidzvrCngsx3Ji*?c&e2t=?=ao9A5H>(d3; zDjRz@Qda-=`hVx6mhS=jR91I0jC;(*rujqESJ>fMUKurxp<*g5x=@>#2O8D0L*iSwz*v~!>i*^cy zs}b#+>@_LLJ7c;hh9|{B;ltCXlPUKFlUi0;`A?>t34)QWV@PwoiN?>%(!>(4FU}`e z0{wT#e;`bS+W{0EGc zI`8Tn?vI%FeOWer$G(0bL&wE9?2x|)t!$Cz6V(WR@+tvW!18Y$<~7IoV0LWvuYf|K zTm6Uo8?f&W@dhmWLztqng|gM3MHDieHDK0Jn%?tMjGA-?D{%vj+6dcsIf(!?TD0%G zFeuy_R^3Ja9Vu?3T4f_bH99qHOV}nEKx`F+MW^Z?TL-6Y^dhD zFP_-7A&}vmd=F3=%nrwqK7A^7Hu$KJH~LYo&kFYmPP+!?o?O&0^vPl*vCe#Ly0N37 z+- zFjScCz|W=*>s0aAMrCddtGF{BBI4Xx)fGaN`~AI8u^Ss&6i8rl&cqxp4tItn-?0IF zA+>E5-ewM4*ik|^;eJe#w zXDh``fB{=6(l75y(cdR_#iCwi+)%%b3@yFLC=>rxEW}_f=JebA^BO?Te%JV?gsC2me!yqI3=1oM<;{okiH3t#3;&y0%?yG^g^n+iZhK zt0H_^Sd25iqRm3+uV#>lwXFD4iXi#6u7&YZNq6f3VVmQHf~#by^uB#<{c6LPUm$qC z9EH))p%>_d7tryYmPpwz8oa#z3Qe8_%C~DMCsSArt-Ujk#bNfI@=FlbM4h&q3ut>? z{q*U$9O9j%O;P)@Q#0!GMzwja`6zX5N+uwlQ zzrY)?_!lrm6(p&+=U zX8p6DMjr_JFvX$YdJPb`#i&{zf6e9$ z6YCfScR>zPw}N}NpHMrbyn(!evxW57>2E<{;XqxV4-RNoad{ZrD(+T4kvj+ol8v5>kAFZVM>3KFJg0S4N>~Ohi+GX+30|-c1M$=p?T(D z0K0IL#m9gis6!zWfbn^#%jfz@SCc(9y_k$)t%@2?z5zwkHIUrhGhbUwxiiCdK=PJq zySezX*;@{v;k|jlM zPP=Adig_g98i*kbu=`W(R;H`X$`tGlp?{|~qip@e7L@##{0b=XkxbTLiK8xC z0mG2dX?e@N*tI=$RkaPT5Or&97L5(ovg#*ED>=4~j3HDwxR1a>BVt+rwzup|#YbU0 zT5Mo#+ElTH+ha37^+`VyvI&w%P^ziL(GTQ9t;lFdj2DW?>ASywjooBm%Wk;BPpM4Ol2M8LpJl+}Nu;n@^IgvE60RA6M-&wV9Q zVAa6d-S41*-A;(WfLR9?Q;mV`V_>?B8~Ru&u#ic0F$>*5D7c|SN#HRj84G!<6i19t z4ycu%Wkvl`Fqewws5S)D$`39IwJK(}(pxK+?PzpkLR8s&%-I9R=Y?9vwra+K6n%?D z&K|Oxo?Vu2yXqX>JwdbK`R#Uf&sb%T_SY_$ErDo=xIEdJpKWv}Dmy?+bm0}5)5cGS zU6|@rZ5Ay5*+!>ZxeX#RPvbwhugTw;8LPBwaL;w}mRe(Hy$d;~TCG_~+ftqF)W#}P z)$VkCvI7(H1VkXkYR`aLYxAw?I^<-?9`od>H!}hZR4(9wmqa10=GUMAykc~?H((Jk9$^9oiPtnwTi!a zy{hc;ys}5~${vGP4mv@{K8V!)p-`v`dBopY_wehOKPM~Sn7s{8^II(z33l;`r%hvjy>7mb^wAw zmr>By=dwH*FBl5TuKxW38=?NM^LE>-{tIc))W7faF%7^@KP4q507jsJr!tUU^L*Ij zJIJa21GLOSLl|Fm?e{`&cO4VKZBR%TCU?x-KlC?X7bf0-MJHm4rW3Pu?Mn2kuufaF z6(#C@zt5TY?AqUpoF@@Y7O4 z)EJ2+MGfNftbpnShUtd^SKiNcG2>q5g}Teyj}K+Rv`_VXe~cOu3+$| z4*a=(DoO|yBd(-S9b`DNbMmyBWe~C?{?t2ly|+^iIl7j3AWV*S_#3dx5pTdEN0`zd zIl9fLX)nvsZo<%L)GkMUG$Q2awcaj!<*1MbO^%j5L2w=X(i!gUei}+h5hJan6dhf# z`;(KZgL4H$S1l=e*FWa%xwu^Y0$(iz#@FCpOzA0$4HD3yW+ffP&M27Og@C$ zMV2@eayQoIJh3>U&hmD?#I{qUBkFW$KW8&3EYH`eA`XQOfegFkEr3dYkLt3smUvn> zeVl6}UxuMzgF@%v-iG57a)$SmEsbtI3I%)h6W{;DU=(8-)KQ#ep1eZ!{{@ z=OI=7A%Xnm<<}8`?yTzKGAdfdJy5Y1BD$Z*@X@-Oyzemp3_EVKY@12jbi#yH&Tk;)dov!4F zr1o?$dd#{qqtSK9`$YxffK0_t=)RD$`VVNw8EIe80 ztnEHZH5ojpUWO9q^|ujATW4)d(#G36s|3v2U8BMv$-kKhbZ0HC-gZI7UWjPcX8459 z+G&|S@b!8}d?V!+pLs_)_v-U$}IvE1DGDmZ)l`lHbA1_10 zM+OD-Ck6xbKbGla2+-;j&5>3==}`ZB87ls5P*DFzS*X3U_Ue;$wd+=Wihab9w#?d? zqG@r*tZm76YV1rV2P=&(3Uj?lLGfIFeZj~^&h=NAXHYAnbRv^2xbZp%zCR{BJGk_& zW9Z0gr!w7cbvm1};zQ{AAtTgy3@U$`mGgW)L4rxz{ET3(@Xl#s+CLSlb1c>|Nn;rA zw4|O{1^7*hEYmV&#G*{**wHIK42KC%wEP#OXGI%xXnrQiM1a z`@ZfrDs;<;GC#bU2y|yHEl#h2ioFn#I5B*}t>_2J^pOvOS6#7f4$d036TTlP)AIWU zh3<#SqU*Pszf`7^LGaQMTmi4;(C>H4wEXQs!TU&Ac)bSPZ_D(NqiZqXFhx@!jtR$- z@0{M0t5lh3j}^f*WKvf=4ecoy^~h=Ha_zipWfYHJl3}-Hwz?B%l^F~RF$Zx&D!0^Y zVC2C(1T#_#cKKTDQZ8D4L;PZ{ZQ?P`&T=U*zDi7K8am|^eQezd+N)#5G;|VF=dkK9 zN#i2Fn#_*JLfmD`aoF>W>fD4Ylh8Rto;z#lN$3Ko*b5L%LK2;vO_u}5A!3$%Pb|ki zk`2<56@W;Y)D(-<@dX1ADN^TW$6G6-aO9K3=^Bg{0~TDZI$dY?)#2f0xT=m428$wQ z*@1A;R=G`#)DyB?hSX0IITE1V!F=fD4I1bYUR)-I3{;cCE_&#TQD6eL^#4dHjE{D@PrTz15t5;~Hbj|VfL zmobFge3+23$_*yVw!ROS{2MQ*-A#JRJUmYaWoioNiV+(>M4a+8C`AvczM7xaO5 zBuAwEs0}2{q_bGUK3Fg`krH-e?j);X=YcPw+g^ZEHI%6X(Na3yT6G5JDh$`xskE99 zTZ@MW8xoOI;D`;p2r%E6ug!vKXq&Grhh(|vSyCkCB!!2J>9XPGQ7@YbDLfFWbC`da z6fT9zSy;RIcal+^n{Y)Ak0%-8 zfybUi0q-Aq9#c#l<`luU{Ds&XGKn~UD}l8un`u%sC3A)XJEW88r=Q`KHGvzrTKPiM`O0u9w%QngsdE&g5$)Km^8^h zS>Kfzmjv|?{_NS-Q`55MQR?snE$JL|QjT#9(|UPpriQ+jr%|LcHis(jrmmB<3Ncl_ zNSPo({jgUI`~k>5Aj_r?E{OnS3M@t#vL{5N&ydZcewD02eSLKm5g~?*|D_MtS0&^T zA;P{0g}{nY;#asYjDOePfc<(9Z@_Xr2vamGDZ4O!vPU8fPG^u9{xz6 zm<{C#G8RKh@P(wG)4&O<4X4_30 zOOTBdHt9TJ^iLr~wO>{2dk(U343OYEc4}OVwJLkE)4C;j)mqlhB!r^E<{@=^x03CvLy6ni)W*70~>|w zV@Dx*7M5TE!?T|4g)2p~F_elcMGY)8!u6HoN|7=un`yQIzXsZZ#>_(wc$N<1vCx67 zEI4@#{tMwq6yA55qKujNSn?eo#61$c zG%P=;QnRgWLUJACzqJ5f90|UFMG*>I!0w=|#a9WXr-1wNC@ui}tr$wkL-5Z8g`Z*$Fj5=^uy=UHBe+60M|lW@xgY_wcnIDO zmy7ZLNtqm}g2@Y~BmMvnhi#IRmRP95|o&AHwpSV>7?f#r^6S zuQ_wTtXFFmww?Y_AHGYy!{>-ivjqx;I-johH(+-@@dhl;CrnXgSBXzQVb>}lI*}n| zSkK^$>ZM8@=cYlo+n`VlV%0&SU-0gUv|wjdLIZ8kYIjz#A#+QClDvCq|7@e2IzK?GTj+D+t3Ehi%@5Aq%k~3H6aKq>akPF6yaRh2 z{LhZW7YVe$ZH0VGY6Es|=M7l69a9|K{?tg#uG*U})!tK`I^@4LC^vX6ULJa)Em%N) zPGfBl>tl-;0V&RlI}tVmFga>P7St#`+dlNPN}-wEx5w)m``#+m2mgdqb+$F|j34~o zhzlP5V}S06?GoEaWn-Ki3A{A0?UIebi)68Lvb0xdwApYJS1J(Y%l}UD8CzR$KF{=B zS9Y{pbFlN%=yu>hEM3XXyee|{p;TGP|H)S5{o&-&U=a`-KudZ7O~Z2$@AF;>!ZsNL zu<)Ng2Mdkxg|%bHB>s)nZR!HEG8(eDqWu=>Ji_fTWJtIVjy$VY$IKr+GMm13e^tDs^pz_dFf(ar77(W7J*iT?kB4TQZNJ=yGM>xa5k$o+yW&6vjUq z&AB_K$j#S@e0Nq=Zj$>Tb7mvD|#P z0NzNsd9JpM_RL!9!qGo%sX1-)ma#_X{AhfYSP~;1ewxnrZtn6jh>);@p*qLRg-PKO zc7k)}%7Fm#9GF}0`pE`C?yf5`coKEcowc+KjzPs!vduTt(S!}$P=7XM?c0fk`6!0uCl=!dl~7}GtmK6)J%3LmY*+{0wp{h$QxnRTKc3MRU&B6E;YtlHj5BkI24;1GU zhmR2LC?@gi5`KF|tiq$t#t6@f9DK{!nEODT_|C>)Iy)QlJ?I#_Jwv|+b2jD~)tMP~ zo2BOiG4d!(Z?|V8LFLcCq|dO4)VQp9lw7+Ll}@)kR)NsCwaIE{qH^Ut9;&U*ZiCO; zE9cN<89GxUkF1ZXw`OE*LZhzBzUcC}-xGABNN0clL55!g6EK4+ee1qJY;Ic?#G*&z&4!&S9K^93O$8z zg1-U#UKMY^vR8#EngN~lb_MVy>uY{mpftVbPc>@NxlWDIug(IVa{<&w@GiiU2t%V$ z`yLQO!>yLp4gQ0uT7^GGyz-l4nKeASU>fxhxYbe;ooxwQaj#XEcnW%ciEPIHsLBBesARk~J-qJUW{H4zHC z(VVI6#&ZOC$9ZmHw%gc5MTYQ%0f-UYcGmMUb!=SdluHZFhw^WUBv~ByKo?ZTb~Bil zN5tmL>j@F-_9rH(E%hWq?=~uPla0g0pMd+{M4UUTDniNakU4a7^F5H)3lE8q#3m;~ zIcOXrWXX5+0JuqVNIHnxK`70B6bt2_77SfZD7{sREt@R?wermXoG=6Zyr)yvzHQn3 z8md#}#?8M70^hRv1r{op-<2&J-@+ujWO~3E5tNW4eF#eU>}jN!1B?_$0qh@P?noDw zn6Nheg?Jb$VJAxfEspftfn1*>9n+a3{YiiUbEMO+!8p>NIbE+!-!v&A752}Yei?3( z!{%+dSX4SyJ-F1HR+qY7{b=W=#{8sqBx0h1(W}9mzNI?b5y2lPTg^!k;8D-u_O~CX zHzj-?=4YunX>PsBD=&V}`&L-`l*UGC{e zHJ?0=eAY;?_w^+NqtU9}A?ODL*0>wtx{wTTv+Nwf0Pss6@3(mS>~#nh(x5p610K46 zpP!ZzE4B6&yWg6!%lG$(kLFt~h0VoA}5;S1ibJH+m@jN+hekZ<}M zu!|jUz#?{-(l4?5nNgP^0E!29Fk<&(g3)NzE_QxEBE;^nGj;s**1cj^NJFgHo#>~f zgxE0>W5ljFFM8rLOCfnKGEE;m@lW@5ey@1q&j%8GD+jKmk`cI6=KvvtFS!VS8JH*j zxB%N!T;SqEL|)=cxQK&<_-{g8bRin|@?jcwy@W?h>Cn>v6t@W;B5XCAwP}291Kvu< zH*7HK48$B}LC>YvzHjwOb)DRV95b9Wf*A)^ey~CuS%Stbjol93Q5d^zImh{E@!Egr zDiLd5MyFOkNnmLm@%$K6g$LkySZGA>8^}^$Jp7mE&1faaJ|6DeH#7-H_ne5WpmDt~ab{{W6DQb=yPg zKWJ2^PkpM!MVATpXTF`tb7xg8gQzWmcS6NpfXJUI(aHHUbKp4qnU;K~Me~s4fHb}= zs4SC)Y}RmX5WKnob{rvo`RPu|>faz(YR^`D5Bj8XzMKENEF^XezD*EWcMLE|ZOOl5 zP$*-+HmY+IuE^Lgh&*>zRmPH!LgvstgWp14FF+(?5}llk<-l>sm?d9-o|(wxu0QpG zESj_y%i=c*h9@VB-YUhuKpIdhcU$8$8|b#)O<9X=0~u^m?A(cGEF|J&6iIuETc0`f= zp^MQUdzshoq<^(6o8GstACG4^7_Rx{qZ^qM^k_B0k>XquzCd&|WW7!9!;bgC(eS?| zfL6!4LWnxgs?Oz}kNo{5kl<5AhNHm-LZ)$&S3+$Ab2J=bbu`exg2JTJer#Z9iFzl; zw$QzB)aF`ey4}E7?z8y*AcoVIPoZ_B*Ptky6szQG*z$1l6;6QAvEB)aoB>NkhzQ>= zN_>?G^YTlY@W2y$jR21C%vB*w4IblB!+~_hhpwb|pe)(c+prn*eXcbdsYlpIeK&Tb zl7GPxEXIC@gT)onH*4pYF(e9W=Vw@Gglj8Ds2FAN!cIZ#e->04ae#F=Sqmk6Dn_w( zkm5jV=O>iaD^w!XwiqHIiJ8K(tZ@^53PR`)31HsZVNM0lV_Z*!o-=FbEd2EVIBOI7 zH5hB>IywwBIai&ZM+X!|@hN+D0YtVnUu$>wKy>X(dop`8qI$4@jqIYP0BPlm)C07hxH6cpg;9Xfqc4-C(*L!unLr_UkwKJ&jXod`C%7hzuR3nel?d2u z7{39Tp_gpOYKWRF0{F_A#bbCYs|Q$g^%dR4D(aX`z(9X=-PCrScRkG{S|a*itzV zCAZSr!Oaq(P|VMAoKrIe#{BXaI?0~66iNiz6WE_Xd*ZBsTDd(T1~AH=5Mm_ZEoD#K z0#q`4VmJOGdxCxq#-4Z%J(7gswkKyAott{zL^571>+NERPFoLF#;fdB21Kx%%(_0) zXwO%>bsn;b+HO&}CN*voTJBolrcm?AxK6Nw4^kmp2Z^UYdo_nP!`-Er);!Kb|t+igQf~RJ; zTh{PYp@rq&dKcgA?V{sA{r`eOq4!um=5N4$pq@8iIZ%%&DkCfRSh6ej#=$#q*IBOI zf8D6b?KXF9G#XF)P#eLQSiVdc8jadd(=#+O%hmMIi$w{(H}xP@tK7~wEvy_`$UI>lcjHpnDnnKUp7l12{Vy@dhkxgeeX-I#9%&+D7V|W0Pm8ENqkx z#W8+L12(V?zRDU3X08#SK^IVWe5y13^xBc-4dhW_{%IYN3;Zp_Bf=W#0S$MAs_Xo; z`p_^0)XVb@mV`Ax=!LX7FQML>F@CWC8nl}+zAaF)EneWKq{O`#MxcSG!X|lzSDY7* ztJvmb{SBrk^Gz$Xug0J%TtHvKLL+<$ z<8T4RM+JjzCR#pc5s+{(jr&-rf0_RX?y6yg3BKQHhB69U-TXMX%j&uN4?rpF<)0ry zg5&ZJCTRwxVH)X|f3l^Db!oEpDSBmwv8&94!2jav&nhV7Q@HBP5Owuu2rBl%L)Q`{ zHo0pFIcOZ$5-jf(t$BdI}C9 zfnSKC;W3v{b+%G%?_8LxHQ{I=?d49-F3i+uw-*am8soL`3OUP$C;(V%rZ!ulBZT70 zCtIcH*XH!~ns5@Slo$s`&JSigFFS~9Jm(NYTCee7Qn<8eXI^XzjAt6v`Nxf4mAi(> zb7xiMB^iOtq1Sk>hrC{ZNM0m5IeE!}b~u~Lvllj>qwoG2J5)Pb5T zdaD!{dcGSV;rzY{&Vhm32A^lj;6}>@;F|I+4ZP6vI_SD8CvI*<5cq|j*J7c9DO)+> zdhq5fVm?zc!r@~{$+*Ij2&4Nz48gR0^R|G|<>P=I>+?8hFRgGDseO|jrlszuW4b5C z^40<*ihB*ORHJ48(^&7#YmQ{3l3W~MfKhO|**_gQEYsLA*Z7_s4iYxr; zfp6*w%RFjRPb{+JXy-Te*i7O%A3XxyVOx5KPQWkP(xYF4+0vUNdw}+}W*bv&IAqrE zUA-$pT`C3JZk)UxHuh%2S{Q9Y>{Z&>qu_6$RhGX`7^dm;6?e2SqhIU%QUithwI^NxblY<`|h}o z0amQKzJ!HF`1I{?Tq~>KlW=y<+|l$GoMbdPim{L3j4qtne-PXOZ3P9TtZwK>A;IB> z#w2Y{Hs;?bH}vwS>XmsJTDYNqN5r|asxx?$8+s*Bwk?cZ8cA zq!vg$nLs(1wPrJj%LV=20wB@jBOFwe)mvpU3GOGLiDD7%pqju!;i75t zG_lirmXvHfEQ!$nD`E&HSHxvd!nd!Yj01Ko)D;mp4w^Hn*g-WL(>p$L&yk!Dtg#+*+JZNGHM@#T9-*77i*P zU)A*fLi_^1u(IT6TO3pbu*X4#>C8d(5dIhZo>%U{(0zc3OiGq|T;vFJos(Whjo^lkf^tH_6w;Uikb2ZhZE{4Y5Vkl+3vWKZLL zK^aQP-(xk@dUhfIWDh?PVdLl+yd1Y|g=1z6uI;;@&@c<>J^5E}Pt=oO_L0u|kSUDh zV^Hb9*04U7$Au8QNVvqYF8dL=2R|a@v4}Mz~BBFEStBu5}mMO*rHMFTByHISEP>m_5Rr!9E9?GlvG$%FP)u$ijJ&X(!A2NW>!&GAM^2 zZ_cnKruS0*wLm2^Xs*LwWYEyB!5B2x=|Qmjb~nGbh(sDuJs3FlP%cL8VW~mRceqO$@vYgXaJvnHfIDSE($>0J>cw5N`lw=q0ydHHHB+hEv)kM7@}CjV%@EH!;`?SC zy)On*VI2K678>C?qu4k)RyB^azUGXikgSp|(vaN1HlL2^BNs_N;71uvLPq7#lrozB3#ep9(@*gi8BO$SFh5WHFkgs#*NmvqxCGR;u?t{vtH!iQf|p^Ip`dp zz2}dlxW6o$-oLN8w~WJL;}Q)ruCg!zpFmdpAHWEF{Ii2nSNFeTyp1db!b)sIcvsjT zI(MBYImBiaJ5F333xz^YT%GA}z<%P2H()t&g(>RlM>%n|wV%3zBbndQSw*cF$I31> zsB$}>)r}m_=`G$$@Kw_-xe;;ScHizN);=PTfn4J5S34LhgDjqGP zwekopbH`nH*iW<%pKJ|Ju0s34O{P?htO^vuU4#cWj{;gi!)KG#VK&n#H{A?nxx}QS ze$plBpZxu`cjD`eu%Lh`-}g6Q2b4EpnR+nAG4-qfW0G|^uOKN+@A>kl={5B{T~Hgr zO!-^F&}h^Pw*w9EafHU|INIA~Z>$dghyV>*td8YpoGw@of9k+L!B0hrI30|*l0tQ2 z*vca(W(OJNM2BtI9EU@JxhwN_Ws4& zb%)yfCKL))dq4I!U}s0(fJNON!lLHVYl2ifnF{s!!F#T&556{hq{t`>~C_O@KzOfVX)+U3d*NQ7Ly+S_NZ zTouxw$<<2qn+xV+f9RZdpP!NvQpE_2k*eanc&RaSz$YWPd_>>2eyLH3>|#;rxZz`{ z^pAQwukQQ@ny!(C+J|hcm!J2=-9Z}y8FtBPKxJS@4vzF~Fo_$3d|+rRc`aY!!yqkJ zVwJ!?44v0GPsT1j_bRq$B%Ysvds2<;jl(H8?mAPsrGfFh;Fufw;2j4Zd#*Umo8lwJT|s;_ z%6BNwcsIB?ll0`T$pb)*|e|6%PQP1dhB`n9BRx!iW*Sw zseKFZ(C(Rt_*jQRbzo(0NS9Ye4K;^J+H7rTNBtTf-!I{}gRFZrV@8E;(m^o9Rlbcx zpgXIoVxz9|jYGv=i0CQ~!$<3C^1jCaFl@(o*){{Tr*p1I6H~MPQEDRE zwZ5(lC09qFotzJu18+ek&w{+A&`!O3L33p~83Ok@fSa9R5Lhc;bfBMKhKA=sq1>`e z5nh$8qkw+lV1WMPGMx+odZ;PYr9fK!q(gmw87l4@6x44m3w83ugEI}X-OwN(D$_@f zG_1Kc8r5Nnro|mMjxG6)aL-(FSW-_Wu!YQ8GrQArqMpvPJ*Hr^aBARz_70$|{-Bp* z*?w4M6!wT{My78SJcNV~1@TE4PC3~oWOet9D}D8o1cG$#_YJV!)0S5kiplvA>Y#OU z#w2Z6y^}|_I|iX%ai>ftd)fJVWp1*SiTSrgoI7i24YmTP@xntBv&1IH@i}N59B;|@ zI45UFz*2V};CHjmVt)UZ0vIFteUGs*RTB{34n~yIbX#SeBD}` zV!l>qXIr<3cj0m2Td8&`)gk;f#^S%?&(Ti3b<5;*tGS~wQ-fPWopb1volSUh+hJUS za^EGqBt}mO=0`7|2r+shROhg9F)3V(Rw9;SmSTVCgkND)=avpdkS-(g+*wNt(p6Bg z7a$TOhEBMJyQ54W`4IS(6fmg(mttq>*zPLRZf8)~?kou+Zx=bHAx)#$4Q#9q_m}o5dt{sR5mLr-Drhb^<%)S&)aHkjW zNaO@}V{RL=GKv!$&1($^mIR(_eo(wacQ$GeyBw^%TdH{H72b-FQ{K>Aqcexc(QBBo zGT)f5%{KV$FeA8hxkYk78ebM9#-yQGVoolAJtr~VDn;D?p@2mn537bd8G)Dfeo9&U zcHc6MVpASg?PXY~VB<~6^&Tt~j=r*Jvd-_vip|of`>|phTn=Xbek|J+@We>N?HP7EcEyG8i*Co#ufg1oy%t272Vj7y zy>AgkEwa58=*v>d^@K0jWWYHB_NmCE^WRGzjV^Aum^9flw z$eT>c7pc|AkU0{DM>Q|pOf61yV&JsL$x{1X2;Ts>jBq0BRqhcpf&Nhk?G)L4+qFsm zrQ8g<-dv``iN%A#ovsy7LZf&L>iD8SY}U52gyX*1tolE z5pa#e?P3HX&_tRFsFj;YV&tPtBq5!0T=FJTK-{%I2P&D7bRYgABZ+KL*|KO>QeH?1;MlTTwchH0gowce1f2Ac^tRQ1-s?rq&=4B6UM zjG>31(t#O6F>EfZqNUApWFEbn4^*Lfbb@9cHJUTE-RKP_68T^IQdC1-w0Fbf4~_0C>w(T+Dz*tbReh149vTXW}ea*Hqqn_!w zkiC+HK3lJX%TUWAvg8xhrxw@nq5^CAw+{1ygvw@YIqq=Y4244PM!(44fc*|9Z@_Yg z6H`>SP{M!Fp)K0P$?qmu4s^ZNsLAd2R5uemA-kxJ;EU0B6NW~k_6wX0jm(@h&n^qE z9LDXLvsJ4c>=$|QZek`T$t;3_%xBz9l(JmUW6DAf=m?%-5zHI~s5qY_>HGhEA&~ZQ%HVk_(bYkh-&YZT6@#g;gMW^NMg;$W+O}LpRCdJA;L}F-44~i+G=Gsba}34U#yGMjryFsI zModSNQ)rfd%+qys?q(BpOZJ=4C+l^>^-!JT5Dg}26NjPDv=hi_HkZJS1w0t6lYN3w znVW1}k$hz>iNvu)oI9&J%|u-#JP9iH!b3-BBsRGtG&yJ-M`$ehjt$@r30)eJ8+3=+ zPNt5{nUCp?;bdI_v^Wafg^cnLxZ3$I%Gx*A|BX>h!7z3uW#pIviFIr5}ufZ%P zukO^k%sb!d-%|3To(?f&6!ox>JlnpI%sNZ%xXwgnw$bTUZX?euoT+|V_F{&*njBJT zV#l`BPg3L19P<#2o2vPB4eVb@zEhUn_ul8qtt2Iw@Gt^!di~zJ-}~JC=sy{@;!q3B z=DO0EM_pd7W)+FmrT9}v{?ih@h{fe6pit=I@@xJE?2Aj@fMs!sDJrKZi_85LzNAi% z+EzrE$uJduXw<25pSqu*&i|fe=1OWLcscZM3{FdLF-7aG5|imRF|f;SGy1c7i(bm; zj~#M95ir_@F^1>=EPFGL^S7-mDnhZOMk28^rXKs6oiUk_RUuHU!*R|2Q5qrxNK0N^ zvu6q^`3R0*AJ**W_l#=KYxZ-11fRE>qb1htHV`tXleYsf16#8nT`-Z!s6uRbXqET? zm$bqa`|;P*y0pGx+Ld-9%m6}il^&K^YUE@mj`MI*3m$HCUjEm&xT3vu!O)PNwYb(Q`KNN}vuF-e<~jEO;CrL(D!lg|Fo3BS*% z&aGpWb^1L-o;#~Lw?wVe-wYLd0ity}L&xYSURM%R@=E$c@8}20bd-;SA7Yvz1;my) z`R~fK{OJgYllMaA&^SMzgS?>-gOQPQh2;3p;R>BgIhw zdxuxJM#Nkf{+xJEFYxkfI8jxpB={TiTagsxBTQ?3z4Q4g+>Cps-k z-dXk!JFQmW6A{EHJ`w&&svMfppW|h7zfa_PS$1joLZb%;9>rU>Up3krogKko21U|)&z1}yFXOwmj)^${@{c*Zam91Hc=7NrGtfVWIwTmiQ2#$+2#AHc4TKEp zSvx$v8oo}#V*ZqcYu^ zgIKGzX1603?&S(g?UH;KsT@we!-*C1zQOJaUt&-3jo&4)kQcg@z3uzWY($QQZB*gN zhDi)`Z*r3IDSh5%z!^iSpvPoK3kL{KZ|-QdA>d6>xJ&z>+iG_~3 zYz=VDPvIx9_c;os49wA_2;eIX2wm{ypmV@x1MNV)4S|yRIfLb}i%A#`!GDgduLu$b z1D4eQ%Yjhd3X5_!;=I0e7^X~1Mc;bin}P8ZFCm$s~hPef5=BpL)hdctO0j8_qg*p?`Rj13;p~jx^spGXSPWy)`MJYi9aQK(+d0*!5pLdGyfU%iPfk65~$AMQ^zD#Lz&%V8$$a7~^mw{0}^?RXWFF@o|m*}W72n|CH9EZaHfIgi3en92?Oe9W3fqvW$G@;} zf_Ng~XCj4*Ljq`V{Qnh@>pK&P>CEwe7GS^}|MY7xj{j%lX+LcO?%&Z!dQ+!##DW}Q zJ!}I!&%F)M>U4QHpjMkATTRM8S=^s|2b?j4)Vkc82?twx#stWcB4-GiQLpq0l7DOA zGFf)ti`!#6bfPh(ICUv}ROw~vAhg;&4HcXDvki*A*RAev9H_^AlAMq!$!?L3I6}`u06z#tBfbx+|Ay7+`O7pNn&qoVpmOe z1J+l%HK--E*<`J)7!l(z_ujcXGr6zMBgy_zF@GpYJt1J{A3+MD#X=Ey_xa9uzVDphd8vyspBR*^0)ES| zw0p9zU+lBQ#C2Gdd4A-^7nF@{k4BQxq9lZjNA=nXl zC5&XsuqCmhLj^449+5M2vg&(sSDhw|5&E_fIU_)crE}{WhXJcSJQaSKC1|)9Qd>k*Vd|4Pv4%f!&~?KaK2%6_ zqD_WN6e+(7$+yX{R-`1%U=1;{Bv@fEmADXtGn-dp4N}=l!!WyK>ju|)rYj`V) zn}s!ye~2{*`p4%l`QOH14IgE5r`(yjeo({d!Ly25zN@6uYi+r;frxx@%7ils+PjaRUpI3^=qay#<1Q= zj|?$$oN7DMaUX_L>!R#!XPH}S#5s-jM*@J;ZQEq7Q+i+ zBQd=2G_@BtkgW+X%s&>L(WJhb*g}|%E)s%FP_t;90UFioEgEu>AtdLRpDaKKxE-D zcnm=n$SYwRQwA-GEF4tXH;i3!og!c0xO?$OnRv|=A85{aL{!_ z6~2PxR5>0l4OH9+RroSR%C9`~p$gZFl!Q@*Z!#;gOB}&ARN_Jm&TL+ZDo8b72vv}l zI%ePiRN)een}sTne~2pFpnr@i@V`t{A-hfy=yCduQXuRa{iQKrGU9Bg3rh7Cwq6E? zI-a(l!|j*$U*gjJH7*_hOP9`^Ud_2#b3yDNP~iya%p-hnfZ-sUdoXLja540(^5{i+ z>gK)heDhfz7)_dcv5%hj(wm2IYG5pD>?g+EuJ6>1z&uQYj?JP{_Z`H}TKJmrx^=Cl*UynJvMZrn&PpJ5HoIL9uYVef=i+8D z<6@U+$8T#F>C8v~mkO@_vwC=JzTKu1JVQ44hn#7s-?Ec^Ph0ggBDJ!W(Q zvCA>)U8kWnj2`3z*;vfjacp;PqMG1{)xaW+(X=iC6B8BP$5q^YCoyJ0sAd{|yQjs1 z2gb4k-h(xqj^3iC+r}>7ZpWqO?>qHe!*6u8i)|9A?bu7)#RDp8OqPdoEqrVLs=vjh8wASh^py%J@?rB z{Dlh_=6Wlhi5p#1zW zrJv0{nT>~MvfVk$@S2>B>9t$PqU`B4^rD7m28$D7KV-74#oaS5zUKBwLavDI?g}<= zU(`%%*=*rQ_XD@O9f{ zWq;V01+y&1qpO%>m0ZG@nLwz!5zstRswmN$d`y59|w7m$cse&NaWI1 zkk1ggRHlDKemVv6OCl>XAfF_1c^Al4BEP*8@%uM z7!GO`+M`|TwqgatLGMgC#-YoJ6w5MKjw^WI079$tEg3-Uoug3rs!U zmGO*=UbSY_bsQVV$*X&DunL<+ObicWelKrWZZ|&lc{RUeyF6F8U7pR`E}KQvE?XX6 zI`P4EYLt=1GTLS{aym&i{;)6`U&zbGv51ZKGl(H28u SVP2CB0{S9Mj1u%~bN>aLmV2}S literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.labelers.base_model.doctree b/docs/0.10.5/doctrees/dataprofiler.labelers.base_model.doctree new file mode 100644 index 0000000000000000000000000000000000000000..ee90bb5c4a26c6138f5be34d142df9f2a94d2cab GIT binary patch literal 153576 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

B0Hz-LtdMG`h(41g+_ z#f5gP?TsM1|hK?@)p@(M)osf<`8#EyseF@&Tp(;do@~MaoiCTuo+pC>DP76XtKg@=vnM1jBbT4Bt5{hBp9)?|{laUl_S_ zAL~aBHAR|YApAe%HMKc zNN_)tXHtaG{c5Z%t9!+fGlT(BkfB#O&5AUKWGgpU4i8r8B{SH2}s>O@_# ziqJP!HiuK-5)=m+RS33ELKsOI$&5!|LC7t5x~mQQ7`Wv;30ptuw?60}XC8Eh?h}y} zeG1xLnRNxi8D;3l`8XEw42uva9Dh*I_Ye6zT9;FthryuD!c)gY1E5tUIVJPS&N`u^ zZ>FRy*SC4I+_4KL!GECKu?z8ua>wY&%pGH*dAYl~%NmHZvp(-3$EmfQmTq7t4m`f~>0xL~swu#U0Vdc^2Lr)_oZN{z?( zEC%W%v&GO!Vb`7O@(X@g?bziV7{Pcjx-8piAMXBZ%W)6!FATOawXzwi8Wl}=0Yn!0%i_iKJwy?9Dv z!$P?K7i>YgDrpVX2k_!y0ucaQgxb4ocOAC-} zB~dIm;<3%J;3$}UKq<-pQ3L0BCaPziZuEF@hxUnNJkt!+I0|3}(p#iQofY!RJopv? z>Yu?%l4^iAELkB+fchDl6QHbR(|cHZrAEk6k&m&Nc?h%q(afV$mjw?&tt9mh z!w5XbvmyN%`yO{hpc1dp$q{w9IvE~*O1Tsa=^frh;Z zq7a|NPHNpWg&fDasioXG9vYFtBleX7p<=e12xM0_$7=_m60y$LK9CuFkxeYhk1_md zDmpl?OD-mf@TOR7k|U^e==8Kg1lt z2yre1d#5+zi%UYvip3LuB_2l<%26WFvIX^b0o-_kh1YCBMEuTzh})+`5Rsl%CW!cw zP6>{L>^9*D#m@aJ5kI_hRPjRv&SiuSuW=baO7oC#*lxk`yUBeE@^mG2)oY`QI$_Z0 zFLj2ThY58vq(2;Zm8=^-v0B4{3X1uj)MS6;Miu7_nMtrO{ZWnQP4cQ@3gmAc`!A3f z%n`%e3zf3Q@QVHp>@FGaz!F)(FDkVtF+6gzN%$LPggrXdGg@+sRn-LWgzEA+`7b3L z8lBpAOEGM?Wv%ce@g&9P+nQA@A5j*)&V+lSTM!w`^*Z0SY>Y13>wI&@;iK1S8-9Z1 z=yGUk#l6l8GYDSkaI#4vcjpR@>VXdDC3k{+364~okfusb0-oZ6T8$myeraK~E5YP1EszlId7^@AFG}P%SLjFJPr@oX_`w z^!9t7ySesA4hMo4kPX~~yCBdA0E!CRVQ{S33yzc;5YlJ{sP`$fA;`?;j!G>gjC7%; zBtemp{#526svg$IpqAAI{X6*Ja6$2trcVsrp}U}oim@(uj7{r}d6_^spg$tu+(lLG zlgj~J3($DcLk_6KP09gHp~m5WTFO0R2x^fO5D!xuM34zbBFkM4>o*3VUU68Fe=_=0 zpQEB9b6Bs)t$&ki&W_)bIs?6$B&1xe)A~Ug59`!7S90zY=#? zg>sb$v^cC=0bHNMir<;TdIX;+>xG_H#$jE=+fRykOV6lXR(6b#OnkX}M2@Qt?=oE1 zmpd#dy@Ry#I+}5C9j7HDZX}d3jLCI7{iT$3r0sqgC`8pkZe75wcX0|+EGx#JT&3=> zK252c4>p_MS@Nv;TF2+xC0cAgtv{lWpfq|LHe;mbqyJdk)2|POk~)(5F;5?^ExxG*`U*hfnWs_8E17=U}jE0_)*3g#F&C@ z1`|4oejb`y@tDHJnKYt^Dx5f)gFNwv0mCSc1_nk7w}Hi^1xDzOLw9H-dj-h=(GDd3 zndoVmc|Zh5P8fAglX4LsKTOKXhexi>gKQBVxdtn3<0^k}c;u%1;Sn@sl<)`=+cE+q zFUUMdH3G05YFPs$d*Op4K!Tq%{cb3ZTmh0rqcOKKK+lk`(3c4~cTrVu8Co*B2zg?<`32m-s|M5_(#hAW0E6v%=;ezUHwK%ldbXCaM4%9~D5C z5gc)BzSY|YMC`ntE`ekUN!h}>$pD0T-^N=hl_;3;eV9o%C;FZ5@5;LICst`Z!$6o3 zK3G%OK{$49zf--z1RK%XjeykUF3+BdjbyrQLDi_Lf4%JG+06igFCHw0kFJz$_=z}+ zo&s7~aaZahhbyJeG8*le5X@$YEZ%Q(N*?HjoWCDgoeV=Rm$Z~lnG!s(oaDmjYMf_S z-p)MT2tOtTpC~*>GjIhTzSZX#nccA`50Zu5aSK+G=jcDrimdM5;k!uCS51AXz=crF5& zMcrPj9@6z2vjHx$bvdAT&KX?Ek+PW95;B>cM9)$#lXdhfKyPjx?6;2IBJ0M#vr4Ta zLXKe*eQZ?|2`7LgEAtHNaCougGK%S>7_$hs#_B7bYCa@q-nO9SSQGjHRLZ(0^htjQ z_BA2ifn`kyzo=BMtO-p?F~EjxM3Z0{LMfqR;mby=ZjaezzgC~5FJecV(o^QefG-hN zjjrvhL<~QP$!Z2zgt3dOMDL|$m9@m}17&22q}Gcnf}oNYIwF7MN2Gl;KVT3l8=2=t zKX8G%-oeIA`urQ{vXc|^En7O?d zzi5M3X289b{2HTHrWx=90pO*v%4}18_V@Vv&VbNm`qUs&C z_bLiM=>rV;uA+FEACe)iqF?|T_*5p+E6TRoZMl^Enoi0I$)di}iR=;Y7#%9{wNNRm zN_>aE1G^049axA7zi4cnm;%YQt!e(UT;uv7qa}m2m08KC2C0wC3h)DjL!(nWYx%K} zgSEck9kQ3T2Eve!wZ7?xWC+$`01nAor>5PZ6kAQOGJ>VVPo159>>Zbbo&JMJA=^b~ zn>Oq8ZxE23op=WpcET^CVW$iIfUPt;oe$lof-rV=@?#?hJKf+NvX`9(!jO-h_WL0j zf}I$EL$cFFSt1E31{-3F{r%o?JJ{_IkxDjpJLd1e&ThN|3%lVL2fJ;?I7kw1;n+!Q zGTWg;uQi%AghGDa%X#R~FQzc+J}v84{jl0G$~#D7gEo@rBKUp&4)P---+sgtF1&{h zJ>ds7FE-ML4t>tw!4TNUb?8tE8)NRX!@lkZ)rSj1PTA$YpDlC9{U3S(^~(K$Fyxc_ zn@`r|iO%@Z5OSXZXy8+!60e6ck#)BLZz(E%9Z{O>?FuL zu!wv7;t==ANz1lqfaMJ3Jw{vlR1b3^V!kt!pGRmkdbKl}A0asyt?C`Km(d2opfTDw zEnf&4-L}$_;;~6yN{meY*2ngUcWe&6dMyz|HZ$rS{toPX z#XGR@6@D2NUwz1E%b;*Y^kobKFwV{%2Ou;Wz1sQ8kB}UE^#$*ky?iwg292-Qspq7# zA3EiI(+|lIT*Uy)!&QUJ;+~RZ)i8P-&eZwurXNjV*;g3@+UQ;H-a`;@dV0q+{r;=0~%LLl(hFIzS0Xe z!MSjkqquDVQfDBeMmrC{7e|i;C6zP|%JE@1}?|1p2Vg6Qrqt~D3!LZ1^ z{32G`CTI?91xxN_{=0dfpJej{g}WO-Vh8Ztez@hbHP@(=FzXHP(%1?2?eJ@}i7I;? zxLp&D&Y{|jfSD_#-_xrm2Jv%q)K`-9D8uZZGh;>F`t)(AW!)L}9ryqm2`*I%3WhSr zPnyOwWOSsR-a1Zb5e^;yrGviy6um)1nd&Sfc885arPKn7QdISRa_tVAhK9W;qTOK( zKl)I|+&1U-VTQ=(z>D5>bWa4Q4)#Mw?lXqzc~=hPM%$op)=Nd731x>vuGfUUb(leB zLGN_J$by8`S30T>3I3uOgkZi{F7-<*$b6`O8pg zMMT|SL&HO1H}-0ke;sC!S(5 z5SyHk4;qAg{xDiCahgL9UXxNJ$ zQZN!XDN8Jc8VAc*%3YqHWD>R+qB5|K3B_R6xoH66bF$8@TE>_#*Dxh&miDtTuOBXJ z=>$}=L+*YxthIx%QHD!@DtOOkcqnYMOVO8qd&`?LlcSeR1Q)%5@MYy9{FI%GGMH+Q z8x6YIL(y>WCIH<%^vtfGv)0M*R zpAU;&zp3`^VFsBAz4EdP;04>Rmmd$)^AAUc-qcb~GS}}VYtX5t>U?Ov>mAzVySx~@~C$h?J zu9ptc3I5V5gM-*%xucCQsgiz_M0>i?gw5T!dZNdajeIpOH;lIucN7G;G4s@W#ir0K zH$Zca$TEJ?sKPJ#C?QNpK1&MPi;d zT{#^2NHU0rYyeowgk~^HT{mC?aw)1Uk; zkw(1py38c#B@MwluOZx6tup*HLf-ieqd7N2DDwW-2t0Sup?T*wp_vz4Ca_$7=ZQ^$9S8Ju3HO~G!uO@Lu{KLPlt=E8IOti zJPU(gnO^0O=9PDG##{ZK%0;I9{J+1)N(0t{l^Z#?R$)mOEk$e<)7@Re`@ZOal9q)J9!?P#(Vcf{TMSJDPlzYZtUD!Wi zUcExnYX=N#Pz0MxFBAj0q?fmMaWRa@RLXVsm`G2PQYn4*7+VeWoISP;V)yLqvEPD$ zv9rhMX=TnHdvU8BB3Z4(`D6PqiK*3YF4pQ{dye9p5XYP=S4-_u8CDI7_3&_5FP0mP zBD>$*kqpQ|T*et>pYpd{KtSgMmYCIoT)+}Q*=&b%i|x`*GRm1x`$rEi?;|;EWF7V) zEH?H-r==$)J>)oR?2AwdRGN}9?>-#rZ~YzE^PYJJmXvw?qFF-8SZ^C8!*fhptVovF zsAKUz4XCmiTIyN5Mj|?2KFPe%;onm;;!aB3a)ypV16ccv@D9@Wm{Db@Az%%=;XHrG zjx0_Omb`rrk2`O6$mRY)@E{%-T*&eQV>VQ#;F2stsgNmI}Uw(j$H zl^ABvYN|cOO#h zwZ$wiEW7jvecb=)9k*lW{J#^KWV7-%Y}I+gATB$r@eVA+gAWv+oHyoy(1sygdvK>WwxHaWTQKU z+Jza7d$Mg~Pp}q!81S*;d$P~-2TSF?Y&JQxulFN3Pg!o&Ja2!m!FOWgmg_@swGEHX z!JgQT+;Tmrm^4ChZ4*QWPM<0lof=HY2k-o4T{8Vwq1PZ2*jReU$la|l3pQPsK3wO9IPXxNJ)%FAK+ z(T3{X)^>21G4e?;REO4SJaAjv(l9+oIj|eO7z$_IEZu~%Lt)pSEB)$W2AKuDMr@2{ z#u;y=h^GXRM~8vs5vY`Mq!h|m$vGFo9~&0o-py@~4>LxNZ!q1>J=6F_6Df{dHcPo_ zMQ+M@fcs|@X*v^`^%671wF|m1U_MY1@oi}rQ&Ime==mhVm~2b4ZbHNJUZ^l`PLm5< zM#gilP~?{l_rc01&Ny!g{M&Cpm0mMOES_)Lj755fH7+JH<&ZNFaX6lIpaDr?1x9oh>ZYn z3P3wJQfhQNis>CFDG4l!sBZ^I#|ydCPJfUnBf(ubODA798F?u|Fv>;H9GOtoT_E^X zWS8BU8r{G?5U36%vSc8VWm?Eht(Ug*kDJ(gpqNQB^ zJoJQT^4A5{F<}_YI(r77J;gfSCPfbW1sUWoPd7w&HegblUN|B^Ot#sCvx7O#7fzxGk2`?yP1I+R=)AP^T87CTQoy%0SlZ?ll~8b%SC+B z5qr5N-7h@&HN_$Xmn&6RL`>ymT2h562H;5*#_udu_@cAniLNQ8rxi*ShNC`8wR-1x zP8H@LI#Y#LZ4Rp(7_ElfXP$f-iWhOg5xq|)Z|C)N^aM{9cu>}ylzs4IV)0v-Th{}v zsaBZIq5fpzd0F=anTXd*?5!#6V96EdzZ_1Y-455mTnPUw(I&CXgG*cq9-`Y2CFT-W za+rW&;^Mv?`l!#z0f|>@Qmz7pDz?@9pw#&Qyr0agTrUC;e8Dy`d|c(S4L=dJ(KDf` z|FTssLG-9zDj=QN{Los-aQQWWI24;~yFh4|hdudi*k=QTS}ei# z8u-PpeuhmpC^}(b(4hdQWK)7Kl{b<&$$0;`mooiI@ONb0_?^ecj+%v1C*)hOo(qqA z;oPbEoPrEv-^?Z15X}vYBqew{smH%1dojl8o4`B&rQ`gI5^q)|XV2vM98}7h{`)un z4(z#8yaP+_6n;?+CFPcTx_XcJJgwg?SO5LH(UM!nyVSd}TO{Arf8Qq@8lC#k?H0Jg z3cx$<|1UMG>~A{9&9o_cndD^!#mL_}&76CVJ_nfwaTZj{N;8-GJFwFX@4!Mc_{Bjp z(}^VG*vLdXHyAA%7|386E{k@qWw^8q6~AahRd$EDFRp))QOg*P9p8Q+V5-xYv{~6T zf8QBUxoj(&jl|$DJ1hE$EJqIG&v}RK&0!n}gPy~fxIK0^=P^GdL*y_r01bR96PcD* zgUh0Wm+1KD()?IJJ95>^cWHoSlimjagscvpZTJb|q7MQ}R@}i02HA@;k&(?1 zIYb}A$;y(*7(Ay^2}Qe#D5!C9V(zMOfoxl6Zd>`21# zpY!4UL{b+2DGx41l>J*+X&dL1QFti-^GB=GVPIe1Os$ zIV~}DuP?}Fu$MQ?Fj^iQ8Bl}qe+FZ>W-m@cbD%11IV$)`Q{{#}jkN5=#Q23A6+niu z#+oY8ydnTy*9ICoK1D(1>uyZ{>ZqK8&vC2mryu_@FzR%0#Yc4Q|IDMI2L zl|a&%y(Ti+5-Fk8mUROVjdQ|txW=fcKZmQ#&G>{X7?Z$hmDSQ=c0&agVW%M@m(&`S z@Muu#1dDL!-cqmLt?i^L(@>=Y1?py5CW(z?FX=AubvpT5Vv^ka7sC)#!gdpwmqtYP z%H4z!D+}Q#wI|ag&Ba0uqcJzw3Jcv&z`2X6EEHV{g|nuowxFyRJ;Xv1Hz^iMp~k^N zmU8=7fSM$Q#4FJ{Fr_(;!A!Y-z|^If(%Ym+iue&|0-wQ$t@4FcRG1kTR{w#Djw~tS zf5FgIzH!qpg3FU4-j9_A=yxR`&U`^GDGbMuFO$HueKHRuBujrk!?bY(BgDB7?4M!2 zaxE+|VIlY{@j$sSktG7tfpR7uJc05nVK^*M{vCXxKsh}*0_8k9JZzA>1pADN<$9?z z%C&21FM#EcYO}JVACD?jEWp(Ek+2r^r2?D0x6e zsSonlJ~xriS(jW28gHcPY=Q#ej_EI@EGKP0b#7K!!ovd5+0Y-b{#1d@0)hA?3%N$cO=$KobyncGrNM@a6&c`@H z=ui(0a3ApXOMY1Gl*&6uQ{0r4&W30I7JoO&TxFy?rKe@!1yv#aBA{d9bCw(_0`-45ySIf3K8EGZ9BQ1y7eN;bZ=g6~p(mQN#p3OiQ^5xn5 zqaTtX@@yD@20oRE6wW#31zruk`_>&qS#;zRMH)Q|fj0AOq`J4sO!}xRkLmMtW--WK zfjFa>U_0Zff8!D73)l&5nYCKF%!*YCJ*kTtSF%^TtZNfL86da@zgQDo3Ox$4s*#|mx zSrZ9VJCui!)K`*%$Yr=E^Jvxe@*PminvruCd;q0t%gDh`n$kCnq)5xiS%+8=mNomK z1HNQ5=N60TWb>Syh`@6fRV8SyoSY^!>_reI6fo>)1NELJ_H)CGkxzjayGeB38jXK+ zn0_D0f!pY3p>Wn@jmMzuaJco|3jFvmW0d5b$_PnOw<9COQf@9M%S%3p^VS4)VfLSB zXIFaF3kJ+9vKLPYKq;6pCEz+LIEJ~gfEg@CesN~X#76{h0b zd0?jOjDIAgxy6?<6*#tBQ{g29aRr%B#JRFFgjpp~osMiWdEm*;KzYHkGtN36o+z?O zPmajuGP5)8t%mj12xFNPdQK8E_KYZ^iBK*hj_IYqbqO5r1yOhuWKu7w*TR?)rIRu?@yS5Mpr8;cnFD*d6bmC7-pE*-m$zRc{5QdrPl^hhI zvD|_Okqk?Cs|LwGlOQ>L%=X9(t4H(TPk6(RV5MzbE)DjE75S2qCrL8v|HuOgnM?14 z8a^4Im`ez8Msw+xGqlQ+S;Z6y;!A{z#n=`L!Gd`t0@LQwz=hz?0gTLC`aC|7xkOJZ zV=l4N9*X?bjezbhUH%abaN1k56}G#_AeHs55m`)>d@lfXnojX2jt^6#ocCHQYHs=Sdhm~5PJfWr|F%LJT(G2#K@m5FX ze@L9NRgUJ{8c)nqaNAhGoeGvcn@R79IE=mq5Use4m5tnmv2~)z z0J6xw!3oD|ktu=c%lXQN5aqD6K~&n|8;Wafw(Sjeg&r=|drCId5H%%jM;9Ym%|sVw zrY>%*MPDaMrXdEr@*s`R^Q{C%K+Q^aNC*=3bAhSZ^+MM5L)CMMJ`9I6Mf1=pQ?x&Y zPo!w+$)RXDz{|kSv2l6-_Xj65&koQ!*%N^0FL$e&v&(E?U55EXoI?;1U3qF=r^BmwEwEnbSFO zN$&}-M|+^%6<0n3NLpx}RZmzXi}&)GvZ@<(CH*weH*8@OPaq^Jln%f3neLZJgBxyZ@WT`j;+*%-3?}WAh78!Ta;T zNx^}~p~fInfiG*}crpeD-khOT9vl!8m@7CS7)zqp6&&zdEnfyGnbq=__(WCv}KTY{EhWot20UykJCDO9G|Sa*2O$mFj(UY^3`=#@BX-@ujx0ECcLcf#`+` z34BjhJaHx>F~X(|1Vb=DeI?}|8DrzyeK_;{7&}5cR24@O)@0{aJGy99OXwrnTIKRN=O=wb|Hbx zL_0IniSX#Zjc~FZRG0F~gVZ$l=*0*@H%hWjNGq#He16}|;>ekkKA`_##q1_c% zxB1vXXxx=_;bN~&=i$L+hmD{ShWsE&xUaQcf;|(rl@`K! zCpcUy;qiI3va*seWbI^Jzrn`!&SA%eS2ZN#O4!A-XfGxfY!Auhdc`cO2_FH7neFjW zd?MR}o?NyEn~3Gu9`|;{{_Rm7L?w@)8kKLJK{ig{pMqfv?lDJt$ zGVd+R#^|z>d2h5~)iQkCf@&Lng5>DafRYurcwGS|MI3W8mroHHho9w4U^NaE>uT;! zIL`)`%aSD7phj1C9Sg#vxP6fAIc0)ET8Me8Nxq62NC7iZJu@K)JMl9_e>Aunubg5I zWg4NHNP-l&0DDRjaWacaEXT8F8HBHs5Ym$gVRfSrv`G(z>b3FNWsxDclP<{JS#C6T z(mig_9lz{PDa3Elg+lDIw|=SmG&uBO$3fZ+Jzbpvflec;&VqTr#y3~-M5oznm&1N_ z7H4}b-pn17B7eUR4!dNo3LJsc2>biu^+5hzI1anhk58#I%e^jK+&KsPSsUH3QR&AM zFQkN`{v&;U=-tWtVmR`#0U6=lW*h2HLGUWKYoSo#_@u(WBvHl#b&eHXm&&8O6W=JW}gc+4-$-?-}&SE8u~y^kQQ>Y&F~6B27zw&zg9;3fb-A=XiVy zaB8;*qv`fK$=mTtxX?QU?QI70t^v4$678_G1aGF$Zwhfx{fFYswMMJgEryM9vjV01 z@l>z7xby0rof*}qHQ!D*=oAJeHBKlpR z)_5~(H-SOaK3D%>RF1dc7&?HcDxjziW9nnhW8+W{j>H9wSK#-Wu+fiCYlmgb{#o#WUh4#4hwF~HQR@FRl>u&pk!xPKRyF%5GYWi*bSFpqPj3K>*4** zi!Xa7V0LqRv21jMZ<21#72R~3OHcE41osmc;U0~4NRr{9cx~7?+y`9|uV*3xcoN79gCIcg z-C`H~x)4MT5W^|Z5s*t4BqfkSC0y+EUk*Y{dy6L#(`#sLQT~`fwy4niNqotkqc@|L zc_aMk#8dbh&j`gr^kHA8x*hI`rSG6`uB}eR6AYL{B#(oq2;u7FD#&ZemQpojJYMU7 z2I@bAs&egxpcs#vEj1^ z`18m3=ZZ=Ab2a|Cd<5i-dkE|)+KvV(bJ8WvhDxIpe z58AKYMRj|I*%tqDQalX;z1-}fxbDXr%FTKmcm&1(N_}!SfBy(j@T>d#K_r1ejJHMt zr-3fP4uOU@caC*HfQh$hTE0P^v3us-4UqEC0c1DhogN@?urFyrJHJa)nF1-7Ap(#WGc_0AOH; z@R!j0;aTb%)Y5FwY;{59y)1-lRY5M6;La7ccuJ9iLUaT2=pFDUF_(ooEG*u5BdL7Q zYp7wFxO!rZm^s2HNQEgt;Uu&JAsBT=<5Q)*AP9@-dxLyUQhfuzt{BwNAr$D-6*OtM K_GhwY?*9Wy{L`@j literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.labelers.classification_report_utils.doctree b/docs/0.10.5/doctrees/dataprofiler.labelers.classification_report_utils.doctree new file mode 100644 index 0000000000000000000000000000000000000000..8aa6f44e222734106218abcbfff90507398e46c3 GIT binary patch literal 83964 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 Rtx}C_kWkm;8Vwd^{vT>@Ze{=g literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.labelers.column_name_model.doctree b/docs/0.10.5/doctrees/dataprofiler.labelers.column_name_model.doctree new file mode 100644 index 0000000000000000000000000000000000000000..fe11089f08a00f549f7c1d2647eac40402ac0601 GIT binary patch literal 65857 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 E0mRJjmjD0& literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.labelers.data_labelers.doctree b/docs/0.10.5/doctrees/dataprofiler.labelers.data_labelers.doctree new file mode 100644 index 0000000000000000000000000000000000000000..b64bd7f1c7ba5d40cccac9d24c8412ca7dae44ea GIT binary patch literal 248623 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.labelers.data_processing.doctree b/docs/0.10.5/doctrees/dataprofiler.labelers.data_processing.doctree new file mode 100644 index 0000000000000000000000000000000000000000..428a4cf5810a14140ea040952704a7c4366284e2 GIT binary patch literal 555299 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

;A6 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 KQI)P8H0@M$Tk>DqFvKnGu5S@?siwV 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.labelers.utils.doctree b/docs/0.10.5/doctrees/dataprofiler.labelers.utils.doctree new file mode 100644 index 0000000000000000000000000000000000000000..6287b8c6e2dc401994e9aac5f5a2c3aae0f0e13a GIT binary patch literal 12860 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 V$7|DnkC-#bJSUcnyoRW`{(pXxH0b~U literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.base_column_profilers.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.base_column_profilers.doctree new file mode 100644 index 0000000000000000000000000000000000000000..79b6009786c66adeecf0bf5c6160b4fa35376ff3 GIT binary patch literal 75639 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.column_profile_compilers.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.column_profile_compilers.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d4ccc1e970b2a9f0d76bcd79a35be6f353d05147 GIT binary patch literal 177148 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.data_labeler_column_profile.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.data_labeler_column_profile.doctree new file mode 100644 index 0000000000000000000000000000000000000000..3e58e3064be940e87abc68d9bfa46f8ac71fa6b5 GIT binary patch literal 65527 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.datetime_column_profile.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.datetime_column_profile.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e61b84627ba55cb35644d41c8581a84a2c557f16 GIT binary patch literal 47589 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 e9_P%P<>LsVZ)_uP!_Joq0efy91 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.graph_profiler.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.graph_profiler.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9872a64f274a64806639597a1a64342a139abd5e GIT binary patch literal 36831 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 X+WjV|uwWB~eZGn6UT8+no7MjVTydhw literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.helpers.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.helpers.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4afff026d2d2a67ae58a6fc45dae9bb70981fea1 GIT binary patch literal 11844 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 bBo%%>DWQdhw#ho@4D$AgW27V`YSjM=j((l+ literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.helpers.report_helpers.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.helpers.report_helpers.doctree new file mode 100644 index 0000000000000000000000000000000000000000..076617a063aea2062b4e3209ab6cdd927975809c GIT binary patch literal 18709 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.histogram_utils.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.histogram_utils.doctree new file mode 100644 index 0000000000000000000000000000000000000000..8207c3886ddc3a01d25effdd33e3899cfa748011 GIT binary patch literal 4301 zcmd5<-)|f>5Kf!kC6^zUq@{gn3WpFPh~^Ff4^S#WRUrX|0|5mAs#e}z-`Qk$z1ZI5 zPN)(*AQj0-NHu>9uly(c5xnuhH@ml+yFf{(cp%b6>+#s0`R4P?_}kXcziuy;e{Rd< zLS~abi{nhi+<3PdtEfnMX8l9|{CEDo-*X+!j*KdF#JyXBMkHhsYo7Ug-gQac%Ea_% z>sJhqtW;UET(m@6tlaZ^qT^at+Jw(dxvjUQv1+VY+Ph2Jcv6Mtg-`f|O!%w9_rA0W z+g@_*oWTz3#g6L)jp1V1wP*GY-GxME+z*S8xix03mSJJxC;7E3V?#cyLmDbXKPT={Z2!aUC#-fquD|gVpUe ztlZZ;VV1|eQIVCrHvNjCS58qnrs-|KaI50TP&`RYd}P1~wKqVe{~=m+EP>jaRbCJ+ zcW}$}GDYx&JW)s2dlvEOQK)*6$}E$a>480RB%yMM%YnpTC`=KOO>d-CdSgvko0}Vh z!B|>Rg#AdRgRDsN>FmGNoDWj$RKmU|uDIL(!J)nh&wsNW(D`sa#KbJ53y$oBtXXGL zAh!3f+=aJiU(mROtZ-F)Id9IR8RyzCv(VCudqlp^$&n)Dr!iD~fE%>@x11Q?LUi*f zMcE48OJu||gJ3J&E92S&L)amc2@63J0fzm1S>!!JfG3 zwwnCBU)C?r>zXt-)vKmhU8d;xHSD-t87{6@1@E6spOtrUoz|Xn-Kfyi2n0>p->4;3 z`FE>^TZz%L61r zYQqe+yjn?k!b?eTgj5;SO$$z(EtqvNL${%MuCxsje#jGl=e%1JENO-9GOz(%r?06D!>|IbeX2 z06qyE@@_L>*|=b14!C2C&!ek#mo$%*j)R!zAP0`24r=JyC}|`32smUMpdC*ina%Y1iA%pdFH(akyjYmgE z{d{VL%KA!=2Qfb!K+_DoyG$!eQ?MeiJVl@^0<#MF{0%W^-6rDJRB*(|>*2h?- z@Gz0wj>=<%O%oi^u`I+DimmW>R^2raG7Xx$*_a=goEY+h+cr~lGLt~au}JU(c`qc2 zc)wv%hFkV^flF-w)TMG<4TD5QYzFPMNTA7#5cuk{0p$`xtUf4m96^t$@?|tj0zZH~ zDw5d<9H_IxMamPV2p9FXc^dK<7j=rW1m_mJU5*mP4g!v*DGBhf)4Y7#JaEfAJEWJ8 zTdnc~E+puMH-!Y@ZD5%mbL1Pm8+LFI=wgwmL4}y!J@=8p7NphN2x9CuY6jF!(6b8i z6%tn8;-UD-xDE;IGzVDsy?8h@;%R!g{De|+6Ae?lGT=A|&mNA)y~s^gSChJQ;7MfA zVEPAC2mbiKcg}^|oF`g|(q<%)hY4mNS4k+J)OuAo<|UOLf&^lwp-LL=ma0#j5H{MK zg&jNfspX=J3;UxkXiJ6Y^2xnsGfQp_*)CEANqqOA^WlHP)Ny%CqxT$fpt6fts*8WStmV#>?26h^%Qo(q2hGxLF) literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.int_column_profile.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.int_column_profile.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a49a545d44b55b7a77a4669b1111851a2bb64012 GIT binary patch literal 80738 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%0AV0!uRW>0V{w)Y&6v!wZ2!H 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.json_encoder.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.json_encoder.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4be9607f0a6a941fcd8695d302d03b119c797f0c GIT binary patch literal 25266 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.numerical_column_stats.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.numerical_column_stats.doctree new file mode 100644 index 0000000000000000000000000000000000000000..8354d923f23ca27dea7d13303299073c85a8696a GIT binary patch literal 83126 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 U__hwA&7Q5IqY^fqYth301LMLXumAu6 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.order_column_profile.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.order_column_profile.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9c9bc65adf8610a8a17d71d53ee062e4cb84c904 GIT binary patch literal 46938 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 NaRmlRV=z1Y{{W#zI;;Qy literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.profiler_options.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.profiler_options.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9fa342ac0165b28a63c449281c769626ded4d82c GIT binary patch literal 727399 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

hl<({tq%P1qlw!0 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 Kg|)Vamj6Hat37T2 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.profiler_utils.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.profiler_utils.doctree new file mode 100644 index 0000000000000000000000000000000000000000..7b58ffc86c42825471007e0d93962fa9e3ffead9 GIT binary patch literal 220324 zcmeFa37lm`bui8_dk-+|TQhJ0fgb4TVFpATWoL#R3A+qq^QQauymzPjz2+^1wUMeWWrzUT=)Yt(oqU@y1wZDz3L@?wMJ6 z+sw@~L*1p#%C=Uc(;SOuy1PJ+v1)B{ycySLHqCVR!0zqZWNU8FWZGXnLomUl`*asg zR{)CkOm(mB(oqR^b$)jdhxX#`g2`Gvp1HWQxzZh|wA;1M6Bl5##@NN;<3p} zs|63?_riK*iv3zL-kDDS*jyRg+KeZ#Pp7-MUD<+7Gu7qQ!Rl_+L#p$uE4o*%zM>U3 zTdOa+>YBALJYn^8vyrq`k5}3i_(ce=1_)cL8Dv_+i0ILhzeX8Jn=L@@&8X~v_Qo0a-lRU-}(lE~MR zzc_KGcdSE-0*du5QDY(yBOvEIAm`HVQV^cXmS$zTs*tpM_*sp5yHcySqKQtO^YCoZ}OE@}a% zK>NGrHRG{PvsJqx9v!cZwMRSCAYSp%%4n!okC?!PadYKN_eDXHIbvOL#wxFjL7;F8 zz#fh%!XeDqE@1SaWwccTGk|id^y!{tU1?~1U4*C(M-10d{`bmg)v44#QZ)pN?nYCi zIYtX3OmKB!_vkQ0g?NT`Pi1rwFnH1}qeIm4EQG5wf zoRND80+6M2^``30NY-0YvQ}R~76yRcn}9|;Hx;+z=41`F6Gfs9a0sQ8MJDEQygGI< zA1nKkIG{?5nnap6E(ij@bmZUSM!q|*K2uR;3bA|`uzZmCu`i*9%T1%5?oqX>W6%*PG?vB0AF?g?!3sD>Opm?>YIgG1k(Y^&HwfreMpO>Fzqc19p9Q(B3f(inoxobB4OKE6pu&dxkFso8OLg z%+Stsj|ws@sK-0ju^BH$UVIs-@`cPs_8u3{V&^6yMEHJ~@E&091Cok+=*E)ET1w?5 zqFt~$eV`NbUp>UML;MT?@<9oRN0@%^nffm>#6VHPsV$=Pj5?8Bl)fSW@<~pz54iT~ zTw%gf{dOuj)$ioUO!fN~X-JmC!hr$-Gzb=m{El}4Rr#Kh8b7v?He=YJ>n%m=RNV|C z=&8>ZLD$&`s(AQZbCQ!0K$8Rt*)~=1Yyc-7u$MF40o+s?n-e&u&FH)KqJk!&`km^c z?vjblg{M3#;Yrk2^Y)*h$<+DWUm=F#=yB&PnN=g9IBo!M7w+XrNTMnzEUfy z$E|iePJR*`EGu}X8Huhyrx9KM@n~DEU6qcNbkJu%ku)MnjVPRK36=z;1bXq$2^R-> zm5g)TfL%+w0~57)a(vYA7=!~1=Xh#Yv?^`lLrpJW;1c16@H77YUG#^g}s#PSL(Y9)B ztQx^S+v3t_h$i2_;QTNNvo!+Ix=Fbci}{-MojVf56k_ZYrTg01Sl0-M-T=;q|3EtwlS07SrCO)+OioP(*_ zVDct{-o4vFzvPV!(fg@u@(}zZ><-^jQ@$Q9oD0d`c7wB(n;gc@tt#W+ZsvE(jg-HeRx#$=Rjjlv1mA4-V2`g5S+U=i?O zHycb2gb^7JPjN_)l$`2_Mj@*E*?t3%0RRx2RCNW@8vmfpG>Ca2jHGaw*M|(TLlZbL zEZS#!MEq!#tOsA0Z@?XFX^Es0{= zYlf=Zs@t`LfH;vutWF_l(!yy7{#yn7Nd=!_%4Yvm3iQQanX`DedZ%@9h-g_CPxUvs z2Bv05o8%f$^<*RbN1H1dg(sl_4m`~y6`Ti=LKTLi3`d$g;x=`9$0`;t(s+V<#5-`B!Q@Zj zAK!M;T|~jHvG5p`5)Df}3bUs%4H*qX*ErrjJy{#8wP)_24%;ft`pg~7!@3tnk%vW6 zpv6I)G(uVVG932isKp`SMHwGBrIJkJjp=W7ST5YfB!$L%K>^kvxX0frH5x6}zS`VHSwzG}WyneB_MD$;P%; zv^Cz*irUpmJAyQJG*xS1ek=mFd~-b3n2Mn(j&7(-c4C%-q@FNlWMD(HF|}@>+HOy` z)~#N>ZQHhy@#a)z4DxBs5g568?eS|)UVZ$U)svN%?^rcaYgOassvVGFYprTkI};O- z65p~4IET5Mv05u$)r>J11fi8x#7k&iEltyg-T<50k#4VM1Y!BUAuM3$&;rDeqk_zn zlIqyhe`3K7*ymNGu8=AIse!v&QOJyTnzfna=P(BC@6$MzkuSt1d=I-Hdck}cq6l=U zBrv$Mr;bg=l_q9;gS=SboJNqtsy4>KsXd|4xDi@TcWosa!pc-V-tAiMyRnG?Zb;c) z+^EMRQFLiM)wm&!DwC5DhKWE=K{KPXnFSoGN;e5NAHZ4oy!eR|^K+=` z^ON?FW4jN|L9bV^fPBZhj??+HTGHC)Osg9d*&=>`bf;I6RWP9zp+gr$iO@-R6f$nfanRZ4GKu35O9@!1 zrZ~_`VYXg6&;%;^(B0iNt)bLEy3>qz8+{a`HVL!!$*Aq7DulFYj7enE>YR?H zZJL+>Y?|bKiW^JgQkjRxrhNv0U^eZu_={{B{pycRJCBDnMkgv`?M8D)QNK=><$`N> zN-_Iptn4&(-SdlAiVD9|L~I0lP>_oyVIGI^03jtA@G#brI)xA=rC3lpGmFJ!p6j~$ z9WG;KjORDy*zO~9(RgMkg0xOO;pFQ8f1h;Q$u*4bpzHDzq#e~YBu{WM+SUAY>EW*3 zz*Pd{Bpf$(q>sj67loRJ%{!veQGWCv9UWRJgC}K%N;ygX69F7de#POmi;C*2B9a*X zc|1k(mlDa80cMT4;*ANKNJ_c9v87VsZ4TMM0%5$C;V&{?^vhwqIK-%uWe=oh;HhmZ z1Y>65n4MJ2aETS&7VAxOQ9VVLlnt611(Q0<^Q%}fCL`UH_rVpf8 zQ{3Yy5DRx|$bU{gT#oHN7wDTFm3P;uMp`~&Hy3*{7{66QW};No>GK( z?paNEB?%&XPk=uFiCX^zOycv;! zx+jiP_$I#sM=($3K}is|EGV12pdW1V7WRf6Pd*Auvg66e@E7gy^vkuwGjM0K!@n46 z@@BEQuPL^RnGRA5+mwC+uPK26L{HS}8wFKy+2 z%Z1M_x&E#EujSaePSSK2-`7SpzG0`kz6Kzo^Qbm~RRB?~g++as@5j0z zddC6GYdqP42TaeTBhiz&q#7nKMSc$^S9#g4I-o7K12h5kq<$?Ts{N?cQ!u6sg&WJg%?pUZB5HL{Rn2~eNo6Wh42cvS@tGw zubQlFjU)B~5Wd%bLk(X}1XuTl8u+@6dUW5)?IZElSUMP*7qL|!=*y3Dz8hbV5b_z4elJ;2>IL}kJJ}B6&bMnt5 zH>^&DQuZB~=zaty49*F?4LbV_ijnBH(KX#(l3QT5KE;h?qMJzv+DD8QGwzaoyp0pm z9xZkiKPVPcOdzM#4%J~6^Kk%zS%5g^gsaB^&uqT%=3eNHGD}NGUNXZecd^L?9=#k3qg`Arq6oQzn$aUiU&GdFidH3j#E?_T5jUX|%ZX6!pLrJ|-Or(hY*kx6p8(-eEc~sTfR})*lubxoAji&i7Nq{} zlA*1`(MF&%KOUr!t9e^Rzz2TmMA|G7&2uKzu+z(66y=!M?J|vNIvY=_`K9>)30qad zk-QViLiu|w=9M$a4W$5S5+Lpnx$s7(arVK4!L6GgbuSP&Vt6AJfn*bo&Te%tnyoNf zP6xA^Q)lfx!4wVL0`GzegSWspK<5HmppDuopOW=3Tc5T-8B9V8B6dK=aoPdTzW0>zNA$hPG+3S!(}*?b7Q%u>F%9+kFm@Gu`S7g|<>8lV2mg$eL8;k|*I= zpG@m=gUQmoGC0V*{v&6B)x4@N@17uD>Vb?t_Y^A;%Xd;re`SO>sYaC+L`>JNYIoq> zM;V+iHCBpQvd3bwle^(RL05waJNZMRH{rRI4+gg>-7~Je1V9FW;Wfi_cc@1fp10v8 z(Gc8z+g??JU19?Iv{yAc?UhlZIS%g<4qS>mL`&H;CS;NVH;{O0y1hdp-`_=2DjmY8 zbZ}WJ;cILul~M`CO+j_il-)!K59}ru(GJ^9)&RV0H(86nXg8r>uHA$&bvC=nSrAC( z`J-8EC?^-&P|`Ksd&-;V;+~=cp0}+G35$~s3M`2jNJognlKM!BIqf+YdS%?d=bS6Y zcAp#MPPd)D)k%y=npjVv_Cm)|7!+{AsA5UqM(W$^I*A+0fW3`C39gg4!@GvJPJ*vg ztWM&7|9U0rBp4WOdoB*$Rz4N2llYJyd|#c!`-m~_Q%n}le4H?lkScs~4MJ!5UuVLz zKKWmJXRV=h!5ApynylwE%XPudIlMAGKcGT_=_Aa`sH%C7>j1(aGl2PW1EGubz(7Ri>>E& zwB9%u9W4QLo|AQsFe{v@8`lpEJ1ZiX| ztCL|jR19Ny1#Wk2;O%j&NEBV0_3NUuH*Vb&of55we+F!`O~MC?Fd~&Z-*9w;KIIJq z=hdUQh8Y5QDYXS}=e4T05n3^{(p_5RG{Q$Wcgrn zBji*-OP!2DIfWF*D4AN3A|@@cLY6U6gPsGN$XR7$<*mQ8;;JX?_loDP<1C?*t`N*?9KrC zFKj+Yj_p1?mrnl~-tdcbZk6ZDy)0eW3Ek47o8n=Kw9ORz_tBJK$#FQ1v0ojILhKbG za)H(B81^)W@E++4lFO7H!h_bH>FAy5MXzelTbv4mAPXGw6|3YD{{q$zStWdd?6<6_ zMU`LWb5`>~2^q%OVr**DF`w`QrUVhf_E`ApE3B_>vi5ITZ6@Lw{<)9Nx;a<(0TCR) zyu&)i6IrU*U2d48jHC>t9fY8$k92C?;ir}z{#P@Yg5>0W{{nV7;R{&g1Y3F|C+|0A zGC0>aIe9k`&sfbz=OS{F-xmW;Hv6RqoDR<2-?F;6RE{yidf)0brInTP_3{a#w`$Zj z3bmNG(SY=4en{=Y$`{BI1imB3w?Z5mh6qh=-NC`6RIvfc);7=XQfdO633~?<= z2)bZLU*SOi3IT-Z&WATrjc--bLcJ!&upiWd#F!6GqCxF-{sjVPVSIm))+j-Sc``T$ zzjS_GXh+QAsVY6&kB4dTe=c>+^RH zcvVB6SCNWJf!W&)gpDmz(bDwm3a^GS7`NwNS3sJXQ7H9Xz|}k1flINkE2KJ;WPR`7%J1%RLB19i!L7T6!kJW~>6!^&|O zKexyNHdO8dhi~>t6u5XCzg@y#SQ*kkyQrO=Ip*3k9raHHqpp5@aSM#fe0=dycnBsB zZo{yBGZS021J3^46@KI-pm`lZE6v%{-4!FASy>xQK0?sCg&8@`zmfSt>gxYS=27Y4 z6xoJBHDsFL6yGn|nO0|*dWIE}nogFQJ5t6U8B}z`pUbWv5LPaBVXMKe16)X@jB<7X z7MU~Vv*>#Sp&P{vi@Z~c?`6I(U{?O+MpW?}yCuGt`2cmzw@dQ-n4Hz}Z%IVr^WZX_ z{C*;Ei*z6k%CSg_sW}>tahi~V(@{h31O%5Pki=LVrb4?*M7p6PKsbhr;0vzcV6qZM z_>w*-9Gs0vmqKjx%Mt$or`VxH!qPv8f2c$F-jYqO?2O|xoGb%!B_PD|Ggsj+%7DmE>$*S1F)7E+t=H)c24oT(%QGEVdL#2(S`#vhw@7r0CpS`3 zC9l9~jO50lei`ASk%p`HH2d=&N@hdpA&lrU^_h;_yRczJF2B;XrI2$~ik8L{UpDq+)Xt$88MkBujqzfI$^%&CyX7`zh}z_B{6>PU%)OBd;yC{V2eW}mP%{u5)7q> zPK8}|(`PjprXE0*kDj_eGuBmB$`_LVA#xgP`Y2ySNb>t)TEk|!^t6U@7i(7IY&XBJ zoHb38W5DAjeQZ~nc)4+xt&>mDqhM{H=f-tO1W#?)r*uoU0Dt-sJiQJ1&V#3Hzo6J& zjf;40@bt_}<94T6heA}`>M+0umrzvLH57Q)B>GZOj2BR}qM>$NZ#9||_%Si~ih2#d zh_WO707@^Wk}8#4jI19_E)13cqyh$C=hXZ98UKM5l%B`20`_FXM){{RHAE!N;+IsK z6{ty$n=QjSSBg+jM2%jCgH~`4q-Rm1)rwmY4Z-dQF72x5Vt^aZaxB<9*_o;f!DE|{ z9*59e6A?I4<~6XtDHwY-5^*k!$^?$K!$S%j?HUakt6-D1qnPGxm+qeYbKaxy4n9

ls_--&+)Yo{>&}80v`Zi1jf^NH~ADgrt z*znf%x1JUfVPu}1{Ut?@$_svJOlWM*${qwZL%ikmF9e{wtLlvuddunGVPYqF=miBv z8x76myaRzKtfFGxM&qcm^cbCBZlD$XI0L-2rLa3+)skI5sLZOjSa{53g@k|*A?&=qb@9RB@-&Y2~ z5E8Sf3Ma2E#PaDfD}Snjv@+|yxLFexT^f(8Vr}_yuFy*$h_K5GOzX~OYHPE%~oglm!t1CvP7KGCNQ>ry5MoDS{5&Y;rb? z@HwK$d(I_9yAYTBV!|(J7Qy^N-<}gyOp*(hn@uQS=)Ktld$4youLsoFyPWjP_AV!X z*|F@m=PuPstXl0Ryj0s7g^x3jZf-OtOTN*0c8NDSGfS6!x3iUl5hW|u!RfFG1!Rb% zSx1&>p@K5}P|e0n(?FEx9O9NT@*oPC=UD65NO=Dp5C{md3- zEU%liWMq6Fl(Z>cCYRDRc>t#|-t}BtT>7|dr3F0)y5`_L(^{8+eAx%RxH>B6-V1|5 zD|>y$)wosmC;U45aYBD;g|WSvpUoN&Y0M}sA7wTYEYTa&y7(A9(H>Bfv}hPpy@Pd_&@%&l`Li;4HwWNvn8S~sy7LvFz+S< z{C$qq3Enr-;oSko+DG}<4j^6TSQ7m18{@v=71=AKm|_}T72wngsdqBTHVhY3BD(Z6 zRpo$^#B==wvx9#&4AP~+{fgU_{sruc#22t=Gqz~joMJmW!!>D4Y)GxboIs@`tDM#4MPoAF8o2Hd!HZt-jU8?xIW`wJAicM z4Hu)HVU2v6Z**0F%NnlyzF696^Y`@9&J`gihpdaTfWC~W`zSw|HLdl6lrCE&U)O&G z3+r}squfQ!QlJ0!18EmVzCe}?7Ef)-ak_ai428nf-Wog(qs8E1OL2pDm>&->p&UR2 z8@x6CwTsg*)ZqDvsLPn!Q#;oWe(y+UF?iSb*A5_Ed4tEPr)&!Fv0PqqXI3Rl`Qa={ zBV}nfdv58=(m}@IF8|U2+%ZgKpf|)gle=e#FU#1rjdXBw8@SH>c=_@nbjf)MJqu4z zS@-Sy+?IPAWN1x1m&wrXa+ga!j_eyuJ{HVH#0E>~pIbpJqWXt9l3?`GV*1JaYWGYr zJ)Ea7Ocp`ZmI9ixq&`9)A{uMd+i)Qz-j)afOt|8Xzni&9me^0{FKR8ZFTZfg@h>ut zf1xPHlh5M_R(PLMawintf4c~zqVWD3IA{eA3HGe;{sqKNQ6>f47$*MrtG52%gE3bt zeLe)EGPU);fQKOWw%U4Z(wr&7?rRl7-GD-<#l!l9ZhsMzN_XuBy$6#8FvypGQeDeJ zwe?G3Vkdd15Q@=8L(^MZAC}{we@KH!8HksbS@}vB6e_ZXNV~BNX}#qQ*O$SMQx=XsX2mSFXePr^ z-eBoR32xUbNRlbJ6|?5dsV`@__Lmae&yWT5+ag{u`%~)bub4dE4(6a!DMeB28%b`hdjU3SjP=^9fW6?O#)N+Q^S$6h1faXCx)&5utVdyD zCwXWuV6+L}3%*(gKh6LzZFBa5@0MBj@B2m9@0X#ge=qn|83aQJo4Xe*Sf%TLTMiZX zWgZOb%U-YuCN3_rzPBe1DT5!UtYt627R_Wh_5w>ke+gT<8Tk8w^JvbUzZ=}2qYB7c zZ8z{vDN5ab9I(gmA}Tzf1Qt;}&bFgomAYM3i2uCQ?Q$HHbDmO8)wIhy>(f{O&D$qs zzPB6jzFGtw@&sZS;nP**J?9dlU5HD5G2x|d;`m&s)J?>UBo{2DZsfmvOWm*sD|NdY zP-CTT^s5i0ZZFYlg)lV23f)?9yJVf)871o6^mWS?xlQ|U;q^fj{DJbcxNTOrWm?h- zw@lNsTH*FyuQK^7+}F$0w$QBcFBvs0$YP6zY*1Qh*@!;MK*UaQ zKM=s|ED`5}$u!EdR`{1LlU9N?@)Pg5&<7FjL_hRBBb@F1?+yO711MKMUCO9u_(1mh z5T=+$R|Pn=KIAJ*uCs-0E8m?{r1?I#s`8o61FKqiZ zvTrc?W-u2K8!T*l4#lpBb2`TadbmvvI9+x3A*ZO&G100T4~1P{P}QX?Y1^8d%G(iDzogZ-;l|8UGg*& zn13oNFv*W_1gncnd9f4f;(k*EQc)N8pEzg*k0|!3E)G3Zh(gBge$~b8bG+^&8QzX! zn$^td$)K^6NY_xnRU0pAYXn}71=_By{Qagy>)SSm%)$I6;2*zT^zP(Cc{w+ zVd>YSx;S&@)D?8q#qE~EEwn|v5@IQJEm9X}*$R4G7x!6%*P6;K!V4P!z#*vek;I05MHT3WHb1rs~TLwfrA4Dix6cQ5##GAsYK zUzGhr8Or+if_>NMvgnovMRY<)o3j@jRc75IU{GK7f@5If;v(y-i#w$Zew?nBy#QM@ zli}D4EdBiTZt}>|_4k9*uQ_-AZt&+hijdh2yi=`{PMyJ z7j_tmA&ep+k z?i=NAduQ1ys@`l(awno{4ix<14G)w*gr!k7%PM@u8WlG-;%bAf6NJ}fIkYtUZ z2LDSZz`uD3;HZH67Z{``MBNo||JT2OJrTnfu;j_GMe|TnY!7rPDW{9!qQjYKugnM| zMzh~qeKoh+svcuJRdJRT^UEam0w^fnH_!aA54LF32ue^58>0-Y>@4vE0pMlHYs(*= z>R($4gSseMK7YtiFgA00!2}aPqpJd(S}^f5rVVMO7wIWnVV03DeS1hHH=y9F;-{M( zi%l>nR8JfJ1?)n>7qI9lwrG->V%rBjeYLTgA<+usTvBD^Jxl57ZH(L&YG8{-jUYXJ zlQGJ`%FYr$5W#x-0sq;e{~auB-%PNjxRCzB7!@R>ejuzuYN>YE}m=rAKM*U7yEiFcRIdvYil91twaRBB21JM-w!sw>|BG7I^(%toRO~0Um#QM5xz*uy-kdJ8;f!;xdunD!VMdR zu8tric4j9pdgQJ>ra=5;Zm_@mL!!i^4B_G&*hg=x#(ksxhpPnWi-`8Mj*SvF6HnW%DE! z=fqLFL4(H{Q=4mbShZ27YMk1ZdJDed%QzBGR63LG0k*(Mba@rN5-louD(Q48020J@ zwbCA_jEyxq@V#gPZo1Kq>+KqRC0GKOzSk>1-u?e*g^bLjRVuSvnatM8%IqRASElsytM1?$s?t{(`dfSQ&%7e-}@j%MH?`Hj0q zLq?PYn>5GKa6+^UY}a!9V>A#p*xfm(v+h@@afLox((Xo#hsKjAD*N`7M6oI77fevm`TjE;Dx6p88A1eNv|m9ZB3`TVfNjwx!IrHiLh1X%Vm~@B9)N z5tw&I^m@#VWtYb7P7|Ey9n-NuU3(@`rY&>22zr7mQ#dG`D|=p12N!?ig{+{u-DL0R z44Ebm>?AKa(?NW7Fos|%k{&XKxiz9RVr8SG|#+ub{y}MCR-O$AK@DCzjVxw z_G0EJ0XYH&K{!Ckbht}EPV_He&vftwEXh=C(e~dI+hts{{OLICWNgmo8*}O!q4HJT zoIQme3uux2T+#+cM+=(RqM@nK`X<59%;)JU#wY_3JFWddSkrN~+K!fgZACd;L@b|G zVkj89t37ATB+KZk04Fr}e$d=Q8G8(!(@nZv=hB;zQ4-b~@^+t}RCd7cX22+N;MTdf z`xmgw0bjr(jM$Bf-&k z#obQQMZsXI0(+08a|tX=f%Z(bAGQ>i&LfRc1|oLp^aEj)PRr5o`TnJg(~#E4-&7g& zxe_Ew3~WM_4o-dp9&bNN4E9Dd#7hjATS$rT|K<*M4@wL`@@2NOn_ptUx=S@ku0i$< zCRYb@5wV%$B?gEi91MukS8&8YoYNA6&tW=0u8dWqt?>>FE7ET?5W@p3BONIv22pJS z6WGo87|5wN;Gj1#0e{rT;^C-)&$rbeOU{N3UK26l#hI5Qz zj=a*W!L=21Sp}{z(5gUR0Esg3wWdhi!(A4XL8oSn0?JZ`FXba*lrl(Up1SqHxr0tB zk2NNbTZ+nKGJzvl(L~DgosfXOu?VCh+`1hHt>6d6o+Y3UMX_1~`8D{*NH*gmwlx|b z_@E);q+vZe-WQCZ8oj$5MrHELcf&*4_Okh9Y|{2UV+Yr>XKXVU7cUTUQiLc7{$67` zV?$JSB@FcOyz#pTJa<>s2`H2|em_j?Bo1Z8BxN#Lu?%4xSusn$JY6RE z1DNB}&C!(|enSqqkg_~G+@-Gm?C@a-BW8zH>E)SV0-s86E#m7xh5ZvOtqPW#y-p5^ z+8~geX`>9G z_7w7j`kRA0IbHa55CGMI(G|y^F8rz-+kM-deX%^{zmYNA&&pV_F*#awJN%?1K=C)s zQ{pAx$7zhb;YsBLjGgtAPpTa3o`?5Mqy39{UqJ);w~qCHc(Hcm6n_bW;0UP1+}-(& zT~GGOWYr$kr6};TQtNK>bo-@tBp~*MQ~8x4+MZ`@ga!Zx@eu@Ups)5BXFQm!8C@0N z)QrbJGr>=@j9epa+k;CZR zF~1?g3a9#_k*{KuwIGfy8sb43`4(f8fsUQ}ejtK1^27eM14vn3BN+;Yn)!s;=&Ash z)yVw5n1i(K(s~Z^fOKDAnMmE8%i2BFy6e{OA7)K!BWbQKmA{dE3zoNUB-m11Z2!#| z6(qKPAgp3*Nlwmxp$@RIv?3UR1|TpwnG1c8z8~y|-mdStOJ^m~R_8P9Ups(u<@KGR zkgJ#?wQJMOba3(|*m(Pq+WjGJ=sdN{JaGLwJF=y)BNR z)*q6D;>04eeFa8HgOdCaGIB6^NiaVVCrt1@CysJN@(Vd`K=N(yYV^w6W^SGtsxE{O z8GX?{_a4T9ODavsyu#bj^3@Xck)$QX+{TL#QpDUUIA{ew;Pouux0;{Rq9MF|g#Bk? zvQcTTTxq2LSV!ho>KPPyw&T%8`L~YsEx}l;QMn6XR3-^{BRr(-C7VUTCT)K)Y?YBk zp(|H7+_sNN%^1_Utv?32c@pq00?*x5-6#qr0q=u}oy4Im3ZsmUR{o0ugiYQJokP=8pM$=I37dQnabShv8OnYO+YYJD7a>`eSI1HLMR)st-QI++7I=M zwr?#(Tc64Qcp3a`s^MGY3*{GqJtMQP;PRSba_lRXetRjkF`13U(g-_?IZOV|vKHX; zc@>$R#XF^_k7)+%SG+z3k4=FI_m{D)E%&Uqn7vFd4|?)%xi8Zx?+*rR+?E@O!0Tgv zhl6rXc}jiEf!X>PWk&^pad(iwdins%m%m6CFfSHV4Y3=H$YVKY4r1G5=4hoZ+=JAf zNxX?ktBRl}m~<=-3TF~s0jeFX*(utV$fEP84&s@?AeQw2y6oiZ_W@2NwxSI(50TiS z*&t&JhcULJ_0`5Ow`4twcv+*w)?e%NUL#CO{vwhFH_OnZ zaV1A>DWv4y)y3ThB48)Z*Zx79A*Kh$OaxY?@>)usC~V-p`v7~elBahAYOLgme)XZ` z=?bl~1Z$XEquXlj>L><$N3j;N+*JtYlqi3)tzNbiYEwR5xLp3*?oO0}%l1RmCq*4MWkKr^%jnuPz zx57`nm^td8eguPHe^T;*?mDRd^eHhLtNf(01AZ9{3e~yTzkpp1_yQK4!xl{#d!TbS8gm+= zs&J&oI=79{(SjznXlMrM+}*|~0}(r|{Xhik+}r(Y2N1D*odZL`P$Zw|8eJ9OvO1UF z7wejAJF8yTw5P*A3p*!%ZPw&9N|{1Gf$>+cu&(PHh3k^J?C*zuAno$U7qE~4JuM?u z`wRaH3L|^0s#!9ys~RyBU|ym(?-X5mgVc~OV6g?*Qrs5o(|aJSw!l&>c9ehV;!FxG z7GosL)mKsOWK-F6aPkS*ar;s3^mn+E^KvKVgj4O!UvOtKx7;c8Y6>3q3+*ls8Oiy` zzQN?&U@jsySm^YeJF^kt*K<5Uy8qwB7Ej&!@La#x;-ySHuPQ2@$(1;QU2Ku^d?ysT zZ7l++h^|+0&j;ASsi{er5>c$bMS-nb%jy zO~7`sg*iUmD_s>ex8#ruDa$KrZlbRKikd!MZ1D|PS`{oedz~B-#WRl)7FO}aCUq4v z?^RHIe`ZYQ23ir{rwKfFS5ZHdD;lKfxxs;OkI0+vBm0Bb$NA54HAJT?uT(u&aS0+ zSz)(Nu-ej~zA68Mx`RxdUIa}_`kewJ0yFzajvjMQ%i`x}_Fq;6J;B9|I4GQpERsO5 z7+bO<=iLehs;oh>jWqIjWAF{k>ZHe2XQ}I-zxns0ddwEp*PRLR$H8YB67Vj0ol zHB@O@=*WOs_@Fd%vH%B(s4n|MNBf_=Xge~qKZHSg4n!bvzH)Za@N7!caUo2h#3)3k%ldHuR4e_A7(P73Y0}(s*{XhVC zSt6>hPwN7<#t(sV8dqHcPug2uYPJN`h1i|)KG%;#&&aq`ZY4%`HgVL_mt1*T>mCgK^ZdFkvR1EfbTSdhM&+?{ud zU^M*Fx%?R~uE|v}O+_`*c#b_E9>S^6&kBIyS`~)*;KKzu_?l1 z6MiooUuvn<@$=*8*~xnkLb^)XP4+#VbYXA&C-faq$^*{vg8-3tImZgf+yAQ$jwwPy z5rugk4qCyF3O&mJosR+$4P8N>okVwYII4H1rgx0cjf=z4bOkP7Y>h|{V-sC~Kt3~E z_0O(l1OdZY*uJaZf{=TXI5U_OYCL%l7?sHtoeB@h3(nqufK95*n!czWZ0DcWS=CNy?3#i*c}=Gmgl2|#yO)!r4#7QGZEc9Mr;TZ}dun#p+w0#W#j`sQakr_12S z8DQ)K+M+xV$CtIe0CQ`Zm2WOU*<=zrhbA&!34IGwwu@f}lmhjbr?pR}uKu+48a$y!Ll6$G)wj@gt9o;+@yy}qg5l^Q_)tzWI)_~f zGGy$$bj}rqmi~~~ll~uYhE6rN9da5#k>=h9rgH4O*rf5syE`mmNDF-uf9ik_8&kRg zR}AP%0@2;IwBZ_oiJb(Zy;o8vBj6e0I0W3%PxJ7tG9ii9&F>3hZ?2Iq_Iu`#G$Z!j zDMd2;`2otrli}zQ2WHm}XL{GGx7eG7M35)L8#pM(fmf2@D^#t|oZ*Cu0s{+9(++29VV6^nB=-yo%w^hkjm;?LIh{@}U}s zGTG4Gjb?UAG@eS^Lhi&jC8EVMp(&A)Z{RdWCiIk92@sc=G+%Id?sR-e8dYD!h6tl8 z{?sY(jF$qAr07pzP-qt6xBdm}Sp>d-C47!8nroKgyLVPqIZX`r4P5OdqOTEdUw)=O zeVFg%N#Ugn<%fEg!Qwhu-ES!!;Rn=CR=$9R9MV?l(s8_h6(wS%x}rXE$c4&~!~M3> zS$;r$R&*S(?DAmm^IE4!EMH#^uy>Q zf}wVHGv=4T0%q*jUO>HOEEk4iW^Bn>y6Wfxo|G_S3_ydPig;wrSbkqjOxqkrJu$sR z?v7-)vtpfg(CytZULur8Pp1pz@6$)Z;=V|tk)gJcAthk)Y1kP0k)i%JZa6$c&HQyr zp?;S8lern{V=sy;tqy#9JKi3Tb?{6W;mH;g)o?()p*9|mL&yqGyfRZ=WQgQvav}0^ zFgZV%rHB>2xjLthYDDaFI8Lz3rf;bpacMl(Xu`J-keao6yFtHN=~vNrNP>oRO$oV? z5%Q%)37K4tBiK8ZDa4ixd;V)G>W2fkE2ch@u+m|4stBMW!Jgot75oI+vjqE*Op>D^ zVUT!4AH_T39Ad7B9={i7OpdGgQ^)hQ!FZ}6>J2a|lRbYGJOp8~y=jR}noDI^Q$53* z+B*(<`alQ%VPjf-yHPEz632fdf$8q5Ivj;^=x>3EokXHIzNAnlj-MfrBaUzBw+9yw zAqkR1U9$xYnK?eS^{&*^Z8_vpV)U<|uKv{233ytd)D%fE+_VQJAX_?9alIW)Kq?CB zjL`U~CdVe+xu=eA0Whk_xf$-{nMh7OL3mjO8=KTs{AD5Jq;i?IIK|Hxles}w#QCQL zoV%+k&dEohb747^+VA5ktz^pv!AvV%NNe|(i$qmku^!NzC;D7xKd$6R(DQCm43wMS8 z(62ruJ+7UOn_yF>M#rkP(bn~yN;8HGNZe|V!qd@eW2&(wu0uLxN4b2+#bNo7P$0^t zO70C^U}&t;j<+y>ABpVt7l$Mt1U5p;v-TspeQWi~c;zrE+ZdV{<9b63X683T7yLB+Jf(50KWE zeC1eDu6W`mrFt@s(-?`H^HXV@t<3UhT^i)vD>FCml4dcMDP5=$oB-{aPKX=5gm6SU zx51#$Nar2?1?(XyzJMjti7l$SC@;0K3r@&aF?@9(f$jE_w-|Hjs;Bzmsz>6E0`2D>LGzDZ#unP=dz#=f% z;t-gE#-(k{Wbm)JxC9!PX(FDnnvc#!q$R&E<~3~ol%CgE5#qOJZMbdEf4J9l4pqws ziO{N)x^tNy@&jp?QocZz43@CXXZ#D4kTy6}1-!GLA%gd%k;nZ|79|7j_PV+Gfq#J# zWWY7@cXUn$i$TE_&7deQllz_fUmK$gb@md<0R-&8SxK_K+PY+e4zjU$aUur4+Uh5x z?nAhVcbFgko)OP>NBm2VQk^B^rV+f$95v(CbUfCs-4I7(jZVGY67R=P)S4itB#X>@*YmN; z*=~(64%#y*b`({+JD4tNmgZ$JDwCOgJv;;pZp+MKleR}18D>F5 zlEQjBf#>e3MgR(BWZw-FJBdRnEJ>M63M)exM+(c*?}Rb}BbnbVH5`nT2}x@2UAf)Y zU0c#q>;7H(t%LlZ#$;}g6NtcYSWXR&s6-&P;S2`roy7_%U3(Ph0wctBBBrT`~O3DJh)LwWK;U91h z*+pa&NZCc!8mF>V=jamamK-PZgBfTAv40?ysFw7T2{ z6FW&m>LTfqQI`x^9O`1}cer&U(ZoYCx*O0L6v132UlCe4M9nCIcS=z&^y+{Oiq{L_ zxhSw+=z8j!Up6a0!_MOw@^48_(wlD<62e>Of&4>777ofe#wpdwhg}-CI+N*v3+j3z zUe`l00&%L!?I%I+=5_@rpDuzLz1IGt06E|sLlX3uV+C(?UvRE&i`+H=#g}t#9u5lU zoU-K`2TVsf!9l@5l{HkniotKH_5(0{uTua;h~azZ_Y*g|BjpM)+;1azNuLPW6e{Tx zaXHCIOG)3Sz)bi{`mhHp>AMh6VRZdz>m3(XuSYACEyf#R@J+Vh zHgQsqq(u&fx5eAsY)&eHmS~suJHaUxr!Xyy=yL2$#Jex`Pi*1 zZ=1P!W~jQbyO2L-^=JWpe(RwBi5GN7x!G%Ake<`qa^Xi$3Ag!H%gtU%)2d=24M#>S7GRT*3-*UjoX7pdu|xYc z27!_zbqmH1{0rCxgD+qa3~X@-Mtbzg%7rbaX3S*pNlDbGZiA-^k=DqUihm>G8LRo| zTtq7J`(ovX%^2yGAIt5#PnNJtL`Nf-bm)0HpA3A9Q#V~GpTq~l;=18-*Lnr(uY4ow`JOLb~$1UGJl={v<2AkzWSI zFXQ*~$Ca_FTXJ(f#$Uk7s#Ljo>tv6JdjFh|utvSHNnK@D>C^e=>yx=bRwQ>9803rR zsFIufHGmtMK3xbCJ4r*5E9sJv+zeS9l56R=w}t1jyvi$YX)1_N2vd?`!&jo2N;F@SZR`Mn2h@!575vykvN&QXsT7MtwS@H1vAIM zAM+do`%5?AyI!E%M%^+DRlC(YV>M(g0>ih!2AmQjnTOLDIfhMr6)rA2={xf)gO|%h zt(Pf7MetgCrqk>|FU=gujeTK|9wT(eu#fgHU=NM)1uQXaY|-|=G>vmeu6mjWA=oVa zgLGQG*jQVaFIBSCJ=7ER_Aj0vqCA=SV1Qu{hck-0cQv64_k%9%Nz*DxlC{O{WkxP{ z*X9tCX*|{GJ?f{o9np;p_@MmClz#!cZ1M#xvWYD_S2pjRxONx%ALU`mi@n_d!jKLn zV!D%r^cG@>0fv`%4$?y0H1rFiZ}k$vdsVBSy#Pb8t6D$ehor<+tqi~-nw;Mk6I-?& zP)}_6&6VR46aOGx;UD)B>sc_cU$e=sqC(tiiWH5FgemcppM%5Ij}*-Ugp#LdnDavU zhJWV%U2ckIpNr7HkJ{TB5qFW(cl@kvl55GYkz<3&e*`lQ;lvmB=2TUS@HmNV|Hg6I zDQTLe7wTJvVI~z(!^12Odo992E4ZK9voy`oisKj!aY3Mr%?5hmj(b;ZV>e#8Q-+G2 z-Q#mUFBoYxmhem9OD2O8!Bmb64mN4Ku@MQgN~F63|uXUOA-hFkjWt_y^uP}gVx!(fh1t)VNAvm%FBs0Ta- zelT_Q=W$kQZl^BSm%$~>@S>?lunqT=mu4GJCH^EKO#n(2J2%^%oD(UYI^hS0l=p35rxdZw-Nkqae>5~!e40#;FZRxj% zAr+FlU9$zm+Z>-S-dl6Xl@V|6lp@7*K)|d#8GxHdU?g-tb?sS-=W8&XDzk2xQTDpO z#z8rIos!}?gt;>K6+ZB0xMoL<%?Z3o-V(Om-zjCdzaOyw$s!n0$ojiPQa|RLQHXhu z8C5WA^FKw<6VAzRaZotJ-KFD^-7P7K?T@)%yW$jN_uIx8Ly8|RSc{t+yKz=`w zuR{_R;=JER@MMMXYYQbS#2G?z)RL^Y7{K)>E3gMkR-6q~V95&l)rVxo26E;_Y=89s ztL|!J?5N5xZFjf((cQLN+5p|s+Y+En`hfwY0zt7gQVLrrwMMWGv-i&3ncKNDmzlZU zE)f+(1sp}yDN&5^hhjn?h$c$>jwD9^7-Pg>_-jBSe@uMdbIyFvoI5kLwf@*Q zd(ZcI&-gvK64`hpCr=}FU9dyU#*B$N=6I(92aeP;! zXWOR29?f7^A^>4rd!FJK$EA8K$1gq-=JmgMKHZVX4rAuc;Mu%19NEZ=O3r;|*zf9B zDI%VAPEau^nByR+%Ndb3zD$hmAzxFcXi-YE$GU8NACvH7H0rgSBrpQ3^sEvJ|Q zEw6YZXHMR**pQTz(vmlFE<(K-_gBj20yb1YcitoIs}$Xl4@DZ?S#fP3a`-PPX@}%( zsDbP7rd3g;;b{ri$us%q7}x1Yne{)wb=rAS8`F^#u9L^Yi20qP(BiX!>sT}~30#MJ zYYd<`CMJ!cxX$j|8LmU_g7{<~9f_iM!EpUT#R+$7(bR%XlJHti#ay9UbRMTs-rV^@ z>A|MH5f*g*d+&_zkBN?*6JY3c6)pyQFW;g}TZCtS#(<&2X`efGnWxs{Nwn3Iy7QBD z-^E^gHX;-_wh{DFX+FibaUMmk43_i)0t>Jtib~k&luMc1ZXbFZ=ntvlQeH%CBBGs8 zvC;ktYhH2ExLvP=BK;8s7cz%!w1=F@Y_w+>Q?SvVldj&wS>fpW_3~qaO1CAN$%`Lm=u`oY; zVoRt__&a1L)0=iBArxmcnv`jXDURV*^LHhjF@8bGz||ytr<3g!k^`rjX5g){$6XOQ znX%0jz&I;VM?{4w^T(4H6rf{>i_QYmM+kB5pf3*?lA7a~qFbB0B{ zBI5VGYCPnx%RNJx%8Po4t1+!hIZ_bWFg~e;KP}y~y7PNfvwV_&kqwhnyx7P;KRjK4 z_z?>$jl5Lug6m1af~6AT7pyMB5zRsTn9&?>_boinZd-%IrHan2^sP}!!4bbV&^3BnYP+eOm#ssajmEA*j>f$QPW%nUm#u7JjK$M>Y;$Ql|uo`HK8stcz?O# zcTihHHZY#3p66W8J}Zwej@nk+SmeLN_e0~Co9Kqr0Tgf>XQN0V_G8cSwWg^%l1^k& z+2pX`>M*bW?D+%>mK(ziRCq<%d>lS3n>;zWUJ~-GI;0r!yK^xWlY$f(j9y15h2%wW z!JJIIMd}DC+?1a>@Ft3)lYF^K%9jGva2GO_MGbF~SCEeFC$^qVs4ugrGTDXy3>Fj|DKsx?&p2n>`i$~YQTEDfhm5*Mld@?4Npt3 zUY^-a!g`ye9$i)v*QU~^gmU)Iq#C6ZBG#pnnw_a{xM`R{8`!?%ibkq+6jNQvccyZs z`joHa@kW2L2pI7Mjc|L3BIjqE+5v*!e1b*peTKv;W}DU?Rc zMV%*NJIZ{Qx$~7w&<;5u^r8H<3jeIpJ@`y5HivhyRs3;wA&*=l>~5&ea%0Kx^aic+ z4TvtVefo0VN!9FY;tFR9XDwRx2$NV89f~D$Prg{1bMcL|yOAq{xju$KHlb&)I8jt$ zMo(F+6z0m@#K5w%AIU~PohmLh)yJk=+8!2|>rUpuY#S~L;7E6zv zDMyfE64OQj(3+F(ijwncDEfZc95CeR`Xc|S=+wdIhKwPxL!3Hzm?f1PnPYqlqtK{` z=(g=J*9a!3(KJ=pr3Vsi;S{M>Lpue4ks^i9#J5V4_rZhh5iwTDb^69pGChglKMnetX-u}=R4`=y*M zWkr_i)b5=v?k?BiuH1?|UZ;a)*gI5kpQ=;yH_jGoPuF3s)QUV`r+rzGj>K=WN@_S!4lR>oO_@}RY~-_%MIO`I@lxAr+ z+1Z5^$RYC|i5+6}h#hBm^eUcO*BbCFKIYt z%=Njhbc5@<2Dy!py9!qiA95xdR}D`Whz9Yvl4!_h7IBe1*d?lTtR>hq42L}DSPNTX zN{_Wr3Vy7mgRb#oE$qMIV=YmacIY?yGvem9v%BvZri-I9m*MgrHXovx29HtoD-pBv z_yDS=PwJcXRoouwyYx#Bt(57eKjzwf2j}YaU6gl)Khx|xIBDl8B7ELo6NH!sz^8eC z+|@jC>fM3AzGXLA3-(|K)bcc|HSoudu^px8px)Yfe_~Oy_(%4Te*zm=n(L|E9)3*m zYH;=5I)R^);%DD6@oU<%o63UPJVCLjZWQfumIwZ9+qON+_V8kF7{*Ru@HX<{>!y!$K6=5>v#|g=!QT_*w=5YaFd-JDy@{CpB|$ zXr(`?t7iCf)L)M!4tV9MUf&H8;Tv}?ZK1!2>@!QMV}Vyl;b>|XArqdXHZ^MZ;1Peu zuzGz@!NEqmg;YQ;`(AtZzTK{Y|L2mCism>tprm8d4hNUOXKE^;oon%(oMb7ZtdxPj zB^8q@qVqM#r9Z>VjoJ|8o=ZlgGW+YO4=xy`gGDC#H1MZQ)mrSUiyAoI!ta%uHSjk$ zcsa>wDJ`uB`9L*>MgtM7^S}|Kg(nNNws8tap8OfL@7YQeXT9ut>gVcy*3cE5jfP!vf?@1e$t2vYgBTS{WFyvE? zx)lC|h^{BCg5+3>5Jc1H8s6a63toL|6gsZ;qI0j*oi!A)fRk4WsfXXtJ+J3pzjyD_ z($b#ZvZveD9@|;m+tN<%MM`(?z~4wYSW}Qg@w6@m%EQ2nBYgMeS6u_n&N%I6su~K3 zs+kL_@$gWDyT{PHHmgSWx+bca@YDrpQOnZ@hsOOakjbtRs%Lm?S8;nJA&>g&+-1vC zPbs>wsGInM{EnD5iT)b5t3uK4>qD7$9BAJv%{n=NVerTK6ak%tco|j;2oi+JQ}Ik9rW~|*Jt~5@c$g_6 z3N5Ye;!~LZY$DWByC@aGD6Jj-7$dc4vGCOt$p7!SWKVh^u0KJ+-g1v+W)btQz6~$D zvUq)sej^T1kMYJtQ}QSWAM~yC6zn#bjvE;ympG?0YPek+5=-9OUr-m&qR*d4N91t! zjbI@3a86%^{hZ@^yK^_4CRK<`tOA)KViLKJ$SXwtL}c>_$TlJ`6Zs91PmY2-OyuuG zUMKQ_F_1$<{z~LEBJW=fato2Eagg;yo+k2LA{S18Tufwf3dAI`e;VW#B7a*8@(&`b zHh_#1`Tj<1G$CBgF8V!OXT!! zkY|Ye{9PcwBJ%b%Aparqi|assOXP(cKz>5xxtl;^p|+ zMN;9MnStXlLJ6l!kd{gxayWb0vOqhnB@a^G5)tjv_K(q?pgn zd&XW~nX%ieGPbi7IdXWqZCiq;>+n literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.text_column_profile.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.text_column_profile.doctree new file mode 100644 index 0000000000000000000000000000000000000000..00e9b2496cfdbaf66cf034770e874d349ae52deb GIT binary patch literal 104808 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.unstructured_labeler_profile.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.unstructured_labeler_profile.doctree new file mode 100644 index 0000000000000000000000000000000000000000..50f11093d21b556b737c9bd2b4606aabd8204ecf GIT binary patch literal 30250 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.profilers.utils.doctree b/docs/0.10.5/doctrees/dataprofiler.profilers.utils.doctree new file mode 100644 index 0000000000000000000000000000000000000000..7b242ec0036b576e240a58383f0868807ae062fa GIT binary patch literal 2328 zcmZ8jO>bN^6it)POeUF`BrRpr1gKC|D%u%TSO8mgM4bhqfRHN7^XwU$_}LHJFPSVV z!J<+tc~|oT`4Q|neqYHF~bE(`xrl@lO@!iujufO(LS==lZG`p~TnQY21@N|{7qBs%{#Ymir zJ#iLZ&R#ig-R$MBzrXnI>sevVA8y8|r}$b*#qA6gx>;S>#>TX@aMPML>u{z|&UaC@ z_!OmzN2#=GFH-S2czb*scmm)l3KL(70~EAZ7bKo-hiE-T zAoc~82hFmy3aha<8A-IKU8L)wE_)rry`?c;8_#cTp5F=MBr#p)WW6*tk3c34w_T9T z>As^NVSG+>VmGpwNmye8%L!*Xy7+GEz>xtr*T*dRPy!e z^+J#FMY%${$rZI4T*1O}ngbbnOEaDh72k!4)J5qD*O_6kieXs#<@0Z!JBjbp%}v6s zHI@jf8H5C$Q>mGc;mDMJGYVvaC^4LE?QDe*zlBL1^rnE;^>lM%%QGCO130iGz>mU# zVi+r`S0!C>(9N*k#UKdxEzgW)gz*C6KpF{U%tJpjdWkcF4#`M?u9E90`e8y#Z^#W4 zb|n-wW@TQGPIX|l0we@yHN}{ihocGswc4e-zkv$JOJ>MAPkK7$>%urrZhKY|$vnA~ zPS*N7B1}5EQ0X8|m4mh$#IrEMVI1^Nt7!(wG-f0QeIH_C zc1!5xD_d3j$g=S~06A8zp2xQGM!-@R{(waNo~nS65fl z;@S(Nr^c>kj9<=R>1HuJNFG%w@F1S&xG0Z{*$4jo@mJq~*@<0dTWJzA zm)tL_G{WZ!DTbad&_c|Mc)lObAjq6_z1fvdT#*#=J{-Gi?dh5bxe^M$5bs@OlI}+? zr|7ajOEk3uQTMBLy(G$Hw4wGa6BPY}i?5pvELRl5`=Tt6BE37+YtjsX_fU_?q+UV; z?Nqpz=7cL3n|8-MUvP#-y+$sAMQ`|$=7Yy+*|7{G|O>=ymh7I>b34-!~^ix*<% z!Y~2;x&T>kqIfZP;t~GN#K?v5?F*>9$C<=@O6d`?MpB=(c6FJzk=hQ$LTF;Q&)0GiB=W7!EU|6o|zc@C*!oXz&j> z{M+~wbc}xj&>48P9R^UHup0&&@L>m6S9U0Mrb>n$G^=!52Q1C2rnS=>S}vyl1Ix0d A00000 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.reports.doctree b/docs/0.10.5/doctrees/dataprofiler.reports.doctree new file mode 100644 index 0000000000000000000000000000000000000000..cf3511e306346f7786db0d9eca06445fa57ac4f9 GIT binary patch literal 4138 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 a3^z7maQsdB#A(JPi+>q<(z>4 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.rng_utils.doctree b/docs/0.10.5/doctrees/dataprofiler.rng_utils.doctree new file mode 100644 index 0000000000000000000000000000000000000000..05203d91f6fcbf4a4da084b8e5e4e1067ca6305d GIT binary patch literal 5252 zcmd5=OK)6B751y!Za?E>5*CR=M`(mC;%+ps029H4Oo$-RpfCdxQdCoYZ*|v=?~AIs zc6$*R5F^D>t(eOeu|WI;{slrp`~jA*9yD9NQ`Pr&wB4lP|_l-S$SKG zNcr^C`=zr4M_secoI|%M<*se9+E}@4n`0Y$b|sEdQTB>Hx9i*(74-{)yU|^iqfnFG zt3k}Qh7i9SDNp>bwXn!1gFX+Al^D>P!mb)Vq^VNw$eVIg-jd65&pztDqlMDlAN=%Z zZ+!hL-CSkQbT{ONIkI{v?i{{y-Sz)+F1f8Va;JW{2-on&DVi*K~2O_^vc?Vew7IA>lqd#2=t z{E|GJx@_`^mmLUh3ME)y@idS#_w7#Zo1YyKDzF;9&j$011SE@qq-9(1I3FsW%PCmw zqX!DwM4PvvEXPmcjMDLZ$j1w0PntMN>APNCK&@-VRO_=vAUcCNLvq-zq+ z2y6T1P#EUD!MrzE?T!6|_I{MMJ@4kY{GhaNyquApOHM9d&erq)DO)c$kbIBWUO|Qp zrZ`+B#s#EN%rG4x#ZUlEt+C&}?xB~ z30^kr=jOm(1;^a^3E7+AQ8J(G`*s7@JIs;0Nw?i1Q(O{uV=6JdmkBh;oTo-FMjc!TGaqw4VAzU**MKP5o%R8Jp!=hY}o49-Ow zBHgeND)ZD4<0^T>zQR$nX#QzFnzNjQLX;UErKMfU&ro_A~VJMsy!v^QQJfyDo_BY%F6y!J-``-jUaN#%jxf6N17lFy%V>Lbt&fi0z7C(dO3 zXXxC@*+6W5l6msavT4@_MI1Y#$={HTLhccx9xuX#KEdm#*R(JONdV84-TM78P>xw) zX`4Ucae;=o&RaV@+o~Ip5(C7V(1s^D1{+=t!`a6eu8)U>iZR+US-|KWK(kQSpk^Df ze|3;$Cd~|5-FouzqTQm$4{{kB4KkIKkZe<%o3kKG=uM?@IbhW5q8=>eIL#W$6bq5;w$5Q##DE@Kdl&`a8FUYLwcM0P0xskTCNS*#`= zfOUch*-WJz&)1&aaT1`LYI6TXlxtCh8ADTpRae9)&$M9EI~_{`!%iX{;pIYSu`trS zAJav~R<2e7A@ABvTt*`VxO-}YHRENB9-Zz{dxL&K30fyw0}s<_AzZ$J=X^Z`MRzHx zz?^glBF0e?neuxJ|M+*qZs#IrfJGo00|yzZZw|)8dI}HQmd51zsM|d~J?-RYMrLUz zQ^Rg3PP$mByQRHOJDe%l!Hh`YDC4?1ksrSP<*x$SZ8Zoks3FNj&8;Opsu;GAF?HG&8-tCtF literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.settings.doctree b/docs/0.10.5/doctrees/dataprofiler.settings.doctree new file mode 100644 index 0000000000000000000000000000000000000000..51f42c35ef6726c556068b9028d97397ad028ea6 GIT binary patch literal 3098 zcmc&$O>Y}T7*3Pei4(_8TG~sKk_swP(bxz$K&gaKB@RURP$)=9)o8ps_6*sbS>_{g zget+IQY+1^!{6b*@FTeM%&vE1M^tbEOO|%tnR!2+dESp-TEF$XE9KAkO~Hkn4QQH5 zl`<3jW~vgGGik%?aR1lvJRJFsrsqaEov`3na3bL%OEr_>S@6Ah+=|Q$=Jz)YORP|` zxz1a>%{QKfBi`{XD{RIVw*2Nd%vvF*Cd4y1vi>cbMcWHIFGA@D6y5Ocg2J*5e9w1C z<0@bC?YV~|zn%%n!pM!O-=fxPF?JS_#YomfYNFR0Nk)x<5Z^6H^Xh9eb;adkOp{a1 zCh?5(8U*iY<%i&YQv>AT={SP00`q8k^>PIt7sipXuh>YnWJT$|~ zv!#uJnTI{l2Ep7pS#@K+;#)$dY_@<;1s#7I&hxv#=NBV$cv!k2;_Ho+Db z4DIqIe95rK z2>Ofac}M(CB+(nej~IOp7X0Vf)bHZPta0v$Kk}P39D&tDS&-41G|}%Z=vb@5|NtJsGX8m4MAtqW$%VZjS`#YLBu(mESyg%}tDU(c7 zt8~BubE$}nq|xHv6%o?771eNLoMG*+1O2Cu6ItgL_*+%W;BPSV>L}!^gF!tJs}Hc36qIR zaVq$ZvyPD#oNkOO97JsbIUQl@!? zL!_iYDHgN9+rCGgRpe6SR|Ocgle)YhO#%SbQXoJ$Eol}N_Dcz%l_tLZrKm8>rHah* z$fsR4E0kem@n%Vp#F8^%M8(fONrj=~ECv#b5iV}j*}xz8E`l*=Yqacypv?RjiCv-W zI=A8%jG%wSGkD&pEya6pquVx1@N+Mw6lf!-U|}Y5VZ&D|fBf0%$ec8}*|<+k5gGEz z@0tr~>5OnO!$O$-5SB2}bP8c^{KDW#AF-wuC7qG<{v(R=k$rL>$ETf+CySSUjmfh(hWO2@J|H1MFLZbT!dqggo-))Mbn!hH0$nTyDNrGeL&tMeuqA0V zm_Q6|lV;J5X@Qvr@{K60zWG!B#Q07W*oy*SJrDfp$nd*yjCg|a;N2G8fT zrls&lv~DAH>%f3wFg=8qu@C(I|MouTcNS?>Vz844RM`k3aH%A*TGZz%uoorOIXnSq zmycD}Fta@R))irMy0fIQQ(G-BU0>3Vs;_NqGdHj5n(wUmE!46^xmc-!-%eDPfgXqf z&1~cGT>ctQ_#!+(Hew_~eq&-aD5I6Zrlc*2w;ORuylo+q%%!L#Y8pAWmBy+&FHmt3 HaO1&Wub0Kj literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.validators.base_validators.doctree b/docs/0.10.5/doctrees/dataprofiler.validators.base_validators.doctree new file mode 100644 index 0000000000000000000000000000000000000000..98f0fa722113e8d30f5ad369ff55824f0f7b4eda GIT binary patch literal 26522 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 ZtL}FjFjT=7eQ0K`K}KEKKN&q(`(HI4F*pDK literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/dataprofiler.validators.doctree b/docs/0.10.5/doctrees/dataprofiler.validators.doctree new file mode 100644 index 0000000000000000000000000000000000000000..1f4a6227a663c92ff083f68899576b492f8d4e4a GIT binary patch literal 4155 zcmc&%&5s;M6`%F)eD3b-u8qyXUT2ahiX*%;R^R|Z5JVyrSY-ksaUhaas_CwoD!aR@ zsjA+cMIhlrz$?`)#UUX6gGjkV%3s5QKY}~I>aXb;v~g}3X{4@Kuj;+`d!O}}_TL{I zw(_4n&?y(ma!kW8ks;I0_CgtCF-wg5)V=o9{n_2KeMQf;%v8XfZGj`;A_^5t+#_d) zp52H@kIVC2%>pB2QXl7S-r?Ox?jG;kwh<;`jV(KPNFxzaBb9cZ3rss7u%(y2w)ct4 zb-`sfY$v6VZX7?deNwB-w{54?a%y)XkuW#SX4DR-F-pub1M9ps+alCn^KKAPtwF?h zJE3v$)eEz9wV2W1iDGllli9AJ3%}*~0l&@n_#M8@kL^2?4>ePI^6p0;zy71|Pf{fx z>j?~^_?nA|sR=aHlR~q#jqzD+`dDe0bNBRGHsiYm>MPg|D}wF5E5j^;qB&BxR_hfy zuS2y5g=$lN*8{*`fYtm(K>ITOui*bG{;$Cz{=M9ilY*V!hXNfa(1(X*oXRW-8=fkh z$XkFx21c=_7t6h?1o7MUyG=wIhQkf;q!I=Adm;&)4iKgGEQjDVfLS$VAl=k1O4)nM@{fA5i-+E=f@Y&@fykyY@x zze1tkz^5tYzdhaIA58g&m;B)+|LBtc?zF{!f5|^Cyj_{O2X%u@GdcMtX7z2yP_f7N^S<~al4|+fq?$8oGR4SD(Int&c{N!<~2v_;98PNCaPD+Jx_JsnGA73r@ zDep{;qaJ`~mHclVh`bo|QEll0k{q^&GBM z+4>i3{^vI@Tc3UF&{RIkW^5Js-NMa!72&o)YLwjpj+YIjD!Ywq2CD#W+_X;JxNN&o z!_h>pF8XzkPp^VzFC@A-MYqmVNFq~AK9}>$0x0%>3ksCtBe9&iW={N=ZdHO+ri&z}c%B7-tV;X4Y?M=eIa} zys@)!1^>4l7MHFRsE*!Q-`F^554`~zC~@Eu!60Y%BbqESlmNgTVtoyL*xpbqkSZi- z+6WGa@tu8YJAq8*un};Gkfa!?#M1GO9n#E5vLe}Q0ui+zW^qdDr~|4wK_K8%LL-0S zK~4d*iT1uXzi;jY;(zlgat{IhvW_G8s#?n1t+X0!}?~_NG6PtAZ26 zuo#Xqa7+*MlUE-60LTv2JlGK9DJwB|Dlta-Ixd)*=VG{tBZ%l5IztMDejw}FV+3SO z>fEf=Cpz^Ja%m6sMPlfZaIxSK{s`WkNcyiACQm;FN_8P0dGh#66GW75dxsqpJ^mH{l7GQJ&urgQ%|!~t{7C=Rlz%bJ z_>2DgOSF^EF@iqjf6DBB(3W0TbXp-@~8R`p-^r)z-&Q-ot`9C&h^;`DscL2NcZD~~adi2uQ z54kUmgdU+~jq0oj$I!HT#CG`Y$3Nd{wZ5)Z`~LhH_}+XDpKX`TYRm5U=s=SFa{7z+ we8(sr?fh@$d-!wS9zv5sAq=D4k!I@Mo$Xv~ znG$Fp0tw7prhljZr9YzY{bp~HOhTa#tw6AI=FFUPzWL7O*VgX`+bhM-?dqJ1Y&M{A zoXMDJ?>1r?*_36*zxMZk^UwW}>neJorBxC0ZUq_<7fGyG=AU`j3+hHBdQhG3XcieE zv*tK&@iy-~^GCevT1J?JEo`~YQ>JuK4=T`D|DMf)>G{SBUwDCQZn$<%Vb^%R@4BRM zl&`sV<=@DyCn95hWXIHPQe%`DTZ6bl9BU%h!RJntP^}@vcPpc5`Lz+-e7+dd=uELm z(6O##=rnA3zRPd(ZGOPl_@VoH_(a3`;dej$`0?kT409!a(!-bR-EJuE$2 z+8CUdK@XHhEO$;>>i-F1}M6&i+83|MRUFYhx_OopxTdQW~j(?-*DEiuJ30y9W&LRNL7e) zydIshLCLCH|K{YJc8>tYSLK_J_?^J4w?0Y0?n_YPKgO(nEjwn7Ye)Q{>s0V~R&!@A zqBV_z&zrbmtqhSLmxO$KkWI4j<8bzx>qSNuz6}mTSdqY^N~SyPzrqR?tw4 zrjT@vq7e&z`>nQFg3;hVEgB;zQ>l^ACW1Ey!RHGZ?gnH_d`m7HrW&`OhhV- z|90iizgn)Bvz!1HhE$9S$hL!IOyPaV4cF(!$_CNR-8bc_^= z4fm%T?hu4bNt2t6`$VIJGylr%=}VOR8R25e6Z}Em^+X2VZ|jsI%YL>_h@J zHb4keN=c{{wO$GJqNLQr1AuhtSSAfG3)Oe72pjG0(v98PYH{fL(*3CU%7i9!^XgsI z&WhVaC5xmDb;`S~NG1u$ff&%rI*%&(Ydqi!{}{Q5F$vj?0al}kmIj-Gwj|za#0BlP aL>47BMjesUz_`sg)ZD5(g*m{E2Y&-j5Xj8{ literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/environment.pickle b/docs/0.10.5/doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..7c172859c49e778452d40d7da21b139c0b29db2d GIT binary patch literal 650218 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%0A=Ddi{|m;sGw#142(w3LbwQT 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/examples.doctree b/docs/0.10.5/doctrees/examples.doctree new file mode 100644 index 0000000000000000000000000000000000000000..412e2466d29d3222ca17ff6f6c8e88092ce11243 GIT binary patch literal 4707 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

+
+
+ +
+
+
+ +
+
+ +
+
+ + +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/_images/DL-Flowchart.png b/docs/0.10.5/html/_images/DL-Flowchart.png new file mode 100644 index 0000000000000000000000000000000000000000..696eeb5dc8e5b8d10dcb1afd7d6f165301904cb6 GIT binary patch literal 7609 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�|%AdoE{cBt(ai>em5}`oW(ntw?ksf6@F7g600dK4ufsPToE0O(R&x4Je z<2;~uu+9CuFK`C+1VT#213C!cIV1Trb|U$6xIk{Gt9%10i&)fQhF09kv@4KX?n~dL|K$ty@Qa2}-Wix4J>#s|)pjw5AfmyZHC|dfN zdx3~2B*`Ag1msK$tauX{j^XuqfH=cPB(7xV&Qh_#1cUc=)AxLbNf&HJ@Rv4&dH-%d)FL)IdL0L zBg$7_L}in~@3z~HsGoF8YBL&SIOLfBlV*eYU0wo)M&lhTf;yKm-`h#>L>5f2V7efR zg5xY8jzZHCWOrflVPkrzkIx<|Q1T_ZDS75YN_gIsUXE?=y}&qmvsuif1SM)g;;7V@ zFGAf34MN}q8!E0zs}B)C!bvxKGy*j6E^<@dzQ1>=?dV7Uel%?SSJBgOu5(3610$Bw zwghh66Xj(DlSP|Va-6%Wg`s8}G5m$ZQ<5jzk0FQ7zge||V%kh<*)*u%IH0tE|+z)H0RTCCsUS2hoj zWd5OX?D1Gpo;SHDa+p)pCBx9LEnG8q(7iAuh<=4fPqqR&X3=gIKITns^s*sg%+kGlh3Kn)Q*X#~#)z1TK(t?g$!|qHE7JWwZ&&*q z3JJ_Dg}rSAgE(?6VjV!{5`&80Qggj^qsT{ag2kSWx!>ZYXE&N&w`3fYBU}@Lqm9T? za7`qLXf;R6DHEw*45#XEQ6HI%RLZRylvh&V5-suVYchq-<<{l#hS-L;xhKX!lg}9p z9vElDTZQ9BxeT+1RQEzl?a@tj6KgsLrsxP|h$+=ZxpMg=Qij%S66>Eq^wpls!+ej+ zf(q(w1z;j%NdJ()>5sFtGMG9S$Sw#eJx@Ul6haAs=|!FlAL*fVhNt{imbSnZW*ctw z8WZ7N9n!TjzJwxG9>b>M2@pPxK5Rxm%injBI?e^r^ZX=|`a`agEc^bn}$L7DRW#Y7;r^*s8Iq+S< zz5p`w;_Pn0F}l4M>SDi+`RfR+78lfXaW(GwhFJRiFtb`Fbxmfxep0E`(P+KR+sRNN ztbT}F47-3Oy6Ukuz%uJGs$iFxl0%R3cPn_7$Zb0ebUYib(NIOTrd9;fKQq%`do)7Z zO8ANAxSe{Nm(7pCZFLG-H_E7D7(Y6V)g?M<#>vmgHCm~@9$}SatTr$;Eml$ryxvn|zLh_x z&UjI(J_W`4KXcUaD?+Zlrp=qZ>Z0NgriC-dqZ5VGH6+$eQ#S zf}_5pd_)I9&~|B$aA;;_T zQjn^G#ed`!qV<7ptykyH?Ms~Z>p2KOV~M1Uo?rr_tL{7Izn zmhu;8js|@q7^5hsF)0h24^%HnN?s53I|86x8kRRFJ86h-tJvYrpBj(G45epXb}W_h zoC1Fk4Uh5xJ3JjC{L8SU6&cvE6|ywu{p`+Q!ixGGT=t@5zj&U!e&~)9^y--Vte7X0 zDmx}7^dsl_3==0@zD3Dy2KQI3n4in3mb;vK&5DM3H_qqCwmwHl1^&)`;>BtHw6)F^ zTK|N}wxRY8)9Qh-DEzkKN0~}bD|kZYan9UM&MCiIgxsKNLFWhX$x06+dck*icVzr! zr%c$&$UX5*W?gWSbn&kK$zb|TKefdH>TxdMxtwx=VBD?YW3o*oJF>cYzz%U7#2esh^!!^S-j=JZRc+sbG@EFth&FFJqo z$h6Z6bal`UUj`Z-6Sgp5qEzvYA2yaL--CiO!aS6-M+!+034tk^ZVVikLWxNlj6F1XYni>Es$x5( z+t9ER&FEDH%HnokA;@bZv~u6B%E7+PDKP8l{zv%Zq8~Fdm*4}w2W9KVYk4j7&5E4N zw{HcBj@dG5Te+x|=v+Q>6uTRL$=kP~e(KS~Q{P{IBN)~BeERPC_h^wb{#}TEhvLUY zA2w8^FJhi2)iUFlBHyH>U-E?Y(w+?&m>91RypQit1+h`x2^uswkDQbne1prvKx0n6 z=3kg*A8a?|-#p`C#QSp*cr)^gvEPkDl|%0PK5pA_yw-e345LbDByllrh9c9+W>szz2wymrSt(f8a zM#1S=G!jH}0VM3bqi`lprqf~li2YXEjg28`S<}e@3F|CX6*5mO=q$sS_!YsT2E18?KJY1P za_9_=ask^$jRJoiCOjNA&RNC2t$HBL7vh4-JbH_*#~NSeh4$yC)Jv5{4V9MyDa&Ou zKlzkF-uNyZ__?*N9bev}i!K6I>$_Ar57h6V3QKP?$8jq#l$vuB zTD4iZq276ly1kWIY9fnl*22@dEVRf-p%J`m5l6bNDO$0u%G?vW`UTAuN9q1T1*u5X z`$WnBu&V53_`t}zUP=R>GLoY9@xwB`Lb{vD4)$>>NBTRx-{m>=j1=_^6FWBRc*gge z_cc1Z-m@)$*O+N|+pNt%f{+qvf*5|@i6UD_qcs8jO{)hIBa(aK*jhj)DSb>x*aDX% zv3z)r3OS7cog25_eSFH8hM&I*U_5$5lchNMCF>9OSr7uOp@+?58&1MLqJpf4Y5{kN zd)1~Z2+QAsL4+#urQfxzJ!#U0U(S8AU_A6=VZ5sCejd+xSw+!t@IJlsDbIXVZQCqC zTrr^HXZ_#x->VXEbVzvq`QNqSP6FGju+ItUMDebBG^q^lH-_t?@pavpdmiaz`nN(f zH0{dBvgs+iQp=iU!*tL@pQigexsua(S(>Z=`iAm<{MP5oKy!LP5#IzlBW7pk{l=Jg-m95v z|F#csW0LzYqL(SQ4KX3?krH7u@69aqeto7=rZ^WB;uW4!gv8Rz_wtwYy81-9tD2oX z9yAhs+KkQCr)jht=Ncd$&!#W+pr{B)m&7K8 zO-Oft@ATYr?>+ZkZ;bo>WBmUZ{~6*)p>4S z?sJ?+OzrJ$?1XuEEdP80x3#Sa56ArhEf{2n%@u7s45Ph){wGV6NHD`Nes$SP7u1}? zCWx-~YD3YRGbh_+mG(v-WjJzx^Ai*KrGW=JQPRh36NU6uVl`AQb>jW$uW;<8Q~BCr z%Eh3odhA#{m#w7sJ!VPMT|fDr=q68++;i!!(lzpRub+);35Br4))YipvHc( zol`LrEtcLzK`R1i!dDp=JkJ-zptF{b_D)g}Zm})@3S+uUw+o zwyObs#86GJ>sclpksfmClwACR`O3=5XoAE>k{#!%Q&&{uuPG}l`}wd)On$J(8bo*O z*ug!d=#O9gmgKRqItsUCaP?u{J@O|SxcUgO!i~i)y1jb`&WT%mIU}ngE9=dmLMB<0 z$tg!iN4Jxjdd_iwj_rQQ933Mgqo+@wCZG2(`ZiZDv1HGNnJQ!#{hMC|fwcr;CaMkj4~+4%*Fgu%gs2Zdc`WAXDN(GpuL^}_i1L<9E)b?ZtB zFXNTg439Xc9v7Lxk1v{kJ#R9mx4cp*v6&g{AI;SlEZLB(UuZ9zZBpMhJ5=Ma_)VLJ zQBY}axK>p~#h(yECYk-5QAkCXU}ZV&xVa*2r-Z>)*;Qfk{g)KkPZ)M)7v;~ed(P~a zge_9>+wtEHTuUkW+1}DJO?+$JF4wx(KwMnB$A_YC+b!*&x=4wPx^R)2c7nr38F!@s zrrF$mOD~1XE7EgQNMeDqFB#TNdb)lQUgRTR|MIq|r1Yf&?dH_i*A^#^yXOubJ$lqY zfuc`ZRb4#}riqmK8lBZ=9^(2OmrFTa-E|DkU_3&`o5)xCuzH3@QdNKIY`TN{83bmv z(*OLvfA~OuIFKKQm2PdWp?50mG|9=r!jh(6w3ytrfB$~dPrn?^>aZAVjCl;(lemWx z>o%Vm_;5(jChFqFi~INPJyt|acj|Q~G+Oq!&B-rJ5_Kmgp#U$U~ZLwUD8`LP}naZHtdaVXB;f3JL`xW2FWY9ha7=T{#=tdC#6$g$O~ zUMyi?;O0bUu3Yb0&yxMt#u9F8b7P^7hm*4fRxh7X_5O*DY?-R6s;deLZKdvOqG62K zp<#F(Lv14SGmRm9xPY**?!GXDP~+_xPC`e-m;3I+(}nR{b$^MiOiE5xF*Qv*&A|a% zwW<3H*7+((RNDUA7iFH}>3i|lepMmm!5&O3EYulqOSAJKx{$)3zIdUoprG(_GIH>+ zSBlx>op&6OWSpl@tK7W#x<(5Y8SLibJycjoY<#>lhi1B(gG25&N7oWN!BR3)n)Q;I zsG*^ur%#^P9DMfViITc{Ah$trVqagMaF-zCZXw3qB)qzME1!gwnOTxTq`3RU-J_!^ zq;lhI7ZK@{kC8X#9z1-Q1k0D%v%AD~soIJ#4*RfhWjHj~xc1NjY|fqn8m8XrnwrDK zo<7zB+pJ4UG3)88WW~(d+S(z2$qv?rIy%WcC2J!CA9%W7Ri6zd!2c6SLkuU z{BZHjWv|LDzsc5=;Hy`!s%dK{0XTCUKYkhQnKwTfaQyYC&!0b6yL|a!jTZcXl`tl@ zc2XAh?o~xar*utqb#`Il!YW^v)p;}h;^l_}ELCb()IK{5@oRVV9Gh@8@xJLf|3KJb zYGOh#ZLjB}T2*yNwXWdW*3sq!u}xb0>(`?I0FKHY61Gotoa|0wFmzMqDO}3BFE!`4VpgxdVb*(tFI}541Vy1K#s=--swFVMyUGq zso~YxTPI6B~(jP=FX#4dFpQF&*Rga-t zUqAVEW}EnmFf(I1pHnhQJ4YrcDJdO3e)MI@m>H}jC>_I0#XYDG{9^?D1K|8MwEq7C ze^+h(G9{*$G&F)H^9OgMqSN2skI?SzeX7I669NL7P=vVUl$3sXyqBW9RT(3T+5;O^ z-P}AGh*5lTv8emXQ1Br!d`@yo%3&fm8`~uy9CbrqGH)?o-GynArY11VhP5mIPD~Bn z$}0U`MTNSaUh0&`QW1?6X>c&+)2B~CK2%uy!}DI44GkdWaakr2M+^I&htv%A<7tG` z!ooUBy`E)@Q@vB(&R7E*lugsuot-)e(kmX*Y64;(4r@=*^g$+zRTj=7+@%CfJ&jJq!cwtEHa#PZ)s^Ug^g7> zRk}7-LNv~`odQbs)cNW=*lOV@+|- zva+(+Wa~xeo=+CfDJ+aMN+Ci;%~Kq8tI}t*QHEuq(*r9ni^0exS?PHUIAsqB*~Zo^ z<1$L(BiFy4^p9<7QdwE`*zgVk7Gplvl60DfNAvM+CSLmyC19?}z_cQs(qJ!u)=RQ- z))bC~-MdE~yZ|r6y#L)pu7K@Wh%e7w;03=^ega+jw{I37-oHNuGSW{!bN zC)S_@&n_sa)!5h=a`x6EZvDcq>4I>fsTaUbvU*BDL`3@M&(|h;N_6jUqXF#kSBMbR zo?3?qFl|fKuKxVFsy|9rZ(|dFMZoEQxGC)uY+;MeP zm2#2eM2k<3v)qxkxVmkXyDin`tOTopwhS}78z{JryeEC>l^okAZx_=%2zL4>;3B+@;e<}g36v!5DVldqV~LtzJXrnRNz)Ujjl zj6{zeyU60Xey5~seMCm02`b7$_>`MWkkP2&)@m?QARP@`V&)ph@G1@CR zdday@oodLg7f+Gc7**^naV7NN$GOrB%SwA#WXq0maL7eRN7o$}7Vf<74YaY-$2gK~ z7d7?E$jC^zJ-v?{r%&%ccu;$aAJNYWT8VG#+OcF5+Yo<111_|vDi-J|Z#{kfd{Dud;a{qJ@EfiAZIEb(KNrl{7g+>KMf{bE_qFA6j9`Rl+?V=)7OzG zn(nU%5p&J^_~I~$^B#;~dJt&Yz7y9Pl2j9TP3jmyyK(UIYaAA^viCUqHB=&CbG})z zrm|8-QDP$p2@-{HVYBZ1JF64cp5wsNV1x&{JEPd*;^Nr3xYByMN>`*tH#aw7VW=4! z#}`47z%cpu)?^faS&aXy`tyHL%Ko1kN|F`ez`l~nDG@MjCoQd}t!>tBW>M$XiGM(q z?;@&<5cGXpnrc}@vxsfnegE}R1gHE=@*QQ;@FY^t!V1l|Hy20cn@Q|bfA`^ zykU*Q&SG`V9TCjZDNsA*%-fLkv@oc z?prP{E?Hd@3w4AJi=8`m+|kCOj?Wx~dAn$YW^3*_0!!-ofm(%ZLh{bOZc zo=B1l=B}=;_Ggn1<(Frbe%`RYGRNomO$%;b1;DJy|F~Rn9t$=-B}lOyd!beAoCyVz z57-juYoTEE6b&I#Ku{3e>F0uoUw(-~uvz7Q9El)}41+W%Qv9nQ_F&U&b@0@`Bl$hy zTgc^rGNpTD55~*#ZzXO96&_+;AU41AEKE1D#uLz3}ch}+L4v+YGv&Un2GCb z8E(}1d3hQ@$aJ!9dq3LElnh#NBq-w_>({S`TUzjkTJY=I4I&FK zCp@qX3!#`Y3@W*%fy-r2sC*86^{`ASF&huMlrTy^dgJ`V-+h_vgZsA*Y{b@eF*56;7-ZtZR4|WJUj0FsT z{xxQH*7n24kLFNg>UbW(IRasdXT7ZVX7)E&pc0oZw0e-pvamlZUMR9$0VJe5k&T;hU+fZ%zhd#18^5u~j zU-J)7>3TlHg1~5PN-5n&n~rm7XI+{qS&G=Un=#SL3k&w9rste?Mg=-QG8^-lZVEj0bG+`nSB&%v^ZB%%+E4*kHgLi) zouF*YU}e3R4pkvg!#M!o$Z`~BKnI^>W88ZAZ+do=t<+lE_rIg`rGz_^1X^l>d9Dw# z%!!o4X_lYVsjq{3dhgynQ9pPg7;~Q+^)i*j^4%JmAfu$z)N2S&zjb7bG4Fz-Tou}w zl$4ad)%3!GdWJ#C{O9xart>3>%(TBxWJbwi2+Vmo&FIEbZ#yE_U=;zuH>(Zd1ASy= z;{jS5+$D9BVi?@d&yVZXek`PJE0p5HhY!LweO_!yhGiayM4jJMN|BYncnuT{C~gz0 zuc!(s=G+S*05dQ&!p32DbL{~O`dKy>A?l(+E501HbLUR`8ZN>Wf3)_LW2DW7ssjPa zUJ}lcd$m6Y|Mb?!=LN$PfQ8|eDp-D_U>W85GsE?Zr25EqKqUv*W8p$}(x4u|?F;l+ zsWHT#XT@@aGcz**aht@Jx?{lWZs@uL@_%kuAF#CrDA`G%e(DaxMJd4LOMfEAmz)p;A4_4|yz3ke%76I--e7(e0 zx67dSzLUJSKJFsAFA)uPP+^vD-`uFM2Ts4uy8hEACEyQsLLTe+RLx{({NNencuHcY zJh#?Rp|Q8mVH<_=Hr88K23l}3*9&Xt3=9Z31qA{;}yLA+23)79$$!|)5(gFBC(5$8;Cf5Gi`DN|2Dwa z*Vq5$OClXYt?$D2PvqygpQ5dgA6N)}B>FM3GKh{{mXl9l3cXI4I+7Iwi+cL( zS>UTz%M0PFtEbPNRfdW|W3>cOcuG`M58^1Zra|zG)z#Gtev^Z>++GQaks46izVmR_ zKk;yW7PslUC_X8ft>%#T2un@neE8^*aPY{;i185M>6yUFGD^42br-Sq=?eT%pyqyh z`nInV=gyr2_jgnef{UJe>~LG1+*`vv7qqlqt*@`EDJ%D%Gf-BJ27gF+PGVzTl}QY* z22{Y#r?sukgYILmAr&oi3!!XdLbwaO*ba-l;g2wbXAH9Iv2EM7nU6F?SJ&4&p|ejz z!9?cmdQXWf4vd%6?Cf{Ad$%^1_`vl9V3=;>hJr$kTRbQ!3(m6U)vHej1_pQ`S3}Gb zQibm%@~_MnNGxIjXp1a75lpLuBhr~436=(gPWEFh?6tq1mq8}{ix;f`uHlBeK)eQK z@JI;5O0;1G?;;>JCx;hAZL2HFF=D!gVRv$%q$T}cvn~AkF**6K6IG0N02Q?SJA*9+ zb|x#!%chWjXcFV2q9mmr?eeQNR`q2T0}HroK!~hQ2Q1X6J^x;=((+E0ENXPUgbBl} zZbOA?1Zz4(R02o`;xr&^j?22Q&NouAxJ7}J1n(dz?k0ITA3TuPVTdf*&z@~G;$&x+ z1*6>B=I~#noq3Y8y|Hi_U7njgpP%IMo zIwq#%)%JXTSmkYS_Nh(3YY#7da28QWQTt1Dz>ez4C28s8*RS6hrM`ZB5ghJ?h>e$Q zp|vMMYlpqzc6WL|Rj#xuDQ2ROFDH0G`3D9HY*7CrsNvg$t`e}&#=g62z-*!*o`OXP zhWR-j@YMnE1Ls@22;kw{) z0~bbC1&=S>M$4QkWH)@pAGBqdk&=I*(^NW?8x9cqh=ahpKqfvn8AactcStkuff^TJ zq)pRf(3|0g;!D@XZ)R^%kqG$+`^x^*@VB1V`WE8&!@Rfru10@hK0k2+t8F53~ z-}j$8n&6@(@Xov6rOzJ}>ngA?U|t~L6@WsgIBkw+l%;R2 zW^AcIQjTAmOoN_-WRQj+116t<_vIzcTZ9>ux@iMfyL#=~`l^DvI{t8 zS!;~5(u3;;`PO!UFpUDeJ2p${!(lk`rfUMqQc>@Q0wiF~fT-Zmws%7U1VI28qye!% zv?%>g$cMy&>wF5FRsZ?*xq4h(n2=89&4)K{-VBSRD~4FpVXju7h;=UvcBl`Ms2lHo z3Kw>`YB&5@8SJK;w{GR$8I&e5NL`ha8ya6*sQUQf8N)aP|MP@bEZJXQ>J_zL6g&^<%VuKAm3f@}& zVPU<;u6@m;zCaa+;G-+feywm@%l06DOpBnLYLOZ3k=dQ25qx zsCBZ_R1Zk=CNDAyWZyYmh6sKDI&IP*(AWDBXCDtY)Y3`>-DX}Lz>b1#p!$JfVX5HN ze^1b9pq0nc4{8TWQ5?q9&hrX-i6GNycfo=42=Ka;+!J9Ah-nJ)K`^fsAR&;xfd9v^%n1wH&w}?od zRgpE^(6_4YUE{EWXmGOf>$0&AM@9yiBc#ZaA(KEu{GDm|A6NR`(KwIloBwU_vI?I| zY%UMBfrK9;o;Y%(96@l67JwfeGjmVh;B8}L9e*wOFWn48y=ksdT4fgdS$ zoRzg=Xe$})G30ExkL&jO`_{MC$AjSt{U17D(Q970az#$MgyGOdU6lK56H|?okBrv;6iw0 z`9tOTLu-w`1%anLTnzlqa*WcBFMcB9c8_>=84WcJjb+=d+`Pfilew+!Olz(9oDc5) zqE63oi@}oQKZx0&3(csM4azH@APZJ}7n*zWs=2Jm68=4$0guz{{gXW*5}u`~+b)np z6C|EK@`XhPFt08fH;M-Of;dd!)tL(k3gJy*LUs_5qywN@cIPYa*|X>O(APcd?2r2~ zoZcq|g8(o#HV!9fcb;xu)I4V$*aFqr(cycQ7;k;!~1FcmeO zo%3PigqMkRyh0s)z~%u3f7!O{KokTA&POcg^y@c4M76ni+y?_NAb$mN?^KA6g?a9o z6S@{Ai>CMs<#FyFx-sJ$B40v8m%8ns$TmXlDq)K2K*=M^)^g=)8=*7~8XRd3oRI`h zJ?ofij9Ll7HEb<$b)uxA8t>}e%p0x^ZBOl8TYQwVv1X|qgq-Tc#8YsT10-~$+pKq& zU5+=o7Nn#X?r&ok5h;?L^JNrz4OPLsB~clK5Bk^zWV1HM%X5XbxTiZrW(a~Gi0ZhU zv$Hexar=xkT>=>6>c}`UFo-B!pOr%)HYhO~E7czXip!amg@TBUz|z8d>tzyUl|D>! zN&~~=ow+Fyz}A2?;b6(E_AHeqtWA{}t}RVvIC}8Jab`$kps{ zF;@-LULh&z)#JXTzcI+Nh0>{3a8;~ja6zOARQRwqS6y8^JZ60H3EgLqxadL)QVuAw)IF@y zTJR3$9Ak}L2E0$EPPvgpdVKmFVccA1m#=$*Gg;RAsM@4x#lFT}s$Ht}ECUcqgRl^F z|JwKfywm~1Xxmz^-^yRe?0SE&90zgz)|V z$^xtJs0)RKUoe47tX{suP__`z*Q#VehW$_f5f)Oq16So ziWP@_cK3m`2%ii7c*#V*_ikf z6NDv|oRy_gwzV-82r(t_$P`$L%-7sD7AJ`u(Ao*s;V4wtHfWP+Az1g~NqK=J0-yO9 zE{jhKHLOkbq`_q4MV|hap+OD`>EOcGmx|`l`La61xBj>S{IR!Ew!S-(fbDD&|c=4V%7)(H?lsq@a4NG2q z>x_$!HwX5$+IOF}nCSy+NMRYk_mG7)oQf=BV5ZujMR239tQuhmknfPhsibITXn=Q= zXGQG1zT<&YPGH%6C{FD;X3YV?!R^VVXB_xos=#w=h7J%8S(FXHEGC47g=y$xz0QL) zC7Y|`s5F9~Oj_UN3D2gx;NkMj&zel;k9LFQ>^DQHM>L1yVTZax!>_EITyvqrcn;8o zl!#XI5f`85&n>E+SUGU5t;s{e2_I#Xg7<+Akk%L(T10|@yrP)cz-{IO%=SYx+jY2E zX;tWn0bOAZ{kXGBOTl0O!_y>7toPHxUp2w_Bd{6-CnhEeZ#B0hD6&A0AfDaNRTPRl zyt*J}x9JNAJ0V?oWBmD5G#G)_GIpUHl{|`!UC%k8gYwT|IgLkKVj5tfvYJ`|;TEsA zkv1r-W*8*LWzN`Ps%Im)D`%Lrf?r$;{f(aYXv{ITCxGVN{WzwlOJ{Db>rlZUpG!=^ z+GJ5Kuy=R|g2Avv#pWBNU|c_FnL+moiDi4irTS>8$H+5AHw#b9FuUN8#)VSSw6q14 zV@u=U;X}WtzKn{C3>Xm-EoB4!V3SAabfH*zAAIq657zZIE-g zj>ESBG@t{9?&qJcPY{dR4;R_Ur<0DF9aHG z(7JgOtxpXojH&2*3?e$&v9YmQ5DH{MFNq10knMZWiiFfRZ_ePLCieI^%BL?*ErHHA zA==h(wRKsSS-L||h@_-7ykTOY^UP~qR4Sc^_MYt31JLKJSslB4{^t89!d(EGI`H+0 zHcJB0xC9`bxt_?_URV#=Q1JpZ2Xz4v&k_a;{RN{?6Utni-Wfh#T~zn4nd86temiN? zaOUG-Yb_Kw&>c8nib{)4nMaAqeZz$Dj$UvQb)o+w8>m{^lPBB9OV=i|0b?dsrrSsT zWSBD%5ObV4(||%Z2Z%RBY9ftt)6gEN#$|DtQd2f$agL+dJ`G%8U0{l1#3DlO?W(=j zGUj=Jow&{%GY#-4Q=_7ejOTS(Wk=x0*lYT2oJBhM3OdVr0R`HCRG`nUG0xUTjqMK8 zeHRF%>C99O#~qeHt9YOJMSl0*P*dPP{IURuEXmL_&GkcZkgE z@WC?5UFF+RL6;XGew{dg*+`)<=prz~VkR=o>HxGsM%6C2mu<#@4-H;Dh|O!Lr7RFf z^qk|m4k0yy`K^`6tt9A=Ndk3>CxttO5h8&U(2C9fg48+iq=j!CswgK-aN2?C{Dkgj zh9t424T}^y03QRkT;|exBMIPcX|oAI-$Dh;rV@+$ydTgpakNi`?S`MTnJs?nScUIb zM8h;_Qtf7JfCLG}-%0vpUi2RztM7acUsyok44tURTY$}zf_f3*?JU%7RVjMB26=VW zKf--cd!wJ$vjOU=J;Ykc;QB&$riPwgSZqe!5pqf0w;+=(KZZN?u)_nA3W-+ju&7^$ zgoNNpw2XocE4>0l`P+RuKKm2JA^D;5tG_%!sZf%~d<5>jp$XmaO~c3aJnPX<^)OtMl+#vhs;jUU2`wV2e_%yYl3LctBn5bs!qT zs|fJ-e+?T62O;8j9)AP`-1Ze~Y5CN%cTga2ay5Fxkrrm(nj@zxO}pm|Nrk literal 0 HcmV?d00001 diff --git a/docs/0.10.5/html/_images/histogram_example_1.png b/docs/0.10.5/html/_images/histogram_example_1.png new file mode 100644 index 0000000000000000000000000000000000000000..062dfdbb9829f3032b4c1afd55fefc61a08b5d56 GIT binary patch literal 11387 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 G+kXRhHtTNy literal 0 HcmV?d00001 diff --git a/docs/0.10.5/html/_images/missing_value_matrix_example_0.png b/docs/0.10.5/html/_images/missing_value_matrix_example_0.png new file mode 100644 index 0000000000000000000000000000000000000000..21799cddfe73821d7ed15fe29b805df8f2e1879a GIT binary patch literal 37730 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/html/_sources/API.rst.txt b/docs/0.10.5/html/_sources/API.rst.txt new file mode 100644 index 000000000..fdbf2242b --- /dev/null +++ b/docs/0.10.5/html/_sources/API.rst.txt @@ -0,0 +1,16 @@ +.. _API: + +API +*** + +The API is split into 4 main components: Profilers, Labelers, Data Readers, and +Validators. + +.. toctree:: + :maxdepth: 1 + :caption: Contents: + + dataprofiler.data_readers + dataprofiler.profilers + dataprofiler.labelers + dataprofiler.validators \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/add_new_model_to_data_labeler.nblink.txt b/docs/0.10.5/html/_sources/add_new_model_to_data_labeler.nblink.txt new file mode 100644 index 000000000..130e413fc --- /dev/null +++ b/docs/0.10.5/html/_sources/add_new_model_to_data_labeler.nblink.txt @@ -0,0 +1,3 @@ +{ + "path": "../../feature_branch/examples/add_new_model_to_data_labeler.ipynb" +} \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/column_name_labeler_example.nblink.txt b/docs/0.10.5/html/_sources/column_name_labeler_example.nblink.txt new file mode 100644 index 000000000..6f95cf7cb --- /dev/null +++ b/docs/0.10.5/html/_sources/column_name_labeler_example.nblink.txt @@ -0,0 +1,3 @@ +{ + "path": "../../feature_branch/examples/column_name_labeler.ipynb" +} \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/data_labeling.rst.txt b/docs/0.10.5/html/_sources/data_labeling.rst.txt new file mode 100644 index 000000000..db76fe791 --- /dev/null +++ b/docs/0.10.5/html/_sources/data_labeling.rst.txt @@ -0,0 +1,365 @@ +.. _data_labeling: + +Labeler (Sensitive Data) +************************ + +In this library, the term *data labeling* refers to entity recognition. + +Builtin to the data profiler is a classifier which evaluates the complex data types of the dataset. +For structured data, it determines the complex data type of each column. When +running the data profile, it uses the default data labeling model builtin to the +library. However, the data labeler allows users to train their own data labeler +as well. + +*Data Labels* are determined per cell for structured data (column/row when +the *profiler* is used) or at the character level for unstructured data. This +is a list of the default labels. + +* UNKNOWN +* ADDRESS +* BAN (bank account number, 10-18 digits) +* CREDIT_CARD +* EMAIL_ADDRESS +* UUID +* HASH_OR_KEY (md5, sha1, sha256, random hash, etc.) +* IPV4 +* IPV6 +* MAC_ADDRESS +* PERSON +* PHONE_NUMBER +* SSN +* URL +* US_STATE +* DRIVERS_LICENSE +* DATE +* TIME +* DATETIME +* INTEGER +* FLOAT +* QUANTITY +* ORDINAL + + +Identify Entities in Structured Data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Makes predictions and identifying labels: + +.. code-block:: python + + import dataprofiler as dp + + # load data and data labeler + data = dp.Data("your_data.csv") + data_labeler = dp.DataLabeler(labeler_type='structured') + + # make predictions and get labels per cell + predictions = data_labeler.predict(data) + +Identify Entities in Unstructured Data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Predict which class characters belong to in unstructured text: + +.. code-block:: python + + import dataprofiler as dp + + data_labeler = dp.DataLabeler(labeler_type='unstructured') + + # Example sample string, must be in an array (multiple arrays can be passed) + sample = ["Help\tJohn Macklemore\tneeds\tfood.\tPlease\tCall\t555-301-1234." + "\tHis\tssn\tis\tnot\t334-97-1234. I'm a BAN: 000043219499392912.\n"] + + # Prediction what class each character belongs to + model_predictions = data_labeler.predict( + sample, predict_options=dict(show_confidences=True)) + + # Predictions / confidences are at the character level + final_results = model_predictions["pred"] + final_confidences = model_predictions["conf"] + +It's also possible to change output formats, output similar to a **SpaCy** format: + +.. code-block:: python + + import dataprofiler as dp + + data_labeler = dp.DataLabeler(labeler_type='unstructured', trainable=True) + + # Example sample string, must be in an array (multiple arrays can be passed) + sample = ["Help\tJohn Macklemore\tneeds\tfood.\tPlease\tCall\t555-301-1234." + "\tHis\tssn\tis\tnot\t334-97-1234. I'm a BAN: 000043219499392912.\n"] + + # Set the output to the NER format (start position, end position, label) + data_labeler.set_params( + { 'postprocessor': { 'output_format':'ner', 'use_word_level_argmax':True } } + ) + + results = data_labeler.predict(sample) + + print(results) + +Train a New Data Labeler +~~~~~~~~~~~~~~~~~~~~~~~~ + +Mechanism for training your own data labeler on their own set of structured data +(tabular): + +.. code-block:: python + + import dataprofiler as dp + + # Will need one column with a default label of UNKNOWN + data = dp.Data("your_file.csv") + + data_labeler = dp.train_structured_labeler( + data=data, + save_dirpath="/path/to/save/labeler", + epochs=2 + ) + + data_labeler.save_to_disk("my/save/path") # Saves the data labeler for reuse + +Load an Existing Data Labeler +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Mechanism for loading an existing data_labeler: + +.. code-block:: python + + import dataprofiler as dp + + data_labeler = dp.DataLabeler( + labeler_type='structured', dirpath="/path/to/my/labeler") + + # get information about the parameters/inputs/output formats for the DataLabeler + data_labeler.help() + +Extending a Data Labeler with Transfer Learning +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Extending or changing labels of a data labeler w/ transfer learning: +Note: By default, **a labeler loaded will not be trainable**. In order to load a +trainable DataLabeler, the user must set `trainable=True` or load a labeler +using the `TrainableDataLabeler` class. + +The following illustrates how to change the labels: + +.. code-block:: python + + import dataprofiler as dp + + labels = ['label1', 'label2', ...] # new label set can also be an encoding dict + data = dp.Data("your_file.csv") # contains data with new labels + + # load default structured Data Labeler w/ trainable set to True + data_labeler = dp.DataLabeler(labeler_type='structured', trainable=True) + + # this will use transfer learning to retrain the data labeler on your new + # dataset and labels. + # NOTE: data must be in an acceptable format for the preprocessor to interpret. + # please refer to the preprocessor/model for the expected data format. + # Currently, the DataLabeler cannot take in Tabular data, but requires + # data to be ingested with two columns [X, y] where X is the samples and + # y is the labels. + model_results = data_labeler.fit(x=data['samples'], y=data['labels'], + validation_split=0.2, epochs=2, labels=labels) + + # final_results, final_confidences are a list of results for each epoch + epoch_id = 0 + final_results = model_results[epoch_id]["pred"] + final_confidences = model_results[epoch_id]["conf"] + +The following illustrates how to extend the labels: + +.. code-block:: python + + import dataprofiler as dp + + new_labels = ['label1', 'label2', ...] + data = dp.Data("your_file.csv") # contains data with new labels + + # load default structured Data Labeler w/ trainable set to True + data_labeler = dp.DataLabeler(labeler_type='structured', trainable=True) + + # this will maintain current labels and model weights, but extend the model's + # labels + for label in new_labels: + data_labeler.add_label(label) + + # NOTE: a user can also add a label which maps to the same index as an existing + # label + # data_labeler.add_label(label, same_as='') + + # For a trainable model, the user must then train the model to be able to + # continue using the labeler since the model's graph has likely changed + # NOTE: data must be in an acceptable format for the preprocessor to interpret. + # please refer to the preprocessor/model for the expected data format. + # Currently, the DataLabeler cannot take in Tabular data, but requires + # data to be ingested with two columns [X, y] where X is the samples and + # y is the labels. + model_results = data_labeler.fit(x=data['samples'], y=data['labels'], + validation_split=0.2, epochs=2) + + # final_results, final_confidences are a list of results for each epoch + epoch_id = 0 + final_results = model_results[epoch_id]["pred"] + final_confidences = model_results[epoch_id]["conf"] + + +Changing pipeline parameters: + +.. code-block:: python + + import dataprofiler as dp + + # load default Data Labeler + data_labeler = dp.DataLabeler(labeler_type='structured') + + # change parameters of specific component + data_labeler.preprocessor.set_params({'param1': 'value1'}) + + # change multiple simultaneously. + data_labeler.set_params({ + 'preprocessor': {'param1': 'value1'}, + 'model': {'param2': 'value2'}, + 'postprocessor': {'param3': 'value3'} + }) + + +Build Your Own Data Labeler +=========================== + +The DataLabeler has 3 main components: preprocessor, model, and postprocessor. +To create your own DataLabeler, each one would have to be created or an +existing component can be reused. + +Given a set of the 3 components, you can construct your own DataLabeler: + +.. code-block:: python + from dataprofiler.labelers.base_data_labeler import BaseDataLabeler, \ + TrainableDataLabeler + from dataprofiler.labelers.character_level_cnn_model import CharacterLevelCnnModel + from dataprofiler.labelers.data_processing import \ + StructCharPreprocessor, StructCharPostprocessor + + # load a non-trainable data labeler + model = CharacterLevelCnnModel(...) + preprocessor = StructCharPreprocessor(...) + postprocessor = StructCharPostprocessor(...) + + data_labeler = BaseDataLabeler.load_with_components( + preprocessor=preprocessor, model=model, postprocessor=postprocessor) + + # check for basic compatibility between the processors and the model + data_labeler.check_pipeline() + + + # load trainable data labeler + data_labeler = TrainableDataLabeler.load_with_components( + preprocessor=preprocessor, model=model, postprocessor=postprocessor) + + # check for basic compatibility between the processors and the model + data_labeler.check_pipeline() + +Option for swapping out specific components of an existing labeler. + +.. code-block:: python + + import dataprofiler as dp + from dataprofiler.labelers.character_level_cnn_model import \ + CharacterLevelCnnModel + from dataprofiler.labelers.data_processing import \ + StructCharPreprocessor, StructCharPostprocessor + + model = CharacterLevelCnnModel(...) + preprocessor = StructCharPreprocessor(...) + postprocessor = StructCharPostprocessor(...) + + data_labeler = dp.DataLabeler(labeler_type='structured') + data_labeler.set_preprocessor(preprocessor) + data_labeler.set_model(model) + data_labeler.set_postprocessor(postprocessor) + + # check for basic compatibility between the processors and the model + data_labeler.check_pipeline() + + +Model Component +~~~~~~~~~~~~~~~ + +In order to create your own model component for data labeling, you can utilize +the `BaseModel` class from `dataprofiler.labelers.base_model` and +overriding the abstract class methods. + +Reviewing `CharacterLevelCnnModel` from +`dataprofiler.labelers.character_level_cnn_model` illustrates the functions +which need an override. + +#. `__init__`: specifying default parameters and calling base `__init__` +#. `_validate_parameters`: validating parameters given by user during setting +#. `_need_to_reconstruct_model`: flag for when to reconstruct a model (i.e. + parameters change or labels change require a model reconstruction) +#. `_construct_model`: initial construction of the model given the parameters +#. `_reconstruct_model`: updates model architecture for new label set while + maintaining current model weights +#. `fit`: mechanism for the model to learn given training data +#. `predict`: mechanism for model to make predictions on data +#. `details`: prints a summary of the model construction +#. `save_to_disk`: saves model and model parameters to disk +#. `load_from_disk`: loads model given a path on disk + + +Preprocessor Component +~~~~~~~~~~~~~~~~~~~~~~ + +In order to create your own preprocessor component for data labeling, you can +utilize the `BaseDataPreprocessor` class +from `dataprofiler.labelers.data_processing` and override the abstract class +methods. + +Reviewing `StructCharPreprocessor` from +`dataprofiler.labelers.data_processing` illustrates the functions which +need an override. + +#. `__init__`: passing parameters to the base class and executing any + extraneous calculations to be saved as parameters +#. `_validate_parameters`: validating parameters given by user during + setting +#. `process`: takes in the user data and converts it into an digestible, + iterable format for the model +#. `set_params` (optional): if a parameter requires processing before setting, + a user can override this function to assist with setting the parameter +#. `_save_processor` (optional): if a parameter is not JSON serializable, a + user can override this function to assist in saving the processor and its + parameters +#. `load_from_disk` (optional): if a parameter(s) is not JSON serializable, a + user can override this function to assist in loading the processor + +Postprocessor Component +~~~~~~~~~~~~~~~~~~~~~~~ + +The postprocessor is nearly identical to the preprocessor except it handles +the output of the model for processing. In order to create your own +postprocessor component for data labeling, you can utilize the +`BaseDataPostprocessor` class from `dataprofiler.labelers.data_processing` +and override the abstract class methods. + +Reviewing `StructCharPostprocessor` from +`dataprofiler.labelers.data_processing` illustrates the functions which +need an override. + +#. `__init__`: passing parameters to the base class and executing any + extraneous calculations to be saved as parameters +#. `_validate_parameters`: validating parameters given by user during + setting +#. `process`: takes in the output of the model and processes for output to + the user +#. `set_params` (optional): if a parameter requires processing before setting, + a user can override this function to assist with setting the parameter +#. `_save_processor` (optional): if a parameter is not JSON serializable, a + user can override this function to assist in saving the processor and its + parameters +#. `load_from_disk` (optional): if a parameter(s) is not JSON serializable, a + user can override this function to assist in loading the processor diff --git a/docs/0.10.5/html/_sources/data_reader.nblink.txt b/docs/0.10.5/html/_sources/data_reader.nblink.txt new file mode 100644 index 000000000..4722970da --- /dev/null +++ b/docs/0.10.5/html/_sources/data_reader.nblink.txt @@ -0,0 +1,3 @@ +{ + "path": "../../feature_branch/examples/data_readers.ipynb" +} \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/data_readers.rst.txt b/docs/0.10.5/html/_sources/data_readers.rst.txt new file mode 100644 index 000000000..4679d33a6 --- /dev/null +++ b/docs/0.10.5/html/_sources/data_readers.rst.txt @@ -0,0 +1,164 @@ +.. _data_readers: + +Data Readers +************ + +The `Data` class itself will identify then output one of the following `Data` class types. +Using the data reader is easy, just pass it through the Data object. + +.. code-block:: python + + import dataprofiler as dp + data = dp.Data("your_file.csv") + +The supported file types are: + +* CSV file (or any delimited file) +* JSON object +* Avro file +* Parquet file +* Graph data file +* Text file +* Pandas DataFrame +* A URL that points to one of the supported file types above + +It's also possible to specifically call one of the data classes such as the following command: + +.. code-block:: python + + from dataprofiler.data_readers.csv_data import CSVData + data = CSVData("your_file.csv", options={"delimiter": ","}) + +Additionally any of the data classes can be loaded using a URL: + +.. code-block:: python + + import dataprofiler as dp + data = dp.Data("https://you_website.com/your_file.file", options={"verify_ssl": "True"}) + +Below are descriptions of the various `Data` classes and the available options. + +CSVData +======= + +Data class for loading datasets of type CSV. Can be specified by passing +in memory data or via a file path. Options pertaining the CSV may also +be specified using the options dict parameter. + +`CSVData(input_file_path=None, data=None, options=None)` + +Possible `options`: + +* delimiter - Must be a string, for example `"delimiter": ","` +* data_format - Must be a string, possible choices: "dataframe", "records" +* selected_columns - Columns being selected from the entire dataset, must be a + list `["column 1", "ssn"]` +* sample_nrows - Reservoir sampling to sample `"n"` rows out of a total of `"M"` rows. + Specified for how many rows to sample, default None. +* header - Define the header, for example + + * `"header": 'auto'` for auto detection + * `"header": None` for no header + * `"header": ` to specify the header row (0 based index) + +JSONData +======== + +Data class for loading datasets of type JSON. Can be specified by +passing in memory data or via a file path. Options pertaining the JSON +may also be specified using the options dict parameter. JSON data can be +accessed via the "data" property, the "metadata" property, and the +"data_and_metadata" property. + +`JSONData(input_file_path=None, data=None, options=None)` + +Possible `options`: + +* data_format - must be a string, choices: "dataframe", "records", "json", "flattened_dataframe" + + * "flattened_dataframe" is best used for JSON structure typically found in data streams that contain + nested lists of dictionaries and a payload. For example: `{"data": [ columns ], "response": 200}` +* selected_keys - columns being selected from the entire dataset, must be a list `["column 1", "ssn"]` +* payload_keys - The dictionary keys for the payload of the JSON, typically called "data" + or "payload". Defaults to ["data", "payload", "response"]. + + +AVROData +======== + +Data class for loading datasets of type AVRO. Can be specified by +passing in memory data or via a file path. Options pertaining the AVRO +may also be specified using the options dict parameter. + +`AVROData(input_file_path=None, data=None, options=None)` + +Possible `options`: + +* data_format - must be a string, choices: "dataframe", "records", "avro", "json", "flattened_dataframe" + + * "flattened_dataframe" is best used for AVROs with a JSON structure typically found in data streams that contain + nested lists of dictionaries and a payload. For example: `{"data": [ columns ], "response": 200}` +* selected_keys - columns being selected from the entire dataset, must be a list `["column 1", "ssn"]` + +ParquetData +=========== + +Data class for loading datasets of type PARQUET. Can be specified by +passing in memory data or via a file path. Options pertaining the +PARQUET may also be specified using the options dict parameter. + +`ParquetData(input_file_path=None, data=None, options=None)` + +Possible `options`: + +* data_format - must be a string, choices: "dataframe", "records", "json" +* selected_keys - columns being selected from the entire dataset, must be a list `["column 1", "ssn"]` + +GraphData +========= + +Data Class for loading datasets of graph data. Currently takes CSV format, +further type formats will be supported. Can be specified by passing +in memory data (NetworkX Graph) or via a file path. Options pertaining the CSV file may also +be specified using the options dict parameter. Loads data from CSV into memory +as a NetworkX Graph. + +`GraphData(input_file_path=None, data=None, options=None)` + +Possible `options`: + +* delimiter - must be a string, for example `"delimiter": ","` +* data_format - must be a string, possible choices: "graph", "dataframe", "records" +* header - Define the header, for example + + * `"header": 'auto'` for auto detection + * `"header": None` for no header + * `"header": ` to specify the header row (0 based index) + +TextData +======== + +Data class for loading datasets of type TEXT. Can be specified by +passing in memory data or via a file path. Options pertaining the TEXT +may also be specified using the options dict parameter. + +`TextData(input_file_path=None, data=None, options=None)` + +Possible `options`: + +* data_format: user selected format in which to return data. Currently only supports "text". +* samples_per_line - chunks by which to read in the specified dataset + + +Data Using a URL +================ + +Data class for loading datasets of any type using a URL. Specified by passing in +any valid URL that points to one of the valid data types. Options pertaining the +URL may also be specified using the options dict parameter. + +`Data(input_file_path=None, data=None, options=None)` + +Possible `options`: + +* verify_ssl: must be a boolean string, choices: "True", "False". Set to "True" by default. \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.data_readers.avro_data.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.data_readers.avro_data.rst.txt new file mode 100644 index 000000000..d3227df29 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.data_readers.avro_data.rst.txt @@ -0,0 +1,7 @@ +Avro Data +========= + +.. automodule:: dataprofiler.data_readers.avro_data + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.data_readers.base_data.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.data_readers.base_data.rst.txt new file mode 100644 index 000000000..b82883cb9 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.data_readers.base_data.rst.txt @@ -0,0 +1,7 @@ +Base Data +========= + +.. automodule:: dataprofiler.data_readers.base_data + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.data_readers.csv_data.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.data_readers.csv_data.rst.txt new file mode 100644 index 000000000..85a625d69 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.data_readers.csv_data.rst.txt @@ -0,0 +1,7 @@ +CSV Data +======== + +.. automodule:: dataprofiler.data_readers.csv_data + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.data_readers.data.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.data_readers.data.rst.txt new file mode 100644 index 000000000..813e81805 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.data_readers.data.rst.txt @@ -0,0 +1,7 @@ +Data +==== + +.. automodule:: dataprofiler.data_readers.data + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.data_readers.data_utils.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.data_readers.data_utils.rst.txt new file mode 100644 index 000000000..309208b73 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.data_readers.data_utils.rst.txt @@ -0,0 +1,7 @@ +Data Utils +========== + +.. automodule:: dataprofiler.data_readers.data_utils + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.data_readers.filepath_or_buffer.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.data_readers.filepath_or_buffer.rst.txt new file mode 100644 index 000000000..89e78cc2d --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.data_readers.filepath_or_buffer.rst.txt @@ -0,0 +1,7 @@ +Filepath Or Buffer +================== + +.. automodule:: dataprofiler.data_readers.filepath_or_buffer + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.data_readers.graph_data.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.data_readers.graph_data.rst.txt new file mode 100644 index 000000000..b8b982f79 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.data_readers.graph_data.rst.txt @@ -0,0 +1,7 @@ +Graph Data +========== + +.. automodule:: dataprofiler.data_readers.graph_data + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.data_readers.json_data.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.data_readers.json_data.rst.txt new file mode 100644 index 000000000..ae0a51d13 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.data_readers.json_data.rst.txt @@ -0,0 +1,7 @@ +JSON Data +========= + +.. automodule:: dataprofiler.data_readers.json_data + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.data_readers.parquet_data.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.data_readers.parquet_data.rst.txt new file mode 100644 index 000000000..dfdcbe4bb --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.data_readers.parquet_data.rst.txt @@ -0,0 +1,7 @@ +Parquet Data +============ + +.. automodule:: dataprofiler.data_readers.parquet_data + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.data_readers.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.data_readers.rst.txt new file mode 100644 index 000000000..56d68fe83 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.data_readers.rst.txt @@ -0,0 +1,30 @@ +Data Readers +============ + + +Modules +------- + +.. toctree:: + :maxdepth: 4 + + +.. toctree:: + :maxdepth: 4 + + dataprofiler.data_readers.avro_data + dataprofiler.data_readers.base_data + dataprofiler.data_readers.csv_data + dataprofiler.data_readers.data + dataprofiler.data_readers.data_utils + dataprofiler.data_readers.filepath_or_buffer + dataprofiler.data_readers.graph_data + dataprofiler.data_readers.json_data + dataprofiler.data_readers.parquet_data + dataprofiler.data_readers.structured_mixins + dataprofiler.data_readers.text_data + +.. automodule:: dataprofiler.data_readers + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/0.10.5/html/_sources/dataprofiler.data_readers.structured_mixins.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.data_readers.structured_mixins.rst.txt new file mode 100644 index 000000000..157e03d2c --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.data_readers.structured_mixins.rst.txt @@ -0,0 +1,7 @@ +Structured Mixins +================= + +.. automodule:: dataprofiler.data_readers.structured_mixins + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.data_readers.text_data.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.data_readers.text_data.rst.txt new file mode 100644 index 000000000..6ac6b9648 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.data_readers.text_data.rst.txt @@ -0,0 +1,7 @@ +Text Data +========= + +.. automodule:: dataprofiler.data_readers.text_data + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.dp_logging.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.dp_logging.rst.txt new file mode 100644 index 000000000..d1c6c910d --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.dp_logging.rst.txt @@ -0,0 +1,7 @@ +Dp Logging +========== + +.. automodule:: dataprofiler.dp_logging + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.labelers.base_data_labeler.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.labelers.base_data_labeler.rst.txt new file mode 100644 index 000000000..839a74157 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.labelers.base_data_labeler.rst.txt @@ -0,0 +1,7 @@ +Base Data Labeler +================= + +.. automodule:: dataprofiler.labelers.base_data_labeler + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.labelers.base_model.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.labelers.base_model.rst.txt new file mode 100644 index 000000000..c4bc9b08b --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.labelers.base_model.rst.txt @@ -0,0 +1,7 @@ +Base Model +========== + +.. automodule:: dataprofiler.labelers.base_model + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.labelers.char_load_tf_model.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.labelers.char_load_tf_model.rst.txt new file mode 100644 index 000000000..7dad3aa71 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.labelers.char_load_tf_model.rst.txt @@ -0,0 +1,7 @@ +Char Load Tf Model +================== + +.. automodule:: dataprofiler.labelers.char_load_tf_model + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.labelers.character_level_cnn_model.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.labelers.character_level_cnn_model.rst.txt new file mode 100644 index 000000000..80113a935 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.labelers.character_level_cnn_model.rst.txt @@ -0,0 +1,7 @@ +Character Level Cnn Model +========================= + +.. automodule:: dataprofiler.labelers.character_level_cnn_model + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.labelers.classification_report_utils.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.labelers.classification_report_utils.rst.txt new file mode 100644 index 000000000..4c3624869 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.labelers.classification_report_utils.rst.txt @@ -0,0 +1,7 @@ +Classification Report Utils +=========================== + +.. automodule:: dataprofiler.labelers.classification_report_utils + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.labelers.column_name_model.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.labelers.column_name_model.rst.txt new file mode 100644 index 000000000..e4a5bc988 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.labelers.column_name_model.rst.txt @@ -0,0 +1,7 @@ +Column Name Model +================= + +.. automodule:: dataprofiler.labelers.column_name_model + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.labelers.data_labelers.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.labelers.data_labelers.rst.txt new file mode 100644 index 000000000..6ac45d9e6 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.labelers.data_labelers.rst.txt @@ -0,0 +1,7 @@ +Data Labelers +============= + +.. automodule:: dataprofiler.labelers.data_labelers + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.labelers.data_processing.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.labelers.data_processing.rst.txt new file mode 100644 index 000000000..58d572a29 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.labelers.data_processing.rst.txt @@ -0,0 +1,7 @@ +Data Processing +=============== + +.. automodule:: dataprofiler.labelers.data_processing + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.labelers.labeler_utils.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.labelers.labeler_utils.rst.txt new file mode 100644 index 000000000..f14cabd5c --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.labelers.labeler_utils.rst.txt @@ -0,0 +1,7 @@ +Labeler Utils +============= + +.. automodule:: dataprofiler.labelers.labeler_utils + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.labelers.regex_model.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.labelers.regex_model.rst.txt new file mode 100644 index 000000000..e85772ad2 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.labelers.regex_model.rst.txt @@ -0,0 +1,7 @@ +Regex Model +=========== + +.. automodule:: dataprofiler.labelers.regex_model + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.labelers.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.labelers.rst.txt new file mode 100644 index 000000000..7d660273e --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.labelers.rst.txt @@ -0,0 +1,30 @@ +Labelers +======== + + +Modules +------- + +.. toctree:: + :maxdepth: 4 + + +.. toctree:: + :maxdepth: 4 + + dataprofiler.labelers.base_data_labeler + dataprofiler.labelers.base_model + dataprofiler.labelers.char_load_tf_model + dataprofiler.labelers.character_level_cnn_model + dataprofiler.labelers.classification_report_utils + dataprofiler.labelers.column_name_model + dataprofiler.labelers.data_labelers + dataprofiler.labelers.data_processing + dataprofiler.labelers.labeler_utils + dataprofiler.labelers.regex_model + dataprofiler.labelers.utils + +.. automodule:: dataprofiler.labelers + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/0.10.5/html/_sources/dataprofiler.labelers.utils.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.labelers.utils.rst.txt new file mode 100644 index 000000000..a0486f9be --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.labelers.utils.rst.txt @@ -0,0 +1,7 @@ +Utils +===== + +.. automodule:: dataprofiler.labelers.utils + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.base_column_profilers.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.base_column_profilers.rst.txt new file mode 100644 index 000000000..13cab9ff4 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.base_column_profilers.rst.txt @@ -0,0 +1,7 @@ +Base Column Profilers +===================== + +.. automodule:: dataprofiler.profilers.base_column_profilers + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.categorical_column_profile.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.categorical_column_profile.rst.txt new file mode 100644 index 000000000..a525d86c8 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.categorical_column_profile.rst.txt @@ -0,0 +1,7 @@ +Categorical Column Profile +========================== + +.. automodule:: dataprofiler.profilers.categorical_column_profile + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.column_profile_compilers.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.column_profile_compilers.rst.txt new file mode 100644 index 000000000..9599deb9a --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.column_profile_compilers.rst.txt @@ -0,0 +1,7 @@ +Column Profile Compilers +======================== + +.. automodule:: dataprofiler.profilers.column_profile_compilers + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.data_labeler_column_profile.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.data_labeler_column_profile.rst.txt new file mode 100644 index 000000000..282408931 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.data_labeler_column_profile.rst.txt @@ -0,0 +1,7 @@ +Data Labeler Column Profile +=========================== + +.. automodule:: dataprofiler.profilers.data_labeler_column_profile + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.datetime_column_profile.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.datetime_column_profile.rst.txt new file mode 100644 index 000000000..d4467634f --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.datetime_column_profile.rst.txt @@ -0,0 +1,7 @@ +Datetime Column Profile +======================= + +.. automodule:: dataprofiler.profilers.datetime_column_profile + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.float_column_profile.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.float_column_profile.rst.txt new file mode 100644 index 000000000..d23bb4336 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.float_column_profile.rst.txt @@ -0,0 +1,7 @@ +Float Column Profile +==================== + +.. automodule:: dataprofiler.profilers.float_column_profile + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.graph_profiler.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.graph_profiler.rst.txt new file mode 100644 index 000000000..196194771 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.graph_profiler.rst.txt @@ -0,0 +1,7 @@ +Graph Profiler +============== + +.. automodule:: dataprofiler.profilers.graph_profiler + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.helpers.report_helpers.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.helpers.report_helpers.rst.txt new file mode 100644 index 000000000..c20d1f391 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.helpers.report_helpers.rst.txt @@ -0,0 +1,7 @@ +Report Helpers +============== + +.. automodule:: dataprofiler.profilers.helpers.report_helpers + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.helpers.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.helpers.rst.txt new file mode 100644 index 000000000..b82f660b5 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.helpers.rst.txt @@ -0,0 +1,20 @@ +Helpers +======= + + +Modules +------- + +.. toctree:: + :maxdepth: 4 + + +.. toctree:: + :maxdepth: 4 + + dataprofiler.profilers.helpers.report_helpers + +.. automodule:: dataprofiler.profilers.helpers + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.histogram_utils.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.histogram_utils.rst.txt new file mode 100644 index 000000000..039bb08d8 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.histogram_utils.rst.txt @@ -0,0 +1,7 @@ +Histogram Utils +=============== + +.. automodule:: dataprofiler.profilers.histogram_utils + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.int_column_profile.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.int_column_profile.rst.txt new file mode 100644 index 000000000..b6d8d7921 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.int_column_profile.rst.txt @@ -0,0 +1,7 @@ +Int Column Profile +================== + +.. automodule:: dataprofiler.profilers.int_column_profile + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.json_decoder.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.json_decoder.rst.txt new file mode 100644 index 000000000..761551996 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.json_decoder.rst.txt @@ -0,0 +1,7 @@ +JSON Decoder +============ + +.. automodule:: dataprofiler.profilers.json_decoder + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.json_encoder.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.json_encoder.rst.txt new file mode 100644 index 000000000..bef659ecd --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.json_encoder.rst.txt @@ -0,0 +1,7 @@ +JSON Encoder +============ + +.. automodule:: dataprofiler.profilers.json_encoder + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.numerical_column_stats.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.numerical_column_stats.rst.txt new file mode 100644 index 000000000..a8b6ac226 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.numerical_column_stats.rst.txt @@ -0,0 +1,7 @@ +Numerical Column Stats +====================== + +.. automodule:: dataprofiler.profilers.numerical_column_stats + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.order_column_profile.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.order_column_profile.rst.txt new file mode 100644 index 000000000..7b1605659 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.order_column_profile.rst.txt @@ -0,0 +1,7 @@ +Order Column Profile +==================== + +.. automodule:: dataprofiler.profilers.order_column_profile + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.profile_builder.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.profile_builder.rst.txt new file mode 100644 index 000000000..d73e6d9a2 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.profile_builder.rst.txt @@ -0,0 +1,7 @@ +Profile Builder +=============== + +.. automodule:: dataprofiler.profilers.profile_builder + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.profiler_options.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.profiler_options.rst.txt new file mode 100644 index 000000000..127e8e1ad --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.profiler_options.rst.txt @@ -0,0 +1,7 @@ +Profiler Options +================ + +.. automodule:: dataprofiler.profilers.profiler_options + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.profiler_utils.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.profiler_utils.rst.txt new file mode 100644 index 000000000..5e9c6533c --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.profiler_utils.rst.txt @@ -0,0 +1,7 @@ +Profiler Utils +============== + +.. automodule:: dataprofiler.profilers.profiler_utils + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.rst.txt new file mode 100644 index 000000000..7a5b45394 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.rst.txt @@ -0,0 +1,39 @@ +Profilers +========= + + +Modules +------- + +.. toctree:: + :maxdepth: 4 + + dataprofiler.profilers.helpers + +.. toctree:: + :maxdepth: 4 + + dataprofiler.profilers.base_column_profilers + dataprofiler.profilers.categorical_column_profile + dataprofiler.profilers.column_profile_compilers + dataprofiler.profilers.data_labeler_column_profile + dataprofiler.profilers.datetime_column_profile + dataprofiler.profilers.float_column_profile + dataprofiler.profilers.graph_profiler + dataprofiler.profilers.histogram_utils + dataprofiler.profilers.int_column_profile + dataprofiler.profilers.json_decoder + dataprofiler.profilers.json_encoder + dataprofiler.profilers.numerical_column_stats + dataprofiler.profilers.order_column_profile + dataprofiler.profilers.profile_builder + dataprofiler.profilers.profiler_options + dataprofiler.profilers.profiler_utils + dataprofiler.profilers.text_column_profile + dataprofiler.profilers.unstructured_labeler_profile + dataprofiler.profilers.unstructured_text_profile + +.. automodule:: dataprofiler.profilers + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.text_column_profile.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.text_column_profile.rst.txt new file mode 100644 index 000000000..097e6e02c --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.text_column_profile.rst.txt @@ -0,0 +1,7 @@ +Text Column Profile +=================== + +.. automodule:: dataprofiler.profilers.text_column_profile + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.unstructured_labeler_profile.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.unstructured_labeler_profile.rst.txt new file mode 100644 index 000000000..c49f68004 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.unstructured_labeler_profile.rst.txt @@ -0,0 +1,7 @@ +Unstructured Labeler Profile +============================ + +.. automodule:: dataprofiler.profilers.unstructured_labeler_profile + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.unstructured_text_profile.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.unstructured_text_profile.rst.txt new file mode 100644 index 000000000..27b56ea93 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.unstructured_text_profile.rst.txt @@ -0,0 +1,7 @@ +Unstructured Text Profile +========================= + +.. automodule:: dataprofiler.profilers.unstructured_text_profile + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.profilers.utils.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.profilers.utils.rst.txt new file mode 100644 index 000000000..ddae85e63 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.profilers.utils.rst.txt @@ -0,0 +1,7 @@ +Utils +===== + +.. automodule:: dataprofiler.profilers.utils + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.reports.graphs.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.reports.graphs.rst.txt new file mode 100644 index 000000000..3a7adf900 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.reports.graphs.rst.txt @@ -0,0 +1,7 @@ +Graphs +====== + +.. automodule:: dataprofiler.reports.graphs + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.reports.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.reports.rst.txt new file mode 100644 index 000000000..59525629c --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.reports.rst.txt @@ -0,0 +1,21 @@ +Reports +======= + + +Modules +------- + +.. toctree:: + :maxdepth: 4 + + +.. toctree:: + :maxdepth: 4 + + dataprofiler.reports.graphs + dataprofiler.reports.utils + +.. automodule:: dataprofiler.reports + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/0.10.5/html/_sources/dataprofiler.reports.utils.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.reports.utils.rst.txt new file mode 100644 index 000000000..97e26cde0 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.reports.utils.rst.txt @@ -0,0 +1,7 @@ +Utils +===== + +.. automodule:: dataprofiler.reports.utils + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.rng_utils.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.rng_utils.rst.txt new file mode 100644 index 000000000..e4b84b46a --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.rng_utils.rst.txt @@ -0,0 +1,7 @@ +Rng Utils +========= + +.. automodule:: dataprofiler.rng_utils + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.rst.txt new file mode 100644 index 000000000..d5ed33a58 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.rst.txt @@ -0,0 +1,28 @@ +Dataprofiler +============ + + +Modules +------- + +.. toctree:: + :maxdepth: 4 + + dataprofiler.data_readers + dataprofiler.labelers + dataprofiler.profilers + dataprofiler.reports + dataprofiler.validators + +.. toctree:: + :maxdepth: 4 + + dataprofiler.dp_logging + dataprofiler.rng_utils + dataprofiler.settings + dataprofiler.version + +.. automodule:: dataprofiler + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/0.10.5/html/_sources/dataprofiler.settings.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.settings.rst.txt new file mode 100644 index 000000000..81c664c07 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.settings.rst.txt @@ -0,0 +1,7 @@ +Settings +======== + +.. automodule:: dataprofiler.settings + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.validators.base_validators.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.validators.base_validators.rst.txt new file mode 100644 index 000000000..b8f328736 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.validators.base_validators.rst.txt @@ -0,0 +1,7 @@ +Base Validators +=============== + +.. automodule:: dataprofiler.validators.base_validators + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/dataprofiler.validators.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.validators.rst.txt new file mode 100644 index 000000000..704dfee21 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.validators.rst.txt @@ -0,0 +1,20 @@ +Validators +========== + + +Modules +------- + +.. toctree:: + :maxdepth: 4 + + +.. toctree:: + :maxdepth: 4 + + dataprofiler.validators.base_validators + +.. automodule:: dataprofiler.validators + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/0.10.5/html/_sources/dataprofiler.version.rst.txt b/docs/0.10.5/html/_sources/dataprofiler.version.rst.txt new file mode 100644 index 000000000..3977b6379 --- /dev/null +++ b/docs/0.10.5/html/_sources/dataprofiler.version.rst.txt @@ -0,0 +1,7 @@ +Version +======= + +.. automodule:: dataprofiler.version + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/examples.rst.txt b/docs/0.10.5/html/_sources/examples.rst.txt new file mode 100644 index 000000000..3637da6ac --- /dev/null +++ b/docs/0.10.5/html/_sources/examples.rst.txt @@ -0,0 +1,24 @@ +.. _examples: + +Examples +******** + +These examples provide a more in-depth look into the details of the ``Data Profiler`` library. + +Basics +------ + +.. toctree:: + :maxdepth: 0 + + Overview of Data Profiler + Data Reader + Structured Profiler + Unstructured Profiler + Graph Profiler + Labeler + Adding Models to a Labeler Pipeline + Creating a Regex Labeler + Creating a ColumnName Labeler + Merge Profile List + Dataloader with Popmon Reports diff --git a/docs/0.10.5/html/_sources/graph_data_demo.nblink.txt b/docs/0.10.5/html/_sources/graph_data_demo.nblink.txt new file mode 100644 index 000000000..e627c61f8 --- /dev/null +++ b/docs/0.10.5/html/_sources/graph_data_demo.nblink.txt @@ -0,0 +1,3 @@ +{ + "path": "../../feature_branch/examples/graph_data_demo.ipynb" +} diff --git a/docs/0.10.5/html/_sources/graphs.rst.txt b/docs/0.10.5/html/_sources/graphs.rst.txt new file mode 100644 index 000000000..23c2d316b --- /dev/null +++ b/docs/0.10.5/html/_sources/graphs.rst.txt @@ -0,0 +1,196 @@ +.. _reports: + +Graphs +****** + +Graph Your Data +=============== + +We can plot some of our data as seaborn histogram plots. Below will demonstrate how to do so and provide examples. + +The following plots are currently available to work directly with your profilers: + + * histogram (numeric columns only) + * missing values matrix + +Below shows how to do so with examples. + +What we need to import +~~~~~~~~~~~~~~~~~~~~~~ +.. code-block:: python + + from dataprofiler.reports import graphs + +The main functions that is used to plot histograms are in graphs. **You will also need the `dataprofiler[reports]` requirement to be installed**: + +.. code-block:: console + + pip install 'dataprofiler[reports]' + +Plotting from a StructuredProfiler class +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +With a StructuredProfiler class variable, we can specify what columns we want to be plotted, and plot them into histograms. + +.. code-block:: python + + graphs.plot_histograms(profiler, column_names, column_inds) + +These are what the variables mean: + + * **profiler** - StructuredProfiler class variable that contains the data we want + * **columns** - (Optional) The list of IntColumn or FloatColumn *names* we want to specifically plot. If specified, `column_inds` cannot be specified. + * **column_inds** - (Optional) The list of IntColumn or FloatColumn *indexes* we want to specifically plot. If specified, `column_names` cannot be specified. + + +Additionally, we can also plot the missing values matrix for a StructuredProfiler: + +.. code-block:: python + + graphs.plot_missing_values_matrix(profiler, ax, title) + +These are what the variables mean: + + * **profiler** - StructuredProfiler class variable that contains the data we want + * **ax** - (Optional) MatPlotLib Axes to plot the matrix within. + * **title** - (Optional) The title of the axes we want to define. + + +Plotting an individual IntColumn or FloatColumn +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +With a column's Int or Float profile, we can plot their respective histograms. + +.. code-block:: python + + graphs.plot_col_histogram(column, axes, title) + +These are what the variables mean: + + * **column** - The IntColumn or FloatColumn we want to plot + * **axes** - (Optional) The MatPlotLib Axes to plot the histogram within. + * **title** - (Optional) The title of the axes we want to define. + + +Additionally, we can also plot the missing values bargraph for any column profile: + +.. code-block:: python + + graphs.plot_col_missing_values(profiler, ax, title) + +These are what the variables mean: + + * **profiler** - The StructuredColProfiler we want to plot + * **ax** - (Optional) MatPlotLib Axes to plot the matrix within. + * **title** - (Optional) The title of the axes we want to define. + +Examples +~~~~~~~~ + +Histograms +---------- + +1. This example demonstrates how we can take a StructuredProfiler class and plot histograms of the specified columns. + +.. code-block:: python + + import dataprofiler as dp + from dataprofiler.reports import graphs + + + data = [[1, 'a', 1.0], + [2, 'b', 2.2], + [3, 'c', 3.5], + [None, 'd', 10.0]] + profiler = dp.StructuredProfiler(data) + + # This will plot all IntColumn and FloatColumn as histograms (The first and last column). + fig = graphs.plot_histograms(profiler) + fig.show() + + # This will only plot the specified column, 0. + columns_names = [0] + fig = graphs.plot_histograms(profiler, columns_names) + fig.show() + +.. image:: _static/images/histogram_example_0.png + :alt: First Histogram Example Image + +.. image:: _static/images/histogram_example_1.png + :alt: Second Histogram Example Image + +2. This example demonstrates how we can plot a low level profiler. + +.. code-block:: python + + import pandas as pd + + from dataprofiler.profilers import IntColumn + from dataprofiler.reports import graphs + + + data = pd.Series([1, 2, 3], dtype=str) + profiler = IntColumn('example') + profiler.update(data) + + # Plot the axes + ax = graphs.plot_col_histogram(profiler) + + # get and show the figure of the plotted histogram + fig = ax.get_figure() + fig.show() + +.. image:: _static/images/histogram_example_2.png + :alt: Histogram Column Only Example Image + + +Missing Values Matrix +--------------------- + +1. This example demonstrates how we can take a StructuredProfiler class and plot a missing values matrix. + +.. code-block:: python + + import dataprofiler as dp + from dataprofiler.reports import graphs + + + data = pd.DataFrame( + [[None, '', 1.0, '1/2/2021'], + [3, None, 3.5, ''], + [1, None, 1.0, '2/5/2020'], + [None, 1, 10.0, '3/5/2020']], + columns=['integer', 'str', 'float', 'datetime'], + dtype=object + ) + profiler = dp.StructuredProfiler(data) + + # This will plot the missing values matrix for all columns. + fig = graphs.plot_missing_values_matrix(profiler) + fig.show() + +.. image:: _static/images/missing_value_matrix_example_0.png + :alt: Missing Values Matrix Example Image + +2. This example demonstrates how we can plot barchart of a column's missing values. + +.. code-block:: python + + import pandas as pd + + from dataprofiler.profilers.profile_builder import StructuredColProfiler + from dataprofiler.reports import graphs + + + data = pd.Series([1, 2, 3, None, None, 4], name='example', dtype=str) + profiler = StructuredColProfiler(data) + + # Plot the axes, can be a list of multiple columns + ax = graphs.plot_col_missing_values([profiler]) + + # get and show the figure of the plotted histogram + fig = ax.get_figure() + fig.show() + +.. image:: _static/images/missing_value_barchart_example_0.png + :alt: Missing Values Column Only Example Image \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/index.rst.txt b/docs/0.10.5/html/_sources/index.rst.txt new file mode 100644 index 000000000..5e97ab064 --- /dev/null +++ b/docs/0.10.5/html/_sources/index.rst.txt @@ -0,0 +1,587 @@ +.. _Data Profiler: + +==================================== +Data Profiler | What's in your data? +==================================== + +Purpose +======= + +The DataProfiler is a Python library designed to make data analysis, monitoring and **sensitive data detection** easy. + +Loading **Data** with a single command, the library automatically formats & loads files into a DataFrame. **Profiling** the Data, the library identifies the schema, statistics, entities and more. Data Profiles can then be used in downstream applications or reports. + +The Data Profiler comes with a cutting edge pre-trained deep learning model, used to efficiently identify **sensitive data** (or **PII**). If customization is needed, it's easy to add new entities to the existing pre-trained model or insert a new pipeline for entity recognition. + +The best part? Getting started only takes a few lines of code (`Example CSV`_): + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler + + data = Data("your_file.csv") # Auto-Detect & Load: CSV, AVRO, Parquet, JSON, Text + print(data.data.head(5)) # Access data directly via a compatible Pandas DataFrame + + profile = Profiler(data) # Calculate Statistics, Entity Recognition, etc + readable_report = profile.report(report_options={"output_format":"pretty"}) + print(json.dumps(readable_report, indent=4)) + + +To install the full package from pypi: + +.. code-block:: console + + pip install DataProfiler[ml] + +If the ML requirements are too strict (say, you don't want to install tensorflow), you can install a slimmer package. The slimmer package disables the default sensitive data detection / entity recognition (labler) + +Install from pypi: + +.. code-block:: console + + pip install DataProfiler + +If you have suggestions or find a bug, please open an `issue`_. + +Visit the :ref:`API` to explore Data Profiler's terminology. + + +What is a Data Profile? +======================= + +In the case of this library, a data profile is a dictionary containing statistics and predictions about the underlying dataset. There are "global statistics" or `global_stats`, which contain dataset level data and there are "column/row level statistics" or `data_stats` (each column is a new key-value entry). + +The format for a structured profile is below: + +.. code-block:: python + + "global_stats": { + "samples_used": int, + "column_count": int, + "row_count": int, + "row_has_null_ratio": float, + "row_is_null_ratio": float, + "unique_row_ratio": float, + "duplicate_row_count": int, + "file_type": string, + "encoding": string, + "correlation_matrix": list[list[int]], (*) + "chi2_matrix": list[list[float]], + "profile_schema": dict[string, list[int]] + }, + "data_stats": [ + { + "column_name": string, + "data_type": string, + "data_label": string, + "categorical": bool, + "order": string, + "samples": list[str], + "statistics": { + "sample_size": int, + "null_count": int, + "null_types": list[string], + "null_types_index": dict[string, list[int]], + "data_type_representation": dict[string, list[string]], + "min": [null, float], + "max": [null, float], + "sum": float, + "mode": list[float], + "median": float, + "median_absolute_deviation": float, + "mean": float, + "variance": float, + "stddev": float, + "skewness": float, + "kurtosis": float, + "num_zeros": int, + "num_negatives": int, + "histogram": { + "bin_counts": list[int], + "bin_edges": list[float], + }, + "quantiles": { + int: float + }, + "vocab": list[char], + "avg_predictions": dict[string, float], + "data_label_representation": dict[string, float], + "categories": list[str], + "unique_count": int, + "unique_ratio": float, + "categorical_count": dict[string, int], + "gini_impurity": float, + "unalikeability": float, + "precision": { + 'min': int, + 'max': int, + 'mean': float, + 'var': float, + 'std': float, + 'sample_size': int, + 'margin_of_error': float, + 'confidence_level': float + }, + "times": dict[string, float], + "format": string + }, + "null_replication_metrics": { + "class_prior": list[int], + "class_sum": list[list[int]], + "class_mean": list[list[int]] + } + } + ] + +(*) Currently the correlation matrix update is toggled off. It will be reset in a later update. Users can still use it as desired with the is_enable option set to True. + +The format for an unstructured profile is below: + +.. code-block:: python + + "global_stats": { + "samples_used": int, + "empty_line_count": int, + "file_type": string, + "encoding": string, + "memory_size": float, # in MB + }, + "data_stats": { + "data_label": { + "entity_counts": { + "word_level": dict[string, int], + "true_char_level": dict[string, int], + "postprocess_char_level": dict[string, int] + }, + "entity_percentages": { + "word_level": dict[string, float], + "true_char_level": dict[string, float], + "postprocess_char_level": dict[string, float] + }, + "times": dict[string, float] + }, + "statistics": { + "vocab": list[char], + "vocab_count": dict[string, int], + "words": list[string], + "word_count": dict[string, int], + "times": dict[string, float] + } + } + +The format for a graph profile is below: + +.. code-block:: python + + "num_nodes": int, + "num_edges": int, + "categorical_attributes": list[string], + "continuous_attributes": list[string], + "avg_node_degree": float, + "global_max_component_size": int, + "continuous_distribution": { + "": { + "name": string, + "scale": float, + "properties": list[float, np.array] + }, + "": None, + }, + "categorical_distribution": { + "": None, + "": { + "bin_counts": list[int], + "bin_edges": list[float] + }, + }, + "times": dict[string, float] + +Supported Data Formats +~~~~~~~~~~~~~~~~~~~~~~ + +* Any delimited file (CSV, TSV, etc.) +* JSON object +* Avro file +* Parquet file +* Text file +* Pandas DataFrame +* A URL that points to one of the supported file types above + + +Data Labels +~~~~~~~~~~~ + +*Data Labels* are determined per cell for structured data (column/row when the *profiler* is used) or at the character level for unstructured data. + +* UNKNOWN +* ADDRESS +* BAN (bank account number, 10-18 digits) +* CREDIT_CARD +* EMAIL_ADDRESS +* UUID +* HASH_OR_KEY (md5, sha1, sha256, random hash, etc.) +* IPV4 +* IPV6 +* MAC_ADDRESS +* PERSON +* PHONE_NUMBER +* SSN +* URL +* US_STATE +* DRIVERS_LICENSE +* DATE +* TIME +* DATETIME +* INTEGER +* FLOAT +* QUANTITY +* ORDINAL + + +Get Started +=========== + +Load a File +~~~~~~~~~~~ + +The profiler should automatically identify the file type and load the data into a `Data Class`. + +Along with other attributtes the `Data class` enables structured data to be accessed via a valid Pandas DataFrame. + +.. code-block:: python + + # Load a csv file, return a CSVData object + csv_data = Data('your_file.csv') + + # Print the first 10 rows of the csv file + print(csv_data.data.head(10)) + + # Load a parquet file, return a ParquetData object + parquet_data = Data('your_file.parquet') + + # Sort the data by the name column + parquet_data.data.sort_values(by='name', inplace=True) + + # Print the sorted first 10 rows of the parquet data + print(parquet_data.data.head(10)) + + +If the file type is not automatically identified (rare), you can specify them +specifically, see section Data Readers. + +Profile a File +~~~~~~~~~~~~~~ + +Example uses a CSV file for example, but CSV, JSON, Avro, Parquet or Text should also work. + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler + + # Load file (CSV should be automatically identified) + data = Data("your_file.csv") + + # Profile the dataset + profile = Profiler(data) + + # Generate a report and use json to prettify. + report = profile.report(report_options={"output_format":"pretty"}) + + # Print the report + print(json.dumps(report, indent=4)) + +Updating Profiles +~~~~~~~~~~~~~~~~~ + +Currently, the data profiler is equipped to update its profile in batches. + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler + + # Load and profile a CSV file + data = Data("your_file.csv") + profile = Profiler(data) + + # Update the profile with new data: + new_data = Data("new_data.csv") + profile.update_profile(new_data) + + # Print the report using json to prettify. + report = profile.report(report_options={"output_format":"pretty"}) + print(json.dumps(report, indent=4)) + + +Merging Profiles +~~~~~~~~~~~~~~~~ + +If you have two files with the same schema (but different data), it is possible to merge the two profiles together via an addition operator. + +This also enables profiles to be determined in a distributed manner. + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler + + # Load a CSV file with a schema + data1 = Data("file_a.csv") + profile1 = Profiler(data) + + # Load another CSV file with the same schema + data2 = Data("file_b.csv") + profile2 = Profiler(data) + + profile3 = profile1 + profile2 + + # Print the report using json to prettify. + report = profile3.report(report_options={"output_format":"pretty"}) + print(json.dumps(report, indent=4)) + +Profile a Pandas DataFrame +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: python + + import pandas as pd + import dataprofiler as dp + import json + + my_dataframe = pd.DataFrame([[1, 2.0],[1, 2.2],[-1, 3]]) + profile = dp.Profiler(my_dataframe) + + # print the report using json to prettify. + report = profile.report(report_options={"output_format":"pretty"}) + print(json.dumps(report, indent=4)) + + # read a specified column, in this case it is labeled 0: + print(json.dumps(report["data stats"][0], indent=4)) + + +Unstructured Profiler +~~~~~~~~~~~~~~~~~~~~~ + +In addition to the structured profiler, the Data Profiler provides unstructured +profiling for the TextData object or string. Unstructured profiling also works +with list(string), pd.Series(string) or pd.DataFrame(string) given profiler_type +option specified as `unstructured`. Below is an example of unstructured profile +with a text file. + +.. code-block:: python + + import dataprofiler as dp + import json + my_text = dp.Data('text_file.txt') + profile = dp.Profiler(my_text) + + # print the report using json to prettify. + report = profile.report(report_options={"output_format":"pretty"}) + print(json.dumps(report, indent=4)) + +Another example of unstructured profile with pd.Series of string is given as below + +.. code-block:: python + + import dataprofiler as dp + import pandas as pd + import json + + text_data = pd.Series(['first string', 'second string']) + profile = dp.Profiler(text_data, profiler_type="unstructured") + + # print the report using json to prettify. + report = profile.report(report_options={"output_format":"pretty"}) + print(json.dumps(report, indent=4)) + + +Graph Profiler +~~~~~~~~~~~~~~ + +DataProfiler also provides the ability to profile graph data from a csv file. Below is an example of the graph profiler with a graph data csv file: + +.. code-block:: python + + import dataprofiler as dp + import pprint + + my_graph = dp.Data('graph_file.csv') + profile = dp.Profiler(my_graph) + + # print the report using pretty print (json dump does not work on numpy array values inside dict) + report = profile.report() + printer = pprint.PrettyPrinter(sort_dicts=False, compact=True) + printer.pprint(report) + + +Specifying a Filetype or Delimiter +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Example of specifying a CSV data type, with a `,` delimiter. +In addition, it utilizes only the first 10,000 rows. + +.. code-block:: python + + import json + import os + from dataprofiler import Data, Profiler + from dataprofiler.data_readers.csv_data import CSVData + + # Load a CSV file, with "," as the delimiter + data = CSVData("your_file.csv", options={"delimiter": ","}) + + # Split the data, such that only the first 10,000 rows are used + data = data.data[0:10000] + + # Read in profile and print results + profile = Profiler(data) + print(json.dumps(profile.report(report_options={"output_format":"pretty"}), indent=4)) + + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Getting Started: + + Intro + install.rst + data_readers.rst + profiler.rst + data_labeling.rst + graphs.rst + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: User Guide: + + examples.rst + API.rst + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Community: + + roadmap.rst + Changelog + Feedback + GitHub + Contributing + +.. _Example CSV: https://raw.githubusercontent.com/capitalone/DataProfiler/main/dataprofiler/tests/data/csv/aws_honeypot_marx_geo.csv +.. _issue: https://github.com/capitalone/DataProfiler/issues/new/choose + +Versions +======== +* `0.10.5`_ +* `0.10.4`_ +* `0.10.3`_ +* `0.10.2`_ +* `0.10.1`_ +* `0.10.0`_ +* `0.9.0`_ +* `0.8.9`_ +* `0.8.8`_ +* `0.8.7`_ +* `0.8.6`_ +* `0.8.5`_ +* `0.8.4`_ +* `0.8.3`_ +* `0.8.2`_ +* `0.8.1`_ +* `0.8.0`_ +* `0.7.11`_ +* `0.7.10`_ +* `0.7.9`_ +* `0.7.8`_ +* `0.7.7`_ +* `0.7.6`_ +* `0.7.2`_ +* `0.7.1`_ +* `0.7.0`_ +* `0.6.0`_ +* `0.5.3`_ +* `0.5.2`_ +* `0.5.1`_ +* `0.5.0`_ +* `0.4.7`_ +* `0.4.6`_ +* `0.4.5`_ +* `0.4.4`_ +* `0.4.3`_ +* `0.3.0`_ + +.. _0.3.0: ../../v0.3/html/index.html +.. _0.4.3: ../../0.4.3/html/index.html + +.. _0.4.4: ../../0.4.4/html/index.html + +.. _0.4.5: ../../0.4.5/html/index.html + +.. _0.4.6: ../../0.4.6/html/index.html + +.. _0.4.7: ../../0.4.7/html/index.html + +.. _0.5.0: ../../0.5.0/html/index.html + +.. _0.5.1: ../../0.5.1/html/index.html + +.. _0.5.2: ../../0.5.2/html/index.html + +.. _0.5.3: ../../0.5.3/html/index.html +.. _0.6.0: ../../0.6.0/html/index.html + +.. _0.7.0: ../../0.7.0/html/index.html + +.. _0.7.1: ../../0.7.1/html/index.html +.. _0.7.2: ../../0.7.2/html/index.html + +.. _0.7.6: ../../0.7.6/html/index.html + +.. _0.7.7: ../../0.7.7/html/index.html + +.. _0.7.8: ../../0.7.8/html/index.html + +.. _0.7.9: ../../0.7.9/html/index.html + +.. _0.7.10: ../../0.7.10/html/index.html + +.. _0.7.11: ../../0.7.11/html/index.html + +.. _0.8.0: ../../0.8.0/html/index.html + +.. _0.8.1: ../../0.8.1/html/index.html + +.. _0.8.2: ../../0.8.2/html/index.html + +.. _0.8.3: ../../0.8.3/html/index.html + +.. _0.8.4: ../../0.8.4/html/index.html + +.. _0.8.5: ../../0.8.5/html/index.html + +.. _0.8.6: ../../0.8.6/html/index.html + +.. _0.8.7: ../../0.8.7/html/index.html + +.. _0.8.8: ../../0.8.8/html/index.html + +.. _0.8.9: ../../0.8.9/html/index.html + +.. _0.9.0: ../../0.9.0/html/index.html + +.. _0.10.0: ../../0.10.0/html/index.html + +.. _0.10.1: ../../0.10.1/html/index.html + +.. _0.10.2: ../../0.10.2/html/index.html + +.. _0.10.3: ../../0.10.3/html/index.html + +.. _0.10.4: ../../0.10.4/html/index.html + +.. _0.10.5: ../../0.10.5/html/index.html + diff --git a/docs/0.10.5/html/_sources/install.rst.txt b/docs/0.10.5/html/_sources/install.rst.txt new file mode 100644 index 000000000..bdf4c3bb4 --- /dev/null +++ b/docs/0.10.5/html/_sources/install.rst.txt @@ -0,0 +1,145 @@ +.. _install: + +Install +******* + +To install the full package from pypi: + +.. code-block:: console + + pip install DataProfiler[ml] + +If the ML requirements are too strict (say, you don't want to install +tensorflow), you can install a slimmer package. The slimmer package disables +the default sensitive data detection / entity recognition (labler) + +Install from pypi: + +.. code-block:: console + + pip install DataProfiler + +Snappy Installation +=================== + +This is required to profile parquet/avro datasets + +MacOS (intel chip) with homebrew: + +.. code-block:: console + + brew install snappy && CPPFLAGS="-I/usr/local/include -L/usr/local/lib" pip install python-snappy + + +MacOS (apple chip) with homebrew: + +.. code-block:: console + + brew install snappy && CPPFLAGS="-I/opt/homebrew/include -L/opt/homebrew/lib" pip install python-snappy + + +Linux install: + +.. code-block:: console + + sudo apt-get -y install libsnappy-dev + + +Build From Scratch +================== + +NOTE: Installation for python3 + +virtualenv install: + +.. code-block:: console + + python3 -m pip install virtualenv + + +Setup virtual env: + +.. code-block:: console + + python3 -m virtualenv --python=python3 venv3 + source venv3/bin/activate + + +Install requirements: + +.. code-block:: console + + pip3 install -r requirements.txt + +Install labeler dependencies: + +.. code-block:: console + + pip3 install -r requirements-ml.txt + + +Install via the repo -- Build setup.py and install locally: + +.. code-block:: console + + python3 setup.py sdist bdist bdist_wheel + pip3 install dist/DataProfiler*-py3-none-any.whl + + +If you see: + +.. code-block:: console + + ERROR: Double requirement given:dataprofiler==X.Y.Z from dataprofiler/dist/DataProfiler-X.Y.Z-py3-none-any.whl (already in dataprofiler==X2.Y2.Z2 from dataprofiler/dist/DataProfiler-X2.Y2.Z2-py3-none-any.whl, name='dataprofiler') + +This means that you have multiple versions of the DataProfiler distribution +in the dist folder. +To resolve, either remove the older one or delete the folder and rerun the steps +above. + +Install via github: + +.. code-block:: console + + pip3 install git+https://github.com/capitalone/dataprofiler.git#egg=dataprofiler + + + +Testing +======= + +For testing, install test requirements: + +.. code-block:: console + + pip3 install -r requirements-test.txt + + +To run all unit tests, use: + +.. code-block:: console + + DATAPROFILER_SEED=0 python3 -m unittest discover -p "test*.py" + + +To run file of unit tests, use form: + +.. code-block:: console + + DATAPROFILER_SEED=0 python3 -m unittest discover -p test_profile_builder.py + + +To run a file with Pytest use: + +.. code-block:: console + + DATAPROFILER_SEED=0 pytest dataprofiler/tests/data_readers/test_csv_data.py -v + + +To run individual of unit test, use form: + +.. code-block:: console + + DATAPROFILER_SEED=0 python3 -m unittest dataprofiler.tests.profilers.test_profile_builder.TestProfiler + + diff --git a/docs/0.10.5/html/_sources/labeler.nblink.txt b/docs/0.10.5/html/_sources/labeler.nblink.txt new file mode 100644 index 000000000..bed6517bf --- /dev/null +++ b/docs/0.10.5/html/_sources/labeler.nblink.txt @@ -0,0 +1,6 @@ +{ + "path": "../../feature_branch/examples/labeler.ipynb", + "extra-media": [ + "../../feature_branch/examples/DL-Flowchart.png" + ] +} \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/merge_profile_list.nblink.txt b/docs/0.10.5/html/_sources/merge_profile_list.nblink.txt new file mode 100644 index 000000000..50698d637 --- /dev/null +++ b/docs/0.10.5/html/_sources/merge_profile_list.nblink.txt @@ -0,0 +1,3 @@ +{ + "path": "../../feature_branch/examples/merge_profile_list.ipynb" +} \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/modules.rst.txt b/docs/0.10.5/html/_sources/modules.rst.txt new file mode 100644 index 000000000..0593459df --- /dev/null +++ b/docs/0.10.5/html/_sources/modules.rst.txt @@ -0,0 +1,7 @@ +dataprofiler +============ + +.. toctree:: + :maxdepth: 4 + + dataprofiler diff --git a/docs/0.10.5/html/_sources/overview.nblink.txt b/docs/0.10.5/html/_sources/overview.nblink.txt new file mode 100644 index 000000000..3d9f89d3d --- /dev/null +++ b/docs/0.10.5/html/_sources/overview.nblink.txt @@ -0,0 +1,3 @@ +{ + "path": "../../feature_branch/examples/intro_data_profiler.ipynb" +} \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/popmon_dp_loader_example.nblink.txt b/docs/0.10.5/html/_sources/popmon_dp_loader_example.nblink.txt new file mode 100644 index 000000000..3beced0ab --- /dev/null +++ b/docs/0.10.5/html/_sources/popmon_dp_loader_example.nblink.txt @@ -0,0 +1,3 @@ +{ + "path": "../../feature_branch/examples/popmon_dp_loader_example.ipynb" +} \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/profiler.rst.txt b/docs/0.10.5/html/_sources/profiler.rst.txt new file mode 100644 index 000000000..b51a72313 --- /dev/null +++ b/docs/0.10.5/html/_sources/profiler.rst.txt @@ -0,0 +1,962 @@ +.. _profiler: + +Profiler +******** + +Profile Your Data +================= + +Profiling your data is easy. Just use the data reader, send the data to the +profiler, and print out the report. + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler + + data = Data("your_file.csv") # Auto-Detect & Load: CSV, AVRO, Parquet, JSON, Text + + profile = Profiler(data) # Calculate Statistics, Entity Recognition, etc + + readable_report = profile.report(report_options={"output_format": "pretty"}) + print(json.dumps(readable_report, indent=4)) + +If the data is structured, the profile will return global statistics as well as +column by column statistics. The vast amount of statistics are listed on the +intro page. + +Load a File +~~~~~~~~~~~ + +The profiler should automatically identify the file type and load the data into a `Data Class`. + +Along with other attributtes the `Data class` enables structured data to be accessed via a valid Pandas DataFrame. + +.. code-block:: python + + # Load a csv file, return a CSVData object + csv_data = Data('your_file.csv') + + # Print the first 10 rows of the csv file + print(csv_data.data.head(10)) + + # Load a parquet file, return a ParquetData object + parquet_data = Data('your_file.parquet') + + # Sort the data by the name column + parquet_data.data.sort_values(by='name', inplace=True) + + # Print the sorted first 10 rows of the parquet data + print(parquet_data.data.head(10)) + + +If the file type is not automatically identified (rare), you can specify them +specifically, see section Data Readers. + +Profile a File +~~~~~~~~~~~~~~ + +Example uses a CSV file for example, but CSV, JSON, Avro or Parquet should also work. + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler + + # Load file (CSV should be automatically identified) + data = Data("your_file.csv") + + # Profile the dataset + profile = Profiler(data) + + # Generate a report and use json to prettify. + report = profile.report(report_options={"output_format": "pretty"}) + + # Print the report + print(json.dumps(report, indent=4)) + +Updating Profiles +~~~~~~~~~~~~~~~~~ + +Currently, the data profiler is equipped to update its profile in batches. + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler + + # Load and profile a CSV file + data = Data("your_file.csv") + profile = Profiler(data) + + # Update the profile with new data: + new_data = Data("new_data.csv") + profile.update_profile(new_data) + + # Print the report using json to prettify. + report = profile.report(report_options={"output_format": "pretty"}) + print(json.dumps(report, indent=4)) + + +Merging Profiles +~~~~~~~~~~~~~~~~ + +If you have two files with the same schema (but different data), it is possible to merge the two profiles together via an addition operator. + +This also enables profiles to be determined in a distributed manner. + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler + + # Load a CSV file with a schema + data1 = Data("file_a.csv") + profile1 = Profiler(data) + + # Load another CSV file with the same schema + data2 = Data("file_b.csv") + profile2 = Profiler(data) + + profile3 = profile1 + profile2 + + # Print the report using json to prettify. + report = profile3.report(report_options={"output_format": "pretty"}) + print(json.dumps(report, indent=4)) + + +Profile Differences +~~~~~~~~~~~~~~~~~~~ + +Profile differences take two profiles and find the differences +between them. Create the difference report like this: + +.. code-block:: python + + from dataprofiler import Data, Profiler + + # Load a CSV file + data1 = Data("file_a.csv") + profile1 = Profiler(data) + + # Load another CSV file + data2 = Data("file_b.csv") + profile2 = Profiler(data) + + diff_report = profile1.diff(profile2) + print(diff_report) + +The `.diff()` operation is available between two profiles, although there are different +outputs depending on the type of profile being differenced. For example, for numerical +column profiles (e.g. integers and floats), two valuable calculations that +`.diff()` returns are `t-test`, `chi2-test`, and `psi` (Popoulation Stability Index) +for understanding distributional changes. + +The difference report contains a dictionary that mirrors the profile report. +Each data type has its own difference: + +* **Int/Float** - One profile subtracts the value from the other. + +* **String** - The strings will be shown in a list: + + - [profile1 str, profile2 str] +* **List** - A list of 3 will be returned showing the unique values of + each profile and the shared values: + + - [profile 1 unique values, shared values, profile 2 unique values] +* **Dict** - Some dictionaries with varied keys will also return a list + of three in the format: + + - [profile 1 unique key-values, shared key differences, profile 2 unique key-values] + +Otherwise, when no differences occur: + +* **Any Type No Differences** - A string will report: "unchanged". + +Below is the structured difference report: + +.. code-block:: python + + { + 'global_stats': { + 'file_type': [str, str], + 'encoding': [str, str], + 'samples_used': int, + 'column_count': int, + 'row_count': int, + 'row_has_null_ratio': float, + 'row_is_null_ratio': float, + 'unique_row_ratio': float, + 'duplicate_row_count': int, + 'correlation_matrix': list[list[float]], + 'chi2_matrix': list[list[float]], + 'profile_schema': list[dict[str, int]] + }, + 'data_stats': [{ + 'column_name': str, + 'data_type': [str, str], + 'data_label': [list[str], list[str], list[str]], + 'categorical': [str, str], + 'order': [str, str], + 'statistics': { + 'min': float, + 'max': float, + 'sum': float, + 'mean': float, + 'median': float, + 'mode': [list[float], list[float], list[float]], + 'median_absolute_deviation': float, + 'variance': float, + 'stddev': float, + 't-test': { + 't-statistic': float, + 'conservative': {'df': int, + 'p-value': float}, + 'welch': {'df': float, + 'p-value': float}}, + 'psi': float, + "chi2-test": { + "chi2-statistic": float, + "df": int, + "p-value": float + }, + 'unique_count': int, + 'unique_ratio': float, + 'categories': [list[str], list[str], list[str]], + 'gini_impurity': float, + 'unalikeability': float, + 'categorical_count': [dict[str, int], dict[str, int], dict[str, int]], + 'avg_predictions': [dict[str, float]], + 'label_representation': [dict[str, float]], + 'sample_size': int, + 'null_count': int, + 'null_types': [list[str], list[str], list[str]], + 'null_types_index': [dict[str, int], dict[str, int], dict[str, int]], + 'data_type_representation': [dict[str, float]] + }, + "null_replication_metrics": { + "class_prior": list[int], + "class_sum": list[list[int]], + "class_mean": list[list[int]] + } + } + +Below is the unstructured difference report: + +.. code-block:: python + + { + 'global_stats': { + 'file_type': [str, str], + 'encoding': [str, str], + 'samples_used': int, + 'empty_line_count': int, + 'memory_size': float + }, + 'data_stats': { + 'data_label': { + 'entity_counts': { + 'word_level': dict[str, int], + 'true_char_level': dict[str, int], + 'postprocess_char_level': dict[str, int] + }, + 'entity_percentages': { + 'word_level': dict[str, float], + 'true_char_level': dict[str, float], + 'postprocess_char_level': dict[str, float] + } + }, + 'statistics': { + 'vocab': [list[str], list[str], list[str]], + 'vocab_count': [dict[str, int], dict[str, int], dict[str, int]], + 'words': [list[str], list[str], list[str]], + 'word_count': [dict[str, int], dict[str, int], dict[str, int]] + } + } + } + + +Saving and Loading a Profile +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The profiles can easily be saved and loaded as shown below: + +**NOTE: Json saving and loading only supports Structured Profiles currently.** + +There are two save/load methods: + +* **Pickle save/load** + + * Save a profile as a `.pkl` file. + * Load a `.pkl` file as a profile object. + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler + + # Load a CSV file, with "," as the delimiter + data = Data("your_file.csv") + + # Read data into profile + profile = Profiler(data) + + # save structured profile to pkl file + profile.save(filepath="my_profile.pkl") + + # load pkl file to structured profile + loaded_pkl_profile = dp.Profiler.load(filepath="my_profile.pkl") + + print(json.dumps(loaded_pkl_profile.report(report_options={"output_format": "compact"}), + indent=4)) + +* **Json save/load** + + * Save a profile as a human-readable `.json` file. + * Load a `.json` file as a profile object. + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler + + # Load a CSV file, with "," as the delimiter + data = Data("your_file.csv") + + # Read data into profile + profile = Profiler(data) + + # save structured profile to json file + profile.save(filepath="my_profile.json", save_method="json") + + # load json file to structured profile + loaded_json_profile = dp.Profiler.load(filepath="my_profile.json", load_method="json") + + print(json.dumps(loaded_json_profile.report(report_options={"output_format": "compact"}), + indent=4)) + + +Structured vs Unstructured Profiles +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When using the profiler, the data profiler will automatically infer whether to +create the structured profile or the unstructured profile. However, you can be +explicit as shown below: + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler + + # Creating a structured profile + data1 = Data("normal_csv_file.csv") + structured_profile = Profiler(data1, profiler_type="structured") + + structured_report = structured_profile.report(report_options={"output_format": "pretty"}) + print(json.dumps(structured_report, indent=4)) + + # Creating an unstructured profile + data2 = Data("normal_text_file.txt") + unstructured_profile = Profiler(data2, profiler_type="unstructured") + + unstructured_report = unstructured_profile.report(report_options={"output_format": "pretty"}) + print(json.dumps(unstructured_report, indent=4)) + + +Setting the Sample Size +~~~~~~~~~~~~~~~~~~~~~~~ + +There are two ways to set sample size in a profile: samples_per_update and +min_true_samples. Samples_per_update takes an integer as the exact amount that +will be sampled. Min_true_samples will set the minimum amount of samples that +are not null. For example: + +.. code-block:: python + + from dataprofiler import Profiler + + sample_array = [1.0, NULL, 2.0] + profile = dp.Profiler(sample_array, samples_per_update=2) + +The first two samples (1.0 and NULL) are used for the statistical analysis. + +In contrast, if we also set min_true_samples to 2 then the Data Reader will +continue to read until the minimum true samples were found for the given column. +For example: + +.. code-block:: python + + from dataprofiler import Profiler + + sample_array = [1.0, NULL, 2.0] + profile = dp.Profiler(sample_array, samples_per_update=2, min_true_samples=2) + +This will use all samples in the statistical analysis until the number of "true" +(non-NULL) values are reached. Both min_true_samples and +samples_per_update conditions must be met. In this case, the profile will grab +the first two samples (1.0 and NULL) to satisfy the samples_per_update, and then +it will grab the first two VALID samples (1.0 and 2.0) to satisfy the +min_true_samples. + +Profile a Pandas DataFrame +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: python + + import pandas as pd + import dataprofiler as dp + import json + + my_dataframe = pd.DataFrame([[1, 2.0],[1, 2.2],[-1, 3]]) + profile = dp.Profiler(my_dataframe) + + # print the report using json to prettify. + report = profile.report(report_options={"output_format": "pretty"}) + print(json.dumps(report, indent=4)) + + # read a specified column, in this case it is labeled 0: + print(json.dumps(report["data stats"][0], indent=4)) + + +Specifying a Filetype or Delimiter +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Example of specifying a CSV data type, with a `,` delimiter. +In addition, it utilizes only the first 10,000 rows. + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler + from dataprofiler.data_readers.csv_data import CSVData + + # Load a CSV file, with "," as the delimiter + data = CSVData("your_file.csv", options={"delimiter": ","}) + + # Split the data, such that only the first 10,000 rows are used + data = data.data[0:10000] + + # Read in profile and print results + profile = Profiler(data) + print(json.dumps(profile.report(report_options={"output_format": "pretty"}), indent=4)) + +Setting Profiler Seed +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Example of specifying a seed for reproducibility. + +.. code-block:: python + + import dataprofiler as dp + + # Set seed to non-negative integer value or None + dp.set_seed(0) + + +Profile Statistic Descriptions +============================== + +Structured Profile +~~~~~~~~~~~~~~~~~~ + +**global_stats**: + +* samples_used - number of input data samples used to generate this profile +* column_count - the number of columns contained in the input dataset +* row_count - the number of rows contained in the input dataset +* row_has_null_ratio - the proportion of rows that contain at least one null value to the total number of rows +* row_is_null_ratio - the proportion of rows that are fully comprised of null values (null rows) to the total number of rows +* unique_row_ratio - the proportion of distinct rows in the input dataset to the total number of rows +* duplicate_row_count - the number of rows that occur more than once in the input dataset +* file_type - the format of the file containing the input dataset (ex: .csv) +* encoding - the encoding of the file containing the input dataset (ex: UTF-8) +* correlation_matrix - matrix of shape `column_count` x `column_count` containing the correlation coefficients between each column in the dataset +* chi2_matrix - matrix of shape `column_count` x `column_count` containing the chi-square statistics between each column in the dataset +* profile_schema - a description of the format of the input dataset labeling each column and its index in the dataset + * string - the label of the column in question and its index in the profile schema +* times - the duration of time it took to generate the global statistics for this dataset in milliseconds + +**data_stats**: + +* column_name - the label/title of this column in the input dataset +* data_type - the primitive python data type that is contained within this column +* data_label - the label/entity of the data in this column as determined by the Labeler component +* categorical - 'true' if this column contains categorical data +* order - the way in which the data in this column is ordered, if any, otherwise “random” +* samples - a small subset of data entries from this column +* statistics - statistical information on the column + * sample_size - number of input data samples used to generate this profile + * null_count - the number of null entries in the sample + * null_types - a list of the different null types present within this sample + * null_types_index - a dict containing each null type and a respective list of the indicies that it is present within this sample + * data_type_representation - the percentage of samples used identifying as each data_type + * min - minimum value in the sample + * max - maximum value in the sample + * mode - mode of the entries in the sample + * median - median of the entries in the sample + * median_absolute_deviation - the median absolute deviation of the entries in the sample + * sum - the total of all sampled values from the column + * mean - the average of all entries in the sample + * variance - the variance of all entries in the sample + * stddev - the standard deviation of all entries in the sample + * skewness - the statistical skewness of all entries in the sample + * kurtosis - the statistical kurtosis of all entries in the sample + * num_zeros - the number of entries in this sample that have the value 0 + * num_negatives - the number of entries in this sample that have a value less than 0 + * histogram - contains histogram relevant information + * bin_counts - the number of entries within each bin + * bin_edges - the thresholds of each bin + * quantiles - the value at each percentile in the order they are listed based on the entries in the sample + * vocab - a list of the characters used within the entries in this sample + * avg_predictions - average of the data label prediction confidences across all data points sampled + * categories - a list of each distinct category within the sample if `categorial` = 'true' + * unique_count - the number of distinct entries in the sample + * unique_ratio - the proportion of the number of distinct entries in the sample to the total number of entries in the sample + * categorical_count - number of entries sampled for each category if `categorical` = 'true' + * gini_impurity - measure of how often a randomly chosen element from the set would be incorrectly labeled if it was randomly labeled according to the distribution of labels in the subset + * unalikeability - a value denoting how frequently entries differ from one another within the sample + * precision - a dict of statistics with respect to the number of digits in a number for each sample + * times - the duration of time it took to generate this sample's statistics in milliseconds + * format - list of possible datetime formats +* null_replication_metrics - statistics of data partitioned based on whether column value is null (index 1 of lists referenced by dict keys) or not (index 0) + * class_prior - a list containing probability of a column value being null and not null + * class_sum - a list containing sum of all other rows based on whether column value is null or not + * class_mean - a list containing mean of all other rows based on whether column value is null or not + +Unstructured Profile +~~~~~~~~~~~~~~~~~~~~ + +**global_stats**: + +* samples_used - number of input data samples used to generate this profile +* empty_line_count - the number of empty lines in the input data +* file_type - the file type of the input data (ex: .txt) +* encoding - file encoding of the input data file (ex: UTF-8) +* memory_size - size of the input data in MB +* times - duration of time it took to generate this profile in milliseconds + +**data_stats**: + +* data_label - labels and statistics on the labels of the input data + * entity_counts - the number of times a specific label or entity appears inside the input data + * word_level - the number of words counted within each label or entity + * true_char_level - the number of characters counted within each label or entity as determined by the model + * postprocess_char_level - the number of characters counted within each label or entity as determined by the postprocessor + * entity_percentages - the percentages of each label or entity within the input data + * word_level - the percentage of words in the input data that are contained within each label or entity + * true_char_level - the percentage of characters in the input data that are contained within each label or entity as determined by the model + * postprocess_char_level - the percentage of characters in the input data that are contained within each label or entity as determined by the postprocessor + * times - the duration of time it took for the data labeler to predict on the data +* statistics - statistics of the input data + * vocab - a list of each character in the input data + * vocab_count - the number of occurrences of each distinct character in the input data + * words - a list of each word in the input data + * word_count - the number of occurrences of each distinct word in the input data + * times - the duration of time it took to generate the vocab and words statistics in milliseconds + +Graph Profile +~~~~~~~~~~~~~~~~~~ + +* num_nodes - number of nodes in the graph +* num_edges - number of edges in the graph +* categorical_attributes - list of categorical edge attributes +* continuous_attributes - list of continuous edge attributes +* avg_node_degree - average degree of nodes in the graph +* global_max_component_size: size of the global max component + +**continuous_distribution**: + +* : name of N-th edge attribute in list of attributes + * name - name of distribution for attribute + * scale - negative log likelihood used to scale and compare distributions + * properties - list of statistical properties describing the distribution + * [shape (optional), loc, scale, mean, variance, skew, kurtosis] + +**categorical_distribution**: + +* : name of N-th edge attribute in list of attributes + * bin_counts: counts in each bin of the distribution histogram + * bin_edges: edges of each bin of the distribution histogram + +* times - duration of time it took to generate this profile in milliseconds + +Profile Options +=============== + +The data profiler accepts several options to toggle on and off +features. The 8 columns (int options, float options, datetime options, +text options, order options, category options, data labeler options) can be +enabled or disabled. By default, all options are toggled on. Below is an example +of how to alter these options. Options shared by structured and unstructured options +must be specified as structured or unstructured when setting (ie. datalabeler options). + + +.. code-block:: python + + import json + from dataprofiler import Data, Profiler, ProfilerOptions + + # Load and profile a CSV file + data = Data("your_file.csv") + profile_options = ProfilerOptions() + + #All of these are different examples of adjusting the profile options + + # Options can be toggled directly like this: + profile_options.structured_options.text.is_enabled = False + profile_options.structured_options.text.vocab.is_enabled = True + profile_options.structured_options.int.variance.is_enabled = True + profile_options.structured_options.data_labeler.data_labeler_dirpath = \ + "Wheres/My/Datalabeler" + profile_options.structured_options.data_labeler.is_enabled = False + + # A dictionary can be sent in to set the properties for all the options + profile_options.set({"structured_options.data_labeler.is_enabled": False, "min.is_enabled": False}) + + # Specific columns can be set/disabled/enabled in the same way + profile_options.structured_options.text.set({"max.is_enabled":True, + "variance.is_enabled": True}) + + # numeric stats can be turned off/on entirely + profile_options.set({"is_numeric_stats_enabled": False}) + profile_options.set({"int.is_numeric_stats_enabled": False}) + + profile = Profiler(data, options=profile_options) + + # Print the report using json to prettify. + report = profile.report(report_options={"output_format": "pretty"}) + print(json.dumps(report, indent=4)) + + +Below is an breakdown of all the options. + +* **ProfilerOptions** - The top-level options class that contains options for the Profiler class + + * **presets** - A pre-configured mapping of a string name to group of options: + + * **default is None** + + * **"complete"** + + .. code-block:: python + + options = ProfilerOptions(presets="complete") + + * **"data_types"** + + .. code-block:: python + + options = ProfilerOptions(presets="data_types") + + * **"numeric_stats_disabled"** + + .. code-block:: python + + options = ProfilerOptions(presets="numeric_stats_disabled") + + * **"lower_memory_sketching"** + + .. code-block:: python + + options = ProfilerOptions(presets="lower_memory_sketching") + + * **structured_options** - Options responsible for all structured data + + * **multiprocess** - Option to enable multiprocessing. If on, multiprocessing is toggled on if the dataset contains more than 750,000 rows or more than 20 columns. + Automatically selects the optimal number of pooling processes to utilize based on system constraints when toggled on. + + * is_enabled - (Boolean) Enables or disables multiprocessing + + * **sampling_ratio** - A percentage, as a decimal, ranging from greater than 0 to less than or equal to 1 indicating how much input data to sample. Default value set to 0.2. + + * **int** - Options for the integer columns + + * is_enabled - (Boolean) Enables or disables the integer operations + * min - Finds minimum value in a column + + * is_enabled - (Boolean) Enables or disables min + * max - Finds maximum value in a column + + * is_enabled - (Boolean) Enables or disables max + * mode - Finds mode(s) in a column + + * is_enabled - (Boolean) Enables or disables mode + * top_k_modes - (Int) Sets the number of modes to return if multiple exist. Default returns max 5 modes. + * median - Finds median value in a column + + * is_enabled - (Boolean) Enables or disables median + * sum - Finds sum of all values in a column + + * is_enabled - (Boolean) Enables or disables sum + + * variance - Finds variance of all values in a column + + * is_enabled - (Boolean) Enables or disables variance + * skewness - Finds skewness of all values in a column + + * is_enabled - (Boolean) Enables or disables skewness + * kurtosis - Finds kurtosis of all values in a column + + * is_enabled - (Boolean) Enables or disables kurtosis + * median_abs_deviation - Finds median absolute deviation of all values in a column + + * is_enabled - (Boolean) Enables or disables median absolute deviation + * num_zeros - Finds the count of zeros in a column + + * is_enabled - (Boolean) Enables or disables num_zeros + * num_negatives - Finds the count of negative numbers in a column + + * is_enabled - (Boolean) Enables or disables num_negatives + * bias_correction - Applies bias correction to variance, skewness, and kurtosis calculations + + * is_enabled - (Boolean) Enables or disables bias correction + * histogram_and_quantiles - Generates a histogram and quantiles + from the column values + + * bin_count_or_method - (String/List[String]) Designates preferred method for calculating histogram bins or the number of bins to use. + If left unspecified (None) the optimal method will be chosen by attempting all methods. + If multiple specified (list) the optimal method will be chosen by attempting the provided ones. + methods: 'auto', 'fd', 'doane', 'scott', 'rice', 'sturges', 'sqrt' + Note: 'auto' is used to choose optimally between 'fd' and 'sturges' + * num_quantiles - (Int) Number of quantiles to bin the data. + Default value is set to 1,000 quantiles. + * is_enabled - (Boolean) Enables or disables histogram and quantiles + * **float** - Options for the float columns + + * is_enabled - (Boolean) Enables or disables the float operations + * precision - Finds the precision (significant figures) within the column + + * is_enabled - (Boolean) Enables or disables precision + * sample_ratio - (Float) The ratio of 0 to 1 how much data (identified as floats) to utilize as samples in determining precision + + * min - Finds minimum value in a column + + * is_enabled - (Boolean) Enables or disables min + * max - Finds maximum value in a column + + * is_enabled - (Boolean) Enables or disables max + * mode - Finds mode(s) in a column + + * is_enabled - (Boolean) Enables or disables mode + * top_k_modes - (Int) Sets the number of modes to return if multiple exist. Default returns max 5 modes. + * median - Finds median value in a column + + * is_enabled - (Boolean) Enables or disables median + * sum - Finds sum of all values in a column + + * is_enabled - (Boolean) Enables or disables sum + * variance - Finds variance of all values in a column + + * is_enabled - (Boolean) Enables or disables variance + * skewness - Finds skewness of all values in a column + + * is_enabled - (Boolean) Enables or disables skewness + * kurtosis - Finds kurtosis of all values in a column + + * is_enabled - (Boolean) Enables or disables kurtosis + * median_abs_deviation - Finds median absolute deviation of all values in a column + + * is_enabled - (Boolean) Enables or disables median absolute deviation + * is_numeric_stats_enabled - (Boolean) enable or disable all numeric stats + * num_zeros - Finds the count of zeros in a column + + * is_enabled - (Boolean) Enables or disables num_zeros + * num_negatives - Finds the count of negative numbers in a column + + * is_enabled - (Boolean) Enables or disables num_negatives + * bias_correction - Applies bias correction to variance, skewness, and kurtosis calculations + + * is_enabled - (Boolean) Enables or disables bias correction + * histogram_and_quantiles - Generates a histogram and quantiles + from the column values + + * bin_count_or_method - (String/List[String]) Designates preferred method for calculating histogram bins or the number of bins to use. + If left unspecified (None) the optimal method will be chosen by attempting all methods. + If multiple specified (list) the optimal method will be chosen by attempting the provided ones. + methods: 'auto', 'fd', 'doane', 'scott', 'rice', 'sturges', 'sqrt' + Note: 'auto' is used to choose optimally between 'fd' and 'sturges' + * num_quantiles - (Int) Number of quantiles to bin the data. + Default value is set to 1,000 quantiles. + * is_enabled - (Boolean) Enables or disables histogram and quantiles + * **text** - Options for the text columns + + * is_enabled - (Boolean) Enables or disables the text operations + * vocab - Finds all the unique characters used in a column + + * is_enabled - (Boolean) Enables or disables vocab + * min - Finds minimum value in a column + + * is_enabled - (Boolean) Enables or disables min + * max - Finds maximum value in a column + + * is_enabled - (Boolean) Enables or disables max + * mode - Finds mode(s) in a column + + * is_enabled - (Boolean) Enables or disables mode + * top_k_modes - (Int) Sets the number of modes to return if multiple exist. Default returns max 5 modes. + * median - Finds median value in a column + + * is_enabled - (Boolean) Enables or disables median + * sum - Finds sum of all values in a column + + * is_enabled - (Boolean) Enables or disables sum + * variance - Finds variance of all values in a column + + * is_enabled - (Boolean) Enables or disables variance + * skewness - Finds skewness of all values in a column + + * is_enabled - (Boolean) Enables or disables skewness + * kurtosis - Finds kurtosis of all values in a column + + * is_enabled - (Boolean) Enables or disables kurtosis + * median_abs_deviation - Finds median absolute deviation of all values in a column + + * is_enabled - (Boolean) Enables or disables median absolute deviation + * bias_correction - Applies bias correction to variance, skewness, and kurtosis calculations + + * is_enabled - (Boolean) Enables or disables bias correction + * is_numeric_stats_enabled - (Boolean) enable or disable all numeric stats + * num_zeros - Finds the count of zeros in a column + + * is_enabled - (Boolean) Enables or disables num_zeros + * num_negatives - Finds the count of negative numbers in a column + + * is_enabled - (Boolean) Enables or disables num_negatives + * histogram_and_quantiles - Generates a histogram and quantiles + from the column values + + * bin_count_or_method - (String/List[String]) Designates preferred method for calculating histogram bins or the number of bins to use. + If left unspecified (None) the optimal method will be chosen by attempting all methods. + If multiple specified (list) the optimal method will be chosen by attempting the provided ones. + methods: 'auto', 'fd', 'doane', 'scott', 'rice', 'sturges', 'sqrt' + Note: 'auto' is used to choose optimally between 'fd' and 'sturges' + * num_quantiles - (Int) Number of quantiles to bin the data. + Default value is set to 1,000 quantiles. + * is_enabled - (Boolean) Enables or disables histogram and quantiles + * **datetime** - Options for the datetime columns + + * is_enabled - (Boolean) Enables or disables the datetime operations + * **order** - Options for the order columns + + * is_enabled - (Boolean) Enables or disables the order operations + * **category** - Options for the category columns + + * is_enabled - (Boolean) Enables or disables the category operations + * top_k_categories - (int) Number of categories to be displayed when reporting + * max_sample_size_to_check_stop_condition - (int) The maximum sample size before categorical stop conditions are checked + * stop_condition_unique_value_ratio - (float) The highest ratio of unique values to dataset size that is to be considered a categorical type + * cms - (Boolean) Enables or Disables the use of count min sketch / heavy hitters for approximate frequency counts + * cms_confidence - (float) Defines the number of hashes used in CMS, default 0.95 + * cms_relative_error - (float) Defines the number of buckets used in CMS, default 0.01 + * cms_max_num_heavy_hitters - (int) The value used to define the threshold for minimum frequency required by a category to be counted + * **data_labeler** - Options for the data labeler columns + + * is_enabled - (Boolean) Enables or disables the data labeler operations + * data_labeler_dirpath - (String) Directory path to data labeler + * data_labeler_object - (BaseDataLabeler) Datalabeler to replace + the default labeler + * max_sample_size - (Int) The max number of samples for the data + labeler + * **correlation** - Option set for correlation profiling + * is_enabled - (Boolean) Enables or disables performing correlation profiling + * columns - Columns considered to calculate correlation + * **row_statistics** - (Boolean) Option to enable/disable row statistics calculations + + * unique_count - (UniqueCountOptions) Option to enable/disable unique row count calculations + + * is_enabled - (Bool) Enables or disables options for unique row count + * hashing_method - (String) Property to specify row hashing method ("full" | "hll") + * hll - (HyperLogLogOptions) Options for alternative method of estimating unique row count (activated when `hll` is the selected hashing_method) + + * seed - (Int) Used to set HLL hashing function seed + * register_count - (Int) Number of registers is equal to 2^register_count + + * null_count - (Boolean) Option to enable/disable functionalities for row_has_null_ratio and row_is_null_ratio + * **chi2_homogeneity** - Options for the chi-squared test matrix + + * is_enabled - (Boolean) Enables or disables performing chi-squared tests for homogeneity between the categorical columns of the dataset. + * **null_replication_metrics** - Options for calculating null replication metrics + + * is_enabled - (Boolean) Enables or disables calculation of null replication metrics + * **unstructured_options** - Options responsible for all unstructured data + + * **text** - Options for the text profile + + * is_case_sensitive - (Boolean) Specify whether the profile is case sensitive + * stop_words - (List of Strings) List of stop words to be removed when profiling + * top_k_chars - (Int) Number of top characters to be retrieved when profiling + * top_k_words - (Int) Number of top words to be retrieved when profiling + * vocab - Options for vocab count + + * is_enabled - (Boolean) Enables or disables the vocab stats + * words - Options for word count + + * is_enabled - (Boolean) Enables or disables the word stats + * **data_labeler** - Options for the data labeler + + * is_enabled - (Boolean) Enables or disables the data labeler operations + * data_labeler_dirpath - (String) Directory path to data labeler + * data_labeler_object - (BaseDataLabeler) Datalabeler to replace + the default labeler + * max_sample_size - (Int) The max number of samples for the data + labeler + + + +Statistical Dependency on Order of Updates +========================================== + +Some profile features/statistics are dependent on the order in which the profiler +is updated with new data. + +Order Profile +~~~~~~~~~~~~~ + +The order profiler utilizes the last value in the previous data batch to ensure +the subsequent dataset is above/below/equal to that value when predicting +non-random order. + +For instance, a dataset to be predicted as ascending would require the following +batch data update to be ascending and its first value `>=` than that of the +previous batch of data. + +Ex. of ascending: + +.. code-block:: python + + batch_1 = [0, 1, 2] + batch_2 = [3, 4, 5] + +Ex. of random: + +.. code-block:: python + + batch_1 = [0, 1, 2] + batch_2 = [1, 2, 3] # notice how the first value is less than the last value in the previous batch + + +Reporting Structure +=================== + +For every profile, we can provide a report and customize it with a couple optional parameters: + +* output_format (string) + + * This will allow the user to decide the output format for report. + + * Options are one of [pretty, compact, serializable, flat]: + + * Pretty: floats are rounded to four decimal places, and lists are shortened. + * Compact: Similar to pretty, but removes detailed statistics such as runtimes, label probabilities, index locations of null types, etc. + * Serializable: Output is json serializable and not prettified + * Flat: Nested output is returned as a flattened dictionary +* num_quantile_groups (int) + + * You can sample your data as you like! With a minimum of one and a maximum of 1000, you can decide the number of quantile groups! + +.. code-block:: python + + report = profile.report(report_options={"output_format": "pretty"}) + report = profile.report(report_options={"output_format": "compact"}) + report = profile.report(report_options={"output_format": "serializable"}) + report = profile.report(report_options={"output_format": "flat"}) diff --git a/docs/0.10.5/html/_sources/profiler_example.nblink.txt b/docs/0.10.5/html/_sources/profiler_example.nblink.txt new file mode 100644 index 000000000..8b1612784 --- /dev/null +++ b/docs/0.10.5/html/_sources/profiler_example.nblink.txt @@ -0,0 +1,3 @@ +{ + "path": "../../feature_branch/examples/structured_profilers.ipynb" +} \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/regex_labeler_from_scratch.nblink.txt b/docs/0.10.5/html/_sources/regex_labeler_from_scratch.nblink.txt new file mode 100644 index 000000000..a0d3fe033 --- /dev/null +++ b/docs/0.10.5/html/_sources/regex_labeler_from_scratch.nblink.txt @@ -0,0 +1,3 @@ +{ + "path": "../../feature_branch/examples/regex_labeler_from_scratch/DataLabeler_from_scratch.ipynb" +} \ No newline at end of file diff --git a/docs/0.10.5/html/_sources/roadmap.rst.txt b/docs/0.10.5/html/_sources/roadmap.rst.txt new file mode 100644 index 000000000..93886690b --- /dev/null +++ b/docs/0.10.5/html/_sources/roadmap.rst.txt @@ -0,0 +1,58 @@ +.. _roadmap: + +Roadmap +******* + +For more detailed tasks, checkout the repo's github issues page here: +`Github Issues `_. + + +Data Reader Updates +=================== +- Read data from S3 bucket + - All in the current `dp.Data()` API paradigm, we want to enable passing an S3 bucket file path to read in data from AWS s3. +- Pass list of data file paths to data reader +- Pass in linst of data frames to data reader + +New Model +========= +- Transformer model from sensitive data detection + +Historical Profiles +=================== +- Some questions about Historical Profiles / need to step back and rething design to start: + - Meta profile on top? + - Stored windowed info inside? Etc... +- Branch with current state of Historical Profiles +- Two example notebooks of current state: + - Notebook example `one `_. + - Notebook example `two `_. + + +Conditional Report Metric +========================= +- Based on what is populated on other metrics in the report, have "secondary" / "derivatives" of that number (or that number in conjunction with another number) populate in thie report as well. +- For example, if null_count is not None, then populate a null_percent key with a value of the dividence of (null_count / sample_count). + +Space / Time Testing +==================== +- Automatic comparison testing for space and time analysis on PR’s + - Standardize a report for space time analysis for future comparisons (create baseline numbers) + - Include those in integration tests that will automatically run on code when it is changed in PRs +- Could be an optional test, if the user thinks there is concern around the change driving an issue in the library performance + +Testing Suite Upgrades +====================== +- Add mocking to unit tests where mocking is not utilized +- Integration testing separated out from the unit testing suite. Determine how to only run remotely during PRs +- Backward compatibility testing along with informative warnings and errors when a user is utilizing incompatible versions of the library and saved profile object + +Historical Versions +=================== +- Legacy version upgrades to enable patches to prior versions of the Data Profiler + +Miscellaneous +============== +- Refact/or Pandas to Polars DataFrames +- Spearman correlation calculation +- Workflow Profiles diff --git a/docs/0.10.5/html/_sources/unstructured_profiler_example.nblink.txt b/docs/0.10.5/html/_sources/unstructured_profiler_example.nblink.txt new file mode 100644 index 000000000..1589c41d4 --- /dev/null +++ b/docs/0.10.5/html/_sources/unstructured_profiler_example.nblink.txt @@ -0,0 +1,3 @@ +{ + "path": "../../feature_branch/examples/unstructured_profilers.ipynb" +} \ No newline at end of file diff --git a/docs/0.10.5/html/_static/DataProfilerLogoLightTheme.png b/docs/0.10.5/html/_static/DataProfilerLogoLightTheme.png new file mode 100644 index 0000000000000000000000000000000000000000..35e59c3497b6cd5ef9248b9e075b3af25a7779e8 GIT binary patch literal 118089 zcmeFYby!r<_dYtLgtUaxEjb7x-6b8;HA;wdcMKs?(%s!H-5>(eCEeX2T{CkB_4ECH zf4_V0zxTP%b1yQ_9M0MM?6db?>s{}=)-gmyNd^n!1qJ{Bz><9{sRjTb-T(kdsA#D0 zGeN_r!T`WiBXbD}6h$uJBC>M5WPK z{CyR~)Wz}NlDuL-CgjmAdA~#xN>Cp9Qn%dqmtU|mQI9owkDpvVQE8*ftupGTBasZ4 zXNKcw>WP=Y&Z4I<;DY~_QwO00M>M2#2L}MvVXZ~=dT0|A)UWbV4Gkd5Nj*Zuj2wvD0Ps!3Fgc?E1g}Ne3Y5Ps_-+&& zzR4jPY*uVnfeO@Gv%*@gNRU<96kkLJB=_zNIwFi&2Y6{#QxVUPdm~r3sK1Ox%rZl^ zuM!<17EgQnJNWx|CT2k#BgU7&05{?vhlfC`ZRoJiRg|}|h%1`qnHm9~eohqOso6tj z{_Tpob{5&i8sLc{YowC;7LKJG7g+8q#w68o^vAxQQVXo#dLb(BTmdR2+RxK-qGg6r zFxbl|--{ozZwB>=T4CGg)l#u*4vvmQOP*1EX+cS6XIiJXbS4gYh9|3=O1k+Df8&XL zMB3o^{`C2lMF;ck8&e+)8B17!_7BopSczm>8tN-Tz*k*X+3)~uVk259AGNR2s5MM@ zjvJ_^n*)*>4=%VhQWHfS;ohuVG8D;0@ri`YsOLQcKkyCHh_nbpVsp7KyIe4D_HPua zY;a}ym;ziRLw{EXG@(hY;iW8AyF|a1N(H(oYd%XTnmURnr2DjG|E-8huBX9oRzWo_ zZ>mRzxNEq$IDf~=>qG0sE2P6)CW z)srSs68n>= z0KhC$x)ap4#jALmZ=q`j0An^^iMlIgiYE?6b!1yv1_{eqbg%qLl)f@ZIrZhUUn-Ih&>O@SzMFUqb(+Q95O-O=y(G5}~%5ue-mPGx{Y?q$!OrJ@0`K_)dz zNvMwwrDEBfgvJ(jxz|zVy;ORjUBs;}zTRi@A4`8TUhac4)p?#z;s=BHr6QovwFcGHyda?`^&c-;?z< zK-wI$%0L*mp#CLQXM-PwplU%U{wyM6QZ(Z!iXYW8N#9pg6m$Vj9O%&Q&T&A_DiDC z3>I1sb)&JOBMA{Tik74!?-zH#W6F{INR1hVVM70nVlMO-jR;jxG{H}uJfx<;MVaR4 zj;QOGUnW#&e<3=H%4A!`1@vb1?@GQVP7h7U!W_^4M5r5ZEJiv;u?e_eWA*a)*a;3jHTh9+7;wjz&8O)x~6nI=AZI{GRqB9=Y2`K@g~ zzX{7XM!uLdv4j};{`k$MP2gD)4DhU3EG*yTi~eD~jC z#AvJ0knad+v zDOss@lC><=M&TXW9w4lhSt%mZp$n^mVnKwFzW4=+wTfkT;Rh_Cnqg(Uhl=f-h z7fh^%=NYfPes+@7KV_Hb)b5-e;qBSwq9;;fJscw(<5fM~`#}a2SG^{UvPB_3^A=4q`?+JU3s@)7 zCcP#J3&IOrhwZqCYwSNx4!ucE=RA0B^IFiZ@x9yaDN;9>TV~i`h+x<(#g?n%{j%8y zb39Y(8f`QCiJZO|^XC@HW=->FNu~{i-ORIcMs@T1jZ-JA#za9Hoh3$f)gI-;<+|_zBYIMs7z)(}7J{?859ui57`r6-A|$ zr9Yf=E&I^Eqrvbd@VIGh8pjuTZF+2+ZLVcFWqKo6$>(^_ZeO;jKF`(s$}hAZ+Y;&N zckgn&K=FmbSWr$VMF@K4^!u5crl;X$j;EBz@TJ9>$J)_8+u8D__hir-*Yu8Fre$8us=8nrVpcqo*;T5g(6}jKRn+hN}_BOINkfy zH=Z-TAS3eh8~XYaYpngJA5qLuY|)ROR%5RP{rW73R)oR89Vk_0)%Ia-n{t2(F1 zt-6LMBpt76`f7W|jAD$Y`vilXL*o11L`wBVJa4f$Oy|AlHP<&54BqLf4DCo=P2%8Q zE42S%kG@gTC!}=oHZ9(bKP37!pSkPA!DiK_X@A4JG_^RU@?wwTg%9Wr&{M*t(w9Y>#f{-9VFi&(n7<^8l(K`rgXXs2FxG%U`~n*` zo>r(QoqoSZe^~2o>#)1+*~Yo+HqNs=!b281;*W$B2`}W%^R3^p7Aj;;P&>xQ_wyH` zDj0CpX;ILwWQ#r{AXJo+K0Wgh+sk{9cJJVAY;3+cs{LjDq>xl0QK^HY+q8H6xw0IM ze0yfd=(8cKbW)K+4yXv{iaN)>kCQQEAb8lcm3v+_# zHLzBj*LJPjHmALqWs)s6ap~sG>B4Z>sZ@;AQCJ&MrQSoazP3-r_qLpG>)rTWF^((l zURsw+ofB#KM}uC8*1Agi>;^vGQa?itSg_*Pe10`ZEPuKr|$FUSyjwF_=K4Z4wtLy zky?;hFgM^e5ZZdS3OV2Joy@Jw9CIwFR&Q)5?Tw5WgtW|CKrAd>Q%?*vgQl4dny*cc zn`(KyY~Qu%L8iTjyb15Se72w~;GcJEcYaAoT*o@Wiuy&3`mdqT}Ylp=hb0Z7pY| zr$8Q>m?9wUO4dT=aQh?vltl!zWgrA*JJ#*Hj62}5HCf(mWoo^>(CjKF?jVBAgFTnY zzo(zI+_|!xB(Id-4&OF-r?;oeoCK|OoKo#|9R>LZjZ!dCc<<`oBtaX`LZ)Kp3p11> zon%}q;f95=?@j)glS(C2qMfy=+!41k+JRH*LR#KqQ#)^erpJ^tNs z8@tyMtl*)1Z^7VX_C%>e*%Ouro_{hCR1!HtnJUub)y$>B%R#jTEa&DFJ?v=tTjjcu*jKbY7WnX>M=07*teLf(|Ah`PC$)|8PJumAnZ|7A~||Iw4@_5bYoKd$_bo{v-DS9UOmKj(+XH57g&2>d^t``_EE znL659IX^bnurYTM=KR;?e>?rJmmu(QTmHv3{k4HVXW>R5j3Eg8FM|@sSW)hQ+qWn{ zR#Hse4dJj2GfQ8?`$S|XIyMUTEiR%z-5N8=n2}o?Gu7;Zg;-YG^-2Me$AVt#C#-o3 zTPEvT$jkzC%WzfGnk|wUS{JI$G^(i{rG==i{%hJ&O2HrH849zwuc)Ef@k!IP?MX79 z*~bxukqo|-^t3j^j=E{X%(knO>jlfJ!{VtbKLDEV|Nr~{)fIS3?iZa+s!I7py>ccw zkt_CQrv0ieTIg!l*u==l$i&M_AKKg7EA4X@oB7q@CWpAKsNQriL3LjG!S?f;2-~G* zjWfRCg?j4+4D(^~=X2G@eMNn2WcjU0^n17GJAF0q`CQM99Vz2 zlO>!B8L&s1CuT?S*nBi`a8SEDeI1n6XUZzMfaZwqpcXxurhGKRoA=620Dp&{0r)L# zo3pfg{MQqNO)nv0_$0^&FD%l$D zkc9kFyf2pJvp=t436L>^?X^in5c;j~_EBkpWWX&v|Mv;3#9l%&n}^u%j6^U6MmTUum)gmFwIn4d!FoX_G@ z_xal|rU!YB`64#mgN^JBU0bZgXU4kgi$H7k!JODU@O~b+(e@V8+OBCcSwH5|t8&n} zv3=)UY@%8&#YIi}n}d}g>cox%HgDuXG+R`)J1J}TWvie2`L?1k?BU$`n?Q_AGx)4& zC!^HyC+ARN@95GrF}ptR?Pjd<^!1{n@`qmi1a<>{S#O0i-UizhLy`4h+C0!PFpXHw z2nhj~L>+Ms18X1c&TcV}^1AtY*%NdXZtJzt7)0rFL)i+sB>W$Znl)r{pI8fxYkI!1#u}?Olkhx8H`32{zdH!D}oI=HDF$KIcNM|E_(eha`e{Pm$-$S3M?;togh`t_xg)9m{E|Fi2mZ6y2u!U~hj@%_@-X>Ev({56e zJG-!_@*Wqb4LFeV;8J{fBkoBvYJCT4Wcq0x*t`oGkz#qnx6UAq*bkIuS^S9o#*qAsIG6IPR~LFPw%DsFStz`2H|BV|zc7G7~~wA)*hiupOYjP;R*kvf7^x1Ge8J{_Neh^_~n2`LmvP za=vjRKUZLo71$zt?;F%)y0Rm`7{N8}C2mIyuyfP9R&T?Z6-M9;a+RF&<>W(Lmb)X2WUv(e#Kg*uU1#Stu40F$r&1nTh z^ojwHMSamv9j_{3fioca@meFGy}gGXuh%=KdX>?I@%rIUar>d`ESsi$Jhc=B#;iZ@ z?e&78VLYEgG`3TCC-|O#Q+Pt~Mze?dchZAG^u#F6f%YHB{SRk=D4l#Z512<1 zn@YgTr(bxyE<9K6ml2Kp{!G(DdG*^MyC;1c(hZ6QoR79oP`Qh#CKB3wMU7&%%xc(Rx^~-m#no&&U(B8Q&FqNo-ihN$h6+Bsd2i&}8bhT;B=o7v&0v0#_$= zI#Cg+#>o9jE89H|O@W?sg>$oexm=TFr-AWC`>)D&cL>S)fqa)zI;F%u&yXPjBHNT8 ziALxEw)-z~pN)4z=a!5IxyAE#eZtU}co&geKORyojt`G-uO|}QFQ)I0TWl$YUH>kZ zFoGdDFC1TOa$elMdM&VZQHZKS?()j3OGmj^HO(_#_OdPAjsSP-mOJnj+vNj8*PS$M z1nt4y=RFh;Ngw=ynws~w*eG40g0^YfvrDXt$b*ERW9wrb{iyqC#Su`U_2BLkdcAPh z?O3rtvqDAiX+LS)h`3)!0J&{VU2bZd1js59lVL0M#dFBEOtPDf7sbu5)#pUld*r-_ zub?qB*;udH2A|kAF;3)- zW*=MT!jERVkusrEV#XKew)?k_b`7!=LWEGxUC6^?hTBt!w~K&}_x7gYICUN0Nq1d- zP6@l|yOpnVH?Hea1~@7$o5$72SXoj#5A1KrGscHU>{6#;Ve2iq8h0MxKvsV4b6$D_6X8khF({VEaL3o4Iz?cR?M(>XmPHqdP+f@w;Ql zt%@2*FLCBhH+BUdUqnqjweMG>^NyR*P{l*XaJe2DRct|7@)1`X#jsRD- zP-;sIL&_QBBJw@cDBuADZa<3WBQ4j*p%)(@KjU>pfCN zEGm*1_&A^Tv}*3n67{?j8i_Q&z=0-#UC5Ojt=H}bJ@Vq0e|zm_mKEl<2SUkp@6WSw zymy@)mnyq%#Ik0P*I%esE*#5yIu(jEoAk$=2tzI=f#Kw*qO;7W7_Sx(d|;;KBX=s_ zcy$-c#4BcMc}+|7SZfBt+f z`71jO+zh#BIP7f4-5-AUjW)vldUQ**re(>((m<0PeGhlag)Nu5LuLK~S67{S&O!EV z(5LL6FAw5OcedhLD4a2@iJzTd)7d!RM-y!Wx?C2N}tQYCc;PO_$Z#`RX3bh-afMh zoK_mjbaUyuB0sO=686&N0ip(ORMGT@{q|Rp_)c%lJwGV4Fqt1g8Y;`a-Q#AFWB!AF zyrb-k0Bzs8d7&?%5=Qkon#Jp8N6(tz_pv*a|{5D5=3RjX4X_YH29JqyL7?rhjk=HSD0zg-Pwso<^nV9Lvz&_j5= z8yv*jZ^maBj$^vlo9#?-2dqYa;GBt3*wjUU?qqnflSajNyM@13fcK>uvqWr7>9Fpr zKZgfmk@8W}%tUgC@E$DEYm*jMJ!35D32#NnVD}KhxGWb`$g*>l^p$_HK8AguS8Gbh zYTN1!Q;pV5NUW}=F4NKFOG#MH=96$(v-3g57GW`lvLo4xKP)>2us5>N?si~(*_Oz< zR|*w@-fVOj$^v*_!q;(`APWdMlByh4%g5LHEdTqA*+Gtx(SY1%*i2^07O?1kT|3Bq zl|0XSshEqMiS6cX3A`jYABP>Ui*WL*b?oMZQP3jQ)n3;Su=&F?1D%UhqWl-8a0xV8 z0hh)Shp)o<15Fo_CdlVIqNB&}Xd?x`jV@A!s`_`5F`h!NJ79@uV)9b!Ec?veN=*Wz zrcaj6a=&Lcve4kvY$V@H!jh%dH+O#6w3qw@dwI1g*$%izJ)NZC7yc6*;ow0f+I$hE z?6n@-PjTH1^*Ifo)aMG2kko)rO^o{Vj;9r>ir^`DWHW^4mh_h2F}Y zW_9_nlXs2ai+6iiuH{E3q=v9Bo~0vzz9(>sErFQ#mVt;}U)ydr_Ut8JN_d2as$ZVR zw$(&-V4qVc528NNR%-7!cx}5_?!kS;3woZ}k-m+y{F9^G5_js)KnlKwTo2eDX5RG( zrk=aDDK!tDB#PO}XH;a)Z}F(+53g+oglMtgV?9IOHE0c*5OvC@VnT9UH1N}&EfUp_ z*q1l(aW2>tyn5Db}o+Xh(S+pw3z&ipfO~GHW)7k%-0fa%c^oCfKvJ3TE8kTx=a=n)84Yzj=YVG;4+Op3-jHKlj(~F z6iq5)dycr8El9Y256k{plY0X8a(sW}o;1JX)xz{iBjLOagcAnwNToUPPMjZsi%I(D zwld;yz1RxEksuuz?Bkb&PXQSV$SqT_d*@wa(Mw;Z1@eEq%1eh%I+FPzE* zLvJ&Wt_3CUA2AMqSdQ+sCl6v~`(bLJSXb~eRTnl{IlG~eTwa}vjEtHH;JbN9>1K+P zU=L%tD2^z*hW>5gGGy)=(3e|hcQ9{BX-oXzVGx2Z3v_6Gyq?^pT zH#BFbqXufNjz6rw!GhIU&e(w00*MWElUU#W zP5TaE_&uR~$e7=YInF4CvO6JaRf1XKDh>Q28J+r)B@FcmA796DZP3`D z;L`}<4=gf-YQA zq_WxBu+5w67}$>=l8=d$b47>a+mAS;e-iPcJ!n>otxdqYOwCiAidhwVUMda_WM&90 zeyxLidrs5X=Qtzt+!;E#l)6x>%V(3O-dERi9f?-u{hk#&sdq{4Qxyei9 z1k#k+a=?8vT+lEgwz4I+jd0g;o%7PZFBd@>% z!_ad>WpQPdH-zri7b_sBd;)8+H*{MMx)%3N=~l<#*!6}_0_~3psIVb6uYR14RxE)1 z{^0NiBC8p61h0{hA>f_^k zxl78V9j{6=*y`UF>})Y5=gEbB;Z|m*ZTg~d|J?!1o_I2x1AF_%n=|JkBpwW+mUHfh zZ3UH=l&@4lmx3rfc5gQq^;nh(#2>c@;AesV9@Db7Ngk4EgIgw?>f7Hh3uPmFv`GWp zqS^o$oR@^}OMym5JMOu>3gmxb{rb$CY8tc{hh0ZyjYb<&z5iv1JCvdBtL6!xUg(&J zF)_RMI{2` zk

4M?Fr@J1jz#c8R+E%~5V{F_a-uh5ZT5k9|oV4IojXf)=lPPnRhKo2u?POKj9Y zHn__u!pDdk30f(%N9VH*O}t*P?TDN;m-vIDR2)>u``ixnv!bEVhv|^~8Cqi$u;?}b zyT${V`Dhg$vzNa;i+Zq%$ot&9z?3^jKu#B{TY(Bc?Q(&sW6YhrK@JSi zt@Avc{WjC*Zm%xYw)s|s-LUnhd7@tw|8b{8-viKILz?4~bZZC<=0P5kPe9+uea|B$ z$`~H);p}PqOZ0OV_omqi^g;YD#1}%goRMLa412f zq$TRZsNng~yz`8K>kviQbt7$E5ZWLA?G(j}S_w>~JuZjPQv$G|qQl5!R`HMCw9@Qc zNxN2b!ixC9tjEQ7HPD3tD#Hv^Y z;{Z(8MF*+L3Nx@Cyk@$sf=@Q+k-N{#sZkKqAFWLpJ4?vjm{?GRW@GeBHo^R}xF{vw zM@WD8(rZk+A`M!Vy`6>4=U&v?6?}nA14<3_;_7E~dIooN$KMty`p>xnj@#vl z7hhnu08a?>#|WMkeA<02Io`p=d`6i)YQzpp?Qq{^+etf@b2!d)-u};oQbnQI`i>A# zRUP>(=o_J%;`V!GEHVfye$fSna2rF7otJxHdPp?QD>Fgqa>;=u;vK;`?P@!^1FGRj z&x&6vswiV%boJDSJ-++-LJ`OwOkxDW%zGV8z5a+V95=`hH7*n(DWm@Kl}Lx*p%a#z zENy6fH)hzhBp(q`o-|t^(VImj`dQadW~@IwudRD~{c!R2>V|vNvOtB*6BzrMNQWno zp_QAs(C0EtG7g@GNzEDeW_d*Hl1Ie8F4L*mCgD#9<~jQPGcgt1qA*1#9|C;Syg|7QY!t!<5lqu*sByl_E|G-p9a_U?M& z<>dKXo=WnsiIQR(!&vi|xW1yqkFILF(ryp|G(0DBZHwx)giD{k{1U+!W?3xl_Sd4x z(@880{oB%P>y(@Y`|2hd+RV1QAnlioUwG66R(+8y8dmK47?lKn{{YeK_-K6zB>C%0 z9C)kBcDYb9(s|7Lu!h~IldN6ZEAY>8d^T#YTqT77Fb zLtb$!@9DTWw=K|AUeYt}%{W-*0baLJ)$4#pTvOJ0T-ruEDq9LXN&)!qmw3_o1S>&L zGw|=H(5exVua>TlcHUv!hb`2;>;6vA+jyl`j(J4)i~3XB1Uy8~<{z^T#?KV7wCj=E zp}2#xQKgNobqBI15v7)fyGdtxrF2$m64S5}jZzEJH&$+=AA-vHBh&7`e{%ovpCQA1 zUwUx43Vt)3>+m4&FcHw_Ldl&=e_Y1cfVa#Nb*L;)J@LQ91)1Z6JQ|$jUDcRtCe}_4 zEex!~)=NSfowwNidh6W7a$)ATl%5x_Y8^VD)`N+_4!}s8664_?{y2+X6@M56$;a{i zO~3FVQ;-C-f~I~)sJ_1%`($L97iCYru1xmFt3>jyah0nwb3p-_m{#Ka`hibUqWQI? zp}F9-#3b%D@PsVm6m*Re`T@(k`YMG}E$=T(d`SW%%T}id)py*)9N~^We_DQmT+;5Z zED|Y6>Yi{XrL9T5f7n15Tl+OMR1i~MLYGB`yTG%!2=UttMgCKWa{r(7$CB6iu*j1g zVFgObKhIo&YnMB3d@s=C$f$X`GeGv8*HbBL0vkG#E+DgXbTu}Oj)*qH+B`Ob0@Wll zR13EMeJ0zwsHwD5FBz(N+&0v$t%pN1Gv4PD>RmvThY&;l4f+SA%_{DPsxJa}7rJG| z;LP?h8erq?20=)lla^k*Lv`G}Fe*ZN3m>UnI7dQ#IB2B8iApgt%*|&hqkojo)HSWu z3a-;y&pUoemB}XGDPY|3bQ00sSk6?WKg{+CyUgZO35TA`P2Z-^yMMb)P!Vg>bvzkPt7XXV9M@3sXj&(4zAz->JC z1YR;R6#p&5rSaphM{Ls|)W;YB-5D9w)I!B4lI30|PeZ?VjV|IM`6;2R-`&=i>ovqI z2k%qijAmy1KFfRmE%@$0KOMs~A2j`YD*qZ(ymeRo#JbOc4o}{3!?7AxU0prDl?a0V z>8K$ML@Q>}H{1nW-#XkR3;mcmMYF6C;|;sOS94~hk&$syN%_s``4V1)FxdO zsMFQ*7c=2aD-gvd^}lVIPP*E`n&X#>BRzvAvK#2OY$fOkyACiFwkD+AAB~Vu|3O9o z8V5o{6q(lfThGzWF{_V-SBVsuJs83gJ*a<4p>l_j*|FnUQGa%1E?v+$(|A>~lNwFQJOExb~S~gbEJ71)u-IF97W&LPHCMoDJ|0 zXc!y91iv-GBLkouji-QDu|KY~aO^fi22hD>VpOlwwQh72SO`ncVsB8KfB4fR8-V)< zSn$~2&%Gk4hia8+tG2)s;jlA}QY{z*oI~4}1qb|n>&BNL=`a>fma-;*h`)c+BKtAp zKaK)Aq{B&rrkYVK*-ta3DJgmSl!x1-DbjXZ&iywO7KIZV?zrF+{$wMFgiKjeF;ZWaBAdQBY{x}~I zVPT~{Ep@VW$4TB>t#gME{(JMSbj*jyWIOuvNyy9rR{ZrgJEFH+nW$fob`czPD9 zuE0Z&{JHgfqz(?eFxcwiK~pcqA8g6uMli7BI{3*j32VeKo6I!Xli5#W+1on=&QS>l z0Bfs|{6^3p)m1~o&r6_1fNLJLw(M?#aT?Lqhp=JU<+FZL971yq5OP_(5to?Kpw8<$ z;#72*?=jtDFj>ZQ^_HV)y_H%R^d3}^+xK@!0CE8XT;<5LY0k?er(np5y?258>H3`K zNt=w6JqK;X>$!;%p~U2`toSN|eA_Q-yp3u5R}$a0B8(}c=gm={z-lLzHX62CefneQ zwRrHwvHw|FEsZGZgp~>K2&j3g_gh*RO+on)kPSVLOrf538?ihU0rI1R?>J@SpJ7>M zs7pJn*?ZHPgnI~KZvA#-!l(vidBWtePZW=Z} zOC0g6kH;~p-mdFvWnspvUQya^O@(Bbx;nDzvf2-sqnKcqQP~-QEc23}aup@AC+)tDQS(FOzC$`f- ziPC2>WgU#STD&r9;!8(yG}|1Dzl*R5}oJC?jS5P_k>48&rtEXz6*Jvkjf~u ztpwi%)bDH-C~mr*CSSWb;)tM8MMbctJ=EYLrKEWyfAmxv_At1T2=ck5-AQvCVF^Cr z>hYsR`J>PQi0ODF)yf@nIad?Vb-eVE5u`jZsy|NoWWcBHa4J%h*zoN2LYjx`ag!wZ zDPBqEgj%l3u)fFOq#i&X*%su;8sPt77Yu#4ty6}-J9b_9NMYfu+)Vc$0}_4DfNYf> zma+?1Ndke_tD~DgvX0XjRBmOQW_vV&>Eg1R=cWheOd>=r%9Q7D9kZTbGrjKuvL*L#tFzL7qk9Wt?KN_2~)PS2^PZ+)^NOO5;( zx!@YC&N8v}iAXUvlw>S(i-7$7i)`F6na^S(jU!_?*oD2Z2TcdZksI0pNb|6XeEB`{ zYaZ}1JcS_?0terB??jpY;}^=lM`iQ#%kv>7|-CoO$98 zHJukjl!PcjhQGdkdf~EnzFpD0sUlXbzLjTQAqg%iYi%z?t%MEL8ReZn}BvLGNR+>N8-}oe`MSrQV`6(Jb7u8QEzzLJcHsr zgF=xoLSs$=zL8$Eo06QMn2FNOws<9^4XMW6l z9+Hn%qe=|Ag4!tJf72BIY+6j?oHNy?xZnM`bRPDqkIbOub~|-+$#umWxS{$U>5ssK zFB4wYXwdx!a6d}X1&zsyTh0gET?D@pkl>-7+0Mdx%=0I~guo^!YK2CPH&3%{!63yjY8dC6|TN)kR`uynh)c2zBS1 zI_0a%ePKDUZ;r;lQTF*tI~2OP`*a*9PjAz&-8Xofu43|Un||p-%>Eq1&(Ux*)m(Uu;A&lruj&$|HS%>*#AfrMn*;!NSv5Ra*j1_64Rp) z+S_P)6e;CDQ#ECKbOt|9A&Z;bl07>{(U#*({cv#!uGrjqw#J-M?;^AZsjA%$j9{wF zgk-vJC)XWRc0kRD4x3iPd}{xxWznn^;lsVl@88EOQ9H|r7ALtIAGvyCk`o!OZTCNuROW_HO zEdl}p5EBl$`5*2IPr@_8*`@clj`%CpyZ&d^0i6nup(;CaXZPl39nok;`}YlO?+Lo& zbjz2X=aYnA6W__@JgB$z>oz02|2bpxGWR-V#WC5wdyeR@CKvv$H8b|)|1KdY<7vbdVr*J)M z$-PgXjqM(BML2XhpcQ<;RZ3uO-e7(S|BrBQB<6H!r{hrT7E@|O&%HWQ?=yK`skWRA zu$+M4FG;=HTogG8^7{*u@G5+msK{ZZaDjjxt#}6&$1F0lx2pp7VbUr$&;ZGyW^Qsi zo&P#!o9z78++Mvy@refA2e>}zsZ(tdTg6w>b!55_C%o)cm$P9n6YseH2gf!yoP5`% zYm4V|-%kl|bz_}*5`+5>411h*gB>0{8xph(x;e2d3f5zF%64-L9Df43G2m&-{u5~$Q;{ii|y;By7 zj$6KZ4Uqh|`R|F)t568x)caL*%mi(WlW?QT#23i$B`zEgcE3I*E?;2mg%@F;tqzQi zw}fTT*VgA1s|K3^>P-66`D5_edxr#}lncr6u{c`fRm(wU!iPKXIQ8 zw;?!By4!-fu#PsbhNgg;6ZKw{`?3lBSEaCc7Om-NTWwhO6r2~M!g;X|$$z;b2J)RL z?38|iIn98qJL@t2X12fIz~*T=*vy@Qbh+mUub=c@Yus%9vZS{^oT^N8q#Nyb{JIcL zhOH>%E~37wT51y0(g4#a)ts8H1i_ZOu>}s(Hy7{M=Bue5Gs}<3N83Wmzr09v3#~D58|mEwJnf`_`Xd}lX!nH+LoB(I;q9lohYAMR=H#nE@J&q%Kr3l}Pf5m06R zy}CMqS#W!CN!Kb+wcH<bpl?jWt3 zI))QPoc`7G0Nyn9=MnjRK6GI&Eyb{!5&jw%$mL9jN0&cJ!>Rp$MXD0GGEqoq?1RU6 z+P>d@qRx+0Wk<#-##QmDJGY^iO~gBz(r3fUI7@bZuveZHCTx3^NA?AwCP6E@VFq#u zTQy#k_wa=A0)xn9ajB-Ff`XS0Hum2X9=s9`K(u;uZw#*X7XcJf25GAz#=D%};*p;Z zPsuWZ1R57m^3qONPW1aukR>y;uHQ-NP7x!NQxHMfB#>54BA_$nde;y1iH6NF$7U3# zKL4Slom9BHsgNGv9QOCUzE_%Yj}GR611)-q{Us4zSLv^{z%|)y@{AdcX!p42ssz4{ zIitt71zfyC+-t^xL{6mlO2Mmlzfg$vtJ2c$WiXxuBL5>-PmvKgqdwAlnuDJh?ef0G zEqdwqJCq`kjHrBdVL+(m_nJ(Re+^sdRf3Wly;OIKj4g6))`uxW8@A1m4Xs;jL9vb<`2#x$eSdN3v4C3@{+eaaC60LLm#8#Qruuf%9 z>gTke3L;{SGJJMKoHd)%(Zpx7_5$ljo-`#r9f zgHH{mQnQ4Y^}Kw6`@su4^eqP}@%pohrVz)qkG`7*SmrJIS}pR{+spX|@u@m6Ok(zu zB|8Wf$gpNxD>83QC=(kS@1F;dh$1>0emV*GvmvV{ozz-i9*4-G6LveR;fujPPSE?} zaUxYk7o!hxs-#M$>!V-(qQ#QWCp%oo4!_QB`P}-V<2r^OUORz)ABGp;_Cq!oZLbag zYrC`XNuFo-nGcdC|1>dfsqNTYjf_u~dI6VLLXQU3kDegoG&IU!EjCj7GMt0gGYfb> zQ_pUTA?4+;9G%v(skQ()8&eOB`BOv@3V>dN>c4{1uTCDbzC06+E(PuX>X86H1O^VH zOrM&qXL@ri_X3>?cDq#YNCHP!0wDU4jE~uJ>vhIzY4HTivc+k|;JqFp z`%Bb1$8f0@NQRBMVvDy7*J*L~o`thDk->|2f3*i=&}>F)HD-ng>V?@Y-Qa6+>a0k# z03W;bE=n?wR>C~}Q3F?SSz!w_l5aa{{tk=O=b9eq-Vb{#VLruo_BZb;`W}E@Wvy{P z53kA%!^Qsd&Ub+l84}1PKEE5ytP4M@2ZM={GH!EoR>#6p@DzHm@pO&VRi6K!u>jN$IZcD0^2=qn&(!S&>#QnJjMID;%7|Szrmub4PuUs zcC`WrMG{LRBen#HPLV%+|Gh=%A}yi&Io*C){8vm2lgAe>FM=L%bml0|%9AZJ2QdjL z!cPq_o(vb=qp*fWhkfDuL&x~(AOA^Je2Mi1PmkojJJ+$>a~@loTk*%?NW0)*#@)s7 zlLHCXo{=XY90nE6mhvd;K^&J3{M&nLc0m5pDSedfc-)&2t|;YFDkOcgkIzZRzx%Tjyf9;b;`?tG$C zfgT%YbZtTmxqj|@G-mdC5^pUSq>|cNZsPWC)x$02tZl`W2+&n@durd8Kt~Pk>-!_Y z4;wNH3JQxXQ`P^`86Ox$PreW=yxefoGY@bPury7{YukzCg)1UmZjDXuKW}v{;lZQ# ziA3m(U>_;F`#VHu<@7R!?PqRNZtgR@b1lTnNn`?p~5&!iGdHsD9ur6QQ~!L)VD z=7hY~NTvwPXB3{U`m3S3m3&3Sv;_KlW1)1z_Mr?&7Pm2qe^rZSln`NIXo??vC*h*1 zS0H8?^1XmsT{gH|Xgr|X zFOfZ>Eora!3Axe8~slT#~TVQwW7(JH1^US%$G`H4bz32-#F-e>&i_xJC+7R!HRG4tH#+;h*_d!K!I%6v`xlSKer z7Fw-b_8aeSjg!UMs#^g%OV||#rUU}_uzS61a{Gh{_h_JlK@V;`y1X_TI_&~ilb-=P!5|w78`nMYA+fx9$bmS zhw}*xv-7*Knw4|DCeJxJHpYGjryTI$~n|c8AbWpLAyw=r@i(1cUtXbfDg2E27ZZpygLtaBJy| zjB+?1{E3yZ>eyz!cmy&-Awq;})TCD487p10pZb9w$%&HO;st8u7hHcvG5*w-tV0x7 z-p=&xUl4qhO;S?OKyfml$=$cVa zAlG5)03O10cH|M`q5^?VIu_6d;WnAX5zjh;4n^yO#kM^`caWSoydFCbyGDAh()RV84%#3pJsi6IWUT*c0+)Ck z1NDbdO*v4M8(oEZ3clf!Zq5wDMqt(b&892x(NqI|fxJ}z?OOnG%vMl)`mb}SsJ>cLL2@*Y zv9bdH&xCFAU?&KvhK=KJsmL+c4`mHL`gAcFdxcMo-2d?%-+L5irFW}F--^L}j~Rdo zyM3N-d^>;p9~^=^L?<(76+*kb!%%g6Tk`<9#y=bMQC-5oo}|&q=|OH^s9(7*NnH?f z@Aj}t{1~e(n}3l>Pwv!MTzBfJt<|^#pqE^s<$ZbJRT}kYI0*Z*mH*k%myC*6Tjs zz_Z6DP7SuFCf`nnKSs>s3Yyy_OZ+xx-P@Zq-@j@T?D#a z7(1kc^J=L!8WFDZN|#|Bj^b}P_-Qq884UKM?*IviMBe+mc>?5a;KiL4OV3WJ?>gFP zZddN=+8R|&zo2pg63iwx!Q|_ie=g0$tY;QUmC953J=TM0;w-(AG5Rq{WxS*jC9T)r z|Dwv6fr+8a$RA+=mIP2(-OnzV6W7+~|4HS5XNV#G^o&E*E_$iT3gS{?H}Cc$YG$4H zkMIXeT$JVXa0f7XxJ^yN2T20gv}vc(Af?%AiP#c9r6I!C!Fb4=1B#;&roDS;r4KEN(XRkWbeCj2BH=cyS08#;vNA;W3MW$W?nC`ys zNappw%WaNlp4qRc0jvU3WLVhx_b0Bn{PEiJO2hIU%mmy3b4yE6vY3Klp1a5;i?{Su zvyA2Dy7Q`9W6!U|eT@^WBX#)e79=qBGL2fAQ~ch)k{OVo`1Olxm_ZnHcY9BZ(V~_jhT7l>>Hpyw>ffOuoK|*kyBzHXhYi96UCtQN>369~c64lKhPMmeG!P^R|@J z9F9wH!9Onm1HJq-)u(*#SRU^TY|~JO!AO5e-})<*!iMxUTyK!k>{&vJ70+JpJBK0$ zJ4sSES}QyqIhH@fT+vR>PHp~nDjV0*+cv>uzf>jG?s2#VzIoiU2)4fsKkm&$;=s?J zyF0hEW=v}O9NL@Tav7;K+{TuvXV}0^xEmV#0Ggh#&6oDkDr3b0voLY3FUzXdIQt%< z-{Y*SQN!>(7e7I1dqnO zdga|M82OxNgE9@66R|o7mSP_KtjO~FZ+nk>(>eoZR=2v$ehNm@Z`ru3>e2nC_Iscm zupR~2^%x}Fqm}%Cer4*t9-SK`FYs3J*X}D{+uQ>JbigOcXwd&K2#!D$lX%Ur?Gn zJ-0`&4>G)zlpQ~935QtN1)u(-j`Rq&-o(xCdB1$yvs1RN@;FC3!S-p%bCD;iWOo5v zeux~qUV=Cy_}*DXTKog`d~LRwh@DESu6YZxM~}2NH0-MI2?hV2VK{iBH!~*}YaJo= ze1bg=3EhU39W+HHd9#viT@Z8gJ}NA|CwcF=8==Yn)Ie`}kbl%bs3J)OLax`*nx*>v ze@Z5Rm6anTxVUvPup^+H^6;D?*!(Ns$m-n;@+hKg;1huZW{r|bR>`$(Tcqss#g#r6 zzqIzCez2j>uxN!)M|uE}uDhyMl)GGP@hs$}BGH9$D-BBPIP|}s9r)K(NzU$F z%9+@CYiFWncL1DfU~K(yPB|Sm#oJ&Jn#tOYjcWsvtxPV^lhG1rQBYoZ5Vwkj4n5K> zT{md-=1oNNXiC+Oy$>Gm!jL?+&kp*>%?HTg<5raI&X|-Mcs^3J>)R2w z>gck|AzB93ZTHWqIk*@d!J|GS2Mul41FwZrSwC$3ZjoCdaZK}$@6v0IhU{;Vi9O=& z@f=KMe?a-UYf>eLT&KU!>N(zkmDyfevjA;}95x*u(;xLNw5P7X1-{>iK-M1BJAaDc zzDti`X*H1h*P5^l$>2hgIcDbQG|t4_vUFu;&+K|T2DF0Na=v)H7_q(y@Gn4NJbnw7 z-M+ZImLWF+_e|f9K3GjX+QliLaz|DwD)+Pe%P`nk+nQYgu|dUI3~x{8w7o>cfs3?f zL{v;GIY9#}@E$W-%!`5rLk#gXakH;!Q~#*k<2kC(Z=GH~v8@-D8;;>-Z&?0_ot*mb z=ShIQ3y?m;oUS2{J4Drw@^-BapVdQnGhbn`cUL(q?irc0ldMHkfTK&AN57g5s|qFn z>cOAU=1(QHDC<+7kp8Xt)Ee9UK1npW6D@Nph@c^ zdw6pr9_W~T?`UWfdU+xm#q{^MSyi9+32}{m-*3)jiTnq61;~XEBACALT*{yOfzgu3Rr*)%T!!K)hg&aS9T0|H zxHW~|24eHiM%ef&XLY7WRypfLF+QEoMx@BVb1|PzIffs&1yxXTltTrZZ^YZ(DHw`{T&zSi z*=)0XHnn3K%XtGS5eQe^gUyTZ@b)q<^mvnD_SRj$jjn6xF1cTowZ+RqvP{cC;{U5J z?`7U_uuPjjYY23B4XGCws7rcaq)Z`f zSlissY2cQF)p0Vhylu_M5=*=JN9^$$M|u2ds>_AcrE#_K>5F4rvwwg~AWQ4n7ipLB zUaeV^uMdyy*<7NHe~q2pU+P=U3Oc1Bs?Aqo9c0-C*8y^!4{f@mt^V@RG1$=@mh4w7Mw? zf2vZa|AX{&;rO?>B2ZXqz>2^0Wi$RIfq@KTL`g?)b2PUdf0n>kIs0zEBA%b!hy)9i z_+TTl_vRDjM3ceZ)3567m4k;B5JwP2vb?}K0iZG8hrS5J609&bz2Z%5blrAU<=moDy@%UZ7f66Kx zqT58~46}JxBEj|)b8ijWgl(OE-#_^XpfDZ9xLX>OZhfy* zzgvd-7!7$uF1_A7cv5~agDd%Y?`>r}!k}M*Gy?*BhvjyD;-al|I$;kh&uA({cSSWg6 zOXj?*F#CJpHbp{VuZiPPj*mX=f09$+Pzh8gO4Lx-$*YAAdH9r0%p^aE080>? z&3AhR@B&REw&=fD{-SYM#pb&Up!YRDCU-j4veb2 z(>MONUbr`j2&Po>Kh(wu3}3(8u1S5%u4Nb1L~sZG#ZNleEg2NB-`_eKn-G|T>XviKP9ns8Pqm`%2h!kw(pTh85pu+xtjOrHAI7Qp3)bTh z%y2B8Rg+zAXIswO*O%Ch?H1K~a}J%omIDrTpl7QI21_RUB770>L~^$OE2|!3%PJN# zx&JFR4DirI_Eq%{({~)V`oQxs_GBvT?}X)!fap=_0Ln z15Kncz$I`N$Nf4VY#Yx(#(Lx5t_JjQ_Om7q@sTx{SMiaRv(7Y2aL)r8rn`YmM6L>% zGvqA-#EJ5yxCJ=Fc!eZWug#@ ztO;>{wZPb#TREVlYD#AzteH$#ccgyl`QvPqu~hBh9i*ge?-HM662lvop+CA8$wYw3 zKREJmteVq#@-;KjO7r^*n9rj}cZmOmM<6+|aP{|e!*3;LEoCv-nJAqA_gAjreRU zE3sOmzL*@Sl2f@4*NO=Kx~NzTlvUxscv$`iqiuxC2^Wmcz{Y}AIF9W^lS^8Z%7ZdY zflR=J#RUdE_LW~v4aJrT*f?LP-Kq;Z916c7Mx?o(oMWc_{acxz?^b6bfw&190hqBS-H#B;uZ2+nM?Tfy) z1@7NDN$gp8GjV4Mok!?G(p+#ga2+Jt7(hsTb0ZYHeVB-icHF0_*o|66+OA-E(~TN{adtaQDMpPmo(!uUMhAU+;jR(0T8W5CtfK*N z9Bz@zGMT(^0w!vp$qB03GPx92b*&h>P|vfkI=-Fx@`nEs5AMxS0@t?w;>uZLu_3-4 z0b2Mqv0Lk;W$@QKMA)XT1~@_5JYa@tt__RFA{l1V`s#=@==Y>d+Y8Pz7l0P8t*GI8 z^iM$}m&x_Fs+#3XKF#yHd+QJI0TeU{hLdb@PhLKL)PJ*u>3?PmWl+d7j%&GptJq9G zJo9(`iXLwvaYkRC8V0Dc?}D!11M&t{;Nk5eQ@|9@S-Z(~gl=am0=;OvaGMxZQ9NTH ziPhQa4Kd*IeP8h?O-{GJoDUpUOA(FaGj8%k0nTj(@kX9~>M`GdpjkZU-CFs>hdm7EF-I4T6K1!a zWm@j8#q`+bu(6HZ>exg@sjE-Cit61gcJM$7>4VlD5c(iQ;9FbMC$zE3OLBI}%h*wd zp*y^whwLAq@>Orh9tW+ZLCp>5;Xd(??IVO-Y7&YPZxoRxWI<$QI=|g~Pq2aq$k>$#5bqV?>L=2Um4@uK?5h~T}JJvADa}(D4;-@K9_{# zk{cZqiz^ve%ttb-yCYZIQmdbv}M7r1&N9a+$Q}tQoJ#0=q{+M zp|C3$pQ1vG#S$La5m>V$W`#LgkT)Q?gf9)OnGKE-qbjr&OZ^MCPett)etF3^f7XJ& zPrVR<1GD)h0Ed0+x~zY>|1b86yL9)o-Xu>+nvrQq8FF@;56pc1+99hcQxJ@1V>p1< ze?V{^x0Z2HzY!_HaUt;Iz@Ul20>T1Y!4E)9}Y6~LBHqp7{0qYM9~>uxhw_}PB=Clc7kG~ z7D5J&hwM|_hMx_5?i=UY5g==^zak`rY~+z#C%{t);NRQVK0MpPkA)SnM^S?D7lN;$7^(~<@vpx zADccUB+RgWgCEEb=t)&;q&b}59M$fze^%;Aht6y~X2C1A@r=NZ#OlkE`sh>ZpF~)t z9;OZYpH*HWJ$>Uxqhag?mf`FARL7`PzWI}nP_Zb$^3KXJ-8vC+H366e`A+OcZSTjb zqP@}W6yTGan>%YK>~o;p7DAcFv~OG9R&s@T-Jv*E>tr0^x?@WwNyi8#>SM+QtTA>@ z!S;jR{m0id7|LE9rMP*$I%&AJAngl zXAW!WoJ;ddrACiMzp0d6cS(^TpEK(Y%Rx9Po}Bs<24X%jwcEsRJ_5F?O3 zM6vjB!owKm=WbaG0pjp8ROt0&0b9Iovv;p@o)3v_E!TGE$G$PYxo+Znh(Z6nI){Wr zm8BdW{~!u?$>OM^w&_kbBc{xB-A5SAZkXH`^6cc_u*jcY)VTHD(-eK^I}|p|aMiU- zsbdHseLN&+bhkK>-N(Zaat?z)b_dZrgAS`2<|U(Tq#Jj0n%=Fuh?w;Szq#x+@Hy7- z@0Zn6#G*6!c;g-iHVe&kH1v<^>Toq0HudpFG!e87h$SJev=G~t+Fq0_P z`$mx&nRL(e`iLVGQ1zSdqa~}j3v9zOA#Itdbj(-7m;yLRnc>;N;Hs-^clv>K%brY` z-XyrXhpe|?g!!Vc+miC6%+R&Wnlve}0%sB$@VoLU2eq0&+EWC=wKu^oRy2{;#C2E$ zYxD%xc`x~r3!Ok1w!?;W9XNkE-_>kizruz*L+Fa zc=1K|iveh{On6vj@Zu7DfToZI{G5p8@>d4sLOJgqRkM9#zpz%aXgN&;BPmSVK*xjp zB8CumBcjmy97y^+(r{M*y)015xT=Hlt+`lLvxi6xW8&iQ?TU^1ftj^etXRsU{7J78 z(EMtOetOlLNM8Qw=0S4+pLjpjQIcDuTUXRLsChYO=4ryppi=9D`(G~Bsa}kvKl>xk zSHwL2?exoswg1Mg=zG@y2b#io97rGZXKD-=yGy&J#-eApvt)q@c9vEy1f`EqA| zp5NuHECkqhp_RB@hSXS~Z<9?`Qg);@dm7+3Jgnn5oOX+|cKV6#n+oK|KS31eqxEhU z_S9Q%i#s%Ix>#AMZLN$xKl_m7<>iE$d$Dw*r`)O_`}DR@hff~}>#dn#cAMUev;)P#G*N?vrc=fxE))p|@& zb6Pm+nxTzrA+q0~wO+y7mp2w^GyQuGrZ$yu0^C7iC2mb z5)RnnEChE#H7p;CjD1sBNi>s=1XpKj3(d}b{i#|VeEIoXb&_Ge zJ$eI16aWtXEyO*@-UrTpOdDT$_+Vs2IX-C#>B6cQK`HsDn^pG&+9#MV)H|IBIcbj) z@g~PSXX;qoy?lsKROH#sCS6eeNjb=cHx8(9U3_2k`08dO)vUtO*$#an?>XU5ECxiL zei_A_yw`YZ{(zN2=49yS$669sA%A9m`D1W|Afr_`tIg>z!5bE=a#AN5iPbWg#I#C* zAJ;HH8Mh}-vA&DcO=u2Ik8w2MlY6BjEko$E9fG#~;So%9y^9pD5{spy@7w?E`1(?q zrJvV0paE~E_%ghycp`M!Qc1b@o2-I-VSFO{k&$a7AbBH}@TC6~^}XoO1x6Z&u9J17 zdAd<7ee(EAmLb=W<_W9=<+8XKjR@JMKyq%t0F$k=m$-taQt6!lq`}OfXDyFeQmrAq z!2r;A*q0#VqMoDTkQW(q^zvb%6}N3VuVM@tS4G3CY#CQjX0 z=;n%zCx0~JC7ktS-P`!n@$uf>S+7X=3>MX>!fNST$XNl&5HIFrVN9jnKHzDCLnfB! z37T7A`Q^SdRX!SB>9I0-PU6+5(wV554MPn>n&_`V(!&xV&N9o$UYAD!tMfm$pxww- zRl-9x$->$r#OJ?&2d=7G3C8Vn*%&_-khG_y!y$wUlfR&O^yuZ7UNcF$EP|N7fFFM! z5&WwS<<@jXvsar&7_TR7E{^xT@{otlu}fa3re5v5G8Z2PI3mK8H&PTHVo0CJwNFNK zMj#0%LBUSVD}YHd&@A-oO}q$RUp?POc9FF3=)Y$flK3y#a!?_#FcH_ioI*P-1d}H7=Z%GKtN-Yd0AdLX@#uLDI7d?P6pb%d<6ZwYQ=YkaV3H8c?OF-L)~>FbsxVISU(CMk^#O$Q)bf#I7D0cX{leLk{FP1 zIAjmLO>5%2R1HI|i)pYj{P+?6vDfZxTj{;|mle>o4QPLg*nZ)%r_(c*2Sk5pF^~P? zhhrd})Q%31qe(zW6Xw9I5^kgu^^!fZXpUuXbESugGu3lB4l!jVh`wm^ba;WF*Y4Q^ zK~DBvL`G{6Z^sbD0gybFhasKB*`rsd(FpkchZu9g?$U7N{=}?9$yFN&wS;j2Y^Q)M zNUbD|ZU6i%u)`Qn&YbprS1TEg>sPZF$<%n2#j2sZMvzUN{z@t7698!id>X5`4+yHc ziuR}qq3vh)uRh}q*R|*>EvG7N1uysOd0uzBmVq$#m=^)1ZeFc4(holIq8Qv zP2Ao22t8+mb5^Y(HlVJ?%Oo#>O3=gq>QcHL#nUg8Vo--xG355X;xlP!LJxSf9H(Gy zEft*4Xos89tL<0T`@5r_SwS{g)M|d!cca)00F3FCRM7?<0rIIF6RMaXR!BZP0J8cp zZ}R~#I298A#W{9Z^vU7#1s1^VCS%sW517uh685*!Sxu1O3`wWox>N8Y@#P{&6;`C)F3c`S1TeoL@vvA#vkvOsFU7??mYv+B#7yxc2{GcJ9YUILmk~J6x{1b#$!g@b<3%YH z@U8Q@3<0B-+ze{$rV|EE9i~M`&u8w)B5YnmHUmaZW#&=A!B7KrkR)#4yhcEa>9Luc z;dp&6+tctYo4Hh-dgA+1rCEFH{lN%!128^zyFg5;tY5H2h<3p;weeHd#mJl2qS5)u zUHuMotzcNDMjQFDiR({SB*i4`w#)a;pWUX$5Wq!6$!~Y2+5@u2V}jW9FWc(PU-qj* zFD^EYEBzUd2Slt0rnv0x%#RL1MzK$c!SdSN)tJmGmu?q4LFsdCq*VYA# zIOGhX%KCteDVMqk*|UBEZ0W0>Ihje|tUl~K1#2VW*Sz!576~TqKb^X+`th z+m2UTVBYD^8v?1$7fT@_O3@cBd3DI59oIg?^_BcU9;q7)TVArqw?1Y$m~!vFca@j= zCJ3zm9y}|M;i4B6f9cZ)eiOJYuo;!91^DZOi;QiC*aE2&9=22S=#B~0Ee1iom%})X zpP{^K4oUo_uCzj~&9-lT^nQeSeGO`rPec|dS4{*Mse!ZDG(X7osC;RXD9>xUb94_z zn%!Z>zz7pxjNUkSmHj30vj7Cqs|REU4MrS#w&>c(!^&rZiDTN~szw@O3%tTV)ZN-8 z9$}{M3eh+_gz7Xb;bElVBaA)1B*&lX=^G#WSJwA* zn}ne-Rz5j3D0Tl-lq@iK&?@rw@deQLq4%Au;ts7i?^kkFEj^QoKO3hvm4M%Oi+xtl z=SH`@^{kN7?SiA&uxn%?FJ!|c&2S|~+*$G=cO?PD@)rE%GDqJ73@d{nrWm%KhxXcb z#GKUv4$^@uztdf>e(!avAw-fS6TEXEi;K6^>{uRrA`o?$t5X1ma7=XQK2)uKiLa1& z#0pwDai+dS4*d|5xA-1G>yR9#mFg(n^~U@6It(HOPYu}=Nh#ay z9EMdT=^pe>8b0&zx@v3VES!=vr6Udvc2r?4X;Jt_xjgN4+T}8K2uB?l8NGO%D=f~K zyjzf;uJ7GRZzZjYpY5au_Wvvta^HpL&XsdZUP>|5ti*-x)vi5vE+r|*``NbzI<00_RH`kHyU3mIs@IEkQTDJXb7(Qvfh1lQ&(3~gK3`C@C zfvbxtLMmp$>?3nTokzt75pGks%%X%DgECwzS6Cbcy7(7IN&R?zKzAYrEQHPvUIsG(%yAuz0`A&xEBM}fZuIH@ zv^J8V-yP(yM`_-qdx^KRNE?44Oj5_f)06XkquG~^$yc^JHvQN& zWvJ`4>5kE(7_G5fUjHmRI^($Mt-e@RW7Gf61gl>ry?qZcf;ZA3O3Ys7R}I^x zjbC?qHIs$NW;-uJ2ZYZOxH%hduk^2j7*W^9e&Yl#vBWT;EJ@nZ)VX=MZtDzu8z0Qn z{IoC9`I)CC3`N4H~dri{-i-e;)TsQ65YK3NgHH1L7>o%c7cC)=LozT2#A zIW6&noaBHGDbfyLfhQg@9SOID2WCUicWR7}5?pR;B%kMT4r+b4dDT^~nwe@6D)>M_ z{1in?Uk2i`T}zBxUZg<3^7yDsn=SpymE<*A#89OT{d5|~7&2+>V;_l@Jy|$!@nDib zfHk0^5O9Xem1&sSl@w-1@(d_Mcd5SD1%s2)=vsDZw}0x#epGTAk8VgP!`+M`5h=sP zv(YL2cHy%HA}XJ$@%@8qP(i!ENv z(X}gzNt%L7syi|nwQ+Bp9z_3Hxa>~kr^v{tjV($MJy1^j>X&=rs<(T_}MKlb*)C{ zG$)_r32#?MZPCJAO+ck?wulcG<){ZSi`B|IN%Hs-P-PVFCo2tWM{fz0FH1RNhD>~p_@C{4vE{KiJ~<$?R-&rgOS0tm>S zOGc5A?_o!^5;LOZod?=t%T;C7_sAG6z8JYq)bA9=LESTbk}xW(abJ(b({lApTis;{ z>T)yJOY8}%yA6DR+%CHm?Qh0lfbnU+u607OQE|UH=JhPq;)ufpeXLa?fcgNfdVj&g z>a6RbX)cutG;d{RdAZ`+8jF)Fay^Q9>v)+mlMS+erQbaQ&0D-?5XM_Ito&l{k)mFs zQ*Utel6hqgqrK_gYdFyE+?WpI{&YkpI4EntFzup2que#aqQz~SFWnQrlIrk#wxwBA z@L^lXT?>98&DlqrUSvlCh+(s6zjcZMDaVB`dd5lI1?ws5m?SfPkd>wm)#RN!37t&} zEy{6rj+L}X+N&GmxNwXB=BR&$0d~%oT6C>Im^9 z$^H`*f%ie=10ZWNeMdZW>|wCE@yg&f`l-n6kt#gu5ypJ*glNOB-|10bY|)0EfSuu> zWE3#t)R8O~Odp`s&86FTh=n^EUQIH)x1Ku!h`MV945f{_56nT7h0a zE%jU04cMcX)=jI&F_y>Q+Ry>e8RzAMXXWMbaw~QVhot_M#2=&qDMl+!@nYO{Q+v5U z|N5_^sf)Nh{2yZ9%r8z$#IDxgr@tTmM==K2Ni7PfKvr5DQAb54$H`F4QL{;&yzrW+ z{8g8kT0@oeyWzA#xoU>+^Ou-x$bq8=I%$c2@Q>5o49oLVYF{IU&tekaZTS_|cQuZe zl<65B&)f@j>SsG7Qz=Ik2MA>W7~6NGpBB3Onub#sLM~+VB3TkVub{Hp7>~Zd> zmkdD)foy(ab+mx~;w?Bk2mBzn_9FM%6w2JfG$(iPGr;xuor*yt#8he4xH@)k3rV$J z`}2}EK)Bv6Q-_?*XSt1g4VR@&7jL$BZL5bMV#w%1S{jL$oX*CNT%130shpI#%hL_> zJ1oNLuh{)}2f)a-_NNS38l9ZToNeUMw|VyD7E?2KMf?g;yLYbnJqjbKW?#d}lc+^aAjS%mTBdUE>heEaS# zdK5Zgr#ZLA6&TA~P(1_gmGE@3AO88FT84)Adw)&_88awFkAW%2;Fdnuf&yf=cKcx!WtBWp;3HRNK3{d8+QJza7+KbAzNYPrl^Ya;}(m^ST zB%!W9DhByKFwuPgCVGN7nbJ|3CJoEA(!9^3mM2G2bXl+b3o9Eit)&9&*(kiPt%Lo5 zI{|#DrNj#>p23x~!AJptfK@sQ-ytN-_AtF#-o*dq?za$Bh!wj1ZpfV5!QBwwwZ&la z223kHg|90N|NQDOoVLs}{9^|+v?UnrK4OCU{J@>%+5`v4c2Ps z@gp<*3|O51Fd&XOKFSt>9`V3h&Stj1+H~cO8-^5&a5HOZoMdn-PUiR;WXb3?Vluqf zG{$v7&B(*?GJU@*poQ&`q5z`~9GQF%+F+b=gE2X>IVRF>N*OcGTXPGdNS`RQ|6>R^ z6Z$c7;O^{@%;tWFhRo^M5)3_1t5JtBI4?uM9nrmQn4?HYsox5NNtujl#&zqQCb5Yn zX>t+>y|1`~#_^(LB~<%vmC*P_IWTivjvu(hCTAi(I!-eYmhEX#{lP8l8{$x-SF3{; zkt_8w_#Sz`nUwVs89<&(YW6NU#OmU2fZX&PwM9`w@r%d-7#|6$vFOG zpF7pZc$gvX^yV-w1EmeHwE0F}y?nJh&A_ENWJ}MEg`3&&%$YtwYgZg=Lzq1`ApUL> zWedPfc=+L3q6^|P2^BKjju+d^Z(SbrMYLr=*72);C34=qg-0AHd2?}DS6<7KC|D@^ z$kaERYtnNtgJ&k@s?sGrfrB0Lv!KQEB%+NtAJz5PMD0+`a^rJ~aE7zSzZ}xl^o^ z66dJNEdOl!mvGtjp6ytGuLw?j$xc9phZ~sU&|otuGVv0>CXC{DT~2(*c+Zfy%kLCZ zOcgW>4n<2%@Gv|7&Wb2&I_k+e=$KGjLPe3tksZI6K-sdOH)H@hVP#keWHg5~!BlUh z(v_~5*q0_G^p9yAh9K;oZm|<6vf!$#7JunUyT4o?OBm5_l-x0y@IOF6U4qHNFEkIA4ICPG?~B*Q z9f;YfZ(a&D2ei|n>`#G0FU_Y%Lxal!@U40+dveC*#&!vN9tG)4Ij-49gfvU0EuLGw z`Bp<5*u|d@Dbevq3LxTGuKQD+of+-}wdjeJ`7!T*I%XC<4=-|HN@zhH6 z)ly=G9ifzJ_)ASA>zQVPZq_XSG%=lm-y^KYB@PH@U?5(FZ^tbe80bVyS-Hoamv8& zh5%Q9@uSx#q3EvI(o%}H*Y-&Qzwt8W2o^=jAwB?{Og6Yvi}4@M(nWWHSajzhul68* z{ZJG1QNnZR#n(B~r&Rau#@w_f$8-JVwi5K{K8%Qs4cFoAgHMVMc-~nV5<-66H4<#` z-pWMx2ms60;>rOe$5ya>yXyxnElrbtC)?61hNtKprD$&Ev+DM6tR_cT+|u^^qgr7R z6Rv5uz-G$|P~b|e0Jm#$JG{w9rfMvebzV8LbY)bWRAVN3F~B`CSG*gtdG1wI7LQr( z#`q8%kRkg#J3jKN=t-CLG?2*Wr{vKwk8u)$&*d`+o)J|^IQkpUHS!#&~wVjz_TZi}Jo@m=-=W7?AI2!i2hK zUN|CJ_#&X_(=xB04XVzqNE!RBEga9izu?Q3yO7A<5po2e_+d0 zr`A(o!S$H~W33L#Uljy9BKA7+lPL=e$%_>wY_DolB>SI!@X-%cwP#NK{xon z3XByV-%9(La`n0%Bq|reYk$fv%2#2;zBX?Cies&L7HW9_^WH8A2f+P97uN@y*6VJ( zib001-iNjH#Mvg)pRWq^LA7D_(>PO5#f!4qJ@1YT%yM7HI~EU( zD8KQgLA5Li0J1-{J&J#LeTWrWD2 zVI{|9u<_1|JK)H&rn|p)k|sn((c`_C?>SN2?tDf_KJh3w%m{B<|MW49o$v5`Gq z)v?9xT#Mh!tIGy10CSqT)|(`|>>&p0ksOJsv3jqi)=ZR`gUO2EZ+M4}=h9Mfl-%X0 z@J;WYTTHjPd~4H!`UOs@rT2qfmYqy%pvSDvcBUC7Bb2i>h(6sTaJGNG8LE*kO)o3; z@%?%M@5yssZJEhx>U4i^Mck`({c}MbEm7bJeskdgr;HbTKx+SJ2XH2%zqiwmj=xhG zDyZ^SN%#2+V@(Fn&M@ZWfZQgI9wp_o>T_csT7TcUhqU%hha4eGw4SuTt|nvC#T*y7 ztza@M$=e_=%Mb_Q=NVBNr>%*j>2Vp|!0jX;uR+CHzqPA4aQTG3EuXm>N&h39D1Xia z@an~izwi1mSn_&WXNryR#tTgegGUNp$|aUPr82^}I$mn=(Xs4|+&$IqjrO%h?z=#y zI~&(C@$;v@j8_A;RDj%GM%L;K`Poy!>AFL@XOC^}DLDLG=14wEF3yNo0e*uDFOmfZ zZqq-we~QT8nCq(PEO}V#}@q|l%*y1;#id3NZm zT~B<0$=hG`(DRJr35ktt1Cv}AllO0KGrr@D4s6ZUekNa`|BnpsD1RTj2ZTR-jMR^ zqf$pXlxp4Y1K47G2u=E?}<)Xak}21 z03U^`Uuhn5T;z)VXZeJRN%PK=X{8V4<91C1P|(ZfeQIXE<#NZXODJSL?Hws-Kd@?Y zxhn%=*3Tx;=rs}4(aSNEmQVf$qChW>P#EXlP&hr9oG|9)ec535^IV|WY2qZoSOpwA z&eL^{8@^H{n@+fuRDu>I9FHUyE6H!h1Qt6L5~rI6bB!SEp8dA~P4 zAWe`s@R3}m0?h|UqEJ7VP|#%6mBt|}nbw?U#iGHt_^Qx}q!X?$z*bu&#udMvhV5zg z8UT-4nEo4UYhPpq*ws>%A?)p&8SAP8P9uU3GF>fv^Po$;4;ax|JFU9i8mT=*cNk}B zLtga8_^E9||0a22FV()(5-B^Ee& z%PxuFQTb;1~`PH6v3?{(m%m1w&L_+b$r|-5ny`-K`)XAt)&& zAYIZqAl)5OqcliLcZYOKcX#K+**x!e{=w|oYpuQRE8$OPpiT=w945UwlpqKEQW@lL zr|a@^WQe?wuh_k!4Gf+!Bg$ym23Rq5)Q@QBrDX*|92bx_16Q9f zbbjiY<56}F3`lqF*T@@Q?WDQr*+4G9{JN>*v*n(vs&hvd|>9x>HQV z^|mkNb#tPZi7MP)ch=J4C!^8+>$~6)n`{EU-K-V9o}EpCnSl=52fmS`7c`qonXO?& z%*YCSNDm(8ykZv_mWwBHWFl*L`2ltJgiAk@7n+h&Y@Mxg2%cA-+)r-g^Txp?T(R@c zOyewrU0h*vkjdYX^oVJk-7XHjZuLKz_V6*t!+2Vj&#B|8xao4R*~YTqb(x>2wr}!o z1$m9fFOpZ>uKTIAq7UA}`R;nxH9;i#OH1z-LUq}&(5{hs{Pw16q(66zC8rAH9{Y!(47I;Hje_VkcuN9f7+~@x}_WIhPuYEO9;JeAd z(?HfY!w<***_om7A_1G;A1po`KD*9}A5|;ydv=sb%sg_j!2J2{h*unoKovUqOn%>V zsx~Z_F^}WxwcQSk5O@bj204H8AvsQdt+Dq@>DKXZMis+j<>4QY9b{{4fH}78de*Mw zyfo~{h41&~Th2_L8Jw?tAFZu%BfP2q?M!cA#}Owl_a%LR2FY$)wdXX`-?ZiuM8uJ( z0^0f87vTG+HCmB#m8W%U_E4r#>Dbya>=XB&yKsv%!$+9)04*rrMafytB>&X}1y1`J z!XL_S(^VS;wh8ulHj=e!O3`$YjZOEmlkcdn^F4qk(GW+H$d)>5z2XuFT3i49LO-m8 z{uQa=-=5L6=u70Y3_s9_L(cSU$9cN@G45OFbhdVyUB7}VRmGXr82CWXIus;LJkIxu z!EMs=_+V}tW)m?TrVtrcJE`S|S5FA)j_+Ql3wZcICG2qBMEcotqYy|=>L#Gn;BoYY zefWlxyS&WH5ST=c4j$J&bTgfh_d9{aK{jwf5TF{y`gbCi785;BH{Sk8N4pJTW50!2 zyr6@2S6s-5veOoW;oJCr0j}G(6^9>*M>S>tdoP_w$hczL@$yo$98ZKSTgCBr>Bu2#C$)gJ$HIW0R-4^Gk_)Vyu7fk@s;a`qzY?+AF zv4~v5ftI8hIk}G4N*H$Ca(tD=kPk$t0wD?O*sA{E+qw0-Te|ZbPUT8D7;;XToI#JQ z-L+i-q1wV|fv|j#-@{JYS}2}hr3p*?dkI1$`5+lgk$ax2KQ&$X6Pwe=s4A~s>hJ2* zNahpitLkbBV+(2+C2an8tZ7gqiil92G)}8oavRiBA%Fe+Xbl=Padqth4!IhSdpOhq>Q%PaXuOe2UOBM-z$2SO+lJv&FJkI@t#C9de3)9&OcAqY z%y&n}Z|T8hDtx{d1Jm4FgxIeAGaBb!NsncJAFY!(J?8VdWTW92O{X}@KcL@be7~G- zz!m;fW0J;!qU&RA2g=EI=ywH<(dr|MK@%M=hrP3NgES)^ zYQFt0Z+IL!@mPj|TaF)p`JZ(x;4LlVab}3a3shV|4?8+`&s7iR9lL@o;fze^fxdL{ zj;OTEI_<}j6}4OmO;zSrj87qT$!N&;+)v6<=jxizXRzp7gmHks{|mGe8L%2@ov2Uf z_>4Y|+5K>`n}FHZZsd0Z*<#*(%u=w3yGvxDD#~EwaV4{&Ebh+No`?7H0Vbf5I^Rs8 ztf}c)o%{tEKj^jf5gnF3HisutJ8;j;cD_;-KCK7hrW85F0&qEQ7pkI$_Y^r+N;^MqCq4gtx!X#8CDIbI!=p+P%|)3>X=h}8~~ng3h<>u8<$WFCM~ zV)g#GOizEt?y1M9T%F%ACuM$E;&!P0cuh_GRO7yf7$os+RB%qh`8?Yv!(!36uH|wb zdrdJ~Vze>cj)l&8d*@T1E6zn+Y+K=s=$2o^wrr6lL=5X70~eX6fu@JTYp?Wo+2b~l zFecGe|7A5}wjQn-gP0C)yXb(oKMCDG6S7z$@c3h3Mvg{C{ss-liAL)WSo%z*!9*FN zkLG~vz>yzJ3UQ7?lf9%T{bwHX-?b6A`*)uC-?h|?0f-f^jV#I>tk~>GLVzR_Mf7k3 zo)G7o?=)KXkLGbM!ZBNjXbcJ*-G$N`m`#0?Mc13hzhBu58A=mu#BtFNdh-A5U<{Dk z=7;L7YKz>?o7K^0=Eq|q^9&f>|5aixhv((Rd5toaDrD92g}&E~Z?*I_vTfJ90=J`IX~V0|qWfEs z%fxud#`ugk1_#gu{5!O-1IkkTmH56$vz0}Dy!i(+N5#{Nr2hSvFGuhaV8>T5fq~~H zCp$a4gLEVGT<-4%B!Y9-x{a!f;cG_G1;-}sL2=X6Wxg?{QqkfT8`KJ?j&&OgF?z+9 zs@r~MVd3IB&i}rrK|4AbS77rJDx7(v7kOw+c%;Nf+=hV>Q_*n-fVL6qvj(v{e`a){CT^i9IlWj|pKX?@#9}avA>j+Y#_P``6G>*B?oDTYm<8 zyyDFG0-E7zqQ25KG^*kf)Mtw_9=->;-o;Hdt(g^PKLM{vOTxwZ(D3E`iSJC#;{-i_ z16V}m2knCvsCq3wFUO7{hU2dtM$;PvHQ0B6}6rS({jdi66pJEF9QgPdH4+%UE- zrUOTyVs$VJ%3)B#f5_+kk?a*+uQAcR_X2PR`Chv)vV^bmw6`Pv z(JxjgOgDTrHk9bm$zQ*M0o;=9hPn>Knp@;fM_)&t#86=@IqA>v1sfkxn)2hMB*yYz zkDUUFH+F2-(I+y-)-ul5lN_q_MQELWL4<0sWLoICV&&j{R2E;ZDVke=XfKsB@|#q- zteB2}*0z8DwoVW+6T$9W;LqM8^=E;{T+OOhG9Fp|e;)uYSCBZ4PQ$LBgbCMmjWl<> zE;ed~T=c8B1fsQ^hyP6<0rUY{J2$Is54!_asSe@#_;tb#G8yKeTHC5f&v<8+vrKsX zl7m6x;pOk!BdX~K5Zl#+k+VO*1AK}%^QA*u;^2~8x8-Lx{^g0p&qlSbU;y47u<()r1oP`k}x_F=ft zvHf8eQc$;yBKDvwuSLSC2RR0TzYUf0eW!YllRq$`U`@GG)*Sm#DI?Gb55koyX`#4u zc-izq=Y$_vVLhmUpMgLu79AbqdX!;oK%L+qERjkt$N$%WK@}I=rIPXd4S^~mxEE3v z#r=~4Tphc1Z*CQu<1Q^wfct!2(ZaFl(Td-%vNu{EXduFw&3YTpIjA~1diE)pkClG> zJ}if}T;(eM%@oVbgXI$+Nb_~Wly|q|6rqj0R*GX|E+;^JCxt(vOT|`(-t?W%ap2Lo z7l}HbbEONkC9r3T*f8V=rqN@Aq$#Lt-m?=6S;0F@Ty`u|zRC%)^41lT;P}=z*r; zG8N@}fa=LGOTz2hLMbQpOI|vT%@X{W*GcXvSq2EK)0mH(Ki57V(L{)^|22yhErb$+ z@81jni$>gL;g3ZgDYub?JLLYttfjfRzpkMnZs2#&05L|kSxZaHfQNg1j6u^Mo{I8v zpW{ek`>mxVOf%E@0l9Z`aVPuxWY`SSC>D86R>CN>|Kb!@SRmD{gj)j5^D8S0bE~Tn zi0jx)@cUw2=EYi%B$Q0>@lA+OYC{jc%<^h1OmECofn4}4jw!x%uT_-4?CdIiCZp|n z7{$ZJ`(L%HA9v9gtI8zqzvAm-%4*v{K42*J3Ulqm>A=xJ$-^TqFukmM%Oe5Bduf0J z2#NDMHZx^2uLvXlyNy1}7@?7(8ZC9AJ|}CHO-w&a34+XPZ0u$_LML0++7_G{V?srO zMAxdPYcX{+uncuPp^UrY+685VtUZ6$6P?Rb#{Q-De-=N{y#?G^1+6EjPhVDsEfM6) zEL`T{E*q_G6*&+4*B0!lTZ%J}bH zXYg}WEFsi3W+^E`rVf zMI{}M4#z_LV)iTHft2Ry>fxXHQ_?6%vP=6zjn^tAT!pJ?8!{@qcJ29(+nCpqfi_bn zm~^G#g0g;& zb~Cng)>+XVIK!R<{Q-A4W4on2OU@dsNQ15^k+xs-vq;3jweUdMoB&LXC5)`!*>%TQ zj;SMTM}aO#Aw~D6&{WcVcqGHBPP^1}a`tRA)D5f1|9ZK}#X|}R8EtR7U9<&x0-2o? z4OqhFv+Lwm%`e!wG?N3B_A`PyZvWc$kKLQU{F+Ay0_UT{6C~kWjrZN+?h6)aFE(T> zqPm$CxxQqz_M{g#g>Z%@e4QE^7}QH z8SuGy4w*h+^xjylV=IB!^L2D+^1Bb9n|J)sox84~Ytr`-r;CHCoqHb3@(@)# zTbX7uL7N%F8q4uj%OYxz)_wA)E|CRG^D?)`%ZwjBoKYAkeK5c#q8GO2zGTmQ1~gsO zpdyFQSj(B9;SWMD(6BQpgkM`>zR=Z+d^_^@FYcy{n=F!yl{ zW!6&)Bf<_VgZgB8P+Z{F{6(7m(zd0oXtmy;mJLSCxA*RDr-Ix?sB$m#>!(S|s7N+4 z^x~*4zW&?f%_ZZKJm9`_On|j!Py5i-vk;MR8H=5^_g$%th_gIbxAc)30e-lhPbEa3 zx<6Nytdxel+e86aNc%l7O!2g}e6B?V_No+7N zmb~C25SZNRTr(;p?z4!_OmwatBz1$^`0kZZXHXDm)A34p1D9?JqJ^670yxcNQE6+B zpVpvUYxfC9!X-oxA~^O!yUx{=Tl=@VSbUhXcI|kz3 zkUCK~knklB(td$H2}afVUVu1ssc4+-qQU;N8tBsTJA+(tH-`LqEKVJ!9%Age@QCbM z06DZD6rON3@8_0h+dgmmm(L%ud(8s9kii(-DC4kB^^+f%AHPVL(kZc9XY`i+qGGYW zGIa}akv=@{!R>I2lf0d`7|Rls1O)fyLzF_XnSI`gZ%WbHuoSFU@n8`kl(u{VnAi^@ z68J~v(T*=0LE^_6B0y4kec*JyllEip2nRAs6B}Li+i3_0Wd^_F8;{!eCIVP zO8i_-sPQer-D1;3p9tU7d)?!o`0{KF=5BIj_Lq(%Z_k^#1k}K=>mtYI!^7XJc_{el zH$SB}{y=9uSqi$W@bO$#qH;1KK$~Dd9jrd0Q+ecgGpo%G*)6NV389848upunheyG3 zDZP5Bgo3y@)o!fCtzx!AvB`H2S|e8qy;6%V80qU3%Y;u+W?<>|6tA)~`feKhjD zC|p^m!NQV{_Q9G^FX8RSqZoX<(AV>wIPEko(N7)~(zEpb@jm3P3*L`r)8GyWZdx84 z=oXhdTNich)00Q|lh06=+Pd;XP;+2lbvRWCec!3h5N4$k<@BPl480MB&L5@Ox$$I$Qw$XauqZyNsO) z<%r#srSfVz?H)|HxJMcGhp4ftY{#Lz8T#`u{>pzLm2nC!3}fX>al+o|_9|y$IhB#V z+e;&IENnC^*b^izm*QGStUk|0y%k|B(YZZj3_d9OX>gadk;yWWTmM=un zTy{j7y2}4HMIj~wcYt}bmHT7y+_R*e$hmDA8abUDt;$=rcMXDJl1u0e=@E7GegsKGgDxH?1p1V zaV(N-_G1n9*!4*$dND%hteEz>u!25QS^I8=4h#TDAlL)OirNGT5DTxb=s&c0@c953 zMl2#r(=0ytL8}^G)BmJ#nP!|LjAPsg)wE`2O~bP?M7}&*AAVKmrrP89fY2nVkXY_0 zo>u>oQz(#hB86*jLSBXW6sYc|?zlQR%hG6oIgtLg#{F3)w$AzRbrXD#d5O5^Nksr- z@P?f<4_Aa(PZ!#w?iu-uu;oxZsJkd^#Yt=Tp@l{il1Y1#0={Vm>JmZo&}<7x(k*@n ze!Y3E`P+YucJLBoP*>1+D#rUk#D9!^yqs=}Bbl?nfpRjj6(@fBmR9@l6MpCf40>H8 zEos>wO>V|!uKW@`kmSuzL8;9kVhw32{)Arr=$ycu*?omg%E)BPl(`{_I?rIOtWQEK zuG5q)=QX=}#cx3fU(!u}%W4h3QR1vddNbN5ec>@k2%F50N@Q?@#n4DLpI?E2Iz6XQ zqro{>+kBC)RB|Yb#-bm8d5kA{zL5x=+jGDpuO0!3X3LaMR0(EQh2n5h;0E#7SUl-M zW63)FWPFJTWy{`!=B6WCVE5$?vN9J*%A$X1m!t{{)Xqzgcil*D%TLalk4}F8k;^ew zB}suPrIZKZvMe$WCMVKBF^HWsfQjO~yqbO+?5c!T%Y)P;-9LmlrR0@Vrb{7g3G>;D0Fen8YXq2AT}W@$^24Ou4ri{+0}PIHbxozZC<()` z#@dp*0xd?eB;?iFlF87gY+w6V6e$H^hy*9v+^BdcF6sU==A}n=-D1CC#wo2kt0$I?=+;Vh zFH%_(@DPxiJkH(hmxkuXecjeKQyft`t+yoUYp^#U^1{g^v@k$ITyvnVE@qAUA3&&L&|*J%djwwZFhyMR`t!(=k|?INA_jC!zn z)W{?IB<=OG%y3Xn^Dm-Lv5ixn6-xhi5Gtpx+59dyx<3HHkEPd_JM=XtzmWS0gvtF5 z`ITZC8Ox?x-&ov;81K=Mb}(0tET1)W%FLyFtKE|b1V;Z(Q!?9w)waEFCX zH-gES^Vx>mwcf3MnL$h{F@0~vSoEHq7Ph=6wfFY61ouy8fd1Dmm+;JLIAy;cJR|b1 zLkqqK@(=W@FKFM=s8Anb1~{d|FN_NGEj^a>BrQ6MO1~4lg)upj=rF}=@Qs#jE&x;C zKWTt`Yq0qUl4G71@#jS-D@IU5&j|V77Yx^yO&^W7;nrG?#QuLOaSvG`ywW%&-d|P z!AbCLpz{1O+j;AuIQC_%9~p>y#*^m`{7~5@bO+>^KMO#F+Wq3eMl)lxHHI-m~0L|%p?7y`@Q{k-HHh0@OHP#v%o3f1j_ zd+-u9i$x_{6=kLGK(|Z?hsnvX(hKRU5q?mR7UcS<9z(aep6>a9+^7#J{>{G2JENUG z_}=g-^4+01Ue=t#Yclj*x2Woj)F>0D#me@_!?Osc+^-CeHGInY1u&rKPDfI<2n>~tj!mX-5!KY=iyhs&Io>U`tn#S5MsO565QG(2@AF+ z4gFP*TxUTx1l>!sgkEwid%m3X{`Y#83HdTa2AFDVt(v<9KC~}yM;RjOWV}e1t;X0v zkrU3;_OIj1=~#2^A1Ml|e?RjZ^p!V|neLkeF=t?0+aFtO4DqSaF6oQ70M+}r`GXnQgjdEz%~Q5BtR<(WlX__=v6L6y zFhCN|tl0EbK{k72Jind@X%{CoyYNX{BNX5BR3|s=6D=Cts?_f=JOQu!!1qnq&Lg6E&K4{EvK!v(@TyWeu;NE0MgD*FXNL0 zr^Af>@=b7R;>X|)=JcgP#2`j)czq{sWLa8jq>=YQfodfC$%hq`n{gs0vO&=ty$~Y( zyAP6R3%v(~AlZ?P^MiglPX2)0VsmZ+o)^{EDTXt$iM}QQ$S`IIb^!?(G(h7wLg49Z zX>PW<$r_6a`_mK`9gV;DCtD&f^;SnEOG-e~+d8jkvEZnn;37fMbsM#{bf31;dIih} zeb|pR!FVMGe^kY8gxjz5^mh%Yp5~eXeNLSbgv^U{djqg+moZW1y6X{@?l|4&ft=Kq z8)c08s_Gg#XW)@Aa=}WgraxfvaRKZgyJKD+4>Tc9Cc}_xc3O3p>^my*ATw~b!6cLul-5NTyb zYi>T#=Jc$&0MNm2GSf%`B+eiiOBiDx#`cgxev#-1zx>}Ff-irav%Q^D(XPudP>>F^ zF{!Dk2_Jt;yW!}jzMz|D4Zz@^Qtg+%P`{76e((Ss?xQ_ojitU1b>EDROUbY)Oq(@p z8Q%SV5aNGjIp0MyoywY0pD^GuA6ECzYf9py6UA!NH7v|y-`{4=Xc(Mx)0M(KmKprV z*{L0FKR^W@D&8q{A~U8W1@3*> z&KdTigs)p~(jAS6A0zKoG|`eHr!~GZ-vda*g0Csuarm#66n(rU@;A`;@f&5^;>?$% zIb63ivMF_}<-s#t^k2kbCMLf_Q`lQt_+DtgjiR^~cAe1G^5#Tkv>R6iZZ3DuD))pD z2}1DOC6A77pysDTn2N$@Zfs8;b3puz;{|JM5|v-+)@hy!t?COZ9brK^Ma9&Ve8smv zr@0TN7VNckJ%^1Od{4v&I@<5E;4NN%sqbk1d^;V^4BA0njx?d=P}AkzD;U*l-v?y8 zSGH@S8#f`sYc+3cJo9LMvI;dplAj85e!zldX{LVF;A$*Iyuf%+>7tk@HM^GpoV2{n zPfu%bSkK4Q@IhCrOBh&{SM?xec~fHu4!E`@h_}|)2ZC9%@di1O9&)PYiG3HmI25Xo z$E=$4`D*3zL^yYm1a2domAK0jfAE-gmuc!zPDs1{EdDzG)$iad;RNQ^1QCP~Bu}@Y zPN%R4c{;so7e=*N`7b#~YBg1*G3UIV8gZqp~oO@v5 zVi|!WmEu>hI3Ty^5O7YO%uEO{0vjSgrkxrxa*3IIafvzqh5zCkDD#sx0r%JX&Z&O5 z6&!t~R{6_G-9P_7hP3M+6DTLaoah;Fy~K5q)YsMH2`O9??^NBDATPcOj!Wn6%~P&Z zFhatfAmV_M05j9R{(v-e_Q0Si@R5m?d>=!(c7!>>lrDhU)_^drWyF<@z*~5y()b5 zUflRp&)1u_y!M5=CJWYY%kz@>5atf(3WLM&63peGAdO}V2>_rbFwnLay9Stw$s#!k zTf$p)&0@TW%}UI_?Ts;Qy6PKfdl51wwK5xU((r#BF+0nEaD9sWr*K^~)k_4j8#hVl zjm;V`DiOdboMVD@js=u@!9>^5;rPPvcIb)YX#e@zUsj&w@2wT2LQB+cetz7a-G#}s z&NTE##Bj$q?D^GOzMMsWcrsInaJ6xfnK02kzq-QVZofSIvE4J4B~2TDUm=%lvnKX_NGkMXtUTpdCPW3Yfxe*+lwzh@Z|@72#t zzm9&KsNR$I9{dtw&6kchZZuN;gLoz{Ykd7_6oJzGHf(3-mbvDQUqR}s|M)RFz_sd_?#fK2|mk+%Vy$Vp;vN#E?sGRk$X1K-qy*HSUkFM} z-t(F7MGR<@drYI-7>{i1>g)*q0QPkmTM?S+;Ulo!h?PX0Rz;t3P;!m_p%{_8C9+~Q ziuy0Kj9;eVD^tpuM1$J9Q}(H|`)ymkB5Y zL;e=^tb4JT@4`EL2u+#hd38@7=5=XA_Q&RrS3&g{Rx?5U+>I7^aqIp(hz|Pzm+BQ2 zzr^Tlt(1ihdl-`q^QVZ8PK`B)%6(kz!(AWusn)!2%_vScwzn-M_?r*jo@n_f%{ye( z9bOmn{rHm15iNl6aMC2V0+~bO)iCpu$qP(O{Y)2D?y@JL{hO-~24{iNy508uN!04S~eb;sYOC%9eNy(Smg*f`?BDdO)t9iD zDMrNw5+&Xyx6nfu;zjrrej0F}lPQ#)=i>!q5!jJtmoma|Vtf^Pp;a+8q2nk-ZM8%2z?~#BI))5s+I!ogDo-#Xd^Hr=tvnwrz{R zd$tdc`jx|Hpx0(v{l+)~^PDg;QIG>>cg!_bV%N)CwL}(u*xiBVr?Z!F$*vl7Z7I$Q zH&>Rp5JtrMH^#(Zj2U*FoP!4rsnz1EloBmrUS8scU#p-Bz>*WUL*DS(K&}&iuq~)E z)TknUK?td#Ucfn_=0Mq6uwpg3x(IK{EE*5??CH3Wk9UHlcuhmsM4|BHz$Ronq8+z>rCFp z%UdUY7J`Tmi1dd)?C#7!jQ@m=aZ@&<`3)^~FOILegl)(1}mDol?ND0Pp%Y^lIA--n1FX z9;@v&B}gCd_ay6&uZs9Ss=8?q@2Q&kU{b*Z-@|I?Q#qum7mL89-=-H#1%OoSxdWVam zx{ZJ6Tng(A-G^x|fm}&7y}TCJ-gTa7ZQxU**wP+w7xb$*ybg}d9|Bs^9TjRBRy(nL zP-%sw`zrl!*iqwXrHwRrwQSICEaBYQARMp1WX@>GzjdPE&R3(tju0Sa&gDiU9Z+g! zy~11CT8`LfrgWHi(@Aq|3kgNy(ll)6N&E9W4QsH$u!h>P2|g-YT==y<4mP= z1NIW@tJ61Z{C?W_NrKq$Ug-^5b&hP?9($PTqE%1#o;3V{u-Yh1Vc0I6X;yNtcq(*) zlxx${cE$YNsvVB{og2)y{Hc6puoNm=o>k^^^hiet+YX@~V>D53-%XZoklw5O{NNf3 z|5I@$4eKY_y}8JHG^ZE5{S~W!!@Z*(L7&$Zf06dx6dE3zhqVU_4Z;z7N1Me*)jGD- zwF<8Qv=N5c9suRx^_K1*PWyKhhLe6yxk=&Rs#R-A&WVzLabc!Z1?dJj!Z;9X&C7Cs zJ^Q+9e!zIpYNim^e-uwSVccM*NdH2i%B-4bgHHw+QWvrWt1Ng3U>Cu*Cl7Z!(2fya zNkbI(d1Ke*UfAX6<+5S(0nv2)glPl!3Lmzn+h@IjpJPJVR@rctw68JtAKv<==~1~f zhKzwfFT;-75$NeMl{rT`|71xI#VE8>aWq#IJt8f-YtrtVJ!y_~2t!$uE?m4O@gqZb ze9ngx`m%JZ;en_$J9t$&B7Bu*18?4;Yu6par7n-veWpKh-rhau2J$LrSD*(%UQMLm zP<`}MCavK92D7o!&KuTxPh(*g0_Po9xKGM8Vbz;_GzG3WqNe~D*8cXBfa_AkaRmgwWoVu-##n}jy zdMm!MRs$mkEh8htrrvE&wJXF1sS9-6_i_7L0!e+0oj5y>9e}T(d$#@BeSi?x&_W8I_^nte!j+O~{gAQr)?Vm8<{Bs|e6 zYo<}-FR#~wx=R%%ZpaS&7$1zHmd&ug*7KF>*agciG_oCRP(xn<9DP znC8AL>6%H@WV2-yqYUm+bgYK8T`Dr(jNjWfd`EMppdVisPv7c~X#r|r?rzI^<(uHk zuG6ZhrfS=ZVQh%(77A2IO*vWL5?`<@Xesn?hpKvD4^N2H7}>Zc#hbTs>So{2x9#ZL zD$na87)6aqT#b~Z8TNcA80bRf%6s~|HxWCfFMvT2;WgwXT4r*O zDa_A*T(V@UK&X@9)h4OIEZvqQPu5iHgqLEX^jQ8F*(I5YA6BRUB&p~kp{k4wtwFk8 zD8K$T>J+m8qFPJuRn6QS*INa2D0TAUgO;0r?k@#h za{}3A9?}-Y5eBh01ZGnq!kP!%=q@a}Ow;oGd>yYBo?zT&C8H;7*=V&>Mahp4v%+RL zuUUWe?Q=YkB)xiCunZ2q6}1kjtwtI>HqCd@M~Z5cg6Lp0%tQgS=4(#Qkc-WKmm97j z_@A2xXuzwx5zJu7I0MMZ+!S)}EZat4hGtHMK2VA@O(ucIY6!n5k~wC)&|7SD;);=@j@$8+@4xk&*F21AU8oNJ3;U zJ*sSFec_lZ!+hB=9A`O8uP~f++WvG3uK_ewEZQi{9}>uS>FCE_zeu>`!FyT*`k$NH z?!W--b6 zMmR&PC&b>i+(N$@_NJfL6=CRd1cwaZ+`BvM+Ec~{NU}jko6|MVRNYg1slt1X+aEz+ zLE(^U5z=%_;;M>ii0yVe6qBXxmEL$CVmiVR5S1VD6gT1;F+d-% zIX!!(-UYy%`X@;wl0kltzpaMA4KH(bmIl31)||i(KR|1FQTx_a7j!Z^vb*UiVa`c% z8s8wpOUXMwcH+G{-Umld0kQez#y5w6Ipi`_2BwZs6>FE>RqX7R!l`mfg!V;1FhmfI zVu595(B;Dv9a{ljOgN@cUZ2J_0ZbOo3+SEKR{eoN-QgQR;M-l?C&j^sqg;%ZNha(x z0x>a&tZUz7+$1_O!TRaW5##U(;K9;NFZK-C$2ugXpw`O%q}&YLPH!1HVN;u%eLoTl z6}h)qQ%+fq4%$<v?ofK|UzzF;GVc~Y}Lwq+wbI3YS)5IY#oZ%JGy*E83iTHUMCo>1ym_c>eoA8pIvqc&?VJ(20(GP zW7;%2I<~ntMoDS(Wcs32AMoN+ZW~;!3Y3-!k#6XnmYoMyP%Ew2PtRk@;e#~6=5tB; ztrF}c^uHIt=)cP}J6*b^f2&7r$f|lCtD*G-Qe|t9boCC#h*YfHGZ!eAMN+nF<}=z2 zrEU)De=tmNCBHvfHc8_J?e-IQ!Zl&1(KevmKQ8g_ z)giOcu=J+2jw8j=LXz=gSoI1fsi7-xI4_e}JdF~nl({yeMaC_~9^sBWpDiOR_jqJX z7|F8RmEqDaI?;O^>qwU%nN#fG3QhyPjqn!*7eh5K_iL~9ZhBQ!`6hP@b9afz^TtP6 zUduik)0*)+nOX9rfB=&ym+^kVN;r+kWXW}scb$j>uT6tA?TVkrEldWNBh=3spSJK~ zDc=*jE!~PLMwwh8F+CA2?DnA>S**F?Nz zBGM{5ck6lg8ld@li#n(~Z({q#_i-NXLngDiIQZDHm*XQ9#-%tzS>qkRL%fF-xC|gN zY2_vvOY!-iYTqX(^Rc?u97}r2Z&M0PEowD0J=;cPO(g9q4huqdV%``ZfpG}385?K| zqwP*>8PS?2ZN=uvr^IP#gglv){kMB)+p%#5!+j(M5)u{7UgzEF3?G!e5ZN3{w_Nb- z%yIn9+Za+tnI3t?W@c8)NHkWEI=}KIR&xzvp_?sTK;*2ajDAt_Vj#2f%6wTyS8v^A zQS!*RyF(7NcjjrjyBX%ZF&JwjlU%BL+Vt?isrJ}^0y1nZj*2rKnn|tR{JPNgt$Uc8 zV->O^8YR?mR=Ac)k0ppMGdC zYe=w+3d1=NZx22CUD?itxvGjtd}s?*l#(fc*)0e875Bk9FGTA8Oyhs-p4Ng)FEJxn z>rUNlkVPyp_WewdbrH88V?QX5skb5$PYLovH;!W^pL%7c4uP7XS}Vb<7=#(D@XUX! zbNTmZZx@Gv*6ES7cevZllV~PIEf?4BpjRPr(zTxSSw5Gi@}Mc`LpL*xnC0S&r@1h> ztKxt9w&kdR*4f}>qUvUqSPHCT6iMcUkxPe15hna90po;@E5%j)i1w`85lGL28L(00 ze-G}&V~BS_rDf;jkP{qfR<7e|KkSMGNbJxG4!gD*?%zt!7S*49c%J87s28@H&2vY3 z@X|uE7ph#2PF$6G2f)!5vicLVcGDbx;$Cp>r4IFTb$FLynB?8{_bcL;n;)q`b7@y#$*b9`g?2TT47u3p%RXR8 z9tODM^w?`ki=}G1!jrg z%P3=!<0s9Agbaq1{Es8XsSS12&0mb;viz;`0kGsvd_y~DxIm@xJ+E;fJv4xSBvt4- zK~lv~?)7d&$A2Re(3)ud*74SIFWY^4fmuqE?1!w8MF9&2Lhleg4okPykr`L91tYz} z_qg-((NEtSL^V8rrAiDB?T|A!&(uK5jazD#WFnE7NN3<_+PlrG9oe}a{G#z(BH%W6j8jk8QzriOGwt*O?nY#hjYQ<7D zK}#d^{6Q>K^zQi2`tY~c=N;MO^;_W9)Knh5HqX>V2L$ojEt&B5RJAq`KS)dmw%Pg_ zm}W2rjq8{_2lM7#$efT4edNL3qstJ_i7-h;$2qD!E6AGhPyhpar+qJVA#D790Kz{w ze8IhU2KL^MBW!`CKrAK1;L$z~UZxY-kQ0vum_B(BRT(^t#(RJ3W+d!QCLS3UvVM10 z5x%BbA-Z5Zxx@l#i!RfgM3$ImgyzxL>Gj_!by0x%=r!_XK<5(tA`TQzbyEQ!Q3;X^ zY;y7;$P!j6?)!jJw*aPgpWnEYK;U=fW6AkWMFotg778AkUP!UE=~gbOCo&m)n8&Sy zoQWEL8msXxEK$Gd$LV_48Srcj)JCfE;mh5jN(nF!efy?Ho9H-M9rMomsPRke-wlu; zG^YF(C6yTRf$(b2_hkG|G>yy1|DH2V+9mX89QIL*=SwaYXoLE|cno}WmO2cUGCRoK z33_ZCW6RU=3LW3rGli;yrJ(YVj~`HZ0TalBOu#J@oW5S_-O^Ta*L>)qm6!Do;y3uh zq%9lc9Y9CG^X6wmdTx^NG4kKBDEaLHwWOXRqazg?w9zFSQ7Tsat}5Y(JmSD(t!WA* z`*cX3n)Vh%pu&h~hIt4$PPWsme@(Vdg(-;9Oev_>?R@=7Pq%;$%jb@wBctuZhrLrF zc9(gyxJW;QnLt=2gYmLuW{M>W?fYq$L!`N~tR*i|w+LWP?Kk|dw8{|eXc}Ek$)i?} z4?lp)2d{CJGhsWBh_&1h!w}Rn?~4(XUh775DQDg06@X*RjmGwgpqu1l56_*tctLz5 zhg!`7gybE>y)WVxlscs^0L-j0&!B#@SQE+$FRlvrG7q~dPvTCovKfEAWaa*)HY@l! zKY<9bwdu=})3t-R&&ko6J^Hc2{PJw5mCjd}*M9_@_D5l@piKMlnXIgCL6$Fd7Y6BQ zvFW=`g5skRxPQ=_r6h5biP%P3`SLyv4o(CQDClbFoDWz}fMIEK-tjaSMLi=F2AIksF0x&&_?^2>| zx+}nfV?gQSt!yBwwoSZ=8Je(sCiH5r?Htk{lrvQ~LQAmz9qOT*@xR{(T<@dm0e}9t z|4h8K0bli3e&Mp~jbL`p=vKVO?mGHFr<9=tW2eWM0aSE=#0do{PWs{A0cd5ZaD!^e zOa6^I4*G5H{#{RypQX49X4f`5=ahn>(wdn-7G;QCueb8Wx!uIU&+eW-@3+z#rui)0wE7FI)jaf;#EU(MG`>l&Cf2lxI?x78VgBXyz_=lmj zMYNBt`^F4_LE6i~6nsw@RSJ1I7~L_UK>`7p&Sh$fr>B)Sz|uPAkEirrn;jEqs9`3K z?CPh3jLxbjc@4%NnW2CpFl9Ago=$TR`x#1`Wg1RJm}q>ovh(RuKeS6xAu6h)UQ+^; z#=zO0fi_X{<6=Ad?o=#3)@;;3N3zi)XzE23t)DA8iy)Z?BzkMZAA6f}J%IN`Dd|9Xr*-l0Z(ax5G^tbz!*; zc?ieq2v?4a>)>5_7w_}N8qF`et5d3U%ebWD0{3wM zlF$!#ctTcerpX@$B5HCzyKH8V3wO<#C$Xrp|458W#54yyOQ{L2jQGbj?F zk4Hsb*58&*RVFtf_Iu{e8-w}uD^jt_Cs@>mzoW!}@HD1W0gQ?Osr-8W*S<-$v)+zQOaLrNhtnBd_WAt=Z;yHk|zkd6U{;f(Kh&iOrmX76k5wbpZI()Jz<&*^^zdC6Yqq`uD~Bb-Ku z%eSOHWaRMK*EA*80o%)FF90fYLf<)PV#SAxd_v`&S}-7B@8??#=Z22`aHB0nHI~4* zlFHX~si}zi#}0^8f!2SO`;|Mjp-h#(;G8&6#=~iY{}!4?uD(?O78_QFLAg?{vcg!Q z9riOB8J|hNptuwCp%CT3LIJk5d0?l-Dt09L3wtKK7s^Y)XFcB?E`*hACAofl$8T7s zm({=GIM!PST?Fa_UYMGX{vy_-W+gUG19WO@{NCztMXRkgrzlh~tHZ(4P)Ru0{}~cS z^cO8m-cY@z#K&m%;y4y5KE<+`U8FuMN>RR}B|)=H<=--=L$-}mcNiQH(;(TJia+P!Pw#zu^AwPaC1d3 zdlY5w;zC4CvhOrrDGmqIg(lTpGZ9=_+9$|Ser}RPQGYSGVA{wA+`rAx543Xkjih`i zCAnf<1`EQZl7?i_9>>?z=^n>lv3hs#$Y}5SMt|qDdDIZ|y`JQ>=6ZkrLSOL{;ym=| z|AL4u0W|u)0p?V_g!_>A5&x0JRw0Z03Y|4_S89?86eMh6vOiE`iHzmabwn~N|GDtL zk|TH@Oqn$roq+DbU-%vBu+x8~X&!LLdZMW_I|{DZu(I726sQXzSo`}N8eUV0D>ZjT zB%pa>Vi|;z-ZCHXL3-aY)mw5}?-VS>+D}-xA^dWG2Yly$)A%AQ=?Q`4iw}-N?D2DM ze3irXAx7)R(4*{a5P}WVXpRr)sq9%ikci}H4{1#^1n$eZ`}`?|1-A@CFtDy@;VDru zvd_+ZzGD?YYn&1iu9EQGuhyf^smoRJzJy0crRW2te{Jg)iwgAM&QdVc%d$5NnINAR z&b$`O|3~N$a1CQ}Hb{nv98zq;|m48NVxE59Fm?`Bce@bvrDX|s(2CMe(CB2L0`bw(^YY^e*az)F?K z+G7dYO-()2e;>EqyHQ{tQZAPhZo=aSsuBu%1L=>mU_3yf<=}HQp!Bz$jat};WBA2T z%dig+oGg9xL}yUy`cHi$T-(T_l_!&cYxuoyg%+NSa`gp@ZKb!Uhh*$$GL;TJiW93JJw!-o&!r*_SGjO^*I%<9)CN zNAfiSO%BG4bkH$C1qOZ8P&SsiaqY-7h_y)SMpM;S6{yuhhUF@TmuTj>#nmBxZmJxl|pSz zBs-wmY)48mFzHga5Br!cU=eAP;&6&l7#)R^310tAV+Qy+Rgz*tMM)0D@=rEw?WZgi z3#}OR)2p?#=lzEC-$lFYe>_UDFs{#mYD22g>W#X56M%Qhc?60o1-kd{&(6uKzcILe zaHE;6M}pz=f=rU+8AY&Bh1)|D{rmIpy{2=oo|N0HCbw&x#p1QN%$mjE6Si~_1Kv-@ z&K&gh%}1O&X#zJ!UeOXa=76eh&$#0|`#JfvvvGni;~DySYzI`_j`r5R+u7DAL_Ata1@9Y|I%1ZXR!x11=<3h-_YUk-Vx{>cfAhXpHC~~iz zgkf^E?Smz{a3}@Q0j@ji?wvy;YAws4EN?t_<{<-L8h`Kd-C%(Vbcz+Z?lhuGKmkJ{ z^2)=<$Iw|kwv{MPy578utql_3ReH*Ha>~0Gt1g5SGXYw4f>j^a@4aPxi1!;@W}|<$ zFiSL}y40D&Rnh8r>AXoZS6oBh?ss8%J; zw>ng)gpL6-`n6Bx(nr&hDO`VBR}NXB1vCs^CS2HMqnoygaSK_n#gDcP1*i;kjZ=kF zBoD=FQAn(-@Z>}j7WWWd~zogCgD<0;stGStj->;+YmM%OC=jCLKZn8;k+ zV;RLukFV}IATR*LgAPQOLA?#8Oh?4qit82a6$O^nFe4V79Ln6dD_cw(x6(+GegOuQ zjb7EuFLZF$&_be}LAEC_duoZ)n`XeBnYx41B3s4Lq(@bz6)re}2SB2}7Ad*jpCmKj z^m;x4O{usTepN7zb2$;@`;qUc@NT*#L z(EGL8^#pg!-w)MK!hMg|19Q8=yrMsKmv6q% zYH2I-q8BJkpd?Pd{H*2OE9j7kl-bV1jlpx62pkf}{3yasWAwdeE;-Ptw|6kk~ zBACL%3Mx>Wkez|;f5DuXq3}?I?x?2+SR-&1(I3*MKZ&5vt$6y*MoUhoZxgy~ZepH$ zS(Ax9>H7fS`qMsh`?wr%ckGA5X)1KBNoB;q^~lFqVMnIEQeUBIdN=gdmX8Z+wPSpN zk%bg3&J0XSy{_b2;ehtysi#A~6F{6pn9kaBh7S)FAHD3ytDF*Tg6o{O+z|_o8XFwz zz&IW$P!_@8WWZk3BbS~9*4Wv$w((77;38cw9^H_@b13p9`l1 zUj9)6jTk7(aeAJm(&esFxv+_cf^XU69dGsQ63fimtLi=BvTU?aeW@aA81&&woA8N6 z{&&OcIk&-6q@b|QI%6I8PbVh7auKkULZGf}`)j~hZW8-+H&Udu;a>3%5hwq7f~D_*ZKBdm5B;fCSgPz`DcONWYe(uR<@OfRmW&L6^#oKzh`# zy+bPgKIX2wVX#$T2h8W{HYGm+Fo@6N>21}GB+8 z*9g8wzL~TP-n)(MvF@tMa7*URKT&E{vU6w(d->cg;TIh~7o$?VyjXq`d!Jbwhn)Y? z-)d8B(3EJT^FINOWM_bJR+Rns$2tZ~gdi0@*LT?0eq| zg*?736fRH*@J}p1iC4Zo5U7NPBlTJQQl5sZ6ZY!S&Gbdw_OH<$t+SkC89yRa;kb#;i3k9N|)!rFI8=8mm>JX4}QDG2oU z?Crdgg7Gtl2)hp&&39N9*=xK)lGL!70-<&z9&mFO!XR{QmgF~EFwJYLed{Nc;f{O& zrKe`cz+k4li=jmktfedC#9|Db3!4I)d6Y7DswoG2(ndPQd=Y`+30X)<4;#ZuyS$be*YZU|UM_MD%-m z?BS$F;H&#*Y6OFLuWN*$QFKXGyLU)HMI?$vSvtSA%)bAWy{XOI@ z>y<0YK*w|bVoxt?Iz^g3HmCiT>ocA5e`q;AD*K6H1sBfI@MC33V1>QFz}RX!!<;N?NaV+bit|^q{l3{wI0Y)9?po|$L|hQnx4q@hqz zh@qfm0S_K;4|{#lY6X4#++iPF0wI$awEYh}1h+?Qh+rFS)nLka(vr@*1^EtSuXTN#V?-K$$(#98rPc!p^K4U+}Ze9HRwdr+d`c;-n#|=nzq)| zfTn5w^LHOhTfn{F!Zzm9vLizEL>?jRKOXk;Mtl9awZ+O%cQ<;6JDYu@kciXv5S^|( zX_m|kEq?GRG$BuZrI#X6{7(T6zmTDY!h7=|{t9}h^2^}!@x}D$;-=#d?(`Oeumn<$ zpocHQ5D4#4uG5OC)et0HM#*#UA!x|Ua{?I zrxXAgnn0EK7eH0*iA5qHCTOcsUASGPwAu`}d>8KJsaS-RwhO`tli?olcbAiawFbm~ z+FY<^m;(i5JTWSU7SR~YJn1|uZa4AvMt=w9zOA1@`WWHW`}<073GhaaeO6_1N-lqhlqa}vt@P5RZ&lkJ=ZKElIYXw)Ie;Qs6S zOXY^3XA?wEebdV-nfi7F+1%;xO=!*v{$mCRQ4_txvB#uVR5ZCN!*G1Xm3qo-k3JWl z@6eitp0Pm0SsM>~s+)?V{+aZfH|!L!qk&#R{3;O=o}@>7h#g<6@ARX)b9&_=zK7_M z4G#Ib3fcrrSU^Si(Kg5q(}Ea6tx6v;_7!=vwm?VISLP4lAuF;Tdc3D?Wx23TssO~c zE0W>NuxyF$7K)Xzvnegp`1fZoNJdq3gr#NrCa-BHP3T;W!+`oa?3+jc>A9GH$yf+T zUI0AX*oWg-V(Mo6oe|k~?3^^s`q;)D10ID>gd`#=8b0YX^_YArrDzu=|1a?w z!*q9}cw1<2v)}MEa~X0Wt8W{r>k&7|C10FwL^1CJ+~)O+W)_DH7^N99A1}!nr+6X* z_mmv__)eAU62>9%?0pn}Z>l=nj8+(utF6s)?uNq*ivz~kh#pD(%O3Qp9HY?#=;cJL zqiK3o%|f3$U~__;vZW$0RE<5=*33~~R@>urW~|Y=jDJFhOimwtI>$ZpwIt0kx;^-)3Re^`mB1ARB4Wy(;aqa< zSIV^6S{9B!`AzcpD~YB1FtqdkU9|}j;PaO_bM7y!jn2gsG|`WGPXriqGQ)^Q@RTZa zEHbrR=+2-0gQ$xdsDR5B0R|V}G!&6aJIfu75!bV5aP#Uk zvPKVd^mTH^R?)_&t8AY!a(pU&tfB`eG_~C8rsBR0Ml!acedLup%?od^lVdlYF-^B3 z=$N4s`&6y074JY13rdBr{8zX?lTD9~|4u(fTQav{qt|B>lVU+T2AfF}2igr2FVD@D zNW2c=Wj<)>S+K$wY=%E6^qTBD8A-Hq#3Xn`S7!m$^B8S&-=;q1Rkb9Qi4oJ|vh>mF zAOjbq-pcUatk)xi8J|E&QIC}`x=$NaI^aB>%1w0TuvlXp75QhD52l>HuF@IX8z?V| zK&#&0gnJqRvf5&IW#dHxXXUzZHk1hdgByE+9GJ*7Yg@u?A&Jd|d7J0JGBJF?j*J|-nKAW&53VKic zmFZVyoxAD#r0*dyK3J=VRi*!BRz@L&Zf<(}K9wY=rdK!KY9JI}-Zj(K&0ue9E7>yz zPlTcV?b7$to58YsZJK*Y+xRhLlf9XhhFEhj-Ks|ATl8JBZ%y)VC2zYn#~s!X@C}E7 zCH*I@y2l3tvLa(S9bxLItK09y&;8?*!iW2FByjR&qZDwf z5wV6UZRCeDQjT4l(ad_A^oD+|47^h3nCj~PO9A32hrX{qW>pj=clG(Zw1QTXp45*b zep3IF0szc~J9$R6TQVx*l^X+#_Qxl7c==}wa*rtWJ>CVtoiO+a57Hmts@IE@?F@^T zM}x$Hw+{Hv%_K)kU1?Wy!M;ze!2u*1r%@9{A@_zvlvl_cx>QcGUCezs=DjeU4K++f zvS;+_8NmwmiH#5<7<$E>Q2~JAeGVOLp=x$GQg_Ypg%!G|UTF_s?6QhmbA@_fk%qgo z%EFrilfOhvNm*mYV^kpNB11~NZKy)$tmE+KNV6HRJ2X}s8JI%QqUkeIwqt?9sK#Jc zZ~egg(k0$~guG~Qa;I!G(vy`WW!NlOz| zbB&XsK3XXc#!jl3N&Ib12jhlqfsO6{rWLDO>Nk8?dn5 z&!Qk5u6WJBnwMbI>C>En{(*N)yJ#j_WODm>uOjU0T!lQwf6pLPY12M|Aj@gkm+wRcJG8BW^g_zEPHp4JqP+%i(6BEcEL_cj#r)c{o82?^?4@o&c zfy015D@wz=^}OTa`tH!u2ZQLhlZ+Hy4zsj3N?Uqdc>xXb`e%ur(8rQ3G*wC#XPaI@k~jCz#1G8PR2$JXZWKxEZ+kA7v{U1cz2fFY)wqgFes!d$6V zrSRMqp7aAh9L16J&3yI5Ly}}0{h!A*S|diB`#UN#@>D z>>72tDvywBLn~FrD0qS;JL5v| z9_@!Lwr%~pEv{7Uk|F5<5Je0urrcnj>#)&^4O9f6%GDY@1dmc#5GMQ3Nv-oFpYg)+ zgkK=9xrlA5O9jsfkfFfi$D|AVXFk{|*M6fnZ9mxb#S6x8os1bp&2G^X9Be=WN+@RR zK7Yw+srf#k=FC!p@pe{{z`c4VVqOK0bMFoX#9N`@L!M8F!-8Ns_<+-VE47ME9K4uO zXJ8*mI92)``D3CHMHpX*z?!6$(E+@V*(?}?3?%lIaPLLlHqc~b<`eYNm1d5Y$M zN@o)MDa*d(;rVI#Q(GTU4UF7G_t291Np6!QS0B4WXECS>w1V+O)qTgTSM8v3qC{FV zm!DZ$P&1D#`lzOav7v321-wEX2>@R^DWc~#+Iavo))$)>_8kk}m;6!cVYtn`2D+Ko zswX5TL*|gEJdC4D?|ItYJU~u_QA~*@aQOr8;}RL%{P>Xd`oB2&D5QTBh%b>R-op?< zrup{_{oJODvEuY0(>#8sGAxyreBQl(5wGNQO^?R}O%tE&+g7gH8iC&!9H>-7Zy8c5 z7JnF$X6v>B;DI9`2drWW*ORix^wcC!j>zr=i)}2dGQVh^>Grnr;|#iQNilO}PDta| zs^>Yo8oo&PBmQki(O~(!*wlE zQe1Zj83q=NM_+zv#VoOmNvXyaig!v4>ndw1;^EORwG;s;(VO; z0G|~K#$$f$akyJ*1(?mOgs0RY@9W> zA`A}QQ*WRqPyu>ePqUlFF^u{jr&U8MZj9Y@2fB5Duh+lqDffdOwv!Z4D zuw)8a9NZnsDD)RCj;p{|B$x>Rx`Sy28;G3l`X!BCBegW>vT*?{0DFZc4Y!@W&o07J zB)AZKuHE|o>Vu?KtdWHc#>O84?lMO*`Ep|2SN@5l_-4&!b)4I@Cq;rPpGf*znvgFQF3@7 z)>&SR%n?&Xm) z@_>dvTO$@Snow-xE9f{KgKwrRva_G-hd{sa##x#Son}H_JB%uR>S)!wlZf z;Vxn9oV^T&{yl?cuclHD9m|f-5o3QjOWDf}r00?sLgtx`FO%T4#7V|2HltOZaEndg zPNJZEX)r&cHEheMZx+%r<1mvnl!taH*Hco4mn>cA$Rg93X8Tdyhww8?u#bXCGr@F> zUlZmVFT&3f`Mwl&3ONf~Mr%`dNq0$SXKw9(7XlZKE_IpSe3>SaQD54LUi`f~yeN8k zDKWN-8ZYv-lw)Ol{zvNh8K>VSMVwHPlMF?>%|dUll(|KHObfOcBfG^M60luCa1O^+ z`1k0<>lbV<8!BoVVD;7xa7`H;n{ZPg~^J zP@14ku1~Fum*<=l`NFMD$29~<-W~icu-T?vMvI|Dh&R$(lbMHJsf@l<5xN|{gMf;m zo%8o>q<>JEAXgRSsFl~ztpodb^u?U}%hEVg_6xxX#GbYHbBrF9n~O?qlIV zdO4JZ+E<$b4v@?g2W+}WHUN_$rC3<@KcpA#j_T&!V1OVC1ZoAn`Zd0^QE3FU2!=N! z(qSWvsLZrT$du#rl`aUReYD$QNV3QQv}4;i+d73+MX1bCdQt*JMueJ@nPLLJXwcAJ zBOtUe&^+C|d^-5!eWLGstLm>Yt$IJvt+c#0)qRlPcqV+WtLE#Qc=fT@iHqH^=>u5< zN8zQWyxiD+`L>&5WQnnf6MdyusjsnFszAox&xnJl^j+}Osx$bN=^shDxB%HAcU*_V zR~unW&6Jy^`iRa1@!GW*aomz`zrE#5RCkK2!Qx4X9AbSIRk#q^Esmyq{OS5_?Jfu2 ztHu>w5AJ z>YWE@zQMv*=P!`1zXFEn8NUG}xxd3)6FZ!o){H>2f$?bBJ=`ym2jCSdYAf0== zuq@}lADS??JOTsHrRlzFS$|tU3dhNZ!g8;)RMKk&660 zD3~1hqZ({XXxxFOi1+4z9HW}RIz1N~Uxe&jDK+Y|q48IT*+95!Vb(E?Q3E#T{r$v< zv)Y=8aX`h4^mpChYU(ArUH3&Ylz}i7B6##@(&A&Zb&HI#6#nUEbSNprm=dRQ)Cm_o zJ`#}5i@??Fl*U?i%g-RY_LI<$AbJ* zqKyw}EyZ#4usYIbGiLWk0^w;Ye;DF!%@m|<7>nGecB_p)B) zUq?Whkty`&;$U=!%<)XS0s)4Qae(vAwJLvJxx9*P&FLBh($M>}ZN>QBR=NPe@2I7~ zsGaqA?bpkang3cPqJHyRyhELT@5aDJ+FP~Bi$|RFtA!fhQC8}ET9V%Pv!|~ zotEQZfBaLQ5nB4IBfAT^9cdofLLNU(aooBK(=O?Q_R*EA1i4AWpLal}xNDwWWf*4p zEFCn3#^6jy*}}D@iu_B9_H%(W%d;Hu2&yUl6fw=X<9dK76}##kd-?lkxe@gnjZ2b2 zkIjzbeA{2MZKOv-8Q7r zR{>%=`-Jt}7KN}wwo+gm(C(SRG_djO$IERcE{=~z?`o8d1s=3yW+|#`{jxXO{(#K# zWKc#Gfsz)|$@&V;PaE*w)cv4U!x+>X9)wA}&Ai^(+z&p%ehaCt_;!6$ezW!A5veGG zD3c~`!z)P7)WcD~u7=?qgOBaMUA)iXOXfb+t8h7&*34YSDvR^CM>>7N6{C##j+~Wv(LSc{H5QklS71uR zXu0xwK{~M>fgkF}BHl@VvXS27dY!wu5D6=z0oDn!lw_ix)ubr;tzrTT%zAL-E)SI> zlea9Q0O0nXD^1htczzG=F}YjzA+QTsGR_p`E!$Kki7>yYI+&ee!dY+GlDH~G9thq?`GO|H~d&z`5*#pD< zpc+Qe{$RTnk9-MyrFlviY%4eF>JwpllX&>$-cC4t=`&LinLQVu$L^?&-r=R7!uZ2p z3XS62dmvUF1ha>p$iUVveB|IUy(F%5CmFBpSmRqI3F4L8yF(oUe%4lu)pT^8vPH#7?S;-S*?JwKn| z+mc_oA$C)ouH%#%m>5{P<2~Oj2q`~qhL-+IBRQ`#t_Bolg;o+grv+)Dbw*jwm6R71 zT7G~{=5qK~GF>s@y3L{sP>#ib>xppCisstO!Kl}INgk_`sN7SpX9*~FbZ#N;GRLqd2k)@Fv;Ifm|Uaf10k;U)Nc_=~#xAw_^J5~~#T z&2YxdJ!|6HFGZtz!I`hjfy*NTETjTzWM{@4rZMA~Y8nf&ZE!K0bC(9Za&3D3)4kbY zHD{7Y&A!>uw5!T+1nUVzHOPu8q7?{!L{+As)u)5yS)@JdY53ah~!xYKAF;B9;x?e8P;KDfR^;xoOD?x!l<7k*%%IJuo@z_p|x4y2>O%5Wnmj0+S^k9YDdeOMUh~)S@%lFchIwlr~wQ zh#dk#uPnq*A#+d=C(qX-;NUx=yP&76Up2zJmkOJw5O23<^@>MZEYn%$SQEU5QoV@M zCYKu5`0Y}<66Y#FMVi1qEo+7#7yZOf-f^nGg;7^u8Zwd0-_}4~EzlqQD*(1$Vrs;y zHXH8s=DGYpigQTTVY1(jlC;5o0PV|IdfbsOM-S(6O&qtw8fotS+cw6A*A!W)ON2pA0=_W`_$|l{WpQhMUvYIk9mG zII03N>3lFRc}h;c@iAOE4or<`lzMAiF9|*7-p9OQI*0(4fG?&Gsjjkk2kW&XB1|s@ zVXJ2l?<>w5Cba3qD-y?#B`JY`{GVJc=R)wzkiMSPXV4YX!F=)P8-s;EtPb*7^Tdx? zLsV&k>ktiDnu-|7QtFwD^WOV6g9t7h+}{YJ=B6fJy+rbtWfk;|bZwQn#z{58;% z5(Ds96Do)XR1fQ(fm!yPfu!PC1n-%_g@B3K8N)A6O#gMqu1bnSM7q@+LS34H>@Xr} z+j_*VP!36N@`W7HYn^!c2^&smXbO@dJ~RmC_9|RR(E_ZHuIZFR4^IbY{ZA|K-Xl|K$Az8Q^a#!lDa=7!%3q9jb>e24+cF z=(`XHr^4HNAfJ7^%)S<5fcxH8V0YQ(nk7UmMB&9?fKJrU`wvRWHdVnew}oR^OG651 z!g6wP_lGFOl|ct}ypRpL9OzWNA#E_WSiK?wh~dT<6z3#6dN}Q>{t$%r=j&%bVgy*- zm3C~_n_wFmAJ3A~>UR1GX{hg~aU0u*ogaZP-p~<-Ce3x@v@|*U0s40^k@{_}Dd@+8h|VebL@1^tH#+J3W z(3eHW(%CcCYrC>9OYjpK5NfXMrX^}h3q#l7s|UlyfOQv3Cho3iqvsR(e+uh6iy{Oj zmMP)}yFP>$pB?Z5Mp;?PFR+?>@98|zZzhif`AAg9=k4grRqxsf1yl?^T_(eafM?I= zwNKM)LHF%~N>D1-g*9BuD!Hz`*RWK%4uUgD5{nu{h7W06Wg^LvsWUsw$odG%)-;I%LK@LYqbh13_5!)dKHaCC?D6J zyK?-PkL_Za)~<|&f{?gN`o8scIH}D5SNDpYTS3#8jI(16c>h>b|IDiqE7CBOQ^NT(_*bL= zecE~KI+zMd+VqClsduNuR}%b=U^^(V><~?ULnudx6iKKkfr-k{x%0U5tdB)eAm>b_ zD8lblYaYC%p-zgMLJ~d~0q9zhM{j2XM%}yM{h}_tQYh#mh;>%lrRjuIOI;1O8rLL; z)F@z5QiKjLMF9zU|z2{wkw`sH3{TyLa_W-T7K{dC4?42S;(zKT=m&jUJ$^RmNXnK& zB7GA&gmYmDZ^6 zFvT{2Alc!T{B7YR7P!k56O>N}LqkyOgq?NVn@dE4)k+knv*>3ChV9s5g(Xm-jt#*{ z1h3XU z7=-ETR4Ek)xF>-+)Kpfh#zfR0TQGaiW0Yz`M~etx)`HDhq0K1^PXZ$*o}_d;DAJM0NT4DD2zqlF5b>{(umv#cqKGPvxyVtSi^n?h<}q2HhD+PkGPxVZbmG7KXvU<`2 zu`E8_;9Oh`A}O&L1 z#(RTr>txt`=11gn5&-MbvG1+VMpTD!8nhkft2K89|5=O~!hqh`yJ$i?O8X znG|q=g}i8?O9I$rJALRb-CE2c z3a}1TStwTKz8O$(gBDm#<(_+^j182}Vx$twots0qKzSMI9C8^TaCMPv$+z_^6}#w< zei2fqb-mLE#k~e5wP*8eX$a?2kC_F8a{(6@AY6bbDjMnZ8Q?PnR-nDKz((RBQ) znU2dcd=`&*6Hs}hI&nFpMW!@tmsX8cF$wk~t?;6f90`4Am)v*32L&7mS8VPTTvT2t zzRJ;#3!Iy2MHvAP)qndVw(jkd@SaWp4VX4MWk085tURQ50BnDmxog}(a8o);Xl9_D z`SuS%XuQbIq5U=)Dwl{D zb=X)-v(*?6mx3{0iJO=J9gY%jX35-tuxynwjV^{J=hGf$YvMMSMJ4$(`i)laQ3oS9 z@f%`w6aWiVvm|bcah}J<{w)!F1T4y9MtRwpR5q8T4=zg-gl5S%c}6X2_=my+E(>h} zY62fGHop;AB9@2KKIxsOtIS)f1MyK4x3W}gC`6=ISoZ?qb0hpPzJ7e_PXvk}`@g%c zs~xE5{7r3&S|MAM*&2G6O#Z?WgZu&0?>i_^p;T0$q+t(in(uaR@Am zTSJap8u%RW+amSypL{1wdRs?@SGcAREC%cjxA;vbVpjNq4!?=CG`)Ir6c84~A`aO^ ztb}{yR5aKFL|hWPm90)zjZvxu=s0_WVdyyZ-N+A? zYz;9d!M&i`sNqyPw2fG*6^eqo^4_Xcb-dyR0S0#fb6WCy8i`JyOcmSEZkL61pbT>y zjldBQDvPN|>#@P$Z1)`R;Kt5$-lp3+@1u_LGzdm@yx9!PUGGxwjwo0LJ43x6#sk9G z2`PAw9vTtSNEJP|#I~aVP)`$V1{2Y{J=nLWvn~Kl$$*S(Q7^8;#VaZYVGDX>-9h15 zo@NzZ4z>ce_#K}4EGg+m6yIhk89pKsS9ph5#Ye%L%CRY)R@9Z4{33hYmID5&TDrxg z$IbKorC2(kq>2x+Wn|7P8aZg5=kqhX$cJ6*YJ?87=)E$p@a>}qNd{Nc*UgoB%4Rb@ zzIGZ(>AFc`LtaEVP99a7#O^J|mUdWe*s5kP|vt3PSqL z>1E!l+UhpOr1WIf;%ii(>tAi)mPTC_F;$wBmT#RDt?Ul@Vh-#SzRN;(exLzW`$fh+ zmQ`2SU)*ZP9atP35dv`u`l$i`FALzP&4?4|RCe|KHaeP)%8cF2X@=ty?SH)DlNJpup4G~ehhrqIX=Wg=B`&nR zwKoj~x^6V*u4z~(#vz+vL0dqmGm{blV^6H**p%o?xhypI289`0)jQ#{xk1y1-hPyc zKVSF*Q^1?WLU>}q7vSq#6ekqB0f3Zx$SKOnd9HKg11CcJ`eoy0i6^rGxj|Y3KtA2B zpE!M_lQ4Mgn4ZN-Bgxy2-PvGDCIe+}PoHmpug*osFEGg{<)`-QD7jSY&W01h;j0_V zg!Ed%h~2jbw@l6?>E)1C3ZI8Z8Ly{WMB9*=g+a&AC{`U5i>26z4misI9aVIcEQcnp zUmxUL9WM}W2Eo`j!CU8Crz0V`BF}rIY|-E^Dg1`Ox;vXdcv}1^A^GQ?q}yBUsyfII)4cn@D2hPr{No}6d5CDIS2*= zLk$NqR5-NzS>Dd~G2mIxWpC&9K!%U?U2z&t}s$- zV2ZWmQqIm^lWiu)O2axC@u97cWWau!HdtLVikB&Oa?j(vfjg%&OE!4*8K9+4^zA|W zZ3I*9M+^YRTk$-J$61yvl#&4}*`i|HA|k=h=o~n<{?@&9oVJY>3D{b#{3f=Ed1Ms& ztrc)w|Mo7C(XDJ-R9s9f)V$ybbg0g)c}+ks?s7B#@R?9(;5Y^R%Fcs6C%#z4J- z(wbNt$lnaGN&(vx^+6PJXauseHIFf1Nd_yi;I9Z23-Av_gl?dG?nUmeDW>kpy^KYw;Y5YS0RcVraUUQsW`~ zc(ZwS>KycM8usP*@8s!%#<79pHeEb4MDWoJn-Uz#F@NOO%1k1cyUf1Oz5%n373yC? zJ7Gfl1#GD0O2!dAxiT1FWM#GEp08^sA<&=Pb~V-g{2n3P3H?F`j!`xm>j=(+ zjK?EsR%P*l>g1%jW=%>8(~Cdn88}X>ZinE!4(Q<;}pK<>3mPW>-C^hwu z=~9wFf%$J_3T;x`L$$wZE}M58W{SKESovtOPunjjvXkMuYJ+=K>cI@6h< zd?3h(0m26XHqNfEO)kG$%%H3PhpDq*i|UQqJsnC&OAa6sf|N?bfFP&{D4;Y$Nl2G8 zL#K2}4u}FuiF6K~($d`xLk}=V+T(v zRwTTZRuVQ;_5K_5EkYHN4ZJxAe_x;?m7qq@=tU#LuOe#z8hL2`XZ_&c)Z@YhGjEqx z6+CfMtH8!TlXr1H?xJBMBDoeW7v*#hOD=S&pz|GKI%~*1eoi9<9RdJ~KE=WwjVuKg zki6yfWr13D!{T}o(M3&bftuAtyt0l#s*fh%q5ypl<(uAY8)hqWO8F%k2OkGhVl~mM zzzV6;Hwg{h($^XN5fHD9jY|KUIerB)WtsOIiD#0gTz3bgdaHB4J(RWNIq=4ItVz=H z0zKLePLsuNB7~h~7M50CKi!Epccc7ii9$b$SdW~of1WdtKdfEyUs{4dcmi#g$ zM!_)fLzCYcecEz-+U~8oSBZ}&M$zGwACJp3p!OaJLQO>Zb7*6iCGT6WuEA3HuaTnI z`wY4dgjzhid)$+ALM_59{LVHp;-B}Y@%)!}ca&mvfsPRyUJUCpPmWH!>KjQMYU!xz zxtKrSAMV8h+@rIFpOUaqCGBxx+j}@_<4QUf1TOPN|Kw7rjN_+f=}6=n3g*u)OvqV( zdl$oE-^8jo$cc@B{;9g|xW4I;y`(<`jH{FIOLq-J28GQ!p_Obz`Ic2~?q$qs5rEpA zeXh+z){F!Zr*WUfqJO@`N?TfzB`hbz#66I&QW)AP7-*Q`JnDjd!9$Ou+^OdyAs?E#veLE)$Rfa3FAKKd0vL7Z zMj=X)kZ1g^V(O2;Q13z^)U^)0AJ!aq0n_kZr4cu!EZY&{JtyKBVxZy;za9CYToSmh zX}AVEnez(#+Jt4e6{bIXnzAo zl5+Q@+m3D##cfb{rschts;cEi#h9*xjzKtkNA1yq*P@5dWAEV?pDN&)dpfsI_XoW7 zEg&+wzLu}nsrc|YIF{=q)Q~~mr9>t+C~E^Dgj4h(D+I)CRn(h1jJyjTqDG`;PAzMA zQDY9NJ0u^*nnND*t!r?v)0|vh2P?2aYeG@=Jw;WbS`(bOboIf*qd~+Di>ITYf=^eO zEJ%HMHQa*Zw7Vq2<*9Jq+=$f(SMF(fp~5)c_l5YvpRfx@{+Gcsu9neRF5DZm+g{tn zXky%!mhErq-rY8wc(Q@FhqH?_5l^!*@nD9VYbciO&MQ&2kj`ffvALTpgwh#c`^JNs zOCzrxx*JNSr$yZ8ND$U$%uxJZc;V5L5&}aIfg1zRl3ra}np*miW~lj9+;K6%QsMk> zm;XJ1F&A_U1%W>GqX&ukOG)ezmIJ-9ZZf&Nb>{J?BxRL7SS7dV#!nWgX!5jB2aNi6 z_He*lSHQ@(A+Cm*?lTpu%zk{rA(SL3jNb zJNcGhr<2kqvgf}@P@#Cf%9Qf*#v+8w;~@_`D6qz2q29D*kh1knhYqvxw9irV(W_ZA zK0rF2gdlAED_+5%NPKFt58pI&0!bTxTi{j zOvLFHg1^b%HekD{wC_ zOiad9ODn)pKoga1Vsyfjy(V;OF$v2o5M!!|7m9Im9pb(R*$>5%{Zlb}aLis=ILP0#9T1!{ zKK_+50g)zC86f?-oJ=&R!4ulB47zePWjag+vXY}~>C5@kSq4EvWMq}dMBXOMyeH_J zp5$B#nS*-6%nxqjuqNBX{ow`Ht!o$DZhvTjI7Zwc6@ zc*!&z2J={K__@RWVO41K0Z*82UC@BVmzD54QHQ;ixvXMw8$rB%b`-3gsa$!EfWemJ zGn>s zTRBJos^73%4Sms9Wte@A*jRGb8~{OiE$l`xX)J_#fQ`W77(k=b1O!p*h2VOEHuucR zUkw(kSOQfR>%ym>>YF3)U{n(>pJb7bV_(TDN^x0|AuV`!W_0(^l<5Q|{UxvQ7LRPF z3jEzWVH7&I98-_%`9H0_9Kf_rM?FX8l{3ltC6jG_c+V(FS*&vIFL6u)T#@>-hJFbQoY-vIh)hy5d1l2Ur<^fJ z_mZ&VIsSx;XahLy1H|uqDpvZi?q{XtAlo@YkrIRq2BDT?WiO}m&CwNmYgW5nv;RMw zf~zae%$&Av1dMr@lL2G}GDdy8_4*D%cw`>Ww&48oXbK{P+ExKK(E8iQM?m6&gOyF4 zapNSB!0VRs^eQ5nJ(iO@7;B#iV#()I|E*AJ}9OCuk z%;P5R{2mxkYGLYZW8r^&tigTfoQEyZ2t8cdS0hE7b*qOEIzSfH~ynezZ zzJ(Bl1LEE>pxqH?I3!faPtTShb%?b=tId|M>0yZ3+(v3+#5Sn{l~r>6nbjz*KY56C z=6#JZ$XVg>h{;maelSt`{BSil`{&=0zi-gRcgU8)lyw>@#Wm$Pg|`7j#THUyH?s^( zd8`m4d5XmO_Agab!q<5zi58Y?YQ!dg{FNH`-a+_WdKcB6dlpDMMKwoc0P44|do~g4 z+IFFkYdR#>bf~gx&(b6JC55uT?!6`2cSL*hg>k1^!H2Pz_4)Y`6~6rJH_;|Dvr*v6 zS~_VdeU2xy8*fgDnXf{uGY1||ULYiRZ`VnT z+F0#7PCM^@Czez-N6_o8Jgk35IrEE|>)5A`2iOzjnxL2IoPEvXrbdg%yU!zF-*^di z#+`I;N{kZJL%kZGP&vT&RMrAVcZ#j}pDdusN>nVDX zjFmhkPw1&eZe~twvZds2s0p{-)8br7@U!MXQ}(>DR+HS4R7}B^w^pH=k<;i4hWgyJ z-JQ=v?0tqWyqR^F${d^d0)n1C#HYUFR{y#hvsEg-#ETlH^hYq4lBplpf4$T6j$l|y0Fa^)^$hcUNrMJ+Uc%9eKE>&xnls*M4 z)UHGq6sh?K^Y%db+i>&NqL07F6`hWgeplnr4Yc$EI|G=uf69VATzD%)5kqqJ2(N09 zNW+aiqbW%-g;{YdzeV1NLOPf-eC*xwgTX8=pb#P?X-zlRV7mvJ53t?QfTdC9cq2Y8 zDkN7xuklHd7LO$y+y9qy@rpY{!k)mPlfM}tzQ_D@0&RC*W+^4MWosGwdP=M^6YJ^;V z|0Qe~XL<1~JqsjWjqu=+8eJkR)kAYI9aYh=t_^4WN9?pu_R}C&%_v-nu4%3auu9Ms z(6)vk2b52-cJ){6MvCe^O*10nrxF;zB<+9Lor-s!FPL~tjM^jlmcVN_$kqGl$lwor zHOam3n;USU#!%s>2jpd6H^BC@RY#H+B0wLG5YN4$H|Jk6(PQO7e6nFXA%O(&+`&*% zp~pd>cw%a2(YqKv&U;kb9wff|<{)X);?f!yAGd9ZF@+2Q=e&!^;DpH>1eleT|E^Vz zbGKxjLA`QsL#k-UQz6kHG4JOIdRgqhdbQ$G>V#e-GQ7Iad&RXz<@Wl}fd3JKQ67Eq zGnvID>cv|Xd|7#=KD?c`#WG$Xp>a`9cU~{FJ0=9YS+E$d za;|}Fw5-oOvixayFW-)D)j>KmP~aQw)-Yf}M-0eA>F_zNXpXa@)Q`8W;!k0d5R2}v z$h8vvV@@TE`#=$v4K=RZrAg(cL^=;>-XqeUXFJ_l#Di3^!`WHp4`&jKQfN4Bc zASMdOw}&6d`H<&#1Xb)|_gFa`5A;Fr0q-VEf64J2Rbw{mWyM?yM4GBoE5jSQg62<&wY#H7Gfz zXjvoHbL-Z`SSx6v9y)R7N#}KTt#6!Odna&TzWHeCgbgU*0)5bN@qDr{)`ZzK+#qi%hj4N`Dx8ByuZ&Tc`%tJF$O;{>jS-!XrTX&@) zdGJrsdCDc|jrLyPN!|81R5JAr=j&0=Xx!*=P!*TP6&R4Z36h8neDhw_^?X8y2QuW& zKuQWd=>m)P)RSCkof%^6YEM7U+PohCgfkCQC%}Usf&LRmx_RCThotJ|RYD>9R2tu1 z+TA5Ss2g={2z-cJ*rhCW);Njrj}|KHMfcMeijU6(H%@F z`xQa8B4Iu}4dEYoQ(I(0IcR76bNuDgF!}`73gJH$XSBdjqxg`ScJ|sDS2`b2j^=*Fs z3_v`1{9=~@SP_i)lAG&FqN-3cTbtUTzr->0%<;1#K_30a<}Ji?<;+zGLu#_}D%4`1 zKML>dq55X1riock9fk;nu~QaI^_a*%B3ocED}98+h{-Cy{=WP1e9O=V)3n_?4#7~j z-BdT}as+W!k{C1#XBGS~|0&JKhnC*ZaE<{-{Q+s-s}+{kkABwtqR${wLL2*W#T*-^)fb;w-hHr0wB9YeFv$=u*F*pcJ~I+&o&aN!^3(j0qOh zOGSP)m^-1veuoI#K=kt;F+fx9l>O~#_t@T}cA^Qg9jAotAHLme|I$gRYF*V{Z}gAd zXM#V7(oCjUDY>R~f4Tg63OdOL8iMiwFfPNoGHl*eJw-$~*SX=T^F}Hrs zHQ%mvgse1btR5f#^PVudLO?WB>)$6VK&Ec3H6GCodD@8*Y_~H>w>@u8__NHVpN$jMLQ?X#_(^;td;Hdb-Iu=%gjWmDNPc#yW6` zS#lF}TK^x?(@f_4$L36fBR-e&LH$WnHMP#gbvp~m$0ru5+!(JSvy85pxL-4OYNV)jp)laO53hcC8AUB+RK z4LRji8#C$;Kai$B+kNHqEZ@DkA>xas>#mJ!>OOYALefsRAa=Kn7}R9a9zr^N{{;|W z2SaXgC$sNEz4ga+4a76IoR1fTppUT%Nx-&!51k9_O(+o%-N92~aqiqw-G^i;-IED1 zX?<7caOC*iSOZIgz#dD29h%XOwUBlb9@_lGKLjJI({{YBzW0!>VqTaWuWsy5AGemV z`;x?cjGr`E)WWilt#V&ea6pAAk(CDP8bbuc+BvWHRRV^mQ^ zkIl~Q_siz+eW9+oy`J@_*$Kg ziUlM5crregACLbhzCs8nq_%Sl0WauFZ~>FljR%Ed5S^B+6Zz}`Q@qUrxyu=@*Exo# z1DnZ{RYzHX{vD}lBbZ0L(c#O@>Us@64JkVyRDS${}f<^rq?P#H-^(`FuaWm@dq5xNPa#`k5w6& zZ~0ac$gN|Iv!g^XiKoreqWno5I2o3mX9OZB`V0jQp@X5$_b zwwD(UiQa3p-`r{$oAwep^lR8M9|HAMggjI^z+<^U1Lkktf+ohaGSHNBJhauwAS}B^ zg0fL<#B97-sDmU&#gQi^zg$-=R$28@=roTVWD8&9SJlgR0dv zQ2!#k^sM~g3vr30dRm7q76-2?$wuF&#D_0*g9)N?O8JkvF=%r5111VYGL8axQHodF~1-yWiu zO|Fg#3#DLsc@>avj4Awb&&nVB#T00J-O!Po;8T7GlduZ|=c^`BvZ>kFOfVM#~+GI%AlCCeL(Eb&IcZdDVzE{O%-AkzI?7&|etvD`x z6X5mok{4f+F-;^m*~}V`67JU`&l|}mUgKLEL`Q2M#DnYEkK}l1$RqOE4a{?Kg14nBkvWLa> z3lZ%Xt^2$m6YJ>3*38*dUX>^>t@bY*gR>FXU1!LG)x@v&u)h%>T3$O#fLy3pPku)D z3f0#f_sYL3(};gSMBIFLcK&ac@{*LfxuHr*`u}S0kV4NsB9qj@?~r^-8H{}&wcIOt z7c27dT*W8sKZ>X1v}lbAQHjgI{tZ-EBI-^{wQMe$PQzf5eZl}pl##MPN%9g`3_n-V zhgH=A6ZccRc#nIA+QYn&?e$5h2{ciy4){Q;xVG~+*{>FTdpp-G{ec9jKck3x6 zv>*H4lZKd%sZfil#y&uUZnQyw6AA$ZYm|2k=@$zJ$w$y3ZDwdfk+MQj#G-zgK9p?S z0u{(en@jPwxTfltdtUE5It(L5CO8&+v@CR>`(gZnlnch0*9SAO16vvX8M4Q%5 zsbxmq$uUDTHwrtafjgd*1W$g=I zQ5rg^Td$7xFN{x+GX7~8JuZfoor&-48AVLiiV98HVqBQGa|*Lo#vlj>-SsTWycgoG zjnPcqmO#MyFrCIv6Ov5QSpF4F_Jr!|lNuGlch}M2E7k7?#@Ki;6{lgS0_x*Bljh!Q zuRfnBcn{<#V4wsSV}n8Rhhz!fbHXZm=??s%d-hV(I{ywITJL}bdSQ8`C6^xIs!;Hu zt;sdg*weI4K?QWaA^QTC!s?UoO>mq9P0Mpge>ruxxl%44)wT=%j%(>M!8W*)W0_a| z#RESEgtQQc+os6VDQD3Ln!4|Tlb?Xd0o<7scs(E}%8wc7%o-j)+GJlA+!pDy?QKKg z;O?GZg0n!CpWCsj5X=cN8x(b1`6kiDYhd}Aw$r@)Ml{D`iO(z{p%tdgf=o_48IKX) z$!L#ZhuUl_d56d3&q+r5o-H~u8=H(j zgboq%+v(+pKo8vCvq-&k(dvDb8f?qpM8NsfTE*`IIz+iCiK@M76(dAR7^i)KF;g{Z7Cue~4{4C;K!pgrO+6&Sx-u&vG!*yBSF<7s z$VX-x2?3m^-U>x&c@TpA^F#G61i8wfA^*0@z^X9c{vZ99>-lVNa^tQe1;C}oRO%(| zaO8+!Agi~M8jHUEnd*QXQ%P&cf0L!Bv7vZEv*6u;kFj-y&!u3nB2^zb_O42vc1jj;TSi zZw+eb_9!0PR#PszovQhxO+{CZK79GJ;Uq3nFS7G4N=%9WbBPVMr$iF9!t77Lvbx~Y zA-1U&Bd4^>{=mln>p-qyIRYfp2{|R)6blOPb{W1RYMN{fZvBsy^;alvdLn z!;mYQbNW`LJAp~>YJ({r-*3*-DaF2Gq2AmJ!TMb;8UV)#N9qu$e0)%tIx2mb<=ggd zD=8q-BZ{wr=ELD+Fav8#XT!QGVJCxrL>JL~g^_I!pTPS}xj)Bs(UN>uiIK-VAS(RO z5cu7tR>(Sg%$E)Y3+n#%aGp}EkC;v-kt6*4Y;vXe$9WHzXz?kwJ?>+unqKa^OX6?8 z5=H#i3*C_s?eUaQ6YuIj@fhUgQANo3#?G++#`jQaj5R$YvXlNJotLm#B|gA<)Xwb4 z_LPWyGxDN_4!z>|s!M{fO4?aU+!$8pD#NaPJ;Il6;bCAdSxV&xOw}o^a=bS6P3VNR zx*Z}5KE_WdnsMzi(|$3|n0|bB_LFw*DH?2=ya^vq<_jJ6-F#v-`{wrYm&Q92kAXcu z3jWhrVfF#`M@LIJyvRTp(#GV6%lhFBkP)@EDg}6CVsGHsnP8v!Hn%jqxn3%qx8D^K$nv|Gc|yhY@aQgO@9fllADw|Bd&*Qk2?jZ->|)_@%f1cb zFDx-`dNX|^H5WC+=0lC4b^RT325NG!mg;11#X9&RPvEJ(ju)D}D>x)V)Zn-Q=2ts+ zmiVaa-bu|$$1pSI=RzD+fpr2O$JZ&)N1G0cUKNXW*%z0@=wc#w+>3AHBN~Td*{747 zl#_oVjCE<+&ZeNzEO&08XK7)f;A4bB*pO+!tbPR z3uSU&#eN;~EPlso)%J&dy-gefqgsJ& z_WHtO{uEE+)_YF4(H8n2E?4{6i(%M`dSMSj)NyklFf&;R19OfHoKGn(N*_c`w&k}B zwhq)wy)0JvS(Q6FjTrd0KYFD22s(PNf5i)v6!s?Lb0~+Vy`0Uy{^{kkOa1_v$i}P9 z$#&1!N9(5yd|i?JXtpC5GVRq~iAbTo=%qZm+(eLi^V&CX$F^T3UC^alCG>5_0b132tJhm0yZCA579o?`xrH8#} zEP)<&A3<*JFP1V?HDi7~>&d`;kH1S(70LBn^$wc3XZQXaATU6A9%8-}FDRn)P*4mbuehCb@k`;!xM#Nan}Cjhw= z#XQgrnFOgfehDmkFiY%#+Uk7VVnlu>1*{2O7hu*>G?SogYc6ux2 zrc+rXaUg!83o%l(&d)z#uj*7`U#K-b5RAmf#5BON6mXe~;bD(K*yD11N*RRJ?&Ck| z3bN`NNYGX`PD|>e6}abUd%G1S=I?Pi1~8~Q8Dhd;F@>@@zo~GazVhywf6mwQz%&C1 zuK&;~yK%9y6&pQ!qnfdwG9PTKDK%vu%N$yomV z+U3>oVXo$4XGy{l;lso7X-x*YG5}b#X#%8^`d?)H>znR13cbCv@(rTjVvrw_zjvk` z|5{4d)>gGVGS9+fAE!xQH1#gKQ-pl7Wz|NmhdlOZH*~+^+}0V+a#>VPQo+w8fc9Hn zTU{wq7doh#c3hTu_38|xUJ8nl98TSwyi<`qDFiPRol)pyO56PtG@y0xe%VUD6O1{Z z$I`s3>Rda^hildWR-T8!^TBFCUsVV)SOYCe#dEnUxBluq^BUti<^9O@{mw3nXWpE@u;J`Tsxa)~-t zFI``Uxy7@S=kt;?qHJz$VESB5qv?7#Vvb(s^Ua?WemUJ(I9@8^M^VQtQTepbn*C=M zao=_9L)mk_!KU-BQpcO|tj06}eG0qy^^hN1^mQX4Lfe9iA7QVg9pHOJ_0uNgu`<9! zduv6=B7clupFU3-yHj7CT5xE8!yGI04&t#;t+5ZdV$Zd)rEb2uKgS8QbpqqTi#B5ITD;_#V)uci3R$6Wfp@IIUn1%e* z$Npvq@1wV3cxltf#_GdL?U?0EN8?vA;l}rC#|_RY_VKCil(*=!IIlEgk*AO2hTR=E zR*cN%%eh-W&vgeb+}ZfNWR?$yu5>VCrvMnNkvFR_=i{=d^$r@FH74SSQ5dk4t#$1g zD34JL0h2jn5>rL?20E)<~40;kShzliX z_w{^rw6PaTX<5NfX;Rr$bPjEq>KufVrthBU#K(M;~TDKW7po0-u`>*%2U*Df~OKk9glI*1Twbplc^KZ_B@_e^LCG@LE z`OP=UuVWnogv{SqVR{k<{+iC{>SbE|!9Fs@f))ODntWw%49x zy2tVhzvIf4UbbAUD&Jl7x4$HeUYa-G`Sl*u8mC9@=x7UTT#0xG^%+J~V`N$+EH69TI$Bh zey-3HnqQNl3M>HfDa5mu`-v!el5qMXI%g!Bty>Dx2c2*zNCFFlBwA}?m|2Lg0631g&-eUY{!(6r)tTvuv zPorFh-X(J?6eL2P%jr3{M99-T2#9IgXvL>&5ZO@q3thiTePi$`>wE_J1^Wu`x@6ew zH&xXP^7msc%qA%hN}7m6tqE}*xUCCSbg08ztK_}*rmQ)i3*KAuEZFZ}-{yuAUEMkX zFNOFYb2flV#*3Z@a|GbPAZ~olOh3uTzDyswT{XngbZAsp(^?JZ(BY$qq^I6x-BP#+ z)ah`!q(yH$B8AmvNfAN-88gD-%W9o|-*okRo^-vt2@MULRB+cI*EdTyUn`FKXO_?B_L%X5PA;eAe15U}@nAO^*t}wGf^LfFk)AAW)B= z3ZO&Up2uKRwgzP!k37@k`Zv@v1d$-;PO7GH3EVXx%{U{$(}m;>mEa*9oH(km30cg|3mH}jW+W0@e^gOdhDxi9`i)8 zQzHlC{hLSoWXSvqH;XZV(w^jSjFlon3dTXF!;C9pB3Z zkJ@tn-_Cy`TICgSJP^kevz;Uz{7x+ef+hIOpyh$EUbWHjZ5A`6bu=zU-r&`{r3iU< z683nTp16f&!H;M(B^MPW-f&30W3J)>Dn{l`9+Nd>+aI9th$G z-9#LTc1Y_+8pPjQ2SY&f6Y^^Wn@n&nW_;4r3TQltTOgKK0m!y-56KW2MH{O`6^Mgd zk~z6$IgHs+`8->3+MH%vi#r9@=1XYIxv1@;H=tz@&~*w@7RSF|&t0bErYtH;pegU|>lQD>0blJ^*I`)? zx2{&@cA(pt`_}Vf#%gI)O$gcDxP+PyWB#X_rB*O3Hil$F)ivBcrq@&^CQTjT;1UJ( zWi8>wrD}_MP3(iUpu1s-&Se^SR4Y0ltT+Hwyhpm2pib<6@c845)1}e#ppiY;8%vFS zxL-BK9(zQJ*^6T}@Li4MX(5E*iix}c{6Zc3d^G^paq}pkvznUg-bA5M!QKz+NrO8HhSr%cJ`Mi7JUf|k^lZ| zR4|njFA4|$-^M^1=reK!rn*#pX5rd9djXNkbXwM9$!{>#z<$T^S0B^e zDcb&XU8rIC4`}^sh>V*Ry1bT+jXyCuv9r5r-t38N2NZBdx%D02Yr4O#;uA&U78pPP zjQjeGe4ovlj91pGM~o63Fcx-Rt``UPOj&%!_1TXFE?Jj*tp&2{oirN0<0z7s_mnJx z5=)jUyqBRCS=Cz`c|v=*SSwVansgoVwq~UXPRL4OR_ko z(p;CJfq_Lk^0%!vf7x1VAMp5Rk%LmMC~)I}j7PT|KJ5%rRT48B*9f%` z!$r>?ya%3Pe0VFc?(4jIvv}E}?)zp7L+nb#K%y{Wyt*ZY-IK3h4mnLbx{Hit(TDl} zJzGuuI8eaJ9_hh)s_qT8>!@EmOM^EpS5rL*+wJwWfq6-ReREgJ>l1E+YLeDCW5HWChPwri=Z&2|e( zmQfVlYvopljYo3++0Q3(=f(Gg67n#B#J&IPp0`VO_5P?ieS_$&Y>&k^W{VnWTH3{d zK*7wf>dorQK@3XvguIU8H5hVu=)&02fPW)UF#B?7L1etQ0{9#=fXkTP5N-5h$ok~^ zkG-j^KvMa{W6HVqKYLK}D=9mxKO&M>bJnLCQNO|A%Cil2kf4f=v9%o!hw8?eCc|!Hmp>?`q2*s zNI5)b9Xp@3b%)u$ifR(+%9q{oS_1)@7=0&ky`2w64oM#&R1fCba#F)&%q2NTl1QAk ztfxbyk=X8(OZ_Xn2DP|s1(BZx&#(W{0x1!$M=_KBWpZn?u5%_%#Y&<3Vw0D>Vi=iC zXz-^F)`7_%s%bUkY%+EBS0@Vg!9LG@`A}V>p5%&9v zWRp?CcK7aAf1A|b=cV`*8p6t=xG>AB{BFzIo>hBam(Yff*uwh!REy!C0WnAWT9f`( zY;cI&oepZbrhu-lUxvl2xoSUIPU%}=uNgw`atFs_1wALXM zSO|JoC-ew*?$-s<72QdHbOe3b>T^opvd8POZo(}I*Z&KC#ISQWs>HV12c<#=dWQr) zG98J-y0zH0*f-jKx}tp|1CSo`aoNJKN{ITyK=H zN$OHIhm2NP6%XxfoV5hM@wzGH<^W!&r}JR?x_Cnz&tuVcy($5axbrg&*)0*$ay9apZFMv8INsWZ!Rgi`h_hZ}Et=Wguq}KgJ zzfg$>CAbXBLV%uYv#MbIdN=Fm>Aa@_#5r!LRaB)yemU{`YuvB+!K@Yz>LZw~DyHUv23%EJ3U@{#m)YfnOZ{TM5 zR+5){Xm~qE;>dX@LVlb*K&YdI$kct!71zgwnA7R)$7`8VN=^5_S-5V*uvj+7J*jj@ zG!yV=*y8pD}qH_ka4z-p7YPwZYf()6lucC z$}@-x8B&?Cx;Za|+p|?z#;sUSqx<^Q`#L%M7{dC(%9=+9;4*k?nQax^JXW$MLIusH z5`W_F>-5@eSCznt0@<96_P?lvJ!S%%1~qym!LeQEuo7&wGgZ~>Z&PZBCwxp5V-*L~ z7cCZjiKKq@4xC33@-U8Nd|x=}20_vEdb81l2BfU+XQ}ZB~>o}%oza-2$N#a;{n(QwS znA){i=`#H~rxnX(MlE1G4V0Q#$cQePkehBxR`b}<7R#g4^=faYK$^!wQFeWzewZL71{Cf!}Xn>n}f!6=~?N%`Dpp3aWrowG>j#=D?Zq}f4RCD-oi}-FY`hH3kOfs%UlJ1ld$+LlNn_$ z3GaS^wvT&0i9=P^DWMjwBld=8RQyno&)GK3Ef=*w5l;_yJ?ZPx18mjB34WlSJNWt% z%TFZ+EWDH{_Ctiin-Ck>pXWyji}Q}i`swze@f=ohMMqb|TM0c=vrNHYxZ8lxk|t*H z0*>SmY+7-=kgG09kl^MVaU(IQfZHisdKt5mbcs^%&y#fg85`UQA6|wZcQYHPe-&<9 zxwp%b`W`Eg`bxI*U5_4Y0}y1C*3pbZB~`N=^U&9b3B&FLk56UlDyw(%CRyxk3 zbE}u*UTHB9&bX%k^Vvj+Gec3H=FWai%1JKFVyTx;G05}n)wMXV|5pe}1uz>a2fVwV zY<=8LC0(pMx9F%;@uW6?L#Dlj`&dlMP{L`*Kj}9WSy$YL$G^0pyv9W11gd!n(uEt= zrLv4PSNz;YrEoxuHQO$y7Y0)&-3eIDvy*;Q$YH1 zm$dgqMGZUU&bhkDg<0QVjO4E_@CoJbElCn5jo)s_Z$hiEZr(;Qn!k1n25crTSr&N8 zz_kU}BN&wuxo;BZ%RhaMu|%kI=YDzei@Zw`-_P}HHFIT{>nZp<-y@%;y{Vt2Q-O9^ zU`^;zj^}D5A85zfxuv3TAGY){Q`poDhJ^U9TpmHOH+{OyZ-szT2dsnxx5#uQ24&U~ zyl9BL8D#1{9H4e1%53_VMBV~MkI=ES77dCm$v6i%jBlnzR&bpqje?ycOr3I;&C#hh zUKTBYmfR3?YD`?Up2Ie@9ye zo|Aj!f#heOx~%^0&$v=HZhwo;!R%YfX&Jf>R#QXlZ*=1+EpFBza|s2&+&A6hA_bfN z)JD_E-+LGXWD~|sfO4Wg33?^!w&(JM!08;LiR2M3+9Dssu;`V6zYnI~0HlnkZET|t z%p_@|_Oziz@1@OhlR(6!u7QC!=5QI7%5$P2*iB|TU?jgY{KAET6BG6#BBlC$QqTF6 z^SY~bYEEk5ik~--Yr3B?b$hAD;3rbip`Y-ab8bF+p+5^V=WZ> z%mxOztt*dB4bojcWsOcF$uJ2}Ou^4gzfRbmo?MN8$>J-vDadaJGMYu zdnJ6mzeNg7cfW&*nL?Q3ImN_NYn!hlR%_ooMwKxXBptEK$wp8rC{sacejVl;+I4k#>C#?P0)t%BSr&}Yb=DwXy=e$)6^PYyavKp}b>!`x`4!pzI4PPc|Z zXkh$bBJQy`@9YZ8l=hmfvN;%*LA$N=S>*^eHAdJyi%rbDOAD8}*#v0#IK3LO!VfqF#qNY@q}T2jaL*kTT#u8xbqdzfAIlMt`cEHM zA|Av_Y%c&KEBtHd9SJAa+vq}l%g$HCdwI+QJS^~0 zS=||yI~DjpY<+h))&KiHLMRj=WF^^DX10Wom9jZTR#x_QY{^Pi*?V)cXO1mweyk$Njh;_kMW$MZp29Zp;Irl7NfvG)D?w zJ7#kgX{HQq%RA@*zsV_Gzn7-9rk%Is!by2=GfL!*3Kx}+mdL(0wdgJB_-rw7Yaoe_ zcR4X5H1rk?)uP^|`$~EJB3BFMP=o{mMe46yPjFiSM(kuyBqZQ(>2GOHj^-l7T#Bgs zom*0a;Jqj0^YCG5JpC6RG*-IbpvobuI*tu1VfE*L@4{hA^QBSyNPIvQ`*APm9!bMD zp5-x?{tfkafOw*v!b55(r9WL&GhyD; z`gI=3!_Lr;-k?QsimQ61ArrRkJ#{lT)UZ5$bXvp7-Qor!8P?=m!mUXLnHzCnKI6M! z1N9`UX@fe((NNogsq~F0D=$N^6FStky*%C;Yzh43KCc1!w)4^HRpgnTaWJ~k>Zrae ztvH0ae&ZU5JFFMQ`Bh<6zdgZ)hTSrJu`qb3>)@9(odvBJ62vS4wG*a5jNF@mF6Eb5 zGXVK3MgFXiR8)}q^t;ROrZAu2o!lLAT&deF_GdyN`$z;GhM zrwd4Pt-*TOul0}L2##U%&gD9}Q|T>dD{ynh1mm$A^oL*S0tOp*0Qe)}3vlV@K6?6! zk>uVAUF?A+Y$J+h7VF3h=}$Ot_EG_~w^tJ8yU&`^Ah&C+XEX3L@=}&hg!; zC*LENc0f@4(97j{Qfc1CI*Jc5c4pyGqf(YSu2h<`nf!XHC&}ylsr%wZ7OR(QtikTL z$5Iu#m1eIz&ZZmsWHh35Dfe{0Jbv)t7jfw7FK-XvJxO{K3Twt*s?1w_={mDgpx##> zlp{Mk!j54DgRyZF_MlH{)G`{gcGW`_(6#e9kCp1<*UrTOkwGwEOasU&ZzzHJjFRgD7(_$4|4iH zQL%zfU;V!vMI%iYCNtOKZ!rQbxproK|2bc03MgXg?lTPE#Wr9D*B{j@*Fd+yggICt z>>saIAVI_KS2Q2YlC`%Y$y1`glZo)wmxn@WyAQngq%Uo~O{0aT+LG%RCQlel{NkmG|Pp#f{^x zSQt#5y+s=xEbYtjfRVkNf-BaF$Q-Zejsiy4OsEV#-sUnQ zeGK#N7~|}KlzuC11XCk?PEmB_?q~$$mC@<&*ph*=9h1w0%b#r0RbnK2qC&lD23NcR@E*|tBW(D|SZkC&JZ?}X1C z`7(2OZoBvV+#M4T3AG(`?nWjzsN5`B*>pxMYN!Lq>co|RbCutu>#Xp}%PYzUIoS3W z_qQ=RKi|I-KL?-^=n`;#lW-XMd9J_hkj?JHy2;&W>sTqvfEvk>zqKK9@AB%F#Tt39 z;=8pjM<*2=}_pOnwo8y{Nw^5l#*ov$3Qq~@2l0?w8H zoW}ESidU3^^Esa|;npv)26UeWxQe#}6fKN@!uz><{g4xx{)sm_(9pt*On?NVTJ*ZI zM`R0~oc`>_+MvF|0iI2Q(vf+-{9)EZO{hZFnB2m8KZ8$}L+~XfwR%M4l#n^OKG4!M zq!d3VkY`47!!(uEw&^yFbZH&Btxo-Sj&vg1XLs87x``%qcmxmgVNyVX^Ecp)VT*#J zG1K(ZYgAO`>2yVa{#vvTRlI4v6_KzgieEeegd`%u=w=6 z#Z_s?#g+~=@%_{3UPd1~&>F)@V1!KW%}a`UA91U8oxx3`V10EYPf%Al64S12^Lj$a z#y)w$y|LrQn_7&sI!kV&>28W1K?|cZwQskzk=%M_JH>UQF)g*NDP zyWwz^7y{5!{pmZ?nTlgHIB~tA71B2&1A?4uq@ltc1Zx9$n%(Cfqp~+cSZfVq&$g_% z(p$e$&l4H=9(U6?3IkbMFY4{8m^TImF>I^?obQ4FQhY5i_j$#l9@vvQGZtnj?y@=9 z$=%L5{u1At0T=bFyV^wAWxZC?d8RwxVL!<+qiuv*T7IU@6*S>Kk496p7b3hPE`mT62U_d?w49j`M!w&04zi?;2%8V+F z$F{>bBd3jB?Bk%KrSRX$(5vjy=qDca6pK_#{^LsQ3&BcnhsAarPuxPWT@jQFQa=a4 zkNo#BK+A?G8B(qb$Z$zRaH6hkKCK0_aHa-s+69?{%|7l#2hk9t+1kR#>g=nBgiBxi zET8|5QONcBVIx+UeA?Xl)xEn$B6b`n|GgTRkrf=PN<4fQ++Kj6+<^I{QUfh>RNvjG zBt}JFW@Q;y4Fg%BC3xwwM})DPQSff2q~%Bz4wQTD_E7~6m}Xf$vB8$!YlbLJT;JlwSK9Td0L%o)f>BgX_azB9^{O!}(VZG&) z^?X`2>3@K0($K~9c?Glq)4-U6&bRBInQ>@7&~E{F2=eNHyNJ4ZEv*{2DrsP?ZQf-n zL1pFASi}f;Zg!S#&m(&u=5@20@i~@m-3nm=1LWtyH_17T-6kDJDqXZ`o~%8(8+gFn zhQqYhJ?iVAv&7b3KuetFtj5$jxO)5Z5DEnsj7 zR`!2bAUA+dEXeDVe3x`PTLlz9a=ij{9rM%phmVhURhkyDFES~Un&HxiUL${231|#I zil3*A-QUu3(sLTnTVWM@UKM)9Pe^$6?#=KT=nyCKg}|?COEUj4;UZo(MMiL9ZR-`N zkr`TusIRT1I`#{RECx^{;GI)Q)YiZhj>F0Nde_o*dqngeDcLg*P>`49NSrkLd9lOU zd;e<`9k*=eu{!`$Z|N5^H2dBzkS5MK9rKr7^KE31xK8W_d*^R~jyee87Vo~j$?N1qd70TEH8I^I$?Rr>ZTKrq0L zN4;!59JP`Ub63>cu}+|tupoUqcQq$)8TR~ktwm3Ma>nF1o)wF%TPsG%gy4a!Rm=?h zEtt^9Y;UJ*WMK?)5BnPx2ko6$OKD_&V;C=VxbqOROS6i+g<`cgMyIWF`nc_{AU~he z?33HR?@!?L%tQ-WnUd3*UMb~2?lOsbnPqkN2+K6Q5~Z5Yr6kzQ`&9!w^wc21s!vY+(SHKJb(@I#;;{28k)&^ zL$7OgpG{%;c0%mg;JC;6<0zzNge>M-@l$P}C958w($Lr}ey=!SPW%}mi9;GW-fl27 zQv`n4m92E!$B4wHsI^TC_eLO!>&GXIWnT_C-EH3y6U)LsC_EG@OQ zK7HUlo$$o{HdB7P33kU0tGeCP!}JuVfd5=MKz#$K={BPk=dDj z2DTWxw3ynar=8$|t*@WCptTH~p%K=Tm&X@k#zT^@E0Pyg~QJa)6elmM<@vAUzz9<;S)%Un1r{pNRu3K zEeyawz9+YRyU8}fX^Bgr$QcvE_A(@MdI9OV?`%smAvlSNRtMVPyb|b=dL@mB2XEh? z+Om7!i4nn%lxS{gZd+TrE@j=Y-CH8jd%8~NbDAhCvR)};btJ9<{vOp?cbIi^bh8b} zPWDV%yqmy}kl6V~mx1%q!;i_}4q|pYA3&C|RZq)a%^J9ipBBUfdB3(7iLe+t4UvhV z(phnS#|NA3S(U4sB*I`WpddE@W!Y;|i(NJ$BgIbwocsHGRVIog^OPEedowrUrLREV zjBM^1V5fOCVD72Xfzrw_r9a9;r2(a~Wp=+HdBNy?SQkVy>qp};< z?H@}sb@p?(Uv64Yojd$;aquMfXMl?=jifar5$rT%f2iv&KEVd;Ckj+=9giNLyTh2y zeuH;^7jHbTwi5p?Ify<4n3!$Fh3Vgl5tXm9l<;zvQ@=bF;6N0h-U(^RbJRBD`gGnm z4hG#iJKvw9@jXdhYN6KI)^s{oc6*=7B^8qz`hA8BgJ{V~-N;3wLhmDP-Gb3uR$&px zJg1Z}{^IX3Ud0RDebrG1{SrKbui;FRs1XU+;J(QG$Ij+#W_1V~%`D)Iz4hr~22=Aq zymJb<H;ll>pAmfm}Tn<*O%LV$f zDT2L>h_u(G<4}sw1~6-&tOaOLW;1twEr*HO(0~`lqYp#*eX|FrKnNfe zWsIn7rMGbNozq_wGkE`jeRc^dZzbEy{qz-Xs)%C-rbndp_~O&oQ=e*&I;{G)C)q6k zTgkQI-iiWbJjvjT=B1xzcLZ;9i3Zk{cfwvt4va%8O}i2f_DIi2q(!0Y_a+2n4yBSz zW1sqwNi{_l6~6yv;;VO5ylYf+tN`8OVzQAHC3-p2wRf#lZhD$KDrC{0aIm@B`J55gR=IODz#MV1AITR7800Zq@HWod5g2cdtqDOV`n$veTzvXqak3M|X*afPb>)cReKNz7Bxmm?JW#T6&z-yz zuYvYXP^?jmrl&4uRn1*D-JpNxfNMbf!(9)VnNP%4kdap6s9C;Ix^YLYI6o6PDjGC>Z5 ziO-y-)a2AmQX0FkRE-o#A9tJC-!?}RUj>H%aI4?6`k7l<$H?!U&BU7eD~c5!XiDt2 zszy+)Sn@irFrsn@^$chMjU8b-+Tn@*J`{!hdUl@+jHudR&{HU|>gjjLB9sV>Jcx8QD!SJWiAQEh+fj#2==!cAO`2S)GCKaK@Fsl2%SN%NTR zem^Bjig@$=p4JcbPANdLv*%Jd(%Z^^p8rS3T>Ac%=AYP3f0A?QZj96(jVY9Zh63i; zaNGlLUPK?jQHYZTU5T#CTMJ@QL&Xg1Yu_BqeJG|w>!mP-76s>HZ!uLC1O3-EBCyAV zs>si~`=euQqH^hXIly5O(*-=RFHp{t-^S6C1 zr7ukxT5B37wl^efjIl}sulKXd=DkF%hSQ!&^#EDlLqFusY>PWfQ5##;K*C=0@dWJs_XJcXQg$FVM5utu8kvdGGZV z$wXUU;BrF&qIp%107{BN-^R4$HQcSwX_bU)Kjd+_b;dA^u~L?jxowMpj~)V6cULUG znI<vum-intX23VHmmI-Yb2PDG{+#<= zqK4W>c6k3vnb-x+g9YCeG&cLn+O&2dpu~Wns+M<(!sAbll-otBBEU z1-@3^>v3V=(}_&fIy+Fau3Kxjc*}8$FpgNuScUTD8is#`YJ;0|SshdQJCSZx<`;h5$P|b{0f=2pxg2TR8mLl-EjRwDpNOuptE`U)*TRqC zpPwyucyR7QVi#D+>Vqga&JA2~NYjNR()qVOyU?qi`tF=Kd$Xmwtm?3`w!PNPzbF-t zQ0FH80_F*mV-qfupdei=>PRL>Fha= z#mX9ss@x%O2MLxudL0_pkeV!g1(|_{2%V-L-OV02E*WEDbo;G|{Rt@S?C~NcrvdzS z6mV$5*)b}tNCqXGdi|1!L&&*9cYc^yrGqJQXyT63Jqx+HY*^Arrj#Et3Ah?h)|%b> zZta%Q*_S}qX|gP?m=01Bw9EDNI=pf>W@9`5G{TQ9o5y_?Pcl5DfT_6xnpkOqn->mZ z;y5XxEE?7XOzDb?yJ17<5?)%KuBB6-6XA)k#dDd=!xbzj7F-HuTnY{xTn-{QUsqw} z(!s@u*YL<&DCAy9!6$>7&Sx z+{qj3ouTkhYs-UMwReQ(Q*mp{?C77_4p#VM+k|ZW>zs#DmRc{n`7t*>dr_awM?yY# zifszp^Ax`$i*?aSgq|ITyBk>R=B%&b@ON}>jHLM^cR=0_SLc5+@2t9#DR$44i=9m_ zO-emG;_!RCK`~6Q??Nth6p%FMfT`{8Md%?@p@>wGW!Nu~4vhZJoVGwp_unV)iBtBm z--FS9hU+%oCZyPV(|1J5&k%UBAQ+!OcKztgfp~Y1K2NxaKKh=KAlVX5PZIj8ob%h$ zL~@?}i_5iGe(>pW?}gu9oTB!1S6OMse9cZ9d#1Pd%!EM(pJes^_whQby2K;4!*M{? zt@HKbbF=Duc`n^SopnVWo7FDjd`_*xqyp7c?GE~v%GX+fq3;4d69Cp=0!*4Sqi<33 zTspQ;yDk9C2^b2baSqo?qbVSfjFWJ+!L6OZ=)Ej^YBOCLUW$q}{@7l6 z%$qj%QLPmZy{J}!SO5D`tmXyxWd-MGGy0wH?1-C$tQ9$0vT@vFf|##s=tn~WJn|%l z{_l6e!GyU^K&B3d1muIv27eRgreIFzwFozd_ z_$)~${j!Aq=**y8TL_(-jl4A|cFOd<9n|D%LkxPtcSindy1X1)(~JUqyj&E`8;2J} z!;M2uy2`bjqx(S=MXET}0=9R#Bq#Up-_2_luV19QWx5*sJ$boKkPhUKi@5c{`qIMd zwxypk3KU_w?j_L<7#6>WKK|8&r72prBDMn1qvlsSFJDFVyccz1&WBeUIF^M zTB_JlZ*M}mN$F^Au|W+a`N8AFiE#h$YLqm3Ld5YU;IO{ernkKPh?%6-RbyJo<%aCD zS0V9j%bp3~fu_qT%6CPZ8uyNKWECS4+Y+P5(TI;5Dd=D!KLS32n8(7|1101d~^| zyQ7&;`~K(qKY}@@CNv%^`cx%fTDC}%2?$$kc{BOR4GOwM?bey((5$Vcr7FyqqcOB;YY$uIT{ z>!OnM-2l2N-A+K@9vC>5O*|BV{K!^&yru=j9Dy4*rev$xW$l>#K23?sSzWLPlL|V2 z4tdfgU-5tMe)fgTqq5|2xxOV53!&uU@a9P|?~hcRv(CR5hVgAzMNp^1nSA2N?c}}N zb{YlcfwA4>Z@{F=Z?1}x>XI-gf{dr#SGy_#1tVW5%;#>)Aw;n2n>+03uH&7a%YKy% z>_c(?gaLB9S4&-CR-LAkt>yaSExwA=^xliv=|<>y%8m|S#uS5WTVBOq(f__Dggtu?|ITI#3y#r)l9%al9g>eO{c2*VWffm`G(E#Ph91nn zDr~pa&TQH(Db;Q{0RJRglKUYR$!O*d4)IEVJO!E&BZ}UU99N)KwAhoSW= zBtRF|Lm(}OIr70S_3lb;#c!8BRQd9};{wD6X#UdfP|R8aj#N8JPMkK)Im54Gv7<|H zgF)xl@Byfv4TC7`DPE49AnX2coloHq*CgWHn>O}Ref+Fjss=UbX&e#dEY5XC;eau2 z&zzdN!Pq|7_F=Vo5i#5>@1zdnJa?@}re?a-7hp|P{b|XuP0nGBzP|S>P{4ea-S@x4 z>4`=0WZN&&@3sbK;M;g&@FPrp$y;*=K>vK4xD?jW0UVdG>F+_(4Xa!A|T#5f)9Y7=*|vSrI%&4f9rB~P;d_kR+73WD+( zgWa&NRVMn+H6n9G z^vlk*>7^A10>=12C|`(uNgj}g&2wLB&3e>y_bVmL15T5tCz6tqY9oD$4_jwPv>>ywzs8s%^fx_)^NqeC#yM*h z51J$C;K7Pxp@!97mKF{8!;bY#nEwsVK zE`}HD9MHtp_~sjxwTcf54ZHV?5>q&kyJw_a*sY^!I$zPIm(C?md@> zI%oYNV@?_-S6KVX$*uZt2;F}OqzA*xTN{<2Ra57gb^iV#j#yd`ipR$m&m1JUF2{u% z8lF4vjOX`rSG43)5WhvyuNVOU;Q*_3^kr!jy142TnT3~uEt`nE)*?^OCO(Qew$uKZH+7yO4y9A z7p>PTVM_{8*Vbju79y6QSQ5g{DmQW!PF|{qNQp4A=W`ZBajIAOy06te3NT0x3cAiA zE?^bV*N>w6nEnm2%z=-IWG<(;!E7EE;}6*D1@eoNPdv<|j(@#;z!bx#l2mrpr|w_1 z2h3BQTi`=0{+jFrpA-z`_rW;_%)f)<+OT#6il}QbsI=}1B7{-sj~0OvyAA{MYyA0 zvpZ;TUAp0#FgCBy3@?5Ws(o}!yoD>iKUDVnApT&r+~0b%sMtuItgDh9x3lY8_choA ze%ii0&Jvl`?0mafaLx?ALBKwlYZqHJPwdE3w9i-bnc~B^&A{o-gvioIG^vW3=*p$) zOx43`wWH)ZfOj{r8Oe}jYni!O@kjqaRLlS~0>+#?2Z)CGPI?gs!!P9`M!6X{#&Ks1 zZ#y8FBU09-7^&B;?pt+27M3aCsrk10?I>hxJIUX*L`mQp1d|g;v4>YX(KQPPJBMl-FuY=v3av@qqCtR7o9`}AXlNR{Ba}*w0fp9CMA8J6@QBvXH!9rF=?}NSThU({013;wC3;lVQqv$x}D-{ zaf?O1;2!JE4)gym!H0M55G)P+j(YaVytH$F(Qa!srA&k}-swQ4?(LBaDe0!)b#t*} zX+G0rukozaN6aMr@Zf-N4klg-$X?vnHh}KvEMFi3JxJ-4-LifZAiFkq=1$$bJJQvg znAddndED)>lVe+Hy@@mH|IS??kYHdcJhihSEZ~iIlN=TOeEpWIv8T=}%>8z^!bL3O zgH%SAF#Ai3%sc|~QKs~lI*x^J^b)RF`EcO}!*Hvily^PT{;`bJq~gY0+V9#G3x{ss znToI^X$!1S@i-ek#dC6or^^G#{w$1vZDtanWuwBd!snnS@Yh+XIM;hab`)OkZ0vfk@E zaXER)PwH5SDh41f__C9!mBh=5z8pVmId`pqp`wa1KV5ZgHp`4bPuy)#PHf&A2=4mL z__3+~>~oe3{>%1h{uysQn5BzL^{Mf(t7(pPKjYdum26}$Eh?K{KLG{U>sMo^zdaYI zdN-vCSDy$whkGe~+Xew-7JPqa)~%sG6A-H-Qfw;_YuUt46RIm(RDmvlC&bdiZn#CLMhQ(E-Gn2>q}`Tg#jMhx;&Iko$}USoqM3SvoQDPm$!@1axYft#6$Ub>KCOb zrHyf3wf-quzA>wjTGL6TW9YQ_vSpaUX|7`lPQ1yCOy)rBJ76^`AnFa)uXou;Zuo9+ zgAhxf2J8jz1_Xg=V?>6#3|QGMw>6B8OF*dkafZtcvAlIf0&skBe$)p<~BBxw>8=wvyLH94AMjOy99x~rV%!xEO+=Gx(YQ3{Y++Y ze1c5oMC^aSdJi1-q(@#4_u5hcy`*!<4GhpaGH1V?u5{1Swdr>>G6Yv4(R(L>C1yZw zRYi>JGB^9oE9&pzlV@jEP6SsB^_lSd*!F>bvl|k9lg!;y@s3!t5P}y5Et#-4AU1&( z9={$}2&=^zlX=EuW==*vGJY$wPK6Hq1Z~^>naaV8YJY3|HVDCl91X`rDEkMeTjb@) z-NlBvDG14h$Kf*Xe938mWt_ze&bGgIUm_&U%MFr#!`tutHv{aUz||~z&l#Osd)D8` z@kwYMayiHMIcH|_^+8wU+{p4p+iC)^kf(DRZ(G zj+_Q4`?Gf`lcx~D5w!&H@bfL-q<Q;Nu;g>>6 zfB9wqRSo;Vqkqo9eFOZL-^Z1z#Woy6-z3Lv=yk`D_}ltz0Io#hvwmK}yK(@2l*j6~ zcse~l8HG4*t#DxN9ew7YSs?d%h1g}PU_^|q$TN|88a8sVN^o|o*T3@ zW@*0p_nohW0Q)m7|J*2h+iJtnxLu&}!MgjmK^Kp?IBBaRgKZVvT~v_8Kyu^c?dyvz z*37(FyOKN~%xhRvG(RmOd-B7bu>!ty6efZaPef6RsTIcOm}5%CcjDO(I{OaAjaMtS z?HZrJOnk}x3k_lrf00_$O+2-BNY%^2Fcd+2)VMB7yK=+3_2hzVN>3n5|n~IZGWJFpU7F9fr&41CB74%S4k! z&7=st=n%f#IJ1|1ui#&zMI0X7#C-jGkIKOCU$#!MgXKjP5j<>>t+7KsVmD@gUbqLM z>_gjfRI#S*R4(Hx~-pPVq=4t?+>NXKNwe zK&juCJ^|HwJVixPzHDp0{D^$3Q8%b_*y}KR0OdRs&LKP5io3^?!T}WW;<-iWMPY@bBj=L?MBM zG-IAeyug|U+r4Cdp!g5IGGv!%h;IY5q)|s zg!pVuMB=-fJUbzp=&pqrHvDCl1AORrNBsjBrUB|PW5XO*#j zdj|bdE3wba=icuP!9bI<0B%gINHe_hXu3`w9I${}!4qh_-FFXCJlM43AjjnnRfe$d z_}%@_AhZC()19nO{KqIex#%}L|ADAS8vKEzuz3C%z#2b}J>mIxQnmLk(SmP}VD^Di zYqEWZ$PSv;qm6@ugA!%G=2M9N{xyqGve9%oBQCL( zkpg(w5vMypxD{ycr!BaN9zvqiyNaKh{A#OOBvt6tqe_zh7s8o;4QS>z&O{Lels#m3 zTnWtNvU#2#O@cXcr_qG}Q{^(8>b06`ZCMLvv6YCo_?E-0(^t1ih%Gxh(0QYtCvH$Zf~r;wGN5A8T#}x75*)G z%V>j?URY);p{$XV26qLWe(1Y}ilBU4;-6S&`=R$(Fds}hi4l%>9B3GSrsdN-(3>8K zf%u=5+J;4*H1OYKzpy%q<~aDQaITZUS8CYaxikC{OVpX~OoYNrs7PbNAb>KVuPVdMH&QKEwf*wH zW1JYklP@dt=VmP6wTv*Pn@&{-Y!GZiS!f5Ec{56kB#HLa{vFLGiyA$vbV*}vso57d&>X}5#aDUR$EfU7waR`o*80-wUgUO6= z{P%n`xc^}8hjQ3qpZK+$--R?c##;R)rSK}(5aBgIIat9BzNDjnKz zNZ$jf-)Et}0LPj?@Q4v5w$86iR^2}4(64`+GE|lCfoSm3V%-Pf`e=F)#yY^p>Z9W0 zIwL!QW&PD3Wz%0}QQ;X6mNW^6008@OVY&f+{a=_Z=cJaT7?D9@dHJxDZyRU+vz$raS2mdA&;2?JMMkeK2amUvLtQBjZl`-CxEubr%VQ~nqy)BBCz zx}g;5@Ng~cEQM=kEb@OZ;whfn0H{wpq;7wat7GPU;i}txdgOFIk)DwoM1$>ppY!@SDkx7{89{D;#~gKz!BLP^k650rOc z0@hn|q(f zE*%uHB>wB#f^&N_)%9jO{Uy@R(dvv}%_rOwnf5HUoWsi;tP(-dTj_GOU|zK2)-Xf9 z{ajrlHIL!_XTND74+$9NR5zr&3 z{%!aJl={v|?tf*VS6NPY@7PMbI$X7{YH>If-?lRk`biur2sTG7UEY1#{qas4!Jl*6 zipI?>=w&3d0h%LWYx&PV!puqN2%encewO5~$+bUIU3j`4uby;7rFW~ry9e)51*s4ELS$w2$)fiwkfz5D9d+tADs1p*uSa9M0RYfHzw~s?qt)~p$T=fRh>BgZJnF0;TrqxxyvR42nkP) zq40YxGCjEKY7B?XiH)rh+JZB+1i!kjHr9h3cbr;Gt@^4g@|UDfHPVrp;y=8RAf7*S zU*SxCr(@t05%A)p-)K3LY=hBgbbdG>lNyI_45*MxU1st3 zv+cSf)E)hiOhBzv2-i&-`bpV8o61*07E;pSBW94&??Dfv9XFz|SQ=)fi2}jyTPl;8 zC8z%_X9J)C(CEC06U#%9!sqmYJjpP^x#XHdw5X&x%Z6t%2K%8oSG%+VmWC&>*vr_$ z$=}cy;?rXo(M#`B>4egL$*G>?AHE82Ca18#RR^dvTp0Q69|BYB9|vK~#}-etF*dq}dJ--PrdUUQv6qcsk6AjU==G+%OK zK<}`&jtFs&Jx?qkDn)8sR7V!9(;s(yx6UJ9$$CF)tlzL3qqc@xpyQ~GWJ)1--+MRS zzXiFaqsMsXKT_lc9!%KoqqDBX;WC_N^2AAAAyqO(&0YMW$qiN){o=tI=1carI~ed8 zymSVE94Cd{_oZB~Y+Ja*(o`TPKl!j}n0oKY50^UASf27QpuLHX7g|`jH4f;PvbOml zvb7{XR@O1$HFtxa@dp#pNxH3lG*|pew&Fq4>-Oj!YDJv@iW5B`cP-4orMORtKLwdk z5`fr|@_{u?qmvVtBC6P{3|8B^oFjS7@kT|<@DorKrNEt#1BB?%bLyYv0F0Bzb~-aa zSS`<>G096tNU=nen3%*p6uG{6QN-}wo1yPz?u3Fa$};oDE}h+I#I$LsP-1@sNdA2V zzvWDB9DFVmIDAE!AcnS9eF)}#J@|G-3;X`D_PoYXW>BAf0>vFRY!AI7ig~KYr(3Et z7s$4X+#8thFjQ!w9f8bt6kUY`rC8k@fJP}}?xbtq^DS&>E=AOsmdv7=R}+wV=6UHa zZ<6wj(c(!4|67~N;=}XSX;DKMWWTjochSau*{c5A4JYcYH6D=j41k8eJ)bZ-4UPQy zK}^36J(rCw*R8~(`TBH80SSuS07oigm=`E?4#Ba@o&-AG#`aTfmayEMLpq&>w?{Ww zhME5>Yeuyp&tN%e6&k12a1n^fcSAB~agG4*dURz^Oh{#<@-ol}i#+i zb>9U?UKki2?3ep)d;Gvm7r=|xbzmv?1&4#7u-l?D=|KmMwVoS4JJiuXpB?VoFq(nt z165p0jtiLn-915NK;bXHIK={Hi&3r1PP3k_*>rbi^f+d+JJr1p{ez!1%>c1o+ke3~ zcKmT&Pm-Uwbo31F1ltDRqT%DYP~DF7<6AfNt2f_>{gr~sfetGs_|&&=K6n;p691Sa zEaZ_Kp_%>*8kO9Bm3Tqp-K`gwD*wC0ZU;IOmxTP%Nvs5Fdwrn12GsLry2NJ-1SgW0 zj3c^Fk1~*{fYHTy@&n(ac73*qNiNr>x0-T~Xdpu9!{gpej=p3^`fV_o4{QUAc&B6J z79rs(k+!c3s41S*2;I0_i68EE>u{y!f=Ar`9uxV+)jYL67kx6{|B5ML#Bb5dds%QD zKD-t?viyztuNh2DB(6PQEyi->rJ-k22IO92k;VycORLcGO9DfxyzQn=KNW8vmt>%Z z0#no2Sv`y&7QJ-nIRdE3MmmevX^<*)o*a0YvMxFf<5B1Gg0}kmv<-w`RA;B>Mju;C zXl^f@1*Xo2OUA2d9f$uf(V@a?;?NfO;)M`fhmg1yw!Hgg;dyD&=j6!U+g;Pm_Qd00 z{;JMlp=tNpX@6+8*7m9+u3(?M`82i;20lB73MYg6*pgewJ@_(SCQ8xmiW~Flf<5?l z`Km9+d#J=`i#kSDC&|`)j(TmuW90*^rl&f z9FN0EX=M;_y(2)71EV& zv@fAgLM99t=4b^^>%ubt&7h@3NYiP#qaSw?e~4XgQlykL>B?we|Co2AlOK!SCo6#3@RV#r2?D+nN^I%QWb!0{fwXsDHDLtZMvK zftbg+H{+mRrmHNaS>v5Nx%O3)1;&ieb{2-GLK|amL z4R7*q&&_)v(*9%ew&Qg5T3FjGY^a>I2Otfa9=gH+Q(JTc@r1)(%-V6*1jRNr`3SWN z&4;vF?@*Y@IwX8)7CDeCp_oCme_goqsCZt0a)!C-e`yyTdzNGQEoYC92<|t!9*M9Y zFI;xv0v>8H&2S+azA>AYrwU#q90>7j7=xH!PZahr7}(;@fg5Utw#k@j4eTu=TK(Jw zGiQd03wN6AyJ!JkYzffj#FPSa6q|g1T``o!OAossN(@~5b8;h?o^p`o!_T2vacG|X z1FfO<;>&cre&7G342E~xa(|o+fbRBw8GZ)i&zYs~ABb>>CHpK5h&M_d-Y3d8ABMd^ zuL4TKMR>ARrr%%y6vr+WqXWi9QubAt*EOST0nXp<_lcwC((4fsvhoyQ1@;kY`Yx3> zyB9tj9;WM37KwPy_?*~37)w~?r~UYUwX5#|zkWAuKoTC4q|$6Y^EoW%Bj;c4ruj_H zRAt}jreH;AeYKU1YBd8W)+KQ7+!Cf_>*8SOoU&9q7nzw?T8*`N%dPm;)KL%n`?V1k zn|Xz`T4jxuct&rm9_i6s53sJ*hATGSjcErzn%iZR{$G1v{Z!Q#z6*%7QYxL2(j_Se zq@|@BBt+>>IW*GUDM%mW@`0^FAA!!SDuL?Gmo}G5;WRO1iUCM>wNvVW-Vi(+MyamnIqE6`_ z*5Y>S$vHm(U-ugvMB01J22Zlw+?tSfA>coOU|KGiV6~VjG*;T{FAhsdW7V2OVG93& zYebNW@s)_uderD+@moWwJ2vw7JbkFcI>!aM0#&+jd@#HM`>z~CdJkdvmQ#8z`x`3x za#mWfP~_ch@JF&6dghpp`6iFl3jI4S11OxN9Y0#ySPiU(b#O!u1CBgLjS8rw%FYhy zO6aLPv(;1V=}A)MlP_C;s!Mo;zTVOkHyfqB_MiJKq@MMiOLcm<@Fs3y`FQCfi}h0Q z0gbRrCpi>%TNV{&{UJ{*jf$&w+0wVbTVF~TAk~Vn%7!T38yLXY4ah`2Bb z9b0}U;~R1TgttfGgM7Ray`aq`V`yfob=`IaKvc#y*M!;SLCsVJF>4AGZt=s;FF-6g zgEw!RAp3JQ!;hO4EP)-VY?MEi!?V6^I+bi5GQO(pLn!@&rSwXVK~KV8oHRJN z!p@BtTMBUYLNOlepE@nJs{crR$#`<^foE$mRESeq=%F&n0} z#9hI1^Oo;T;%*${xHC%Wa~&X?+VwcfZ443lhZO6#`e}D&0 zk6eQv8pM8KzlsF{QZP^+%hayFNVp_BL8|d@#J^MQKTGEv=iN6<83oZ6pMOXKgbc2W zO{c6YMlgiUjuvPmZqFT#DYHMHcNdR4sJn(Sa8 z9T!eCzDXnDPQ4MZV3$`9W!x>{@dnW-1+;kG?q6=e>NXN;C;+ZI*)~|)Brh_BbKCvP znSl=Om?g}h(f!=!t7@ByWtxXIv!5*L@48jJAhfcgmY?BS`5tpYl=mRrrYJC z%I|s(8*KNu^Zv{8y^|=cenWL4Na6Se&y)x8^D1Ub?@RL^57MpLQ|aIL^RpSneKsFR z%?_{}nBcuWn8S0=iK@gEDR{7 zjrC4Bp0KI`Y4H-ZvTULM*18%0OF4WFJ=)g^0@8~Ak z=5oPw8<_xuKXZh$Yi$@v92XI)%`qmna*M@zG*tF>N{Kyo5~o=PSvSY_EIRzS;BEOS6xTPa!5D-#NtRukR0P z{`-xK@o{FJrS=**VLbzz8bzdD64Y9y%4Xi!z9=sHqy<7`_P8dB`$;gACcJil3A(VO zadZh@oxQ%f$=nSt0|6Fu?-`teceuNLl6LbhTuE*KBke#(5=~=)gOU$?saY}Gi9Lua zcyYEf*u8-TMdM)z{f~M?=zu(FHI1`=s&qmSe`&WS_u-6dW`A{=6`E`O@Cg&QC34m} z#YKcm!_%|D%FHibgg4pey_T@?D>X;y{(Pc4m9aM$UL+C4YxsL)YzXo1-0vYMkNJqr z(hCY^8L;@(V2T8bho%%% z6M1S>hdy=w(4`R5j>(k<8HvBwu|$WK1)IOebMnyxfTlH?udauy6nVyAm0UGiu(&2Y^f#k``9yeJ}+n0Q63VZn8cPQbmIJ^$mmK$n4>MHX)DpUKEpNmpIe~niD^h4}x z4UEEd8Bx*ec5cZF^Tw$ppI4`%bsPv+yTz*SFcfx_?nx!_NUv_uyjTqiJf0OkziAb` zC-&zI+ack6*O%md2KLicm;LJf1@-L_i49g>!OLYhsAL0=MqPD<&A&nE^|b4&4(HzRd^SCHpNOdmas3&V7c}W{p&| z_uM+6&m+n@q{(mYJ!cB>{#U4SIfSbtgbSOHj&Kf=mdFR7S1Fa+2zkiMbC!e zSEHd9)qpCCQ3WPB+j~D``wZ#wXo=C7nIjKi6f7`7-*l^tCnE-7Ks9$6i?DyauSFVn z`kVe?h}h6W7O-8|%8*CgoEDK4G-`q%LN#6U;EKvy>jKE!L9ldJ9CdQ<2eGYhA`hNb zoFyN_}$JJ~e zdIV9W`bw92`s(#+Nz|#H=@tUP4;SPx2_VkJk${CTmGE5*L-&Tg>Xy7hncki?zKo1% zlV}0z^i28*5M7=7Uib5{`j^ zQ4#mr>z^4Ly#b?tB6^w;c0@Ndy)-itU1;5a8lfQ5Sl|zt*EYGnOSTs5h(HqsU?}W9 z3OqPeaCFfs?W@i7bqPF8EQA((*U?=X=*=>ECM@_LLkAAIlb{)LSlyjy^!X`0uf?)s z!PCjD#$SMXXI(jdq=dAuaH$)!@6kjeZuaHmpFqtghF>#{t zkG}ki1t1`Lyv>RoI`1(+Gi4jtZ=?KZY7;&4;@Q;$Zls(TkqD8|$B?XwdWS`9QX?AM zs_j1JuZc8-gxtBZ2VS%#D%bm?dWk9jKJp;mM`}0o>%x%6C;qA*t!*A++iSD1N;M>m zG@IwlJT(@;BWy+nV)jcz+@|O9?wjr8X6ttac)n{4Yuz}9(S-Ia%k+?Lo5G6U1T2~n zI;3ZQyK&8B(zso=_Yuj(+Dvq7Q!S2Em@8vN?!h0GL+*uaYwXRqS$#&QdvhxxD0)16 zFA5R)Uhrp!$Wv9a|2@6i+6Hp|R1=j?dkzVt-@dHuaaJrX4AyM%u|sHmy3m3ArJLB( zd^LNmA3ZYO-IE{})X9YOKCAqt;kJc| ztj*uJ;u&&7(xCY@K&+Ec(~2lc6J(1^@8~{t0`RH(yp7UXsIUrb1I)MG+@R-?uXXH_d6S3ZP-!_2j16d!~d@Y`$;?w%9pL$8>Rm@+zZDk(1E_n zqpq~NRL32n>!%GVT3gX^j6()XXEDO}@&d8vkA9~0p%$F19B&c~$Mg(}$Bxw^dtc8y z6kCxjR{QvAkp6{HW@sNROMnL=#vs(oSM$#tGys`V@a6Jh{1!a$Af{)>c;qR#P;5_# zVPbgn)KCBPc2xAibt`M+SfKnuYkZ)%;_N?oiH`EMHf;%{pg}FMUuuD)p9WcZf6y84 zz@%|-O;+f3+Eh*+s9uRQB8QYL8wV>0kaoNe=)4vd0uyC%{7zFkAm;y2nlur$;P)Bq z=@VWoB7Js;RTX%89}}-_9bEuGx+{bR7KT@@b7bsdWB;PYMC4=Vi9;zof{#Ch zrwve~o$a4S+bq7X%wZS)?d?>bjwC^xd}r3bCo9ZI9R!b%6A~^15;)%Dk;prgK&x?c zO%3m9RB^^NAqhOuc)W*E+JU=4mP#UMXqV%E(-%p>?U-&T{S^IQ9|E^5C3A4G6!aC< z$NX}wV(1B_^4?&G;ZPSkn>Eb{vJZfMltUF1&$6O!eOe?@lEW3_J`^@%c9n+Xy}98| ziNDrCO8NVF<#DAYcA`#rbEvnIL5z=mI&xS=nU zEGnb`jiajP+XcA8cXAT_P$m*Q=Fx>CDlQ1#Ann&^RqFqNl=-%Zw4Z1^Isfdt@OWq4 z<&4e6#UWS$f4`N6h7x}M*DgpEtkd@Nxgzslc&^~MD9x@}IH`V_$`wpnbm4-q=0a}l zq<4n?_zdYR2_(IHqIgp*;I)^ejPt$bWdWu&M{S&XL(7;zXU~5NCg^g|Q4meWXGs`U zy4i`tE99T*g=bhVqCB|hVLEli?Gq;Rch`k^r`n#5&6t#;Zvj`+`mXt>MlzEpJfvI7 zHuirP19U3^g9JojL@CNAjKsWb+vaLBXFt!b+Gs$jnl2L+^}GF(CZ^D0LjKiNnUGWB zn|s4uG&~<2?QD7+>AZWKM|Sw%WYaQW?n6HnJT1PnTd=Za1;Jfw5FCMs{a>rQCeUb*BGm$^z+Hv|;`Tw>;}#uP{H7p4Ww**|MrS5KZvB z<}^rrf+@Q1_hmU>*PPx51@37wIZZ=SpR~*z#GMv}So?YZ;1A@JXzFKzt{xVX%ct~t zjQ&^01^zV;5s52v>N8;bcIT_3VMd*zXPd}8x*}FBUxkJrEz;U-!o+puK9qWqfrT*U zYGiu^eP>%m!#e+R8uIsWv*3H%S}8#3PWUv96-E%h7TvwOHcv)G55q(X$Y=!vGTV?2 zZ_tXwLQU1#&W4nKn2(OXohKUCt^FE%7)2{5>ugf|fBb7op9tJP;ar!pc&(L+i|Nqv zl%a$TUO|uufR;4SjTf%wMYmUa_!tdRd`)IJ6BsaeY<@DL(o@vJ=2*P@?s?ar{;@YW zABS6l!xD^%#i4yddg|sDv_KTc++Cv8(nsVe(M|!M{3o>q0D?BN9`0oF{K6E7pt6Tw zh&^gcLerthOQsoBPTfL1@_TH*T9Q2D`kue-m-|vn$p)5iv>=ULN>GwRwr+K{VkB$$(B~ro7K)46rCw1beYu1JG{pL5#^JmJ<+N*P4z1)`nngRC3sB%V)vKE z;Xxfd>I4DQX1(m#jMFzYc2ug9!&~*PcsnTAsnAFl>_)Hz3KhNfUz$labCBB&sD>1vJi>TCw33K`itAKx|rY( zU11T}PR8~~ioVQwg%*($Mj_T9^`@uFJM)O5)N086w~G*&Lo2{4QGs^7lpt(>jO>bq ztBCIVux0!EBh3BZht1>i;QXmK$vruanq1zMv8Bz+!iSHtsGx)_H0e5E1Ex3k)`6M) zp0fz8ZIWyMX+c!;^WMCdGu=;|$Ww`jSh;QiQ@&2@DHZtV)AT2@bx#ONqE76Uy&gW; z2#D@@{obqI9=w)b;U?A zE0cu?4|)#kc3JbsjJa*GS9@l#H*`^bh^v0Em$no}&+4Tdw2n>nBrN`Yo*J4fN9yQ_ z1pu}0gY2F27`}UQB_(?eN**ml(6B;C`IO^>gxGC13J3-ED4KX@x9_kzhNw# zmX}tN@lvBc!`Ybhchty$>;tfLk1TbbIjGe4E-|#Gv()77_JZNZIv4h~$YSy5d={;>A-z2=?AadDAnR?LW-i2ly@R-;B@!=Bma<6=eFL zm^w{9VHfd-Zuj`n3I|{S9o{gAy^X{!A;@V25FYZ_8At`9M0yj)G3=Fu*aV#KOO}5OM2GNXcnUuz5GH z@`8%=UZ5Nra?SjsG!QtG^EruE7bTB+@b9fDpeSOp4Y|hj^^^=2T~v>4CeG+N4ii#b z=P`k~2!PL+eUQ6YecFbX0ieuhs&m_oj5TYe|7xYWBrD$oM5y54(!9e28v0TP1v)lm z0ltU}EOA3L_Rq!#NOsh+yjJdQv_)dj_u?HYGgwkroZ*S1c$Aa(9`Y?CCNjd)+Z3uO zgXKjzax!^`4qPb+J@*ao%xCYkD?7IcxqCEE13-AZwpYq8NmF|6@0=q*Sb;l)EI3Zt zOA8Bk88gFBe#fs-BI(GKVn4}U=Iy5PMt7r|S(`$MIw~BfrLAidWdT{Mtw3&rS>SbD zgg%+jvwRCBTK@Be3@z)Y{Z47%#mcLpC6=W!KGvc_NaoV*BFxZx$0zk);FFFl?i_+8 zafZRq>^0h42N~>J<8G>eU%5&@>BbNS!0YV9=!Q7Sd~SW~1M0TYqNYOPnfifN!o7f;Xw1mu-|Hk9(o!)j?6T7Lm?=%j>Lv6|o^a2bA5_y4 z&Oq}_Z3DobReP$&n*iV_>~hEo0^2lh`|?S&O7%rUGAQ?tG3y!5y@rRE*VbIAGW;8V zzBugU5qIMm``3*K6b^d^E}MS75KW+VujHi!8`p`?NV)fTM)$`C@nN9=W-rVcDf4#z z=c2bj!5De`jfsdz(v^l#_~D(CGl=1$*6|3gL443<=*#>sxc@;-S^nCDuFdcDQV2x; zv`p|g>U!5AUJ(rF?r?}N1J|adgh%T8w<4<*T3^0u&__lNXyUXM2nE2v{T6^^yVk?u zAEx%l(^lgHZ3#LNkCKDKDm-FOcvG<#LxVPiNhsX62C6CexBv&rK%394p3TSVKUoyQ~hnz*vpZ{B}0ljlna=x6Co3j z23_HcX=78jp&!x3jIscSn(#SNqON@}#iwt5L1y@-jc>m71|<8IUSA=;+Dj;@sVRl5 zM0&25FVxpigdm#Xwf$LumhZHb<+hgx3qfA+?#LpWmj=!;EcC{RjDbJf0%MvJo|I=$ zd?&7H41Y|Kh|Jz|Hk2f6tl@gHh)r%iahO+ zpl%;%@0JA-uWg3Cj=N*sEA8+?xVS%^Z=C7fNFo^H@TYJ$Dkfr*m}o@ZFP;}{iBEL- zYVYvbWg;63HkObba35GAwpVMbz8PJ)I(@hJCq;;MT=RIoA{*#*fa~PFB^*Sold;Z}!#821U5e#X8sCjIEuC*5zYl^JKfkS2o56-&e?cW+ z%ze=d725M~TGHELlV{#v(3<6EujQ_#@Ve(k;6aoe|5md3^*gQzLyB(cC8hK zyAIaWT)UFJLqnsPq+r=eWjY0IxZO7FKoc=K_j7I!V%Mzm)ZBUQ!NYZB#Ts9CX_qbY zu!saNr=DBoeppAeO=Zv2rm4p5!PvoKaBlFM#7Nb?#h?!_r*CCraa0zCx$f69J0u5^ zy~*JwX@}@O;=#W7P{!6JJc07=1?6E>q*O>){r<(=D+)*ps%*`IGf8%r{HpUSXoklD z|E@65NJt@ajq5fp31}^R^U0ezYfpjWl=#5HV><6IRM5Zwtf^F*S?!dgu)iiMB&X5g zSY1WdXDsEe4A2y-1nm{79~z|aJD{v;UlWq41x`mX_R$sxVuID0%DDz)^R(^ zehBq#(t<8nS;7vU%o#jFuzWCK5Qio+YI)bK1Dk5%l!g^{H5<5pvy{((&F0V9Lb18E zgd=pjM-S+_C>rQKZC*{~kSRJ~-(mm6?`~cpgw?#LD6X`=tHWC_JZSd&&|Y_*E1&v& z+ndrj`a*|@^mF(?@k1ixWhx_L8KFW;LNLGy{_x>L?)mOiv-wQ9sf${#4;-j5PH&lc zn|WvbLpd;JfVDmBv|@u_K>`mP#*+Mh;crjJ*Wc50q*%caa8oH+FY{~c);%C{MA0Wt5@C3kceBuyH zTDNA|5zYoucr5TIw+EyB5|tZf)diU;V!q=S_K$n0UcG%;_!!jVFDYEnk*>)_3;%g@Pqd45j3+|09R~7@9ot z`G0*{g!1VgIg|_&VVsO-TC^UPt{MWbEsl zDoH%?o*Esd27ES1j8e5CI0ed5Ry~#cJD zfNwB)IM&AX@0+K&%bFJke-?%!yFuh*@{D+&q)DH@R`KxoOV z*jR8&2}D|;%dsxfAjU#ea#zDKTq)9HnuHy>!KL%qSG{|AJqSeinVySB#n-8cg-cKP zzf&lAbS_i0>a37p;P(xQ8b<6m4V#zgIvutvxK70q2v*B>fUI1BwAU$wQ+SR-4Ipn; zfDLx^k_v87_i5O761FrqG>SCKb}bBUXUld1ISt*Tzo%O(Nqmr^2@gUerk6J%lJ)Ly z@$?NQnlurkaiCWZUXH1NV1zB__TXe0b+LW=iuf2^5BX%+htq4>R6Tg*s0^m&_*CSz z0@}#8M=77;y+iz20rmrBFuHUXTiFfHgVGjh=pMMq&wNP){QYc9)<9uHKMS556;Rp& zI#snbJ3ap9nt{eOXKJebnlXE7ZQu4#jKe+fBR1DoLn$OpGAGAcD|uBv1G=TQqzTV? zSTZ{z;lkDw!_5P(u@sS(^UGK5$5ZF`Yd#NOhAK0Fhd?k$jRu;dJG?^ZjT?1-Rr+Dy zq8YJ91xH-^M(^=i+DO>3xRSOmNSf}Qo)9RC4oWrLQJO78@nkj7Ue|5tmu_~Zpo=SX zhA<}OV*VAO6nn|%3+|F>pjmG4n7+rqCwT2pI-)s0!+i(ziRG8uZCM5i=Pu3bv~0EH zW$aO*<%WJWDx|(yTrkz;R_hhBE}!8?--?J<-6R&x;xvV?D`4=Q0Svqsr;j2!SXsZ$ z3sLJ%Ejfuq_bXQ%Jp2+u#3FowO6EAC&F552_wX72hLGBU6{CFD@M?Xl)+r_dqQ33M zss>YGO6K~8b>U`T&&JQ4mXl%@2~B~F_0kZrl4jLiiwVdy%oS<}DJ#>E19fc<(ML3+ zlSJoRk%EDChUI>fmk-0>P?KX)OA`O+`rQ>=#Zy5OV9q$T$yIt{E#IUPpQ!DB?XN%P4}*gz$a&XujG(& zbNz}$3b&hv$QAdqn7lWw-HOt166@?N2wJ3FwPOKLNj7z;3Q^ziSHb}=AW$}OUWS(p zpJn%N(Y7bgIVDJv=Q(*LqsEPW7tY9&-T#RHwwZaUD7cI>A#sz@IiYl46xd+)*2j?k zaK-29xyB0bu?NN+Nx@@w8EZCn8`vf%61oX~i+uo0m&Jp`83or0vyo!u5Aa~GLGLG| zN5lGH5#fK!_srF}L5|-q;DNgkGpJqp5%HP?wCS)6_Kt#RkCcRY;6_C)_9w9G_L7E< zyHCySAe}{xUT)-fp}!*W${>V1I zEPL^dIKlyKiWt;>?0p$%$5yCoAQ|C>^;(}4*7X_U z6Lv>tvhQQ=@{69q?uopPI1jYp#M&eQ$OCKKR}6zkL&}7ynaNM4l5rNl+6q#U`^PgP z=-bY;e@>yx@qha`;Js;5W->FVTD}2O1Ukkx4IAM-^OV!vx=vu25rT0N&~JZ_nYBve z0C5d2C6mJVp#83CWMDwVx$#aV^X3O5aKTAyk{cJrjUe19k4hqhcr8f*8hgA$0CzPM zOI4YOH@9VgFX~f-5sK!Xv*0{Rou})ab%G*va_NNb)}Z(_^k-(c)a2WNg@WGWptZ>J zPYwKMSAc@%d^en+qC%w*@W~5}lfli0Lb% zwO&dyy7bP9Gg5HZ{M9Kydp?_kCksYtWo&`0?K$v17XKDFqmt18a65_ufQo2ohJe+3 zs{s7~wQR~HoYNX+t6GGRF(K8X0KV0q<8;@m47$lz{IoPO`KJEgISiO|ZfNO2O;% zEQVb?hVpRWMlx|WdpujVFY37_=kYI-S&QF!S2zBYUna(ZVV6YjeW*eP*zk$F+VUz3 zV3=)~!(nO62z&O=xS-#Ic^7<_9y5C-#zjCydyln0ln8Ok{ZDY6hV*Cdz1!? zA0jE;1jO$z>`s*)9_;V$r|{XmxlCZusiT)mqJ&Gs1A1@^z=qs=;xJXB_dbN|o=Kv( zDg4C{Gn4O&xo97F~UJB~GwmM#k zHF~$19gALKZfwIkUn3**$rNoHm28r0$h!^q3aJF4R@PKojAIjSRO ziMEV7a{Ww}VB-DFy{8>D?K+yGJ=+*LTP+ydeOsvoX^)#Tl%if*)y20yhIDvUHrk<9Qe% zmLx;k%eMZ2ZH1+q-}_iJ=XNZo@q}C6j1LE{j!4erL*qh<PDE~m?+d>vKf}1?fl;MpGp7A2mSxQ{QnjBKd*qu10)y-TlDIapMYfo0`Mavp&(xJ I($M#R0n&7#*8l(j literal 0 HcmV?d00001 diff --git a/docs/0.10.5/html/_static/basic.css b/docs/0.10.5/html/_static/basic.css new file mode 100644 index 000000000..912859b55 --- /dev/null +++ b/docs/0.10.5/html/_static/basic.css @@ -0,0 +1,904 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0.5em; + content: ":"; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs/0.10.5/html/_static/custom.css b/docs/0.10.5/html/_static/custom.css new file mode 100644 index 000000000..8a7c7cb54 --- /dev/null +++ b/docs/0.10.5/html/_static/custom.css @@ -0,0 +1,50 @@ +/* + the ipython3 code blocks coming from the notebooks + were not getting the dark theme styles applied, so + manually overriding them +*/ +@media (prefers-color-scheme: dark) { + .highlight-ipython3 { + border: none !important; + border-radius: 2px !important; + background: #202020 !important; + color: #d0d0d0 !important; + } +} + +@media (prefers-color-scheme: dark) { + tr:nth-child(odd) { + background-color: #202020 !important; + } +} + +@media (prefers-color-scheme: dark) { + .dataframe { + color: white !important; + } +} + +.hidden { + display: none; +} + +.version { + text-align: right; + font-size: 24px; + margin-top: -47px; + margin-right: 3px; +} + +.sidebar-brand { + margin-bottom: -10px; + margin-top: 10px; +} + +/* unknown warning was showing, manually hiding */ +#Visualizing-Logged-Dataframes .admonition.warning { + display: none; +} + +div.output_area.stderr { + display: none; +} diff --git a/docs/0.10.5/html/_static/doctools.js b/docs/0.10.5/html/_static/doctools.js new file mode 100644 index 000000000..8cbf1b161 --- /dev/null +++ b/docs/0.10.5/html/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('

') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/docs/0.10.5/html/_static/documentation_options.js b/docs/0.10.5/html/_static/documentation_options.js new file mode 100644 index 000000000..2fa8c97fe --- /dev/null +++ b/docs/0.10.5/html/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/docs/0.10.5/html/_static/file.png b/docs/0.10.5/html/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/docs/0.10.5/html/_static/images/DataProfilerDarkLogoLong.png b/docs/0.10.5/html/_static/images/DataProfilerDarkLogoLong.png new file mode 100644 index 0000000000000000000000000000000000000000..a339e0f6acee7c29d438847b4cfc48957c6a3296 GIT binary patch literal 20019 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 I($M#R0n&7#*8l(j literal 0 HcmV?d00001 diff --git a/docs/0.10.5/html/_static/images/DataProfilerLogoLightThemeLong.png b/docs/0.10.5/html/_static/images/DataProfilerLogoLightThemeLong.png new file mode 100644 index 0000000000000000000000000000000000000000..ca86fe167d7197e3bb8ccadce91aaae376f27de8 GIT binary patch literal 177437 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%0A=ay5NB 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 r6akxWxj%7T)KQ8?CD{ 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�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 z zl0uYc^9ZKzMG~>%r_K7uq1dwA*On+$N%;&!OBqvGKr7S`o^7A|D%yTF{oBpf)VJ}m zanGDw%q-^;wiFy*EX|%9#^$8;*8N$zQo6|d70Yv}UX#MPrg-E!Q-}j|$*%hyA^P^b zBH(p|feq)A_fCQwYqkT*$_J`?oOcz@=HBWVy_u3Q-g^GaNWRYM%UKGmk7DzTha+Qu zF2az+g{01A!dFxK%apr3)xDVF0LM`F)6)p-2eKmSL1ISN+as=9yl5-;Fi;(JO6aqV ziGmZt2cxo7N7=-*pL`ZNn2~8_$e+wrQXLJ}=suZOj*W0yzEN)TQq^Pof+76|4>)ds zyVhI{R?{FSH1n2w+cz5lhP`oDj=*wt)0;O|PdwDlM@Gn>UEN$QbP816t89x!INa%u zT|)Wl{@6%vWkPTDy7VS9QlV+$Id)E57YjZ;w(S08S!jFmx=Mdn^vr<_!j*WTI(nI3 z^opayz}qO-WYXltb*&HGFAOG{HAu%xN-t)QW!AMte|F1hNft=(J$vqXD_>8>2RCjcM0Ere?55Z#U)+D5qS@waHn@aCL8zZPe|)4 z`ekx0Pf6)Xu-o17XZAW*YVYsc5MgA6>RZJ!&K35tjXxEBDPlzbiRke5?CUNq)laP!* zmvsqyt1*~N`}QU2VTyn9n9xO$x5TL}spi z>N*t3)%y3RqKU1}502F8rA~D=ZP&-o4o>DOC{MO9Rm6KZ>&HP_Ji2ceAligs>*8+V z+uQs@Zv_m5Uq9X!epB<$t_1$6AEw~&n@*mUl&O!pC3&K&?oLx}2fjYS+GKed_kKTD zGdOten!HXjrZ1YXqyC?>JiG7)8CVTB%wNH@|9Ln6x>cBy7CK3hq6N(imA?F+*TMWf z=1%%x?xc_4XDHXdzoMANz<<_Pga#;-5y?o#uzz0U-+cq{rvz#2G*qH=`Udj9FY?ci zwr=JC8*8(MVv@o?Mbv*@OB1`75z}(W*6~sN=SBYMMX(DmVpj7-4%WWhe>Ermen~r$ zaLz!xkwWRbe_rI@CrHfu-^0BBJ@S+_-T&vZMWVrFi)>CX>izx0{`JZU{+RcF4DUz( tXJz{9vNKe`WoP(2B;oyk-@gpj6`?WRXP(C7*iR7fOH1vpYB|8_{2$1jOnm?V literal 0 HcmV?d00001 diff --git a/docs/0.10.5/html/_static/images/histogram_example_0.png b/docs/0.10.5/html/_static/images/histogram_example_0.png new file mode 100644 index 0000000000000000000000000000000000000000..9b8301363678d43fb36f795ec59f86c18897b992 GIT binary patch literal 14056 zcmeHu1yohr+V%ntq9Sq(z#vpGkTU326hx%EEpk)RY|<734oG-tq+4>+pr{B)m&7K8 zO-Oft@ATYr?>+ZkZ;bo>WBmUZ{~6*)p>4S z?sJ?+OzrJ$?1XuEEdP80x3#Sa56ArhEf{2n%@u7s45Ph){wGV6NHD`Nes$SP7u1}? zCWx-~YD3YRGbh_+mG(v-WjJzx^Ai*KrGW=JQPRh36NU6uVl`AQb>jW$uW;<8Q~BCr z%Eh3odhA#{m#w7sJ!VPMT|fDr=q68++;i!!(lzpRub+);35Br4))YipvHc( zol`LrEtcLzK`R1i!dDp=JkJ-zptF{b_D)g}Zm})@3S+uUw+o zwyObs#86GJ>sclpksfmClwACR`O3=5XoAE>k{#!%Q&&{uuPG}l`}wd)On$J(8bo*O z*ug!d=#O9gmgKRqItsUCaP?u{J@O|SxcUgO!i~i)y1jb`&WT%mIU}ngE9=dmLMB<0 z$tg!iN4Jxjdd_iwj_rQQ933Mgqo+@wCZG2(`ZiZDv1HGNnJQ!#{hMC|fwcr;CaMkj4~+4%*Fgu%gs2Zdc`WAXDN(GpuL^}_i1L<9E)b?ZtB zFXNTg439Xc9v7Lxk1v{kJ#R9mx4cp*v6&g{AI;SlEZLB(UuZ9zZBpMhJ5=Ma_)VLJ zQBY}axK>p~#h(yECYk-5QAkCXU}ZV&xVa*2r-Z>)*;Qfk{g)KkPZ)M)7v;~ed(P~a zge_9>+wtEHTuUkW+1}DJO?+$JF4wx(KwMnB$A_YC+b!*&x=4wPx^R)2c7nr38F!@s zrrF$mOD~1XE7EgQNMeDqFB#TNdb)lQUgRTR|MIq|r1Yf&?dH_i*A^#^yXOubJ$lqY zfuc`ZRb4#}riqmK8lBZ=9^(2OmrFTa-E|DkU_3&`o5)xCuzH3@QdNKIY`TN{83bmv z(*OLvfA~OuIFKKQm2PdWp?50mG|9=r!jh(6w3ytrfB$~dPrn?^>aZAVjCl;(lemWx z>o%Vm_;5(jChFqFi~INPJyt|acj|Q~G+Oq!&B-rJ5_Kmgp#U$U~ZLwUD8`LP}naZHtdaVXB;f3JL`xW2FWY9ha7=T{#=tdC#6$g$O~ zUMyi?;O0bUu3Yb0&yxMt#u9F8b7P^7hm*4fRxh7X_5O*DY?-R6s;deLZKdvOqG62K zp<#F(Lv14SGmRm9xPY**?!GXDP~+_xPC`e-m;3I+(}nR{b$^MiOiE5xF*Qv*&A|a% zwW<3H*7+((RNDUA7iFH}>3i|lepMmm!5&O3EYulqOSAJKx{$)3zIdUoprG(_GIH>+ zSBlx>op&6OWSpl@tK7W#x<(5Y8SLibJycjoY<#>lhi1B(gG25&N7oWN!BR3)n)Q;I zsG*^ur%#^P9DMfViITc{Ah$trVqagMaF-zCZXw3qB)qzME1!gwnOTxTq`3RU-J_!^ zq;lhI7ZK@{kC8X#9z1-Q1k0D%v%AD~soIJ#4*RfhWjHj~xc1NjY|fqn8m8XrnwrDK zo<7zB+pJ4UG3)88WW~(d+S(z2$qv?rIy%WcC2J!CA9%W7Ri6zd!2c6SLkuU z{BZHjWv|LDzsc5=;Hy`!s%dK{0XTCUKYkhQnKwTfaQyYC&!0b6yL|a!jTZcXl`tl@ zc2XAh?o~xar*utqb#`Il!YW^v)p;}h;^l_}ELCb()IK{5@oRVV9Gh@8@xJLf|3KJb zYGOh#ZLjB}T2*yNwXWdW*3sq!u}xb0>(`?I0FKHY61Gotoa|0wFmzMqDO}3BFE!`4VpgxdVb*(tFI}541Vy1K#s=--swFVMyUGq zso~YxTPI6B~(jP=FX#4dFpQF&*Rga-t zUqAVEW}EnmFf(I1pHnhQJ4YrcDJdO3e)MI@m>H}jC>_I0#XYDG{9^?D1K|8MwEq7C ze^+h(G9{*$G&F)H^9OgMqSN2skI?SzeX7I669NL7P=vVUl$3sXyqBW9RT(3T+5;O^ z-P}AGh*5lTv8emXQ1Br!d`@yo%3&fm8`~uy9CbrqGH)?o-GynArY11VhP5mIPD~Bn z$}0U`MTNSaUh0&`QW1?6X>c&+)2B~CK2%uy!}DI44GkdWaakr2M+^I&htv%A<7tG` z!ooUBy`E)@Q@vB(&R7E*lugsuot-)e(kmX*Y64;(4r@=*^g$+zRTj=7+@%CfJ&jJq!cwtEHa#PZ)s^Ug^g7> zRk}7-LNv~`odQbs)cNW=*lOV@+|- zva+(+Wa~xeo=+CfDJ+aMN+Ci;%~Kq8tI}t*QHEuq(*r9ni^0exS?PHUIAsqB*~Zo^ z<1$L(BiFy4^p9<7QdwE`*zgVk7Gplvl60DfNAvM+CSLmyC19?}z_cQs(qJ!u)=RQ- z))bC~-MdE~yZ|r6y#L)pu7K@Wh%e7w;03=^ega+jw{I37-oHNuGSW{!bN zC)S_@&n_sa)!5h=a`x6EZvDcq>4I>fsTaUbvU*BDL`3@M&(|h;N_6jUqXF#kSBMbR zo?3?qFl|fKuKxVFsy|9rZ(|dFMZoEQxGC)uY+;MeP zm2#2eM2k<3v)qxkxVmkXyDin`tOTopwhS}78z{JryeEC>l^okAZx_=%2zL4>;3B+@;e<}g36v!5DVldqV~LtzJXrnRNz)Ujjl zj6{zeyU60Xey5~seMCm02`b7$_>`MWkkP2&)@m?QARP@`V&)ph@G1@CR zdday@oodLg7f+Gc7**^naV7NN$GOrB%SwA#WXq0maL7eRN7o$}7Vf<74YaY-$2gK~ z7d7?E$jC^zJ-v?{r%&%ccu;$aAJNYWT8VG#+OcF5+Yo<111_|vDi-J|Z#{kfd{Dud;a{qJ@EfiAZIEb(KNrl{7g+>KMf{bE_qFA6j9`Rl+?V=)7OzG zn(nU%5p&J^_~I~$^B#;~dJt&Yz7y9Pl2j9TP3jmyyK(UIYaAA^viCUqHB=&CbG})z zrm|8-QDP$p2@-{HVYBZ1JF64cp5wsNV1x&{JEPd*;^Nr3xYByMN>`*tH#aw7VW=4! z#}`47z%cpu)?^faS&aXy`tyHL%Ko1kN|F`ez`l~nDG@MjCoQd}t!>tBW>M$XiGM(q z?;@&<5cGXpnrc}@vxsfnegE}R1gHE=@*QQ;@FY^t!V1l|Hy20cn@Q|bfA`^ zykU*Q&SG`V9TCjZDNsA*%-fLkv@oc z?prP{E?Hd@3w4AJi=8`m+|kCOj?Wx~dAn$YW^3*_0!!-ofm(%ZLh{bOZc zo=B1l=B}=;_Ggn1<(Frbe%`RYGRNomO$%;b1;DJy|F~Rn9t$=-B}lOyd!beAoCyVz z57-juYoTEE6b&I#Ku{3e>F0uoUw(-~uvz7Q9El)}41+W%Qv9nQ_F&U&b@0@`Bl$hy zTgc^rGNpTD55~*#ZzXO96&_+;AU41AEKE1D#uLz3}ch}+L4v+YGv&Un2GCb z8E(}1d3hQ@$aJ!9dq3LElnh#NBq-w_>({S`TUzjkTJY=I4I&FK zCp@qX3!#`Y3@W*%fy-r2sC*86^{`ASF&huMlrTy^dgJ`V-+h_vgZsA*Y{b@eF*56;7-ZtZR4|WJUj0FsT z{xxQH*7n24kLFNg>UbW(IRasdXT7ZVX7)E&pc0oZw0e-pvamlZUMR9$0VJe5k&T;hU+fZ%zhd#18^5u~j zU-J)7>3TlHg1~5PN-5n&n~rm7XI+{qS&G=Un=#SL3k&w9rste?Mg=-QG8^-lZVEj0bG+`nSB&%v^ZB%%+E4*kHgLi) zouF*YU}e3R4pkvg!#M!o$Z`~BKnI^>W88ZAZ+do=t<+lE_rIg`rGz_^1X^l>d9Dw# z%!!o4X_lYVsjq{3dhgynQ9pPg7;~Q+^)i*j^4%JmAfu$z)N2S&zjb7bG4Fz-Tou}w zl$4ad)%3!GdWJ#C{O9xart>3>%(TBxWJbwi2+Vmo&FIEbZ#yE_U=;zuH>(Zd1ASy= z;{jS5+$D9BVi?@d&yVZXek`PJE0p5HhY!LweO_!yhGiayM4jJMN|BYncnuT{C~gz0 zuc!(s=G+S*05dQ&!p32DbL{~O`dKy>A?l(+E501HbLUR`8ZN>Wf3)_LW2DW7ssjPa zUJ}lcd$m6Y|Mb?!=LN$PfQ8|eDp-D_U>W85GsE?Zr25EqKqUv*W8p$}(x4u|?F;l+ zsWHT#XT@@aGcz**aht@Jx?{lWZs@uL@_%kuAF#CrDA`G%e(DaxMJd4LOMfEAmz)p;A4_4|yz3ke%76I--e7(e0 zx67dSzLUJSKJFsAFA)uPP+^vD-`uFM2Ts4uy8hEACEyQsLLTe+RLx{({NNencuHcY zJh#?Rp|Q8mVH<_=Hr88K23l}3*9&Xt3=9Z31qA{;}yLA+23)79$$!|)5(gFBC(5$8;Cf5Gi`DN|2Dwa z*Vq5$OClXYt?$D2PvqygpQ5dgA6N)}B>FM3GKh{{mXl9l3cXI4I+7Iwi+cL( zS>UTz%M0PFtEbPNRfdW|W3>cOcuG`M58^1Zra|zG)z#Gtev^Z>++GQaks46izVmR_ zKk;yW7PslUC_X8ft>%#T2un@neE8^*aPY{;i185M>6yUFGD^42br-Sq=?eT%pyqyh z`nInV=gyr2_jgnef{UJe>~LG1+*`vv7qqlqt*@`EDJ%D%Gf-BJ27gF+PGVzTl}QY* z22{Y#r?sukgYILmAr&oi3!!XdLbwaO*ba-l;g2wbXAH9Iv2EM7nU6F?SJ&4&p|ejz z!9?cmdQXWf4vd%6?Cf{Ad$%^1_`vl9V3=;>hJr$kTRbQ!3(m6U)vHej1_pQ`S3}Gb zQibm%@~_MnNGxIjXp1a75lpLuBhr~436=(gPWEFh?6tq1mq8}{ix;f`uHlBeK)eQK z@JI;5O0;1G?;;>JCx;hAZL2HFF=D!gVRv$%q$T}cvn~AkF**6K6IG0N02Q?SJA*9+ zb|x#!%chWjXcFV2q9mmr?eeQNR`q2T0}HroK!~hQ2Q1X6J^x;=((+E0ENXPUgbBl} zZbOA?1Zz4(R02o`;xr&^j?22Q&NouAxJ7}J1n(dz?k0ITA3TuPVTdf*&z@~G;$&x+ z1*6>B=I~#noq3Y8y|Hi_U7njgpP%IMo zIwq#%)%JXTSmkYS_Nh(3YY#7da28QWQTt1Dz>ez4C28s8*RS6hrM`ZB5ghJ?h>e$Q zp|vMMYlpqzc6WL|Rj#xuDQ2ROFDH0G`3D9HY*7CrsNvg$t`e}&#=g62z-*!*o`OXP zhWR-j@YMnE1Ls@22;kw{) z0~bbC1&=S>M$4QkWH)@pAGBqdk&=I*(^NW?8x9cqh=ahpKqfvn8AactcStkuff^TJ zq)pRf(3|0g;!D@XZ)R^%kqG$+`^x^*@VB1V`WE8&!@Rfru10@hK0k2+t8F53~ z-}j$8n&6@(@Xov6rOzJ}>ngA?U|t~L6@WsgIBkw+l%;R2 zW^AcIQjTAmOoN_-WRQj+116t<_vIzcTZ9>ux@iMfyL#=~`l^DvI{t8 zS!;~5(u3;;`PO!UFpUDeJ2p${!(lk`rfUMqQc>@Q0wiF~fT-Zmws%7U1VI28qye!% zv?%>g$cMy&>wF5FRsZ?*xq4h(n2=89&4)K{-VBSRD~4FpVXju7h;=UvcBl`Ms2lHo z3Kw>`YB&5@8SJK;w{GR$8I&e5NL`ha8ya6*sQUQf8N)aP|MP@bEZJXQ>J_zL6g&^<%VuKAm3f@}& zVPU<;u6@m;zCaa+;G-+feywm@%l06DOpBnLYLOZ3k=dQ25qx zsCBZ_R1Zk=CNDAyWZyYmh6sKDI&IP*(AWDBXCDtY)Y3`>-DX}Lz>b1#p!$JfVX5HN ze^1b9pq0nc4{8TWQ5?q9&hrX-i6GNycfo=42=Ka;+!J9Ah-nJ)K`^fsAR&;xfd9v^%n1wH&w}?od zRgpE^(6_4YUE{EWXmGOf>$0&AM@9yiBc#ZaA(KEu{GDm|A6NR`(KwIloBwU_vI?I| zY%UMBfrK9;o;Y%(96@l67JwfeGjmVh;B8}L9e*wOFWn48y=ksdT4fgdS$ zoRzg=Xe$})G30ExkL&jO`_{MC$AjSt{U17D(Q970az#$MgyGOdU6lK56H|?okBrv;6iw0 z`9tOTLu-w`1%anLTnzlqa*WcBFMcB9c8_>=84WcJjb+=d+`Pfilew+!Olz(9oDc5) zqE63oi@}oQKZx0&3(csM4azH@APZJ}7n*zWs=2Jm68=4$0guz{{gXW*5}u`~+b)np z6C|EK@`XhPFt08fH;M-Of;dd!)tL(k3gJy*LUs_5qywN@cIPYa*|X>O(APcd?2r2~ zoZcq|g8(o#HV!9fcb;xu)I4V$*aFqr(cycQ7;k;!~1FcmeO zo%3PigqMkRyh0s)z~%u3f7!O{KokTA&POcg^y@c4M76ni+y?_NAb$mN?^KA6g?a9o z6S@{Ai>CMs<#FyFx-sJ$B40v8m%8ns$TmXlDq)K2K*=M^)^g=)8=*7~8XRd3oRI`h zJ?ofij9Ll7HEb<$b)uxA8t>}e%p0x^ZBOl8TYQwVv1X|qgq-Tc#8YsT10-~$+pKq& zU5+=o7Nn#X?r&ok5h;?L^JNrz4OPLsB~clK5Bk^zWV1HM%X5XbxTiZrW(a~Gi0ZhU zv$Hexar=xkT>=>6>c}`UFo-B!pOr%)HYhO~E7czXip!amg@TBUz|z8d>tzyUl|D>! zN&~~=ow+Fyz}A2?;b6(E_AHeqtWA{}t}RVvIC}8Jab`$kps{ zF;@-LULh&z)#JXTzcI+Nh0>{3a8;~ja6zOARQRwqS6y8^JZ60H3EgLqxadL)QVuAw)IF@y zTJR3$9Ak}L2E0$EPPvgpdVKmFVccA1m#=$*Gg;RAsM@4x#lFT}s$Ht}ECUcqgRl^F z|JwKfywm~1Xxmz^-^yRe?0SE&90zgz)|V z$^xtJs0)RKUoe47tX{suP__`z*Q#VehW$_f5f)Oq16So ziWP@_cK3m`2%ii7c*#V*_ikf z6NDv|oRy_gwzV-82r(t_$P`$L%-7sD7AJ`u(Ao*s;V4wtHfWP+Az1g~NqK=J0-yO9 zE{jhKHLOkbq`_q4MV|hap+OD`>EOcGmx|`l`La61xBj>S{IR!Ew!S-(fbDD&|c=4V%7)(H?lsq@a4NG2q z>x_$!HwX5$+IOF}nCSy+NMRYk_mG7)oQf=BV5ZujMR239tQuhmknfPhsibITXn=Q= zXGQG1zT<&YPGH%6C{FD;X3YV?!R^VVXB_xos=#w=h7J%8S(FXHEGC47g=y$xz0QL) zC7Y|`s5F9~Oj_UN3D2gx;NkMj&zel;k9LFQ>^DQHM>L1yVTZax!>_EITyvqrcn;8o zl!#XI5f`85&n>E+SUGU5t;s{e2_I#Xg7<+Akk%L(T10|@yrP)cz-{IO%=SYx+jY2E zX;tWn0bOAZ{kXGBOTl0O!_y>7toPHxUp2w_Bd{6-CnhEeZ#B0hD6&A0AfDaNRTPRl zyt*J}x9JNAJ0V?oWBmD5G#G)_GIpUHl{|`!UC%k8gYwT|IgLkKVj5tfvYJ`|;TEsA zkv1r-W*8*LWzN`Ps%Im)D`%Lrf?r$;{f(aYXv{ITCxGVN{WzwlOJ{Db>rlZUpG!=^ z+GJ5Kuy=R|g2Avv#pWBNU|c_FnL+moiDi4irTS>8$H+5AHw#b9FuUN8#)VSSw6q14 zV@u=U;X}WtzKn{C3>Xm-EoB4!V3SAabfH*zAAIq657zZIE-g zj>ESBG@t{9?&qJcPY{dR4;R_Ur<0DF9aHG z(7JgOtxpXojH&2*3?e$&v9YmQ5DH{MFNq10knMZWiiFfRZ_ePLCieI^%BL?*ErHHA zA==h(wRKsSS-L||h@_-7ykTOY^UP~qR4Sc^_MYt31JLKJSslB4{^t89!d(EGI`H+0 zHcJB0xC9`bxt_?_URV#=Q1JpZ2Xz4v&k_a;{RN{?6Utni-Wfh#T~zn4nd86temiN? zaOUG-Yb_Kw&>c8nib{)4nMaAqeZz$Dj$UvQb)o+w8>m{^lPBB9OV=i|0b?dsrrSsT zWSBD%5ObV4(||%Z2Z%RBY9ftt)6gEN#$|DtQd2f$agL+dJ`G%8U0{l1#3DlO?W(=j zGUj=Jow&{%GY#-4Q=_7ejOTS(Wk=x0*lYT2oJBhM3OdVr0R`HCRG`nUG0xUTjqMK8 zeHRF%>C99O#~qeHt9YOJMSl0*P*dPP{IURuEXmL_&GkcZkgE z@WC?5UFF+RL6;XGew{dg*+`)<=prz~VkR=o>HxGsM%6C2mu<#@4-H;Dh|O!Lr7RFf z^qk|m4k0yy`K^`6tt9A=Ndk3>CxttO5h8&U(2C9fg48+iq=j!CswgK-aN2?C{Dkgj zh9t424T}^y03QRkT;|exBMIPcX|oAI-$Dh;rV@+$ydTgpakNi`?S`MTnJs?nScUIb zM8h;_Qtf7JfCLG}-%0vpUi2RztM7acUsyok44tURTY$}zf_f3*?JU%7RVjMB26=VW zKf--cd!wJ$vjOU=J;Ykc;QB&$riPwgSZqe!5pqf0w;+=(KZZN?u)_nA3W-+ju&7^$ zgoNNpw2XocE4>0l`P+RuKKm2JA^D;5tG_%!sZf%~d<5>jp$XmaO~c3aJnPX<^)OtMl+#vhs;jUU2`wV2e_%yYl3LctBn5bs!qT zs|fJ-e+?T62O;8j9)AP`-1Ze~Y5CN%cTga2ay5Fxkrrm(nj@zxO}pm|Nrk literal 0 HcmV?d00001 diff --git a/docs/0.10.5/html/_static/images/histogram_example_1.png b/docs/0.10.5/html/_static/images/histogram_example_1.png new file mode 100644 index 0000000000000000000000000000000000000000..062dfdbb9829f3032b4c1afd55fefc61a08b5d56 GIT binary patch literal 11387 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 G+kXRhHtTNy literal 0 HcmV?d00001 diff --git a/docs/0.10.5/html/_static/images/missing_value_matrix_example_0.png b/docs/0.10.5/html/_static/images/missing_value_matrix_example_0.png new file mode 100644 index 0000000000000000000000000000000000000000..21799cddfe73821d7ed15fe29b805df8f2e1879a GIT binary patch literal 37730 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/html/_static/jquery-3.5.1.js b/docs/0.10.5/html/_static/jquery-3.5.1.js new file mode 100644 index 000000000..50937333b --- /dev/null +++ b/docs/0.10.5/html/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/add_new_model_to_data_labeler.ipynb b/docs/0.10.5/html/add_new_model_to_data_labeler.ipynb new file mode 100644 index 000000000..1495e6a85 --- /dev/null +++ b/docs/0.10.5/html/add_new_model_to_data_labeler.ipynb @@ -0,0 +1,488 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "228bb2a6", + "metadata": {}, + "source": [ + "# Adding new model to the existing DataLabeler pipeline" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "cab7a569", + "metadata": {}, + "source": [ + "Consider the case when we would like to explore different character-level neural network models and evaluate their performance on different datasets. The existing DataLabeler in the DataProfiler library already contains a preprocessor, a postprocessor, and a character-level CNN (Convolutional Neural Network) model that are combined to work on such data. All we need is to build additional model classes that inherit the main functionalities from the CNN model and also adapt the model construction to the desired architectures. In this example, we define such a new model to be used with the Data Labeler component of the Data Profiler. In particular, a character-level LSTM (Long Short-Term Memory) model is implemented, then integrated into the DataLabeler pipeline to be trained with a tabular dataset. The process includes the following steps:\n", + "\n", + " - Build a new character-level LSTM model that inherits the CNN model\n", + " - Load the DataLabeler from the DataProfiler\n", + " - Swap the existing CNN model with the new LSTM model\n", + " - Train the data labeler pipeline on a given dataset\n", + "\n", + "First, let's import the libraries needed for this example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16624c48", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "import pandas as pd\n", + "sys.path.insert(0, '..')\n", + "import dataprofiler as dp" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "e90728ab", + "metadata": {}, + "source": [ + "## Dataset" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "3d61981c", + "metadata": {}, + "source": [ + "In this example, we use a structured dataset, the aws honeypot dataset, given in the test folder of the library. This dataset is first read by the Data Reader class of the Data Profiler, then split into training and test data to be used in the next sections." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f031fe06", + "metadata": {}, + "outputs": [], + "source": [ + "# use data reader to read input data\n", + "data = dp.Data(\"../dataprofiler/tests/data/csv/aws_honeypot_marx_geo.csv\")\n", + "df_data = data.data\n", + "\n", + "# split data to training and test set\n", + "split_ratio = 0.2\n", + "df_data = df_data.sample(frac=1).reset_index(drop=True)\n", + "data_train = df_data[:int((1 - split_ratio) * len(df_data))]\n", + "data_test = df_data[int((1 - split_ratio) * len(df_data)):]\n", + "\n", + "df_data.head()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "745ed0d4", + "metadata": {}, + "source": [ + "## Implement a new character-level LSTM model" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "7375b0c0", + "metadata": {}, + "source": [ + "This new model is inherited from `CharacterLevelCnnModel` class, with some modifications on the following functions\n", + "\n", + "`__init__`: to add new parameters for the LSTM model. The new parameters, `size_lstm`, `rec_dropout`, `activation`, `recurrent_activation`, specify number of LSTM layers, activation function, and recurrent dropout ratio.\n", + "\n", + "`_validate_parameters`: to add additional checks on the new parameters for the LSTM model\n", + "\n", + "`_construct_model`: to construct the new LSTM model with the desired architecture" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8568fb49", + "metadata": {}, + "outputs": [], + "source": [ + "import tensorflow as tf\n", + "import numpy as np\n", + "from dataprofiler.labelers.character_level_cnn_model import (\n", + " CharacterLevelCnnModel,\n", + " create_glove_char,\n", + " build_embd_dictionary,\n", + ")\n", + "from dataprofiler.labelers.base_model import BaseModel\n", + "from dataprofiler.labelers.labeler_utils import F1Score\n", + "\n", + "\n", + "# CharacterLevelLstmModel derives from CharacterLevelCnnModel\n", + "#########################################################\n", + "#########################################################\n", + "class CharacterLevelLstmModel(CharacterLevelCnnModel):\n", + " # boolean if the label mapping requires the mapping for index 0 reserved\n", + " requires_zero_mapping = True\n", + "\n", + " def __init__(self, label_mapping=None, parameters=None):\n", + " \"\"\"\n", + " LSTM Model Initializer\n", + " \"\"\"\n", + "\n", + " # parameter initialization\n", + " if not parameters:\n", + " parameters = {}\n", + " parameters.setdefault(\"max_length\", 3400)\n", + " parameters.setdefault(\"max_char_encoding_id\", 127)\n", + " parameters.setdefault(\"dim_embed\", 64)\n", + " parameters.setdefault(\"size_fc\", [32, 32])\n", + " parameters.setdefault(\"dropout\", 0.1)\n", + " # new parameters for LSTM model\n", + " #########################################################\n", + " #########################################################\n", + " parameters.setdefault(\"size_lstm\", [64])\n", + " parameters.setdefault(\"rec_dropout\", 0.1)\n", + " parameters.setdefault(\"activation\", \"tanh\")\n", + " parameters.setdefault(\"recurrent_activation\", \"sigmoid\")\n", + " #########################################################\n", + " #########################################################\n", + " parameters.setdefault(\"default_label\", \"UNKNOWN\")\n", + " parameters[\"pad_label\"] = \"PAD\"\n", + " self._epoch_id = 0\n", + "\n", + " # reconstruct flags for model\n", + " self._model_num_labels = 0\n", + " self._model_default_ind = -1\n", + "\n", + " BaseModel.__init__(self, label_mapping, parameters)\n", + "\n", + " def _validate_parameters(self, parameters):\n", + " \"\"\"\n", + " Validate the parameters sent in. Raise error if invalid parameters are\n", + " present.\n", + " \"\"\"\n", + " errors = []\n", + " list_of_necessary_params = [\n", + " \"max_length\",\n", + " \"max_char_encoding_id\",\n", + " \"dim_embed\",\n", + " \"size_fc\",\n", + " \"dropout\",\n", + " \"size_lstm\",\n", + " \"rec_dropout\",\n", + " \"activation\",\n", + " \"recurrent_activation\",\n", + " \"default_label\",\n", + " \"pad_label\",\n", + " ]\n", + " # Make sure the necessary parameters are present and valid.\n", + " for param in parameters:\n", + " if param in [\n", + " \"max_length\",\n", + " \"max_char_encoding_id\",\n", + " \"dim_embed\",\n", + " \"size_conv\",\n", + " ]:\n", + " if (\n", + " not isinstance(parameters[param], (int, float))\n", + " or parameters[param] < 0\n", + " ):\n", + " errors.append(\n", + " param + \" must be a valid integer or float \" \"greater than 0.\"\n", + " )\n", + " elif param in [\n", + " \"dropout\",\n", + " \"rec_dropout\",\n", + " ]: # additional check for rec_dropout\n", + " if (\n", + " not isinstance(parameters[param], (int, float))\n", + " or parameters[param] < 0\n", + " or parameters[param] > 1\n", + " ):\n", + " errors.append(\n", + " param + \" must be a valid integer or float \" \"from 0 to 1.\"\n", + " )\n", + " elif (\n", + " param == \"size_fc\" or param == \"size_lstm\"\n", + " ): # additional check for size_lstm\n", + " if (\n", + " not isinstance(parameters[param], list)\n", + " or len(parameters[param]) == 0\n", + " ):\n", + " errors.append(param + \" must be a non-empty list of \" \"integers.\")\n", + " else:\n", + " for item in parameters[param]:\n", + " if not isinstance(item, int):\n", + " errors.append(\n", + " param + \" must be a non-empty \" \"list of integers.\"\n", + " )\n", + " break\n", + " elif param in [\n", + " \"default_label\",\n", + " \"activation\",\n", + " \"recurrent_activation\",\n", + " ]: # additional check for activation and recurrent_activation\n", + " if not isinstance(parameters[param], str):\n", + " error = str(param) + \" must be a string.\"\n", + " errors.append(error)\n", + "\n", + " # Error if there are extra parameters thrown in\n", + " for param in parameters:\n", + " if param not in list_of_necessary_params:\n", + " errors.append(param + \" is not an accepted parameter.\")\n", + " if errors:\n", + " raise ValueError(\"\\n\".join(errors))\n", + "\n", + " def _construct_model(self):\n", + " \"\"\"\n", + " Model constructor for the data labeler. This also serves as a weight\n", + " reset.\n", + "\n", + " :return: None\n", + " \"\"\"\n", + " num_labels = self.num_labels\n", + " default_ind = self.label_mapping[self._parameters[\"default_label\"]]\n", + "\n", + " # Reset model\n", + " tf.keras.backend.clear_session()\n", + "\n", + " # generate glove embedding\n", + " create_glove_char(self._parameters[\"dim_embed\"])\n", + "\n", + " # generate model\n", + " self._model = tf.keras.models.Sequential()\n", + "\n", + " # default parameters\n", + " max_length = self._parameters[\"max_length\"]\n", + " max_char_encoding_id = self._parameters[\"max_char_encoding_id\"]\n", + "\n", + " # Encoding layer\n", + " def encoding_function(input_str):\n", + " char_in_vector = CharacterLevelLstmModel._char_encoding_layer(\n", + " input_str, max_char_encoding_id, max_length\n", + " )\n", + " return char_in_vector\n", + "\n", + " self._model.add(tf.keras.layers.Input(shape=(None,), dtype=tf.string))\n", + "\n", + " self._model.add(\n", + " tf.keras.layers.Lambda(encoding_function, output_shape=tuple([max_length]))\n", + " )\n", + "\n", + " # Create a pre-trained weight matrix\n", + " # character encoding indices range from 0 to max_char_encoding_id,\n", + " # we add one extra index for out-of-vocabulary character\n", + " embed_file = os.path.join(\n", + " \"../dataprofiler/labelers\",\n", + " \"embeddings/glove-reduced-{}D.txt\".format(self._parameters[\"dim_embed\"]),\n", + " )\n", + " embedding_matrix = np.zeros(\n", + " (max_char_encoding_id + 2, self._parameters[\"dim_embed\"])\n", + " )\n", + " embedding_dict = build_embd_dictionary(embed_file)\n", + "\n", + " input_shape = tuple([max_length])\n", + " # Fill in the weight matrix: let pad and space be 0s\n", + " for ascii_num in range(max_char_encoding_id):\n", + " if chr(ascii_num) in embedding_dict:\n", + " embedding_matrix[ascii_num + 1] = embedding_dict[chr(ascii_num)]\n", + "\n", + " self._model.add(\n", + " tf.keras.layers.Embedding(\n", + " max_char_encoding_id + 2,\n", + " self._parameters[\"dim_embed\"],\n", + " weights=[embedding_matrix],\n", + " input_length=input_shape[0],\n", + " trainable=True,\n", + " )\n", + " )\n", + "\n", + " # Add the lstm layers\n", + " #########################################################\n", + " #########################################################\n", + " for size in self._parameters[\"size_lstm\"]:\n", + " self._model.add(\n", + " tf.keras.layers.LSTM(\n", + " units=size,\n", + " recurrent_dropout=self._parameters[\"rec_dropout\"],\n", + " activation=self._parameters[\"activation\"],\n", + " recurrent_activation=self._parameters[\"recurrent_activation\"],\n", + " return_sequences=True,\n", + " )\n", + " )\n", + " if self._parameters[\"dropout\"]:\n", + " self._model.add(tf.keras.layers.Dropout(self._parameters[\"dropout\"]))\n", + " #########################################################\n", + " #########################################################\n", + "\n", + " # Add the fully connected layers\n", + " for size in self._parameters[\"size_fc\"]:\n", + " self._model.add(tf.keras.layers.Dense(units=size, activation=\"relu\"))\n", + " if self._parameters[\"dropout\"]:\n", + " self._model.add(tf.keras.layers.Dropout(self._parameters[\"dropout\"]))\n", + "\n", + " # Add the final Softmax layer\n", + " self._model.add(tf.keras.layers.Dense(num_labels, activation=\"softmax\"))\n", + "\n", + " # Output the model into a .pb file for TensorFlow\n", + " argmax_layer = tf.keras.backend.argmax(self._model.output)\n", + "\n", + " # Create confidence layers\n", + " final_predicted_layer = CharacterLevelLstmModel._argmax_threshold_layer(\n", + " num_labels, threshold=0.0, default_ind=default_ind\n", + " )\n", + "\n", + " argmax_outputs = self._model.outputs + [\n", + " argmax_layer,\n", + " final_predicted_layer(argmax_layer, self._model.output),\n", + " ]\n", + " self._model = tf.keras.Model(self._model.inputs, argmax_outputs)\n", + "\n", + " # Compile the model\n", + " softmax_output_layer_name = self._model.outputs[0].name.split(\"/\")[0]\n", + " losses = {softmax_output_layer_name: \"categorical_crossentropy\"}\n", + "\n", + " # use f1 score metric\n", + " f1_score_training = F1Score(num_classes=num_labels, average=\"micro\")\n", + " metrics = {softmax_output_layer_name: [\"acc\", f1_score_training]}\n", + "\n", + " self._model.compile(loss=losses, optimizer=\"adam\", metrics=metrics)\n", + "\n", + " self._epoch_id = 0\n", + " self._model_num_labels = num_labels\n", + " self._model_default_ind = default_ind" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "d66bd25c", + "metadata": {}, + "source": [ + "## Integrate the new LSTM model to the DataLabeler" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "479f407a", + "metadata": {}, + "source": [ + "Once the LSTM model is built, it replaces the existing model in the DataLabeler pipeline, which is then trained on the given dataset. Note that, as the DataLabeler is trained on the above tabular dataset, its label mapping is updated by the list of column names in that dataset while training." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb482ffe", + "metadata": {}, + "outputs": [], + "source": [ + "# get labels from the given dataset\n", + "value_label_df = data_train.reset_index(drop=True).melt()\n", + "value_label_df.columns = [1, 0] # labels=1, values=0 in that order\n", + "value_label_df = value_label_df.astype(str)\n", + "labels = value_label_df[1].unique().tolist()\n", + "\n", + "# create a new LSTM model\n", + "# set default label (one of the column names) to the model\n", + "model = CharacterLevelLstmModel(label_mapping=labels, parameters={'default_label': 'comment'})\n", + "\n", + "# add the new LSTM model to the data labeler\n", + "data_labeler = dp.DataLabeler(labeler_type='structured', trainable=True)\n", + "data_labeler.set_model(model)\n", + "\n", + "# set default label (one of the column names) to the preprocessor and postprocessor\n", + "processor_params = {'default_label': 'comment'}\n", + "data_labeler._preprocessor.set_params(**processor_params)\n", + "data_labeler._postprocessor.set_params(**processor_params)\n", + "\n", + "# train the data labeler\n", + "save_dirpath=\"data_labeler_saved\"\n", + "if not os.path.exists(save_dirpath):\n", + " os.makedirs(save_dirpath)\n", + "\n", + "epochs=2\n", + "data_labeler.fit(\n", + " x=value_label_df[0], y=value_label_df[1], labels=labels, epochs=epochs)\n", + "if save_dirpath:\n", + " data_labeler.save_to_disk(save_dirpath)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "14b78c69", + "metadata": {}, + "source": [ + "The trained Data Labeler is then used by the Data Profiler to provide the prediction on the new dataset. In this example, all options except data labeler are disabled for the sake of presenting data labeler functionality. The results are given in the columnar format where true column types are given in the first column, and the predicted column labels are given in the second column." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bdfcf1d2", + "metadata": {}, + "outputs": [], + "source": [ + "# predict with the data labeler object\n", + "profile_options = dp.ProfilerOptions()\n", + "profile_options.set({\"structured_options.text.is_enabled\": False, \n", + " \"int.is_enabled\": False, \n", + " \"float.is_enabled\": False, \n", + " \"order.is_enabled\": False, \n", + " \"category.is_enabled\": False, \n", + " \"datetime.is_enabled\": False,})\n", + "profile_options.set({'structured_options.data_labeler.data_labeler_object': data_labeler})\n", + "profile = dp.Profiler(data_test, options=profile_options)\n", + "\n", + "# get the prediction from the data profiler\n", + "def get_structured_results(results):\n", + " columns = []\n", + " predictions = []\n", + " for col_report in results['data_stats']:\n", + " columns.append(col_report['column_name'])\n", + " predictions.append(col_report['data_label'])\n", + "\n", + " df_results = pd.DataFrame({'Column': columns, 'Prediction': predictions})\n", + " return df_results\n", + "\n", + "results = profile.report()\n", + "print(get_structured_results(results))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "cc60ff8a", + "metadata": {}, + "source": [ + "In summary, users can define their own model, plug it in the DataLabeler pipeline, and train the labeler with the new dataset. Above, we show one example of adding the LSTM model to the pipeline. Interested users can implement other neural network models as desired with the same process." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/html/column_name_labeler_example.html b/docs/0.10.5/html/column_name_labeler_example.html new file mode 100644 index 000000000..0c23d63c1 --- /dev/null +++ b/docs/0.10.5/html/column_name_labeler_example.html @@ -0,0 +1,821 @@ + + + + + + + + + ColumnName Labeler Tutorial - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + + +

View this notebook on GitHub

+
+

ColumnName Labeler Tutorial

+

This notebook teaches how to use the existing ColumnNameModel:

+
    +
  1. Loading and utilizing the pre-existing ColumnNameModel

  2. +
  3. Run the labeler

  4. +
+

First, let’s import the libraries needed for this example.

+
+
[ ]:
+
+
+
+import os
+import sys
+import json
+from pprint import pprint
+
+import pandas as pd
+
+try:
+    import dataprofiler as dp
+except ImportError:
+    sys.path.insert(0, '../..')
+    import dataprofiler as dp
+
+
+
+
+

Loading and predicting using a pre-existing model using load_from_library

+

The easiest option for users is to load_from_library by specifying the name for the labeler in the resources/ folder. Quickly import and start predicting with any model from the Data Profiler’s library of models available.

+
+
[ ]:
+
+
+
+labeler_from_library = dp.DataLabeler.load_from_library('column_name_labeler')
+
+
+
+
+
[ ]:
+
+
+
+labeler_from_library.predict(data=["ssn"])
+
+
+
+
+
+

Loading and using the pre-existing column name labeler using load_with_components

+

For example purposes here, we will import the exsting ColumnName labeler via the load_with_components command from the dp.DataLabeler. This shows a bit more of the details of the data labeler’s flow.

+
+
[ ]:
+
+
+
+parameters = {
+            "true_positive_dict": [
+                {"attribute": "ssn", "label": "ssn"},
+                {"attribute": "suffix", "label": "name"},
+                {"attribute": "my_home_address", "label": "address"},
+            ],
+            "false_positive_dict": [
+                {
+                    "attribute": "contract_number",
+                    "label": "ssn",
+                },
+                {
+                    "attribute": "role",
+                    "label": "name",
+                },
+                {
+                    "attribute": "send_address",
+                    "label": "address",
+                },
+            ],
+            "negative_threshold_config": 50,
+            "positive_threshold_config": 85,
+            "include_label": True,
+        }
+
+label_mapping = {"ssn": 1, "name": 2, "address": 3}
+
+
+
+
+
[ ]:
+
+
+
+# pre processor
+preprocessor = dp.labelers.data_processing.DirectPassPreprocessor()
+
+# model
+from dataprofiler.labelers.column_name_model import ColumnNameModel
+model = ColumnNameModel(
+    parameters=parameters,
+    label_mapping=label_mapping,
+)
+
+
+# post processor
+postprocessor = dp.labelers.data_processing.ColumnNameModelPostprocessor()
+
+
+
+
+
[ ]:
+
+
+
+data_labeler = dp.DataLabeler.load_with_components(
+    preprocessor=preprocessor,
+    model=model,
+    postprocessor=postprocessor,
+)
+data_labeler.model.help()
+
+
+
+
+
[ ]:
+
+
+
+pprint(data_labeler.label_mapping)
+
+
+
+
+
[ ]:
+
+
+
+pprint(data_labeler.model._parameters)
+
+
+
+
+

Predicting with the ColumnName labeler

+

In the prediction below, the data will be passed into to stages in the background - 1) compare_negative: The idea behind the compare_negative is to first filter out any possibility of flagging a false positive in the model prediction. In this step, the confidence value is checked and if the similarity is too close to being a false positive, that particular string in the data is removed and not returned to the compare_positive. - 2) compare_positive: Finally the data is +passed to the compare_positive step and checked for similarity with the the true_positive_dict values. Again, during this stage the positive_threshold_config is used to filter the results to only those data values that are greater than or equal to the positive_threshold_config provided by the user.

+
+
[ ]:
+
+
+
+# evaluate a prediction using the default parameters
+data_labeler.predict(data=["ssn", "name", "address"])
+
+
+
+
+
+
+

Replacing the parameters in the existing labeler

+

We can achieve this by: 1. Setting the label mapping to the new labels 2. Setting the model parameters which include: true_positive_dict, false_positive_dict, negative_threshold_config, positive_threshold_config, and include_label

+

where true_positive_dict and false_positive_dict are lists of dicts, negative_threshold_config and positive_threshold_config are integer values between 0 and 100, and include_label is a boolean value that determines if the output should include the prediction labels or only the confidence values.

+

Below, we created 4 labels where other is the default_label.

+
+
[ ]:
+
+
+
+data_labeler.set_labels({'other': 0, "funky_one": 1, "funky_two": 2, "funky_three": 3})
+data_labeler.model.set_params(
+    true_positive_dict= [
+                {"attribute": "ssn", "label": "funky_one"},
+                {"attribute": "suffix", "label": "funky_two"},
+                {"attribute": "my_home_address", "label": "funky_three"},
+            ],
+    false_positive_dict=[
+                {
+                    "attribute": "contract_number",
+                    "label": "ssn",
+                },
+                {
+                    "attribute": "role",
+                    "label": "name",
+                },
+                {
+                    "attribute": "not_my_address",
+                    "label": "address",
+                },
+            ],
+    negative_threshold_config=50,
+    positive_threshold_config=85,
+    include_label=True,
+)
+data_labeler.label_mapping
+
+
+
+
+

Predicting with the new labels

+

Here we are testing the predict() method with brand new labels for label_mapping. As we can see the new labels flow throught to the output of the data labeler.

+
+
[ ]:
+
+
+
+data_labeler.predict(data=["ssn", "suffix"], predict_options=dict(show_confidences=True))
+
+
+
+
+
+
+

Saving the Data Labeler for future use

+
+
[ ]:
+
+
+
+if not os.path.isdir('new_column_name_labeler'):
+    os.mkdir('new_column_name_labeler')
+data_labeler.save_to_disk('new_column_name_labeler')
+
+
+
+
+
+

Loading the saved Data Labeler

+
+
[ ]:
+
+
+
+saved_labeler = dp.DataLabeler.load_from_disk('new_column_name_labeler')
+
+
+
+
+
[ ]:
+
+
+
+# ensuring the parametesr are what we saved.
+print("label_mapping:")
+pprint(saved_labeler.label_mapping)
+print("\nmodel parameters:")
+pprint(saved_labeler.model._parameters)
+print()
+print("postprocessor: " + saved_labeler.postprocessor.__class__.__name__)
+
+
+
+
+
[ ]:
+
+
+
+# predicting with the loaded labeler.
+saved_labeler.predict(["ssn", "name", "address"])
+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/column_name_labeler_example.ipynb b/docs/0.10.5/html/column_name_labeler_example.ipynb new file mode 100644 index 000000000..6d3369698 --- /dev/null +++ b/docs/0.10.5/html/column_name_labeler_example.ipynb @@ -0,0 +1,364 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e04c382a-7c49-452b-b9bf-e448951c64fe", + "metadata": {}, + "source": [ + "# ColumnName Labeler Tutorial" + ] + }, + { + "cell_type": "markdown", + "id": "6fb3ecb9-bc51-4c18-93d5-7991bbee5165", + "metadata": {}, + "source": [ + "This notebook teaches how to use the existing `ColumnNameModel`:\n", + "\n", + "1. Loading and utilizing the pre-existing `ColumnNameModel`\n", + "2. Run the labeler\n", + "\n", + "First, let's import the libraries needed for this example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a67c197b-d3ee-4896-a96f-cc3d043601d3", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "from pprint import pprint\n", + "\n", + "import pandas as pd\n", + "\n", + "try:\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " sys.path.insert(0, '../..')\n", + " import dataprofiler as dp" + ] + }, + { + "cell_type": "markdown", + "id": "35841215", + "metadata": {}, + "source": [ + "## Loading and predicting using a pre-existing model using `load_from_library`\n", + "\n", + "The easiest option for users is to `load_from_library` by specifying the name for the labeler in the `resources/` folder. Quickly import and start predicting with any model from the Data Profiler's library of models available." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "46e36dd6", + "metadata": {}, + "outputs": [], + "source": [ + "labeler_from_library = dp.DataLabeler.load_from_library('column_name_labeler')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dfa94868", + "metadata": {}, + "outputs": [], + "source": [ + "labeler_from_library.predict(data=[\"ssn\"])" + ] + }, + { + "cell_type": "markdown", + "id": "c71356f4-9020-4862-a1e1-816effbb5443", + "metadata": {}, + "source": [ + "## Loading and using the pre-existing column name labeler using `load_with_components`\n", + "\n", + "For example purposes here, we will import the exsting `ColumnName` labeler via the `load_with_components` command from the `dp.DataLabeler`. This shows a bit more of the details of the data labeler's flow." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "818c5b88", + "metadata": {}, + "outputs": [], + "source": [ + "parameters = {\n", + " \"true_positive_dict\": [\n", + " {\"attribute\": \"ssn\", \"label\": \"ssn\"},\n", + " {\"attribute\": \"suffix\", \"label\": \"name\"},\n", + " {\"attribute\": \"my_home_address\", \"label\": \"address\"},\n", + " ],\n", + " \"false_positive_dict\": [\n", + " {\n", + " \"attribute\": \"contract_number\",\n", + " \"label\": \"ssn\",\n", + " },\n", + " {\n", + " \"attribute\": \"role\",\n", + " \"label\": \"name\",\n", + " },\n", + " {\n", + " \"attribute\": \"send_address\",\n", + " \"label\": \"address\",\n", + " },\n", + " ],\n", + " \"negative_threshold_config\": 50,\n", + " \"positive_threshold_config\": 85,\n", + " \"include_label\": True,\n", + " }\n", + "\n", + "label_mapping = {\"ssn\": 1, \"name\": 2, \"address\": 3}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9098329e", + "metadata": {}, + "outputs": [], + "source": [ + "# pre processor \n", + "preprocessor = dp.labelers.data_processing.DirectPassPreprocessor()\n", + "\n", + "# model\n", + "from dataprofiler.labelers.column_name_model import ColumnNameModel\n", + "model = ColumnNameModel(\n", + " parameters=parameters,\n", + " label_mapping=label_mapping,\n", + ")\n", + "\n", + "\n", + "# post processor\n", + "postprocessor = dp.labelers.data_processing.ColumnNameModelPostprocessor()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "113d6655-4bca-4d8e-9e6f-b972e29d5684", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler = dp.DataLabeler.load_with_components(\n", + " preprocessor=preprocessor,\n", + " model=model,\n", + " postprocessor=postprocessor,\n", + ")\n", + "data_labeler.model.help()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b405887-2b92-44ca-b8d7-29c384f6dd9c", + "metadata": {}, + "outputs": [], + "source": [ + "pprint(data_labeler.label_mapping)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11916a48-098c-4056-ac6c-b9542d85fa86", + "metadata": {}, + "outputs": [], + "source": [ + "pprint(data_labeler.model._parameters)" + ] + }, + { + "cell_type": "markdown", + "id": "da0e97ee-8d6d-4631-9b55-78ed904d5f41", + "metadata": {}, + "source": [ + "### Predicting with the ColumnName labeler\n", + "\n", + "In the prediction below, the data will be passed into to stages in the background\n", + "- 1) `compare_negative`: The idea behind the `compare_negative` is to first filter out any possibility of flagging a false positive in the model prediction. In this step, the confidence value is checked and if the similarity is too close to being a false positive, that particular string in the `data` is removed and not returned to the `compare_positive`.\n", + "- 2) `compare_positive`: Finally the `data` is passed to the `compare_positive` step and checked for similarity with the the `true_positive_dict` values. Again, during this stage the `positive_threshold_config` is used to filter the results to only those `data` values that are greater than or equal to the `positive_threshold_config` provided by the user." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fe519e65-36a7-4f42-8314-5369de8635c7", + "metadata": {}, + "outputs": [], + "source": [ + "# evaluate a prediction using the default parameters\n", + "data_labeler.predict(data=[\"ssn\", \"name\", \"address\"])" + ] + }, + { + "cell_type": "markdown", + "id": "b41d834d-e47b-45a6-8970-d2d2033e2ade", + "metadata": {}, + "source": [ + "## Replacing the parameters in the existing labeler\n", + "\n", + "We can achieve this by:\n", + "1. Setting the label mapping to the new labels\n", + "2. Setting the model parameters which include: `true_positive_dict`, `false_positive_dict`, `negative_threshold_config`, `positive_threshold_config`, and `include_label`\n", + "\n", + "where `true_positive_dict` and `false_positive_dict` are `lists` of `dicts`, `negative_threshold_config` and `positive_threshold_config` are integer values between `0` and `100`, and `include_label` is a `boolean` value that determines if the output should include the prediction labels or only the confidence values." + ] + }, + { + "cell_type": "markdown", + "id": "c6bb010a-406f-4fd8-abd0-3355a5ad0ded", + "metadata": {}, + "source": [ + "Below, we created 4 labels where `other` is the `default_label`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f86584cf-a7af-4bae-bf44-d87caa68833a", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.set_labels({'other': 0, \"funky_one\": 1, \"funky_two\": 2, \"funky_three\": 3})\n", + "data_labeler.model.set_params(\n", + " true_positive_dict= [\n", + " {\"attribute\": \"ssn\", \"label\": \"funky_one\"},\n", + " {\"attribute\": \"suffix\", \"label\": \"funky_two\"},\n", + " {\"attribute\": \"my_home_address\", \"label\": \"funky_three\"},\n", + " ],\n", + " false_positive_dict=[\n", + " {\n", + " \"attribute\": \"contract_number\",\n", + " \"label\": \"ssn\",\n", + " },\n", + " {\n", + " \"attribute\": \"role\",\n", + " \"label\": \"name\",\n", + " },\n", + " {\n", + " \"attribute\": \"not_my_address\",\n", + " \"label\": \"address\",\n", + " },\n", + " ],\n", + " negative_threshold_config=50,\n", + " positive_threshold_config=85,\n", + " include_label=True,\n", + ")\n", + "data_labeler.label_mapping" + ] + }, + { + "cell_type": "markdown", + "id": "1ece1c8c-18a5-46fc-b563-6458e6e71e53", + "metadata": {}, + "source": [ + "### Predicting with the new labels\n", + "\n", + "Here we are testing the `predict()` method with brand new labels for label_mapping. As we can see the new labels flow throught to the output of the data labeler." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92842e14-2ea6-4879-b58c-c52b607dc94c", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.predict(data=[\"ssn\", \"suffix\"], predict_options=dict(show_confidences=True))" + ] + }, + { + "cell_type": "markdown", + "id": "261b903f-8f4c-403f-839b-ab8813f850e9", + "metadata": {}, + "source": [ + "## Saving the Data Labeler for future use" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6ffbaf2-9400-486a-ba83-5fc9ba9334d7", + "metadata": {}, + "outputs": [], + "source": [ + "if not os.path.isdir('new_column_name_labeler'):\n", + " os.mkdir('new_column_name_labeler')\n", + "data_labeler.save_to_disk('new_column_name_labeler')" + ] + }, + { + "cell_type": "markdown", + "id": "09e40cb6-9d89-41c4-ae28-3dca498f8c68", + "metadata": {}, + "source": [ + "## Loading the saved Data Labeler" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52615b25-70a6-4ebb-8a32-14aaf1e747d9", + "metadata": {}, + "outputs": [], + "source": [ + "saved_labeler = dp.DataLabeler.load_from_disk('new_column_name_labeler')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d1ccc0b3-1dc2-4847-95c2-d6b8769b1590", + "metadata": {}, + "outputs": [], + "source": [ + "# ensuring the parametesr are what we saved.\n", + "print(\"label_mapping:\")\n", + "pprint(saved_labeler.label_mapping)\n", + "print(\"\\nmodel parameters:\")\n", + "pprint(saved_labeler.model._parameters)\n", + "print()\n", + "print(\"postprocessor: \" + saved_labeler.postprocessor.__class__.__name__)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c827f2ae-4af6-4f3f-9651-9ee9ebea9fa0", + "metadata": {}, + "outputs": [], + "source": [ + "# predicting with the loaded labeler.\n", + "saved_labeler.predict([\"ssn\", \"name\", \"address\"])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.7.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/html/data_labeling.html b/docs/0.10.5/html/data_labeling.html new file mode 100644 index 000000000..044fb4b80 --- /dev/null +++ b/docs/0.10.5/html/data_labeling.html @@ -0,0 +1,616 @@ + + + + + + + + + Labeler (Sensitive Data) - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Labeler (Sensitive Data)

+

In this library, the term data labeling refers to entity recognition.

+

Builtin to the data profiler is a classifier which evaluates the complex data types of the dataset. +For structured data, it determines the complex data type of each column. When +running the data profile, it uses the default data labeling model builtin to the +library. However, the data labeler allows users to train their own data labeler +as well.

+

Data Labels are determined per cell for structured data (column/row when +the profiler is used) or at the character level for unstructured data. This +is a list of the default labels.

+
    +
  • UNKNOWN

  • +
  • ADDRESS

  • +
  • BAN (bank account number, 10-18 digits)

  • +
  • CREDIT_CARD

  • +
  • EMAIL_ADDRESS

  • +
  • UUID

  • +
  • HASH_OR_KEY (md5, sha1, sha256, random hash, etc.)

  • +
  • IPV4

  • +
  • IPV6

  • +
  • MAC_ADDRESS

  • +
  • PERSON

  • +
  • PHONE_NUMBER

  • +
  • SSN

  • +
  • URL

  • +
  • US_STATE

  • +
  • DRIVERS_LICENSE

  • +
  • DATE

  • +
  • TIME

  • +
  • DATETIME

  • +
  • INTEGER

  • +
  • FLOAT

  • +
  • QUANTITY

  • +
  • ORDINAL

  • +
+
+

Identify Entities in Structured Data

+

Makes predictions and identifying labels:

+
import dataprofiler as dp
+
+# load data and data labeler
+data = dp.Data("your_data.csv")
+data_labeler = dp.DataLabeler(labeler_type='structured')
+
+# make predictions and get labels per cell
+predictions = data_labeler.predict(data)
+
+
+
+
+

Identify Entities in Unstructured Data

+

Predict which class characters belong to in unstructured text:

+
import dataprofiler as dp
+
+data_labeler = dp.DataLabeler(labeler_type='unstructured')
+
+# Example sample string, must be in an array (multiple arrays can be passed)
+sample = ["Help\tJohn Macklemore\tneeds\tfood.\tPlease\tCall\t555-301-1234."
+          "\tHis\tssn\tis\tnot\t334-97-1234. I'm a BAN: 000043219499392912.\n"]
+
+# Prediction what class each character belongs to
+model_predictions = data_labeler.predict(
+    sample, predict_options=dict(show_confidences=True))
+
+# Predictions / confidences are at the character level
+final_results = model_predictions["pred"]
+final_confidences = model_predictions["conf"]
+
+
+

It’s also possible to change output formats, output similar to a SpaCy format:

+
import dataprofiler as dp
+
+data_labeler = dp.DataLabeler(labeler_type='unstructured', trainable=True)
+
+# Example sample string, must be in an array (multiple arrays can be passed)
+sample = ["Help\tJohn Macklemore\tneeds\tfood.\tPlease\tCall\t555-301-1234."
+          "\tHis\tssn\tis\tnot\t334-97-1234. I'm a BAN: 000043219499392912.\n"]
+
+# Set the output to the NER format (start position, end position, label)
+data_labeler.set_params(
+    { 'postprocessor': { 'output_format':'ner', 'use_word_level_argmax':True } }
+)
+
+results = data_labeler.predict(sample)
+
+print(results)
+
+
+
+
+

Train a New Data Labeler

+

Mechanism for training your own data labeler on their own set of structured data +(tabular):

+
import dataprofiler as dp
+
+# Will need one column with a default label of UNKNOWN
+data = dp.Data("your_file.csv")
+
+data_labeler = dp.train_structured_labeler(
+    data=data,
+    save_dirpath="/path/to/save/labeler",
+    epochs=2
+)
+
+data_labeler.save_to_disk("my/save/path") # Saves the data labeler for reuse
+
+
+
+
+

Load an Existing Data Labeler

+

Mechanism for loading an existing data_labeler:

+
import dataprofiler as dp
+
+data_labeler = dp.DataLabeler(
+    labeler_type='structured', dirpath="/path/to/my/labeler")
+
+# get information about the parameters/inputs/output formats for the DataLabeler
+data_labeler.help()
+
+
+
+
+

Extending a Data Labeler with Transfer Learning

+

Extending or changing labels of a data labeler w/ transfer learning: +Note: By default, a labeler loaded will not be trainable. In order to load a +trainable DataLabeler, the user must set trainable=True or load a labeler +using the TrainableDataLabeler class.

+

The following illustrates how to change the labels:

+
import dataprofiler as dp
+
+labels = ['label1', 'label2', ...]  # new label set can also be an encoding dict
+data = dp.Data("your_file.csv")  # contains data with new labels
+
+# load default structured Data Labeler w/ trainable set to True
+data_labeler = dp.DataLabeler(labeler_type='structured', trainable=True)
+
+# this will use transfer learning to retrain the data labeler on your new
+# dataset and labels.
+# NOTE: data must be in an acceptable format for the preprocessor to interpret.
+#       please refer to the preprocessor/model for the expected data format.
+#       Currently, the DataLabeler cannot take in Tabular data, but requires
+#       data to be ingested with two columns [X, y] where X is the samples and
+#       y is the labels.
+model_results = data_labeler.fit(x=data['samples'], y=data['labels'],
+                                 validation_split=0.2, epochs=2, labels=labels)
+
+# final_results, final_confidences are a list of results for each epoch
+epoch_id = 0
+final_results = model_results[epoch_id]["pred"]
+final_confidences = model_results[epoch_id]["conf"]
+
+
+

The following illustrates how to extend the labels:

+
import dataprofiler as dp
+
+new_labels = ['label1', 'label2', ...]
+data = dp.Data("your_file.csv")  # contains data with new labels
+
+# load default structured Data Labeler w/ trainable set to True
+data_labeler = dp.DataLabeler(labeler_type='structured', trainable=True)
+
+# this will maintain current labels and model weights, but extend the model's
+# labels
+for label in new_labels:
+    data_labeler.add_label(label)
+
+# NOTE: a user can also add a label which maps to the same index as an existing
+# label
+# data_labeler.add_label(label, same_as='<label_name>')
+
+# For a trainable model, the user must then train the model to be able to
+# continue using the labeler since the model's graph has likely changed
+# NOTE: data must be in an acceptable format for the preprocessor to interpret.
+#       please refer to the preprocessor/model for the expected data format.
+#       Currently, the DataLabeler cannot take in Tabular data, but requires
+#       data to be ingested with two columns [X, y] where X is the samples and
+#       y is the labels.
+model_results = data_labeler.fit(x=data['samples'], y=data['labels'],
+                                 validation_split=0.2, epochs=2)
+
+# final_results, final_confidences are a list of results for each epoch
+epoch_id = 0
+final_results = model_results[epoch_id]["pred"]
+final_confidences = model_results[epoch_id]["conf"]
+
+
+

Changing pipeline parameters:

+
import dataprofiler as dp
+
+# load default Data Labeler
+data_labeler = dp.DataLabeler(labeler_type='structured')
+
+# change parameters of specific component
+data_labeler.preprocessor.set_params({'param1': 'value1'})
+
+# change multiple simultaneously.
+data_labeler.set_params({
+    'preprocessor':  {'param1': 'value1'},
+    'model':         {'param2': 'value2'},
+    'postprocessor': {'param3': 'value3'}
+})
+
+
+
+

Build Your Own Data Labeler

+

The DataLabeler has 3 main components: preprocessor, model, and postprocessor. +To create your own DataLabeler, each one would have to be created or an +existing component can be reused.

+

Given a set of the 3 components, you can construct your own DataLabeler:

+

Option for swapping out specific components of an existing labeler.

+
import dataprofiler as dp
+from dataprofiler.labelers.character_level_cnn_model import \
+    CharacterLevelCnnModel
+from dataprofiler.labelers.data_processing import \
+    StructCharPreprocessor, StructCharPostprocessor
+
+model = CharacterLevelCnnModel(...)
+preprocessor = StructCharPreprocessor(...)
+postprocessor = StructCharPostprocessor(...)
+
+data_labeler = dp.DataLabeler(labeler_type='structured')
+data_labeler.set_preprocessor(preprocessor)
+data_labeler.set_model(model)
+data_labeler.set_postprocessor(postprocessor)
+
+# check for basic compatibility between the processors and the model
+data_labeler.check_pipeline()
+
+
+
+
+
+

Model Component

+

In order to create your own model component for data labeling, you can utilize +the BaseModel class from dataprofiler.labelers.base_model and +overriding the abstract class methods.

+

Reviewing CharacterLevelCnnModel from +dataprofiler.labelers.character_level_cnn_model illustrates the functions +which need an override.

+
    +
  1. __init__: specifying default parameters and calling base __init__

  2. +
  3. _validate_parameters: validating parameters given by user during setting

  4. +
  5. _need_to_reconstruct_model: flag for when to reconstruct a model (i.e. +parameters change or labels change require a model reconstruction)

  6. +
  7. _construct_model: initial construction of the model given the parameters

  8. +
  9. _reconstruct_model: updates model architecture for new label set while +maintaining current model weights

  10. +
  11. fit: mechanism for the model to learn given training data

  12. +
  13. predict: mechanism for model to make predictions on data

  14. +
  15. details: prints a summary of the model construction

  16. +
  17. save_to_disk: saves model and model parameters to disk

  18. +
  19. load_from_disk: loads model given a path on disk

  20. +
+
+
+

Preprocessor Component

+

In order to create your own preprocessor component for data labeling, you can +utilize the BaseDataPreprocessor class +from dataprofiler.labelers.data_processing and override the abstract class +methods.

+

Reviewing StructCharPreprocessor from +dataprofiler.labelers.data_processing illustrates the functions which +need an override.

+
    +
  1. __init__: passing parameters to the base class and executing any +extraneous calculations to be saved as parameters

  2. +
  3. _validate_parameters: validating parameters given by user during +setting

  4. +
  5. process: takes in the user data and converts it into an digestible, +iterable format for the model

  6. +
  7. set_params (optional): if a parameter requires processing before setting, +a user can override this function to assist with setting the parameter

  8. +
  9. _save_processor (optional): if a parameter is not JSON serializable, a +user can override this function to assist in saving the processor and its +parameters

  10. +
  11. load_from_disk (optional): if a parameter(s) is not JSON serializable, a +user can override this function to assist in loading the processor

  12. +
+
+
+

Postprocessor Component

+

The postprocessor is nearly identical to the preprocessor except it handles +the output of the model for processing. In order to create your own +postprocessor component for data labeling, you can utilize the +BaseDataPostprocessor class from dataprofiler.labelers.data_processing +and override the abstract class methods.

+

Reviewing StructCharPostprocessor from +dataprofiler.labelers.data_processing illustrates the functions which +need an override.

+
    +
  1. __init__: passing parameters to the base class and executing any +extraneous calculations to be saved as parameters

  2. +
  3. _validate_parameters: validating parameters given by user during +setting

  4. +
  5. process: takes in the output of the model and processes for output to +the user

  6. +
  7. set_params (optional): if a parameter requires processing before setting, +a user can override this function to assist with setting the parameter

  8. +
  9. _save_processor (optional): if a parameter is not JSON serializable, a +user can override this function to assist in saving the processor and its +parameters

  10. +
  11. load_from_disk (optional): if a parameter(s) is not JSON serializable, a +user can override this function to assist in loading the processor

  12. +
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/data_reader.html b/docs/0.10.5/html/data_reader.html new file mode 100644 index 000000000..32bad17c1 --- /dev/null +++ b/docs/0.10.5/html/data_reader.html @@ -0,0 +1,1102 @@ + + + + + + + + + Intro to Data Readers - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + + +

View this notebook on GitHub

+
+

Intro to Data Readers

+

Within the Data Profiler, there are 5 data reader classes:

+
    +
  • CSVData (delimited data: CSV, TSV, etc.)

  • +
  • JSONData

  • +
  • ParquetData

  • +
  • AVROData

  • +
  • GraphData

  • +
  • TextData

  • +
+

Each of these classes can be used to read data individually, however the Data Profiler provides the unique capability of auto detecting what data you have and reading it automatically by using the Data class.

+
import dataprofiler as dp
+data = dp.Data('/path/to/mydata.abc')  # auto detects and reads your data
+
+
+
+

Automatically reading and detecting data

+

Below is a demonstration of utilizing the Data class which automatically detects the type of data for a given file and reads it automatically.

+
+
[ ]:
+
+
+
+import os
+import sys
+
+try:
+    sys.path.insert(0, '..')
+    import dataprofiler as dp
+except ImportError:
+    import dataprofiler as dp
+
+
+
+
+
[ ]:
+
+
+
+# use data reader to read input data with different file types
+data_folder = "../dataprofiler/tests/data"
+csv_files = [
+    "csv/aws_honeypot_marx_geo.csv",
+    "csv/all-strings-skip-header-author.csv", # csv files with the author/description on the first line
+    "csv/sparse-first-and-last-column-empty-first-row.txt", # csv file with the .txt extension
+]
+json_files = [
+    "json/complex_nested.json",
+    "json/honeypot_intentially_mislabeled_file.csv", # json file with the .csv extension
+]
+parquet_files = [
+    "parquet/nation.dict.parquet",
+    "parquet/nation.plain.intentionally_mislabled_file.csv", # parquet file with the .csv extension
+]
+avro_files = [
+    "avro/userdata1.avro",
+    "avro/userdata1_intentionally_mislabled_file.json", # avro file with the .json extension
+]
+graph_files = [
+    "csv/graph_data_csv_identify.csv", # csv file with graph column names
+]
+text_files = [
+    "txt/discussion_reddit.txt",
+]
+all_files = csv_files + json_files + parquet_files + avro_files + graph_files + text_files
+print('filepath' + ' ' * 58 + 'data type')
+print('='*80)
+for file in all_files:
+    filepath = os.path.join(data_folder, file)
+    data = dp.Data(filepath)
+    print("{:<65} {:<15}".format(file, data.data_type))
+print("\n")
+
+
+
+
+
[ ]:
+
+
+
+# importing from a url
+data = dp.Data('https://raw.githubusercontent.com/capitalone/DataProfiler/main/dataprofiler/tests/data/csv/diamonds.csv')
+data.head()
+
+
+
+
+
+

Specifying detection options of Data and loading pandas.DataFrame

+

The Data class also gives the ability to set options or if the user wants to load their data with specific requirements. Options for each data reader are specified in the docs: https://capitalone.github.io/DataProfiler/docs/0.4.4/html/dataprofiler.data_readers.html

+
import dataprofiler as dp
+
+options = {...}  # allowed options are specified for each data reader.
+data = dp.Data(data, options=options)
+
+
+

Later in this tutorial, the options for the CSVData class will be discussed.

+

Additionally, a user can directly load a pandas.DataFrame as any data reader they choose.

+
+
[ ]:
+
+
+
+import pandas as pd
+from dataprofiler.data_readers.csv_data import CSVData
+
+
+df = pd.DataFrame(['my', 'random', 'data'])
+
+# specify via the `Data` class
+data = dp.Data(data=df, data_type='csv')
+print('Data Type: ', data.data_type)
+
+# specifically use the CSVData class
+data = CSVData(data=df)
+print('Data Type: ', data.data_type)
+
+
+
+
+
+

Accessing data and attributes

+

Once loaded, the data can be accessed via the data property of the object. Additional information about the data loaded may differ between data readers.

+

For this example we will focus on CSVData.

+
+
[ ]:
+
+
+
+filepath = "../dataprofiler/tests/data/csv/aws_honeypot_marx_geo.csv"
+data = dp.Data(filepath)
+print('Data Type: ', data.data_type)
+print('Data Filepath: ', data.input_file_path)
+print('File Encoding: ', data.file_encoding)
+print('Data Length (two techniques): ', len(data), data.length)
+print("Data Access:")
+data.data
+
+
+
+
+
+

Checking data file types with is_match

+

Each data reader has a class method is_match which determines whether or not a dataset is of a given data type.

+
CSVData.is_match
+JSONData.is_match
+ParquetData.is_match
+AVROData.is_match
+GraphData.is_match
+TextData.is_match
+
+
+
+
[ ]:
+
+
+
+# supplemental function
+def add_true_false_color(value):
+    """Converts True to green and False to red in printed text."""
+    if value:
+        return "\x1b[92m  " + str(is_match) + "\x1b[0m"
+    return "\x1b[31m " + str(is_match) + "\x1b[0m"
+
+
+
+
+
[ ]:
+
+
+
+from dataprofiler.data_readers.csv_data import CSVData
+
+
+non_csv_files = [
+    'json/iris-utf-8.json',
+    'json/honeypot_intentially_mislabeled_file.csv',
+    'parquet/titanic.parq',
+    'parquet/nation.plain.intentionally_mislabled_file.csv',
+    'txt/code.txt',
+    'txt/sentence.txt',
+    'avro/users.avro',
+    'avro/snappy_compressed_intentionally_mislabeled_file.csv',
+]
+
+print("Is the file a CSV?")
+print('=' * 80)
+for file in csv_files:
+    filepath = os.path.join(data_folder, file)
+    is_match = CSVData.is_match(filepath)
+    print(add_true_false_color(is_match), ':', file)
+    print('=' * 80)
+
+for file in non_csv_files:
+    filepath = os.path.join(data_folder, file)
+    is_match = CSVData.is_match(filepath)
+    print(add_true_false_color(is_match), ':', file)
+    print('=' * 80)
+
+
+
+
+
+

Reloading data after altering options with reload

+

There are two cases for using the reload function, both of which require the data type to have been interpreted correctly:

+
1. The options were not correctly determined
+2. The options were loaded correctly but a change is desired.
+
+
+

In the example below, the data_format for reading the data is changed and the data is then reloaded.

+
+
[ ]:
+
+
+
+filepath = "../dataprofiler/tests/data/csv/diamonds.csv"
+
+data = dp.Data(filepath)
+print('original data:')
+print('=' * 80)
+print(data.data[:5])
+
+print()
+data.reload(options={'data_format': 'records', 'record_samples_per_line': 1})
+print('reloaded data:')
+print('=' * 80)
+data.data[:5]
+
+
+
+
+
+

A deeper dive into CSVData

+

This next section will focus on how to use the data reader class: CSVData. The CSVData class is used for reading delimited data. Delimited data are datasets which have their columns specified by a specific character, commonly the ,. E.g. from the diamonds.csv dataset:

+
carat,cut,color,clarity,depth,table,price,x,y,z
+0.23,Ideal,E,SI2,61.5,55,326,3.95,3.98,2.43
+0.21,Premium,E,SI1,59.8,61,326,3.89,3.84,2.31
+0.23,Good,E,VS1,56.9,65,327,4.05,4.07,2.31
+0.29,Premium,I,VS2,62.4,58,334,4.2,4.23,2.63
+0.31,Good,J,SI2,63.3,58,335,4.34,4.35,2.75
+
+
+

However, the delimiter can be any character. Additionally, a quotechar, commonly ", can be specified which allows a delimiter to be contained within a column value. E.g. from the blogposts.csv dataset:

+
Blog Post,Date,Subject,Field
+"Monty Hall, meet Game Theory",4/13/2014,Statistics,Mathematics
+Gaussian Quadrature,4/13/2014,Algorithms,Mathematics
+
+
+

Notice how "Monty Hall, meet Game Theory" is contained by the quotechar because it contains the delimiter value ,.

+

These delimiter dataset parameters (and more) can be automatically determined by the CSVData data reader, however they can also be set via the options as demonstrated later in this tutorial.

+
+
+

Intro to the CSVData data reader

+

Previously, it was shown that CSVData may automatically be detected using Data or can be manually specified by the user:

+
import dataprofiler as dp
+from dataprofiler.data_readers.csv_data import CSVData
+
+data = dp.Data(filepath)
+data = CSVData(filepath)
+
+
+
+
[ ]:
+
+
+
+# use data reader to read delimited data
+data_folder = "../dataprofiler/tests/data"
+csv_files = [
+    "csv/diamonds.csv",
+    "csv/all-strings-skip-header-author.csv", # csv files with the author/description on the first line
+    "csv/sparse-first-and-last-column-empty-first-row.txt", # csv file with the .txt extension
+]
+
+for file in csv_files:
+    data = CSVData(os.path.join(data_folder, file))
+    print(data.data.head())
+    print('=' * 80)
+
+
+
+
+
+

CSVData Options

+

As mentioned preivously, CSVData has options that can be set to finetune its detection or to ensure the data is being read in a specific manner. The options for CSVData are detailed below:

+
    +
  • delimiter - delimiter used to decipher the csv input file

  • +
  • quotechar - quote character used in the delimited file

  • +
  • header - location of the header in the file.

  • +
  • data_format - user selected format in which to return data can only be of specified types

  • +
  • selected_columns - columns being selected from the entire dataset

  • +
+
+
[ ]:
+
+
+
+# options are set via a dictionary object in which the parameters are specified.
+# these are the default values for each option
+options = {
+    "delimiter": ",",
+    "quotechar": '"',
+    "header": 'auto',
+    "data_format": "dataframe",  # type: str, choices: "dataframe", "records"
+    "selected_columns": list(),
+}
+
+
+
+
+
+

Options: delimiter and quotechar

+

Below, both the auto detection and use of options will be illustrated for delimiter and quotechar.

+
+
[ ]:
+
+
+
+# display the data we are reading
+filepath = "../dataprofiler/tests/data/csv/daily-activity-sheet-@-singlequote.csv"
+num_lines = 10
+with open(filepath) as fp:
+    print(''.join(fp.readlines()[:num_lines]))
+
+
+
+
+
[ ]:
+
+
+
+data = dp.Data(filepath)  # or use CSVData
+print('Auto detected')
+print('=' * 80)
+print('delimiter: ', data.delimiter)
+print('quotechar: ', data.quotechar)
+data.data.head()
+
+
+
+
+
[ ]:
+
+
+
+options = {'delimiter': '@', 'quotechar': "'"}
+data = dp.Data(filepath, options=options)  # or use CSVData
+print('manually set')
+print('=' * 80)
+print('delimiter: ', data.delimiter)
+print('quotechar: ', data.quotechar)
+data.data.head()
+
+
+
+
+
[ ]:
+
+
+
+# intentional failure with incorrect options
+options = {'delimiter': ',', 'quotechar': '"'}
+
+# will be interepted as TextData because the delimtier and quotechar were incorrect
+data = dp.Data(filepath, options=options)
+print('intentional faliure set')
+print('=' * 80)
+try:
+    print('delimiter: ', data.delimiter)  # attribute error raised here, bc TextData, not CSVData
+    print('quotechar: ', data.quotechar)
+
+    # should not reach this or something went wrong
+    raise Exception('Should have failed because this is detected as TextData.')
+except AttributeError:
+    print('When data_type is not set or the CSVData is not set, it will fail over to the\n'
+          'next best reader. In this case it is "TextData"\n')
+data.data
+
+
+
+
+
+

Options: header

+

Below, both the auto detection and use of options will be illustrated for header.

+

Notice how in the manually set mechanism, we are intentionally setting the header incorrectly to illustrate what happens.

+
+
[ ]:
+
+
+
+# display the data we are reading
+filepath = "../dataprofiler/tests/data/csv/sparse-first-and-last-column-header-and-author-description.txt"
+num_lines = 10
+with open(filepath) as fp:
+    print(''.join(fp.readlines()[:num_lines]))
+
+
+
+
+
[ ]:
+
+
+
+options = {'header': 'auto'}  # auto detected (default value)
+data = dp.Data(filepath, options=options)  # or use CSVData
+print('Data Header:', data.header)
+print('=' * 80)
+data.data.head()
+
+
+
+
+
[ ]:
+
+
+
+options = {'header': 2}  # intentionally set incorrectly at value 2
+data = dp.Data(filepath, options=options)  # or use CSVData
+print('Data Header:', data.header)
+print('=' * 80)
+data.data.head()
+
+
+
+
+
+

Options: data_format

+

For CSVData, the data_format option can have the following values:

+
    +
  • dataframe - (default) loads the dataset as a pandas.DataFrame

  • +
  • records - loads the data as rows of text values, the extra parameter record_samples_per_line how many rows are combined into a single line

  • +
+

dataframe is used for conducting structured profiling of the dataset while records is for unstructured profiling.

+

Below, both the auto detection and use of options will be illustrated for data_format.

+
+
[ ]:
+
+
+
+# display the data we are reading
+filepath = "../dataprofiler/tests/data/csv/diamonds.csv"
+num_lines = 10
+with open(filepath) as fp:
+    print(''.join(fp.readlines()[:num_lines]))
+
+
+
+
+
[ ]:
+
+
+
+options = {'data_format': 'dataframe'}  # default
+data = dp.Data(filepath, options=options)  # or use CSVData
+data.data[:5]
+
+
+
+
+
[ ]:
+
+
+
+options = {'data_format': 'records', 'record_samples_per_line': 1}
+data = dp.Data(filepath, options=options)
+data.data[:5]
+
+
+
+
+
+

Options: selected columns

+

By default, all columns of a dataset will be read and loaded into the data reader. However, selected_columns can be set to only load columns which the user requests.

+
+
[ ]:
+
+
+
+# display the data we are reading
+filepath = "../dataprofiler/tests/data/csv/aws_honeypot_marx_geo.csv"
+num_lines = 10
+with open(filepath) as fp:
+    print(''.join(fp.readlines()[:num_lines]))
+
+
+
+
+
[ ]:
+
+
+
+options = {'selected_columns': ['datetime', 'host', 'src', 'proto']}
+data = dp.Data(filepath, options=options)
+data.data.head()
+
+
+
+
+
+

Intro to GraphData data reader

+

This tutorial will focus on how to use the data reader class: GraphData. The GraphData class is used for reading the delimited data from a CSV file into a NetworkX Graph object. This is all in an effort to prepare the data automaticaly for GraphProfiler class to then profile graph data.

+

The DataProiler keys off of common graph naming conventions in the column header row. E.G. from dataprofiler/tests/csv/graph_data_csv_identify.csv

+
node_id_dst, node_id_src, continuous_weight, categorical_status
+108,289,7.4448069,9
+81,180,3.65064207,0
+458,83,5.9959787,10
+55,116,4.63359209,79
+454,177,5.76715529,11
+429,225,4.79556889,3
+
+
+

Options for the GraphData are exactly the same as CSVData.

+

Example implementation of GraphData:

+
import dataprofiler as dp
+from dataprofiler.data_readers.graph_data import GraphData
+
+data = dp.Data(graph_file)
+data = GraphData(graph_file)
+
+
+
+
[ ]:
+
+
+
+from dataprofiler.data_readers.graph_data import GraphData
+
+# use data reader to read delimited data
+data_folder = "../dataprofiler/tests/data"
+graph_file = "csv/graph_data_csv_identify.csv"
+
+data = GraphData(os.path.join(data_folder, graph_file))
+print(data.data.edges)
+print('=' * 80)
+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/data_reader.ipynb b/docs/0.10.5/html/data_reader.ipynb new file mode 100644 index 000000000..d2ce887e6 --- /dev/null +++ b/docs/0.10.5/html/data_reader.ipynb @@ -0,0 +1,689 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "d4d79832-59ab-410a-ad6d-fbba01a3f0d3", + "metadata": {}, + "source": [ + "# Intro to Data Readers\n", + "Within the Data Profiler, there are 5 data reader classes:\n", + "\n", + " * CSVData (delimited data: CSV, TSV, etc.)\n", + " * JSONData\n", + " * ParquetData\n", + " * AVROData\n", + " * GraphData\n", + " * TextData\n", + " \n", + "Each of these classes can be used to read data individually, however the Data Profiler provides the unique capability of auto detecting what data you have and reading it automatically by using the `Data` class.\n", + "```python\n", + "import dataprofiler as dp\n", + "data = dp.Data('/path/to/mydata.abc') # auto detects and reads your data\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "f2315666-20be-4937-9f9a-26d42dc135e2", + "metadata": { + "tags": [] + }, + "source": [ + "## Automatically reading and detecting data\n", + "\n", + "Below is a demonstration of utilizing the `Data` class which automatically detects the type of data for a given file and reads it automatically." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "99e61c6c-43b8-4700-b627-759b5ef8bdda", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " import dataprofiler as dp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8821ad8d-b2c0-489c-ae6a-54c11b7f0a08", + "metadata": {}, + "outputs": [], + "source": [ + "# use data reader to read input data with different file types\n", + "data_folder = \"../dataprofiler/tests/data\"\n", + "csv_files = [\n", + " \"csv/aws_honeypot_marx_geo.csv\",\n", + " \"csv/all-strings-skip-header-author.csv\", # csv files with the author/description on the first line\n", + " \"csv/sparse-first-and-last-column-empty-first-row.txt\", # csv file with the .txt extension\n", + "]\n", + "json_files = [\n", + " \"json/complex_nested.json\",\n", + " \"json/honeypot_intentially_mislabeled_file.csv\", # json file with the .csv extension\n", + "]\n", + "parquet_files = [\n", + " \"parquet/nation.dict.parquet\",\n", + " \"parquet/nation.plain.intentionally_mislabled_file.csv\", # parquet file with the .csv extension\n", + "]\n", + "avro_files = [\n", + " \"avro/userdata1.avro\",\n", + " \"avro/userdata1_intentionally_mislabled_file.json\", # avro file with the .json extension\n", + "]\n", + "graph_files = [\n", + " \"csv/graph_data_csv_identify.csv\", # csv file with graph column names\n", + "]\n", + "text_files = [\n", + " \"txt/discussion_reddit.txt\",\n", + "]\n", + "all_files = csv_files + json_files + parquet_files + avro_files + graph_files + text_files\n", + "print('filepath' + ' ' * 58 + 'data type')\n", + "print('='*80)\n", + "for file in all_files:\n", + " filepath = os.path.join(data_folder, file)\n", + " data = dp.Data(filepath)\n", + " print(\"{:<65} {:<15}\".format(file, data.data_type))\n", + "print(\"\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "49dfc981-59fd-48a5-ad7b-e01f0a52d0b2", + "metadata": {}, + "outputs": [], + "source": [ + "# importing from a url\n", + "data = dp.Data('https://raw.githubusercontent.com/capitalone/DataProfiler/main/dataprofiler/tests/data/csv/diamonds.csv')\n", + "data.head()" + ] + }, + { + "cell_type": "markdown", + "id": "77f8ef2d-5aaf-44d6-b6d1-bf14f7eb7aa6", + "metadata": {}, + "source": [ + "## Specifying detection options of `Data` and loading `pandas.DataFrame`\n", + "\n", + "The `Data` class also gives the ability to set options or if the user wants to load their data with specific requirements.\n", + "Options for each data reader are specified in the docs: https://capitalone.github.io/DataProfiler/docs/0.4.4/html/dataprofiler.data_readers.html\n", + "\n", + "```python\n", + "import dataprofiler as dp\n", + "\n", + "options = {...} # allowed options are specified for each data reader.\n", + "data = dp.Data(data, options=options)\n", + "```\n", + "Later in this tutorial, the options for the CSVData class will be discussed.\n", + "\n", + "Additionally, a user can directly load a `pandas.DataFrame` as any data reader they choose." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b925d4e-ca94-4913-9acf-26a883585e85", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "from dataprofiler.data_readers.csv_data import CSVData\n", + "\n", + "\n", + "df = pd.DataFrame(['my', 'random', 'data'])\n", + "\n", + "# specify via the `Data` class\n", + "data = dp.Data(data=df, data_type='csv')\n", + "print('Data Type: ', data.data_type)\n", + "\n", + "# specifically use the CSVData class\n", + "data = CSVData(data=df)\n", + "print('Data Type: ', data.data_type)" + ] + }, + { + "cell_type": "markdown", + "id": "52c3c3ac-c241-4d91-8ac7-b3d28ffd19c3", + "metadata": {}, + "source": [ + "## Accessing data and attributes\n", + "\n", + "Once loaded, the data can be accessed via the `data` property of the object. Additional information about the data loaded may differ between data readers.\n", + "\n", + "For this example we will focus on `CSVData`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "09fa5929-e710-4107-9313-1370ab639c9c", + "metadata": {}, + "outputs": [], + "source": [ + "filepath = \"../dataprofiler/tests/data/csv/aws_honeypot_marx_geo.csv\"\n", + "data = dp.Data(filepath)\n", + "print('Data Type: ', data.data_type)\n", + "print('Data Filepath: ', data.input_file_path)\n", + "print('File Encoding: ', data.file_encoding)\n", + "print('Data Length (two techniques): ', len(data), data.length)\n", + "print(\"Data Access:\")\n", + "data.data" + ] + }, + { + "cell_type": "markdown", + "id": "b98be971-4768-479d-9e54-00f05a6fb790", + "metadata": {}, + "source": [ + "## Checking data file types with `is_match`\n", + "\n", + "Each data reader has a class method `is_match` which determines whether or not a dataset is of a given data type.\n", + "```python\n", + "CSVData.is_match\n", + "JSONData.is_match\n", + "ParquetData.is_match\n", + "AVROData.is_match\n", + "GraphData.is_match\n", + "TextData.is_match\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "104a32c1-1d50-4aa5-94ce-b2e72de38476", + "metadata": {}, + "outputs": [], + "source": [ + "# supplemental function\n", + "def add_true_false_color(value):\n", + " \"\"\"Converts True to green and False to red in printed text.\"\"\"\n", + " if value:\n", + " return \"\\x1b[92m \" + str(is_match) + \"\\x1b[0m\"\n", + " return \"\\x1b[31m \" + str(is_match) + \"\\x1b[0m\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06868d90-2726-4096-a6da-3866174e6671", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from dataprofiler.data_readers.csv_data import CSVData\n", + "\n", + "\n", + "non_csv_files = [\n", + " 'json/iris-utf-8.json',\n", + " 'json/honeypot_intentially_mislabeled_file.csv',\n", + " 'parquet/titanic.parq',\n", + " 'parquet/nation.plain.intentionally_mislabled_file.csv',\n", + " 'txt/code.txt',\n", + " 'txt/sentence.txt',\n", + " 'avro/users.avro',\n", + " 'avro/snappy_compressed_intentionally_mislabeled_file.csv',\n", + "]\n", + "\n", + "print(\"Is the file a CSV?\")\n", + "print('=' * 80)\n", + "for file in csv_files:\n", + " filepath = os.path.join(data_folder, file)\n", + " is_match = CSVData.is_match(filepath)\n", + " print(add_true_false_color(is_match), ':', file)\n", + " print('=' * 80)\n", + " \n", + "for file in non_csv_files:\n", + " filepath = os.path.join(data_folder, file)\n", + " is_match = CSVData.is_match(filepath)\n", + " print(add_true_false_color(is_match), ':', file)\n", + " print('=' * 80)" + ] + }, + { + "cell_type": "markdown", + "id": "38889990-8e19-4114-a4f3-dc2af938e29d", + "metadata": {}, + "source": [ + "## Reloading data after altering options with `reload`\n", + "\n", + "There are two cases for using the reload function, both of which require the data type to have been interpreted correctly:\n", + "\n", + " 1. The options were not correctly determined\n", + " 2. The options were loaded correctly but a change is desired.\n", + " \n", + "In the example below, the `data_format` for reading the data is changed and the data is then reloaded." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "01870e8d-45ee-4f33-a088-4453c7ffc7c2", + "metadata": {}, + "outputs": [], + "source": [ + "filepath = \"../dataprofiler/tests/data/csv/diamonds.csv\"\n", + "\n", + "data = dp.Data(filepath)\n", + "print('original data:')\n", + "print('=' * 80)\n", + "print(data.data[:5])\n", + "\n", + "print()\n", + "data.reload(options={'data_format': 'records', 'record_samples_per_line': 1})\n", + "print('reloaded data:')\n", + "print('=' * 80)\n", + "data.data[:5]" + ] + }, + { + "cell_type": "markdown", + "id": "e2285f19-9b34-4484-beaa-79df890b2825", + "metadata": {}, + "source": [ + "## A deeper dive into `CSVData`\n", + "\n", + "This next section will focus on how to use the data reader class: `CSVData`. The `CSVData` class is used for reading delimited data. Delimited data are datasets which have their columns specified by a specific character, commonly the `,`. E.g. from the `diamonds.csv` dataset:\n", + "```\n", + "carat,cut,color,clarity,depth,table,price,x,y,z\n", + "0.23,Ideal,E,SI2,61.5,55,326,3.95,3.98,2.43\n", + "0.21,Premium,E,SI1,59.8,61,326,3.89,3.84,2.31\n", + "0.23,Good,E,VS1,56.9,65,327,4.05,4.07,2.31\n", + "0.29,Premium,I,VS2,62.4,58,334,4.2,4.23,2.63\n", + "0.31,Good,J,SI2,63.3,58,335,4.34,4.35,2.75\n", + "```\n", + "\n", + "However, the delimiter can be any character. Additionally, a `quotechar`, commonly `\"`, can be specified which allows a delimiter to be contained within a column value.\n", + "E.g. from the `blogposts.csv` dataset:\n", + "```\n", + "Blog Post,Date,Subject,Field\n", + "\"Monty Hall, meet Game Theory\",4/13/2014,Statistics,Mathematics\n", + "Gaussian Quadrature,4/13/2014,Algorithms,Mathematics\n", + "```\n", + "Notice how `\"Monty Hall, meet Game Theory\"` is contained by the quotechar because it contains the delimiter value `,`.\n", + "\n", + "These delimiter dataset parameters (and more) can be automatically determined by the `CSVData` data reader, however they can also be set via the options as demonstrated later in this tutorial." + ] + }, + { + "cell_type": "markdown", + "id": "cccb6bf9-7fb8-46b8-992e-9caacb7ab3a8", + "metadata": {}, + "source": [ + "## Intro to the `CSVData` data reader\n", + "\n", + "Previously, it was shown that `CSVData` may automatically be detected using `Data` or can be manually specified by the user:\n", + "\n", + "```python\n", + "import dataprofiler as dp\n", + "from dataprofiler.data_readers.csv_data import CSVData\n", + "\n", + "data = dp.Data(filepath)\n", + "data = CSVData(filepath)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e25f5130-4f19-40c5-9d13-549a04f1aef5", + "metadata": {}, + "outputs": [], + "source": [ + "# use data reader to read delimited data \n", + "data_folder = \"../dataprofiler/tests/data\"\n", + "csv_files = [\n", + " \"csv/diamonds.csv\",\n", + " \"csv/all-strings-skip-header-author.csv\", # csv files with the author/description on the first line\n", + " \"csv/sparse-first-and-last-column-empty-first-row.txt\", # csv file with the .txt extension\n", + "]\n", + "\n", + "for file in csv_files:\n", + " data = CSVData(os.path.join(data_folder, file))\n", + " print(data.data.head())\n", + " print('=' * 80)" + ] + }, + { + "cell_type": "markdown", + "id": "8940de56-1417-4bf6-af87-9d4d00b9a631", + "metadata": {}, + "source": [ + "## CSVData Options\n", + "\n", + "As mentioned preivously, `CSVData` has options that can be set to finetune its detection or to ensure the data is being read in a specific manner.\n", + "The options for `CSVData` are detailed below:\n", + "\n", + " * delimiter - delimiter used to decipher the csv input file\n", + " * quotechar - quote character used in the delimited file\n", + " * header - location of the header in the file.\n", + " * data_format - user selected format in which to return data can only be of specified types\n", + " * selected_columns - columns being selected from the entire dataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3d74f2e8-0ec3-4e93-8778-0a5f013e0cdb", + "metadata": {}, + "outputs": [], + "source": [ + "# options are set via a dictionary object in which the parameters are specified.\n", + "# these are the default values for each option\n", + "options = {\n", + " \"delimiter\": \",\",\n", + " \"quotechar\": '\"',\n", + " \"header\": 'auto',\n", + " \"data_format\": \"dataframe\", # type: str, choices: \"dataframe\", \"records\"\n", + " \"selected_columns\": list(),\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "9af108a1-ffe6-4c3a-82cc-833b1a3b57a1", + "metadata": {}, + "source": [ + "## Options: delimiter and quotechar\n", + "\n", + "Below, both the auto detection and use of options will be illustrated for `delimiter` and `quotechar`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "570e20c3-198e-4356-98d3-92eb9655ef4e", + "metadata": {}, + "outputs": [], + "source": [ + "# display the data we are reading\n", + "filepath = \"../dataprofiler/tests/data/csv/daily-activity-sheet-@-singlequote.csv\"\n", + "num_lines = 10\n", + "with open(filepath) as fp:\n", + " print(''.join(fp.readlines()[:num_lines]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "98385148-861e-4eb1-ba8d-e93120515401", + "metadata": {}, + "outputs": [], + "source": [ + "data = dp.Data(filepath) # or use CSVData\n", + "print('Auto detected')\n", + "print('=' * 80)\n", + "print('delimiter: ', data.delimiter)\n", + "print('quotechar: ', data.quotechar)\n", + "data.data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7f5d9306-d90a-4fc6-85a7-a0d535fe2d80", + "metadata": {}, + "outputs": [], + "source": [ + "options = {'delimiter': '@', 'quotechar': \"'\"}\n", + "data = dp.Data(filepath, options=options) # or use CSVData\n", + "print('manually set')\n", + "print('=' * 80)\n", + "print('delimiter: ', data.delimiter)\n", + "print('quotechar: ', data.quotechar)\n", + "data.data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7bfa60f-b5b9-48a5-adc5-3937aed145da", + "metadata": {}, + "outputs": [], + "source": [ + "# intentional failure with incorrect options\n", + "options = {'delimiter': ',', 'quotechar': '\"'}\n", + "\n", + "# will be interepted as TextData because the delimtier and quotechar were incorrect\n", + "data = dp.Data(filepath, options=options)\n", + "print('intentional faliure set')\n", + "print('=' * 80)\n", + "try:\n", + " print('delimiter: ', data.delimiter) # attribute error raised here, bc TextData, not CSVData\n", + " print('quotechar: ', data.quotechar)\n", + " \n", + " # should not reach this or something went wrong\n", + " raise Exception('Should have failed because this is detected as TextData.')\n", + "except AttributeError:\n", + " print('When data_type is not set or the CSVData is not set, it will fail over to the\\n'\n", + " 'next best reader. In this case it is \"TextData\"\\n')\n", + "data.data" + ] + }, + { + "cell_type": "markdown", + "id": "eeb41c7c-8319-40a3-9d87-88edbb3c5290", + "metadata": {}, + "source": [ + "## Options: header\n", + "\n", + "Below, both the auto detection and use of options will be illustrated for `header`.\n", + "\n", + "Notice how in the manually set mechanism, we are intentionally setting the header incorrectly to illustrate what happens." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16a927ef-1ba8-4bf2-ae40-2a9909030609", + "metadata": {}, + "outputs": [], + "source": [ + "# display the data we are reading\n", + "filepath = \"../dataprofiler/tests/data/csv/sparse-first-and-last-column-header-and-author-description.txt\"\n", + "num_lines = 10\n", + "with open(filepath) as fp:\n", + " print(''.join(fp.readlines()[:num_lines]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0701d7bf-2de0-4dce-8f09-7f0cddd1132c", + "metadata": {}, + "outputs": [], + "source": [ + "options = {'header': 'auto'} # auto detected (default value)\n", + "data = dp.Data(filepath, options=options) # or use CSVData\n", + "print('Data Header:', data.header)\n", + "print('=' * 80)\n", + "data.data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b8642a0a-367a-44c6-b611-b89d97b29f85", + "metadata": {}, + "outputs": [], + "source": [ + "options = {'header': 2} # intentionally set incorrectly at value 2\n", + "data = dp.Data(filepath, options=options) # or use CSVData\n", + "print('Data Header:', data.header)\n", + "print('=' * 80)\n", + "data.data.head()" + ] + }, + { + "cell_type": "markdown", + "id": "d6e3f640-c809-4eb6-9571-30065821615e", + "metadata": {}, + "source": [ + "## Options: data_format\n", + "\n", + "For CSVData, the `data_format` option can have the following values:\n", + "\n", + " * dataframe - (default) loads the dataset as a pandas.DataFrame\n", + " * records - loads the data as rows of text values, the extra parameter `record_samples_per_line` how many rows are combined into a single line\n", + " \n", + "`dataframe` is used for conducting **structured profiling** of the dataset while `records` is for **unstructured profiling**.\n", + "\n", + "Below, both the auto detection and use of options will be illustrated for `data_format`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "146109ea-a554-4766-bb19-78c116d2a8dd", + "metadata": {}, + "outputs": [], + "source": [ + "# display the data we are reading\n", + "filepath = \"../dataprofiler/tests/data/csv/diamonds.csv\"\n", + "num_lines = 10\n", + "with open(filepath) as fp:\n", + " print(''.join(fp.readlines()[:num_lines]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dceac967-d326-4064-ba1c-87a1146c9d72", + "metadata": {}, + "outputs": [], + "source": [ + "options = {'data_format': 'dataframe'} # default\n", + "data = dp.Data(filepath, options=options) # or use CSVData\n", + "data.data[:5]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c25524f-ef23-4e06-9023-842c64c2640e", + "metadata": {}, + "outputs": [], + "source": [ + "options = {'data_format': 'records', 'record_samples_per_line': 1}\n", + "data = dp.Data(filepath, options=options)\n", + "data.data[:5]" + ] + }, + { + "cell_type": "markdown", + "id": "d45f3ed6-ddcd-4bf3-95bc-09f23eb94c97", + "metadata": {}, + "source": [ + "## Options: selected columns\n", + "\n", + "By default, all columns of a dataset will be read and loaded into the data reader. However, `selected_columns` can be set to only load columns which the user requests." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c9b45e18-93c6-42e6-b978-af51574307eb", + "metadata": {}, + "outputs": [], + "source": [ + "# display the data we are reading\n", + "filepath = \"../dataprofiler/tests/data/csv/aws_honeypot_marx_geo.csv\"\n", + "num_lines = 10\n", + "with open(filepath) as fp:\n", + " print(''.join(fp.readlines()[:num_lines]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "018f3f4d-32ac-411a-9918-bae78aff0b0e", + "metadata": {}, + "outputs": [], + "source": [ + "options = {'selected_columns': ['datetime', 'host', 'src', 'proto']}\n", + "data = dp.Data(filepath, options=options)\n", + "data.data.head()" + ] + }, + { + "cell_type": "markdown", + "id": "b50679ea", + "metadata": {}, + "source": [ + "## Intro to `GraphData` data reader\n", + "\n", + "This tutorial will focus on how to use the data reader class: `GraphData`. The `GraphData` class is used for reading the delimited data from a CSV file into a `NetworkX` Graph object. This is all in an effort to prepare the data automaticaly for `GraphProfiler` class to then profile graph data. \n", + "\n", + "The DataProiler keys off of common graph naming conventions in the column header row. E.G. from `dataprofiler/tests/csv/graph_data_csv_identify.csv`\n", + "```\n", + "node_id_dst, node_id_src, continuous_weight, categorical_status\n", + "108,289,7.4448069,9\n", + "81,180,3.65064207,0\n", + "458,83,5.9959787,10\n", + "55,116,4.63359209,79\n", + "454,177,5.76715529,11\n", + "429,225,4.79556889,3\n", + "```\n", + "\n", + "Options for the `GraphData` are exactly the same as `CSVData`.\n", + "\n", + "\n", + "Example implementation of `GraphData`:\n", + "```python\n", + "import dataprofiler as dp\n", + "from dataprofiler.data_readers.graph_data import GraphData\n", + "\n", + "data = dp.Data(graph_file)\n", + "data = GraphData(graph_file)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "838db976", + "metadata": {}, + "outputs": [], + "source": [ + "from dataprofiler.data_readers.graph_data import GraphData\n", + "\n", + "# use data reader to read delimited data \n", + "data_folder = \"../dataprofiler/tests/data\"\n", + "graph_file = \"csv/graph_data_csv_identify.csv\"\n", + "\n", + "data = GraphData(os.path.join(data_folder, graph_file))\n", + "print(data.data.edges)\n", + "print('=' * 80)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/html/data_readers.html b/docs/0.10.5/html/data_readers.html new file mode 100644 index 000000000..4b0265771 --- /dev/null +++ b/docs/0.10.5/html/data_readers.html @@ -0,0 +1,453 @@ + + + + + + + + + Data Readers - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Data Readers

+

The Data class itself will identify then output one of the following Data class types. +Using the data reader is easy, just pass it through the Data object.

+
import dataprofiler as dp
+data = dp.Data("your_file.csv")
+
+
+

The supported file types are:

+
    +
  • CSV file (or any delimited file)

  • +
  • JSON object

  • +
  • Avro file

  • +
  • Parquet file

  • +
  • Graph data file

  • +
  • Text file

  • +
  • Pandas DataFrame

  • +
  • A URL that points to one of the supported file types above

  • +
+

It’s also possible to specifically call one of the data classes such as the following command:

+
from dataprofiler.data_readers.csv_data import CSVData
+data = CSVData("your_file.csv", options={"delimiter": ","})
+
+
+

Additionally any of the data classes can be loaded using a URL:

+
import dataprofiler as dp
+data = dp.Data("https://you_website.com/your_file.file", options={"verify_ssl": "True"})
+
+
+

Below are descriptions of the various Data classes and the available options.

+
+

CSVData

+

Data class for loading datasets of type CSV. Can be specified by passing +in memory data or via a file path. Options pertaining the CSV may also +be specified using the options dict parameter.

+

CSVData(input_file_path=None, data=None, options=None)

+

Possible options:

+
    +
  • delimiter - Must be a string, for example “delimiter”: “,”

  • +
  • data_format - Must be a string, possible choices: “dataframe”, “records”

  • +
  • selected_columns - Columns being selected from the entire dataset, must be a +list [“column 1”, “ssn”]

  • +
  • sample_nrows - Reservoir sampling to sample “n” rows out of a total of “M” rows. +Specified for how many rows to sample, default None.

  • +
  • header - Define the header, for example

    +
      +
    • “header”: ‘auto’ for auto detection

    • +
    • “header”: None for no header

    • +
    • “header”: <INT> to specify the header row (0 based index)

    • +
    +
  • +
+
+
+

JSONData

+

Data class for loading datasets of type JSON. Can be specified by +passing in memory data or via a file path. Options pertaining the JSON +may also be specified using the options dict parameter. JSON data can be +accessed via the “data” property, the “metadata” property, and the +“data_and_metadata” property.

+

JSONData(input_file_path=None, data=None, options=None)

+

Possible options:

+
    +
  • data_format - must be a string, choices: “dataframe”, “records”, “json”, “flattened_dataframe”

    +
      +
    • “flattened_dataframe” is best used for JSON structure typically found in data streams that contain +nested lists of dictionaries and a payload. For example: {“data”: [ columns ], “response”: 200}

    • +
    +
  • +
  • selected_keys - columns being selected from the entire dataset, must be a list [“column 1”, “ssn”]

  • +
  • payload_keys - The dictionary keys for the payload of the JSON, typically called “data” +or “payload”. Defaults to [“data”, “payload”, “response”].

  • +
+
+
+

AVROData

+

Data class for loading datasets of type AVRO. Can be specified by +passing in memory data or via a file path. Options pertaining the AVRO +may also be specified using the options dict parameter.

+

AVROData(input_file_path=None, data=None, options=None)

+

Possible options:

+
    +
  • data_format - must be a string, choices: “dataframe”, “records”, “avro”, “json”, “flattened_dataframe”

    +
      +
    • “flattened_dataframe” is best used for AVROs with a JSON structure typically found in data streams that contain +nested lists of dictionaries and a payload. For example: {“data”: [ columns ], “response”: 200}

    • +
    +
  • +
  • selected_keys - columns being selected from the entire dataset, must be a list [“column 1”, “ssn”]

  • +
+
+
+

ParquetData

+

Data class for loading datasets of type PARQUET. Can be specified by +passing in memory data or via a file path. Options pertaining the +PARQUET may also be specified using the options dict parameter.

+

ParquetData(input_file_path=None, data=None, options=None)

+

Possible options:

+
    +
  • data_format - must be a string, choices: “dataframe”, “records”, “json”

  • +
  • selected_keys - columns being selected from the entire dataset, must be a list [“column 1”, “ssn”]

  • +
+
+
+

GraphData

+

Data Class for loading datasets of graph data. Currently takes CSV format, +further type formats will be supported. Can be specified by passing +in memory data (NetworkX Graph) or via a file path. Options pertaining the CSV file may also +be specified using the options dict parameter. Loads data from CSV into memory +as a NetworkX Graph.

+

GraphData(input_file_path=None, data=None, options=None)

+

Possible options:

+
    +
  • delimiter - must be a string, for example “delimiter”: “,”

  • +
  • data_format - must be a string, possible choices: “graph”, “dataframe”, “records”

  • +
  • header - Define the header, for example

    +
      +
    • “header”: ‘auto’ for auto detection

    • +
    • “header”: None for no header

    • +
    • “header”: <INT> to specify the header row (0 based index)

    • +
    +
  • +
+
+
+

TextData

+

Data class for loading datasets of type TEXT. Can be specified by +passing in memory data or via a file path. Options pertaining the TEXT +may also be specified using the options dict parameter.

+

TextData(input_file_path=None, data=None, options=None)

+

Possible options:

+
    +
  • data_format: user selected format in which to return data. Currently only supports “text”.

  • +
  • samples_per_line - chunks by which to read in the specified dataset

  • +
+
+
+

Data Using a URL

+

Data class for loading datasets of any type using a URL. Specified by passing in +any valid URL that points to one of the valid data types. Options pertaining the +URL may also be specified using the options dict parameter.

+

Data(input_file_path=None, data=None, options=None)

+

Possible options:

+
    +
  • verify_ssl: must be a boolean string, choices: “True”, “False”. Set to “True” by default.

  • +
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.data_readers.avro_data.html b/docs/0.10.5/html/dataprofiler.data_readers.avro_data.html new file mode 100644 index 000000000..278485d71 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.data_readers.avro_data.html @@ -0,0 +1,410 @@ + + + + + + + + + Avro Data - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Avro Data

+

Contains class for saving and loading spreadsheet data.

+
+
+class dataprofiler.data_readers.avro_data.AVROData(input_file_path: Optional[str] = None, data: Optional[Any] = None, options: Optional[Dict] = None)
+

Bases: dataprofiler.data_readers.json_data.JSONData, dataprofiler.data_readers.base_data.BaseData

+

AVROData class to save and load spreadsheet data.

+

Initialize Data class for loading datasets of type AVRO.

+

Can be specified by passing in memory data or via a file path. +Options pertaining to AVRO may also be specified using options dict param. +Possible Options:

+
options = dict(
+    data_format= type: str, choices: "dataframe", "records", "avro"
+    selected_keys= type: list(str)
+)
+
+
+

data_format: user selected format can only be of specified types +selected_keys: keys being selected from the entire dataset

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+data_type: str = 'avro'
+
+
+
+property file_encoding: Optional[str]
+

Set file encoding to None since not detected for avro.

+
+
+
+classmethod is_match(file_path: Union[str, _io.StringIO, _io.BytesIO], options: Optional[Dict] = None) bool
+

Test the given file to check if the file has valid AVRO format or not.

+
+
Parameters
+
    +
  • file_path (str) – path to the file to be examined

  • +
  • options (dict) – avro read options

  • +
+
+
Returns
+

is file a avro file or not

+
+
Return type
+

bool

+
+
+
+
+
+property data
+

Return data.

+
+
+
+property data_and_metadata: Optional[pandas.core.frame.DataFrame]
+

Return a data frame that joins the data and the metadata.

+
+
+
+property data_format: Optional[str]
+

Return data format.

+
+
+
+get_batch_generator(batch_size: int) Generator[Union[pandas.core.frame.DataFrame, List], None, None]
+

Get batch generator.

+
+
+
+info: Optional[str] = None
+
+
+
+property is_structured
+

Determine compatibility with StructuredProfiler.

+
+
+
+property length: int
+

Return the length of the dataset which is loaded.

+
+
Returns
+

length of the dataset

+
+
+
+
+
+property metadata: Optional[pandas.core.frame.DataFrame]
+

Return a data frame that contains the metadata.

+
+
+
+reload(input_file_path: Optional[str] = None, data: Optional[Union[pandas.core.frame.DataFrame, str]] = None, options: Optional[Dict] = None) None
+

Reload the data class with a new dataset.

+

This erases all existing data/options and replaces it +with the input data/options.

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+
+property selected_keys: Optional[List[str]]
+

Return selected keys.

+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.data_readers.base_data.html b/docs/0.10.5/html/dataprofiler.data_readers.base_data.html new file mode 100644 index 000000000..0d5b8af01 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.data_readers.base_data.html @@ -0,0 +1,372 @@ + + + + + + + + + Base Data - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Base Data

+

Contains abstract class for data loading and saving.

+
+
+class dataprofiler.data_readers.base_data.BaseData(input_file_path: Optional[str], data: Any, options: Dict)
+

Bases: object

+

Abstract class for data loading and saving.

+

Initialize Base class for loading a dataset.

+

Options can be specified and maybe +more specific to the subclasses.

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+data_type: str
+
+
+
+info: Optional[str] = None
+
+
+
+property data
+

Return data.

+
+
+
+property data_format: Optional[str]
+

Return data format.

+
+
+
+property is_structured: bool
+

Determine compatibility with StructuredProfiler.

+
+
+
+property file_encoding: Optional[str]
+

Return file encoding.

+
+
+
+get_batch_generator(batch_size: int) Generator[Union[pandas.core.frame.DataFrame, List], None, None]
+

Get batch generator.

+
+
+
+classmethod is_match(input_file_path: str, options: Optional[Dict]) bool
+

Return true if match, false otherwise.

+
+
+
+reload(input_file_path: Optional[str], data: Any, options: Optional[Dict]) None
+

Reload the data class with a new dataset.

+

This erases all existing +data/options and replaces it with the input data/options.

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+
+property length: int
+

Return the length of the dataset which is loaded.

+
+
Returns
+

length of the dataset

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.data_readers.csv_data.html b/docs/0.10.5/html/dataprofiler.data_readers.csv_data.html new file mode 100644 index 000000000..8c57986cf --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.data_readers.csv_data.html @@ -0,0 +1,439 @@ + + + + + + + + + CSV Data - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

CSV Data

+

Contains class that saves and loads spreadsheet data.

+
+
+class dataprofiler.data_readers.csv_data.CSVData(input_file_path: Optional[str] = None, data: Optional[pandas.core.frame.DataFrame] = None, options: Optional[Dict] = None)
+

Bases: dataprofiler.data_readers.structured_mixins.SpreadSheetDataMixin, dataprofiler.data_readers.base_data.BaseData

+

SpreadsheetData class to save and load spreadsheet data.

+

Initialize Data class for loading datasets of type CSV.

+

Can be specified by passing in memory data or via a file path. +Options pertaining to CSV may also be specified using options dict param. +Possible Options:

+
options = dict(
+    delimiter= type: str
+    data_format= type: str, choices: "dataframe", "records"
+    record_samples_per_line= type: int (only for "records")
+    selected_columns= type: list(str)
+    header= type: any
+)
+
+
+

delimiter: delimiter used to decipher the csv input file +data_format: user selected format in which to return data +can only be of specified types: +``` +dataframe - (default) loads the dataset as a pandas.DataFrame +records - loads the data as rows of text values, the extra parameter

+
+

“record_samples_per_line” determines how many rows are combined into +a single line

+
+

``` +selected_columns: columns being selected from the entire dataset +header: location of the header in the file +quotechar: quote character used in the delimited file

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+data_type: str = 'csv'
+
+
+
+property selected_columns: List[str]
+

Return selected columns.

+
+
+
+property delimiter: Optional[str]
+

Return delimiter.

+
+
+
+property quotechar: Optional[str]
+

Return quotechar.

+
+
+
+property header: Optional[Union[str, int]]
+

Return header.

+
+
+
+property sample_nrows: Optional[int]
+

Return sample_nrows.

+
+
+
+property is_structured: bool
+

Determine compatibility with StructuredProfiler.

+
+
+
+property data
+

Return data.

+
+
+
+property data_format: Optional[str]
+

Return data format.

+
+
+
+property file_encoding: Optional[str]
+

Return file encoding.

+
+
+
+get_batch_generator(batch_size: int) Generator[Union[pandas.core.frame.DataFrame, List], None, None]
+

Get batch generator.

+
+
+
+info: Optional[str] = None
+
+
+
+classmethod is_match(file_path: str, options: Optional[Dict] = None) bool
+

Check if first 1000 lines of given file has valid delimited format.

+
+
Parameters
+
    +
  • file_path (str) – path to the file to be examined

  • +
  • options (dict) – delimiter read options dict(delimiter=”,”)

  • +
+
+
Returns
+

is file a csv file or not

+
+
Return type
+

bool

+
+
+
+
+
+property length: int
+

Return the length of the dataset which is loaded.

+
+
Returns
+

length of the dataset

+
+
+
+
+
+options: Optional[Dict]
+
+
+
+reload(input_file_path: Optional[str] = None, data: Optional[pandas.core.frame.DataFrame] = None, options: Optional[Dict] = None)
+

Reload the data class with a new dataset.

+

This erases all existing data/options and replaces it with +the input data/options.

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.data_readers.data.html b/docs/0.10.5/html/dataprofiler.data_readers.data.html new file mode 100644 index 000000000..82db6b13f --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.data_readers.data.html @@ -0,0 +1,311 @@ + + + + + + + + + Data - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Data

+

Contains factory class reading various kinds of data.

+
+
+class dataprofiler.data_readers.data.Data(input_file_path: Optional[Union[str, _io.BytesIO]] = None, data: Optional[Any] = None, data_type: Optional[str] = None, options: Optional[Dict] = None)
+

Bases: object

+

Factory class for reading various kinds of data.

+

Create Factory Data object.

+

Auto-detection of data type if not specified for input files. +Returns the proper data class or specified data class for +the given data or input file.

+
+
Parameters
+
    +
  • input_file_path

  • +
  • data

  • +
  • data_type

  • +
  • options

  • +
+
+
Returns
+

+
+
+
+
+data_classes: List[Dict] = [{'data_class': <class 'dataprofiler.data_readers.json_data.JSONData'>, 'kwargs': {}}, {'data_class': <class 'dataprofiler.data_readers.graph_data.GraphData'>, 'kwargs': {}}, {'data_class': <class 'dataprofiler.data_readers.csv_data.CSVData'>, 'kwargs': {}}, {'data_class': <class 'dataprofiler.data_readers.parquet_data.ParquetData'>, 'kwargs': {}}, {'data_class': <class 'dataprofiler.data_readers.avro_data.AVROData'>, 'kwargs': {}}, {'data_class': <class 'dataprofiler.data_readers.text_data.TextData'>, 'kwargs': {}}]
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.data_readers.data_utils.html b/docs/0.10.5/html/dataprofiler.data_readers.data_utils.html new file mode 100644 index 000000000..c8559e673 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.data_readers.data_utils.html @@ -0,0 +1,657 @@ + + + + + + + + + Data Utils - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Data Utils

+

Contains functions for data readers.

+
+
+dataprofiler.data_readers.data_utils.data_generator(data_list: List[str]) Generator[str, None, None]
+

Take a list and return a generator on the list.

+
+
Parameters
+

data_list (list) – list of strings

+
+
Returns
+

item from the list

+
+
Return type
+

generator

+
+
+
+
+
+dataprofiler.data_readers.data_utils.generator_on_file(file_object: Union[_io.StringIO, _io.BytesIO]) Generator[Union[str, bytes], None, None]
+

Take a file and return a generator that returns lines.

+
+
Parameters
+

file_path (path) – path to the file

+
+
Returns
+

Line from file

+
+
Return type
+

generator

+
+
+
+
+
+dataprofiler.data_readers.data_utils.convert_int_to_string(x: int) str
+

Convert the given input to string.

+

In particular, it is int, it converts it ensuring there is no . or 00. +In addition, if the input is np.nan, the output will be ‘nan’ which is +what we need to handle data properly.

+
+
Parameters
+

x (Union[int, float, str, numpy.nan]) –

+
+
Returns
+

+
+
Return type
+

str

+
+
+
+
+
+dataprofiler.data_readers.data_utils.unicode_to_str(data: Union[str, int, float, bool, None, List, Dict], ignore_dicts: bool = False) Union[str, int, float, bool, None, List, Dict]
+

Convert data to string representation if it is a unicode string.

+
+
Parameters
+
    +
  • data (JSONType) – input data

  • +
  • ignore_dicts (boolean) – if set, ignore the dictionary type processing

  • +
+
+
Returns
+

string representation of data

+
+
Return type
+

str

+
+
+
+
+
+dataprofiler.data_readers.data_utils.json_to_dataframe(json_lines: List[Union[str, int, float, bool, None, List, Dict]], selected_columns: Optional[List[str]] = None, read_in_string: bool = False) Tuple[pandas.core.frame.DataFrame, pandas.core.series.Series]
+

Take list of json objects and return dataframe representing json list.

+
+
Parameters
+
    +
  • json_lines (list(JSONType)) – list of json objects

  • +
  • selected_columns (list(str)) – a list of keys to be processed

  • +
  • read_in_string (bool) – if True, all the values in dataframe will be +converted to string

  • +
+
+
Returns
+

dataframe converted from json list and list of dtypes for each +column

+
+
Return type
+

tuple(pd.DataFrame, pd.Series(dtypes))

+
+
+
+
+
+dataprofiler.data_readers.data_utils.read_json_df(data_generator: Generator, selected_columns: Optional[List[str]] = None, read_in_string: bool = False) Tuple[pandas.core.frame.DataFrame, pandas.core.series.Series]
+

Return an iterator that returns a chunk of data as dataframe in each call.

+

The source of input to this function is either a +file or a list of JSON structured strings. If the file path is given as +input, the file is expected to have one JSON structures in each line. The +lines that are not valid json will be ignored. Therefore, a file with +pretty printed JSON objects will not be considered valid JSON. If the +input is a data list, it is expected to be a list of strings where each +string is a valid JSON object. if the individual object is not valid +JSON, it will be ignored.

+

NOTE: both data_list and file_path cannot be passed at the same time.

+
+
Parameters
+
    +
  • data_generator (generator) – The generator you want to read.

  • +
  • selected_columns (list(str)) – a list of keys to be processed

  • +
  • read_in_string (bool) – if True, all the values in dataframe will be +converted to string

  • +
+
+
Returns
+

returns an iterator that returns a chunk of file as dataframe in +each call as well as original dtypes of the dataframe columns.

+
+
Return type
+

tuple(pd.DataFrame, pd.Series(dtypes))

+
+
+
+
+
+dataprofiler.data_readers.data_utils.read_json(data_generator: Iterator, selected_columns: Optional[List[str]] = None, read_in_string: bool = False) List[Union[str, int, float, bool, None, List, Dict]]
+

Return the lines of a json.

+

The source of input to this function is either a file or +a list of JSON structured strings. +If the file path is given as input, the file is expected to have one JSON +structures in each line. The lines that are not valid json will be ignored. +Therefore, a file with pretty printed JSON objects will not be considered +valid JSON. If the input is a data list, it is expected to be a list of +strings where each string is a valid JSON object. if the individual object +is not valid JSON, it will be ignored.

+

NOTE: both data_list and file_path cannot be passed at the same time.

+
+
Parameters
+
    +
  • data_generator (generator) – The generator you want to read.

  • +
  • selected_columns (list(str)) – a list of keys to be processed

  • +
  • read_in_string (bool) – if True, all the values in dataframe will be +converted to string

  • +
+
+
Returns
+

returns the lines of a json file

+
+
Return type
+

list(dict)

+
+
+
+
+
+dataprofiler.data_readers.data_utils.reservoir(file: _io.TextIOWrapper, sample_nrows: int) list
+

Implement the mathematical logic of Reservoir sampling.

+
+
Parameters
+
    +
  • file (TextIOWrapper) – wrapper of the opened csv file

  • +
  • sample_nrows (int) – number of rows to sample

  • +
+
+
Raises
+

ValueError()

+
+
Returns
+

sampled values

+
+
Return type
+

list

+
+
+
+
+
+dataprofiler.data_readers.data_utils.rsample(file_path: _io.TextIOWrapper, sample_nrows: int, args: dict) _io.StringIO
+

Implement Reservoir Sampling to sample n rows out of a total of M rows.

+
+
Parameters
+
    +
  • file_path (TextIOWrapper) – path of the csv file to be read in

  • +
  • sample_nrows (int) – number of rows being sampled

  • +
  • args (dict) – options to read the csv file

  • +
+
+
+
+
+
+dataprofiler.data_readers.data_utils.read_csv_df(file_path: Union[str, _io.BytesIO, _io.TextIOWrapper], delimiter: Optional[str], header: Optional[int], sample_nrows: Optional[int] = None, selected_columns: List[str] = [], read_in_string: bool = False, encoding: Optional[str] = 'utf-8') pandas.core.frame.DataFrame
+

Read a CSV file in chunks and return dataframe in form of iterator.

+
+
Parameters
+
    +
  • file_path (str) – path to the CSV file.

  • +
  • delimiter (str) – character used to separate csv values.

  • +
  • header (int) – the header row in the csv file.

  • +
  • selected_columns (list(str)) – a list of columns to be processed

  • +
  • read_in_string (bool) – if True, all the values in dataframe will be +converted to string

  • +
+
+
Returns
+

Iterator

+
+
Return type
+

pd.DataFrame

+
+
+
+
+
+dataprofiler.data_readers.data_utils.read_parquet_df(file_path: str, selected_columns: Optional[List[str]] = None, read_in_string: bool = False) Tuple[pandas.core.frame.DataFrame, pandas.core.series.Series]
+

Return an iterator that returns one row group each time.

+
+
Parameters
+

file_path (str) – path to the Parquet file.

+
+
Returns
+

+
+
Return type
+

Iterator(pd.DataFrame)

+
+
+
+
+
+dataprofiler.data_readers.data_utils.read_text_as_list_of_strs(file_path: str, encoding: Optional[str] = None) List[str]
+

Return list of strings relative to the chunk size.

+

Each line is 1 chunk.

+
+
Parameters
+

file_path (str) – path to the file

+
+
Returns
+

+
+
Return type
+

list(str)

+
+
+
+
+
+dataprofiler.data_readers.data_utils.detect_file_encoding(file_path: str, buffer_size: int = 1024, max_lines: int = 20) str
+

Determine encoding of files within initial max_lines of length buffer_size.

+
+
Parameters
+
    +
  • file_path (str) – path to the file

  • +
  • buffer_size (int) – buffer length for each line being read

  • +
  • max_lines (int) – number of lines to read from file of length buffer_size

  • +
+
+
Returns
+

encoding type

+
+
Return type
+

str

+
+
+
+
+
+dataprofiler.data_readers.data_utils.detect_cell_type(cell: str) str
+

Detect the cell type (int, float, etc).

+
+
Parameters
+

cell (str) – String designated for data type detection

+
+
+
+
+
+dataprofiler.data_readers.data_utils.get_delimiter_regex(delimiter: str = ',', quotechar: str = ',') Pattern[str]
+

Build regex for delimiter checks.

+
+
Parameters
+
    +
  • delimiter (str) – Delimiter to be added to regex

  • +
  • quotechar – Quotechar to be added to regex

  • +
+
+
+
+
+
+dataprofiler.data_readers.data_utils.find_nth_loc(string: Optional[str] = None, search_query: Optional[str] = None, n: int = 0, ignore_consecutive: bool = True) Tuple[int, int]
+

Search string via search_query and return nth index in which query occurs.

+

If there are less than ‘n’ the last loc is returned

+
+
Parameters
+
    +
  • string (str) – Input string, to be searched

  • +
  • search_query (str) – char(s) to find nth occurrence of

  • +
  • n (int) – The number of occurrences to iterate through

  • +
  • ignore_consecutive (bool) – Ignore consecutive matches in the search query.

  • +
+
+
Return idx
+

Index of the nth or last occurrence of the search_query

+
+
Rtype idx
+

int

+
+
Return id_count
+

Number of identifications prior to idx

+
+
Rtype id_count
+

int

+
+
+
+
+
+dataprofiler.data_readers.data_utils.load_as_str_from_file(file_path: str, file_encoding: Optional[str] = None, max_lines: int = 10, max_bytes: int = 65536, chunk_size_bytes: int = 1024) str
+

Load data from a csv file up to a specific line OR byte_size.

+
+
Parameters
+
    +
  • file_path (str) – Path to file to load data from

  • +
  • file_encoding (str) – File encoding

  • +
  • max_lines (int) – Maximum number of lines to load from file

  • +
  • max_bytes (int) – Maximum number of bytes to load from file

  • +
  • chunk_size_bytes (int) – Chunk size to load every data load

  • +
+
+
Returns
+

Data as string

+
+
Return type
+

str

+
+
+
+
+
+dataprofiler.data_readers.data_utils.is_valid_url(url_as_string: Any) typing_extensions.TypeGuard[Url]
+

Determine whether a given string is a valid URL.

+
+
Parameters
+

url_as_string (str) – string to be tested if URL

+
+
Returns
+

true if string is a valid URL

+
+
Return type
+

boolean

+
+
+
+
+
+dataprofiler.data_readers.data_utils.url_to_bytes(url_as_string: Url, options: Dict) _io.BytesIO
+

Read in URL and converts it to a byte stream.

+
+
Parameters
+
    +
  • url_as_string (str) – string to read as URL

  • +
  • options (dict) – options for the url

  • +
+
+
Returns
+

BytesIO stream of data downloaded from URL

+
+
Return type
+

BytesIO stream

+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.data_readers.filepath_or_buffer.html b/docs/0.10.5/html/dataprofiler.data_readers.filepath_or_buffer.html new file mode 100644 index 000000000..75285752d --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.data_readers.filepath_or_buffer.html @@ -0,0 +1,322 @@ + + + + + + + + + Filepath Or Buffer - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Filepath Or Buffer

+

Contains functions and classes for handling filepaths and buffers.

+
+
+dataprofiler.data_readers.filepath_or_buffer.is_stream_buffer(filepath_or_buffer: Any) typing_extensions.TypeGuard[Union[_io.StringIO, _io.BytesIO]]
+

Determine whether a given argument is a filepath or buffer.

+
+
Parameters
+

filepath_or_buffer (str) – path to the file or buffer

+
+
Returns
+

true if string is a buffer or false if string is a filepath

+
+
Return type
+

boolean

+
+
+
+
+
+class dataprofiler.data_readers.filepath_or_buffer.FileOrBufferHandler(filepath_or_buffer: Union[str, _io.StringIO, _io.BytesIO], open_method: str = 'r', encoding: Optional[str] = None, seek_offset: Optional[int] = None, seek_whence: int = 0)
+

Bases: object

+

FileOrBufferHandler class to read a filepath or buffer in.

+

Always returns a readable buffer.

+

Initialize Context manager class.

+

Used for inputting a file or buffer and returning +a structure that is always a buffer.

+
+
Parameters
+
    +
  • filepath_or_buffer (Union[str, StringIO, BytesIO]) – path to the file being loaded or buffer

  • +
  • open_method (string) – value describes the mode the file is opened in

  • +
  • seek_offset (int) – offset from start of the stream

  • +
+
+
Returns
+

TextIOBase or BufferedIOBase class/subclass

+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.data_readers.graph_data.html b/docs/0.10.5/html/dataprofiler.data_readers.graph_data.html new file mode 100644 index 000000000..f368463b5 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.data_readers.graph_data.html @@ -0,0 +1,416 @@ + + + + + + + + + Graph Data - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Graph Data

+

Contains class for identifying, reading, and loading graph data.

+
+
+class dataprofiler.data_readers.graph_data.GraphData(input_file_path: Optional[str] = None, data: Optional[networkx.classes.graph.Graph] = None, options: Optional[Dict] = None)
+

Bases: dataprofiler.data_readers.base_data.BaseData

+

GraphData class to identify, read, and load graph data.

+

Initialize Data class for identifying, reading, and loading graph data.

+

Current implementation only accepts file path as input. +An options parameter is also passed in to specify properties of the +input file.

+

Possible Options:

+
options = dict(
+    delimiter= type: str
+    column_names= type: list(str)
+    source_node= type: int
+    destination_node= type: int
+    target_keywords= type: list(str)
+    source_keywords= type: list(str)
+    header= type: any
+    quotechar= type: str
+)
+
+
+

delimiter: delimiter used to decipher the csv input file +column_names: list of column names of the csv +source_node: index of the source node column, range of (0,n-1) +target_node: index of the target node column, range of (0,n-1) +target_keywords: list of keywords to identify target/destination node col +source_keywords: list of keywords to identify source node col +graph_keywords: list of keywords to identify if data has graph data +header: location o the header in the file +quotechar: quote character used in the delimited file

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+data_type: str = 'graph'
+
+
+
+classmethod csv_column_names(file_path: str, header: Optional[int], delimiter: Optional[str], encoding: str = 'utf-8') List[str]
+

Fetch a list of column names from the csv file.

+
+
+
+classmethod is_match(file_path: str, options: Optional[Dict] = None) bool
+

Determine whether the file is a graph.

+
+
Current formats checked:
    +
  • attributed edge list

  • +
+
+
+

This works by finding whether the file contains a target and a source node

+
+
+
+check_integer(string: str) Union[int, str]
+

Check whether string is integer and output integer.

+
+
+
+property data
+

Return data.

+
+
+
+property data_format: Optional[str]
+

Return data format.

+
+
+
+property file_encoding: Optional[str]
+

Return file encoding.

+
+
+
+get_batch_generator(batch_size: int) Generator[Union[pandas.core.frame.DataFrame, List], None, None]
+

Get batch generator.

+
+
+
+info: Optional[str] = None
+
+
+
+property is_structured: bool
+

Determine compatibility with StructuredProfiler.

+
+
+
+property length: int
+

Return the length of the dataset which is loaded.

+
+
Returns
+

length of the dataset

+
+
+
+
+
+reload(input_file_path: Optional[str], data: Any, options: Optional[Dict]) None
+

Reload the data class with a new dataset.

+

This erases all existing +data/options and replaces it with the input data/options.

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+
+options: Optional[Dict]
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.data_readers.html b/docs/0.10.5/html/dataprofiler.data_readers.html new file mode 100644 index 000000000..4012c8ed5 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.data_readers.html @@ -0,0 +1,325 @@ + + + + + + + + + Data Readers - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+ + +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.data_readers.json_data.html b/docs/0.10.5/html/dataprofiler.data_readers.json_data.html new file mode 100644 index 000000000..a83f44dec --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.data_readers.json_data.html @@ -0,0 +1,421 @@ + + + + + + + + + JSON Data - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

JSON Data

+

Contains class to save and load json data.

+
+
+class dataprofiler.data_readers.json_data.JSONData(input_file_path: Optional[str] = None, data: Optional[Union[pandas.core.frame.DataFrame, str]] = None, options: Optional[Dict] = None)
+

Bases: dataprofiler.data_readers.structured_mixins.SpreadSheetDataMixin, dataprofiler.data_readers.base_data.BaseData

+

SpreadsheetData class to save and load spreadsheet data.

+

Initialize Data class for loading datasets of type JSON.

+

Can be specified by passing in memory data or via a file path. +Options pertaining the JSON may also be specified using the +options dict parameter. +Possible Options:

+
options = dict(
+    data_format= type: str, choices: "dataframe", "records", "json",
+     "flattened_dataframe"
+    selected_keys= type: list(str)
+    payload_keys= type: Union[str, list(str)]
+)
+
+
+

data_format: user selected format in which to return data +can only be of specified types +selected_keys: keys being selected from the entire dataset +payload_keys: list of dictionary keys that determine the payload

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+data_type: str = 'json'
+
+
+
+property selected_keys: Optional[List[str]]
+

Return selected keys.

+
+
+
+property metadata: Optional[pandas.core.frame.DataFrame]
+

Return a data frame that contains the metadata.

+
+
+
+property data_and_metadata: Optional[pandas.core.frame.DataFrame]
+

Return a data frame that joins the data and the metadata.

+
+
+
+property is_structured
+

Determine compatibility with StructuredProfiler.

+
+
+
+classmethod is_match(file_path: Union[str, _io.StringIO], options: Optional[Dict] = None) bool
+

Test whether first 1000 lines of file has valid JSON format or not.

+

At least 60 percent of the lines in the first 1000 +lines have to be valid json.

+
+
Parameters
+
    +
  • file_path (str) – path to the file to be examined

  • +
  • options (dict) – json read options

  • +
+
+
Returns
+

is file a json file or not

+
+
Return type
+

bool

+
+
+
+
+
+property data
+

Return data.

+
+
+
+property data_format: Optional[str]
+

Return data format.

+
+
+
+property file_encoding: Optional[str]
+

Return file encoding.

+
+
+
+get_batch_generator(batch_size: int) Generator[Union[pandas.core.frame.DataFrame, List], None, None]
+

Get batch generator.

+
+
+
+info: Optional[str] = None
+
+
+
+property length: int
+

Return the length of the dataset which is loaded.

+
+
Returns
+

length of the dataset

+
+
+
+
+
+reload(input_file_path: Optional[str] = None, data: Optional[Union[pandas.core.frame.DataFrame, str]] = None, options: Optional[Dict] = None) None
+

Reload the data class with a new dataset.

+

This erases all existing data/options and replaces it +with the input data/options.

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+
+options: Optional[Dict]
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.data_readers.parquet_data.html b/docs/0.10.5/html/dataprofiler.data_readers.parquet_data.html new file mode 100644 index 000000000..b0ebf469d --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.data_readers.parquet_data.html @@ -0,0 +1,406 @@ + + + + + + + + + Parquet Data - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Parquet Data

+

Contains class to save and load parquet data.

+
+
+class dataprofiler.data_readers.parquet_data.ParquetData(input_file_path: Optional[str] = None, data: Optional[Union[pandas.core.frame.DataFrame, str]] = None, options: Optional[Dict] = None)
+

Bases: dataprofiler.data_readers.structured_mixins.SpreadSheetDataMixin, dataprofiler.data_readers.base_data.BaseData

+

SpreadsheetData class to save and load parquet data.

+

Initialize Data class for loading datasets of type PARQUET.

+

Can be specified by passing in memory data or via a file path. +Options pertaining to PARQUET may also be specified using options dict param. +Possible Options:

+
options = dict(
+    data_format= type: str, choices: "dataframe", "records", "json"
+    selected_columns= type: list(str)
+    header= type: any
+)
+
+
+

data_format: user selected format in which to return data +can only be of specified types +selected_columns: columns being selected from the entire dataset

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+data_type: str = 'parquet'
+
+
+
+property file_encoding: None
+

Set file encoding to None since not detected for avro.

+
+
+
+property selected_columns: List[str]
+

Return selected columns.

+
+
+
+property is_structured: bool
+

Determine compatibility with StructuredProfiler.

+
+
+
+classmethod is_match(file_path: Union[str, _io.StringIO, _io.BytesIO], options: Optional[Dict] = None) bool
+

Test the given file to check if the file has valid Parquet format.

+
+
Parameters
+
    +
  • file_path (str) – path to the file to be examined

  • +
  • options (dict) – parquet read options

  • +
+
+
Returns
+

is file a parquet file or not

+
+
Return type
+

bool

+
+
+
+
+
+property data
+

Return data.

+
+
+
+property data_format: Optional[str]
+

Return data format.

+
+
+
+get_batch_generator(batch_size: int) Generator[Union[pandas.core.frame.DataFrame, List], None, None]
+

Get batch generator.

+
+
+
+info: Optional[str] = None
+
+
+
+property length: int
+

Return the length of the dataset which is loaded.

+
+
Returns
+

length of the dataset

+
+
+
+
+
+reload(input_file_path: Optional[str] = None, data: Optional[Any] = None, options: Optional[Dict] = None) None
+

Reload the data class with a new dataset.

+

This erases all existing data/options and replaces it +with the input data/options.

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+
+options: Optional[Dict]
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.data_readers.structured_mixins.html b/docs/0.10.5/html/dataprofiler.data_readers.structured_mixins.html new file mode 100644 index 000000000..6d59b5ff3 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.data_readers.structured_mixins.html @@ -0,0 +1,305 @@ + + + + + + + + + Structured Mixins - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Structured Mixins

+

Contains mixin data class for loading datasets of tye SpreadSheet.

+
+
+class dataprofiler.data_readers.structured_mixins.SpreadSheetDataMixin(input_file_path: Optional[str], data: Any, options: Dict)
+

Bases: object

+

Mixin data class for loading datasets of type SpreadSheet.

+

Can be specified. +Adds specialized functions for loading data from a string or file.

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+

Initialize spreadsheet mixin object.

+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.data_readers.text_data.html b/docs/0.10.5/html/dataprofiler.data_readers.text_data.html new file mode 100644 index 000000000..ca6764cd6 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.data_readers.text_data.html @@ -0,0 +1,411 @@ + + + + + + + + + Text Data - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Text Data

+

Contains class for saving and loading text files.

+
+
+class dataprofiler.data_readers.text_data.TextData(input_file_path: Optional[str] = None, data: Optional[List[str]] = None, options: Optional[Dict] = None)
+

Bases: dataprofiler.data_readers.base_data.BaseData

+

TextData class to save and load text files.

+

Initialize Data class for loading datasets of type TEXT.

+

Can be specified by +passing in memory data or via a file path. Options pertaining the TEXT +may also be specified using the options dict parameter. +Possible Options:

+
options = dict(
+    data_format= type: str, choices: "text"
+    samples_per_line= type: int
+)
+
+
+

data_format: user selected format in which to return data +can only be of specified types +samples_per_line: chunks by which to read in the specified dataset

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+data_type: str = 'text'
+
+
+
+property samples_per_line: int
+

Return samples per line.

+
+
+
+property is_structured: bool
+

Determine compatibility with StructuredProfiler.

+
+
+
+tokenize() None
+

Tokenize data.

+
+
+
+classmethod is_match(file_path: str, options: Optional[Dict] = None) bool
+

Return True if all are text files.

+
+
Parameters
+
    +
  • file_path (str) – path to the file to be examined

  • +
  • options (dict) – text file read options

  • +
+
+
Returns
+

is file a text file or not

+
+
Return type
+

bool

+
+
+
+
+
+reload(input_file_path: Optional[str] = None, data: Optional[List[str]] = None, options: Optional[Dict] = None) None
+

Reload the data class with a new dataset.

+

This erases all existing +data/options and replaces it with the input data/options.

+
+
Parameters
+
    +
  • input_file_path (str) – path to the file being loaded or None

  • +
  • data (multiple types) – data being loaded into the class instead of an input file

  • +
  • options (dict) – options pertaining to the data type

  • +
+
+
Returns
+

None

+
+
+
+
+
+property data
+

Return data.

+
+
+
+property data_format: Optional[str]
+

Return data format.

+
+
+
+property file_encoding: Optional[str]
+

Return file encoding.

+
+
+
+get_batch_generator(batch_size: int) Generator[Union[pandas.core.frame.DataFrame, List], None, None]
+

Get batch generator.

+
+
+
+info: Optional[str] = None
+
+
+
+property length: int
+

Return the length of the dataset which is loaded.

+
+
Returns
+

length of the dataset

+
+
+
+
+
+options: Optional[Dict]
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.dp_logging.html b/docs/0.10.5/html/dataprofiler.dp_logging.html new file mode 100644 index 000000000..7b24965c6 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.dp_logging.html @@ -0,0 +1,299 @@ + + + + + + + + + Dp Logging - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Dp Logging

+

Utility funcs allowing alteration of logging level/verbosity within dp lib.

+
+
+dataprofiler.dp_logging.get_logger()
+

Access DataProfiler-specific logger.

+
+
+
+dataprofiler.dp_logging.set_verbosity(level)
+

Set verbosity level for DataProfiler logger.

+

Must set it to one of the following values: +[logging.NOTSET, logging.DEBUG, logging.INFO,

+
+

logging.WARNING, logging.ERROR, logging.CRITICAL]

+
+
+
Parameters
+

level (int) – Verbosity level from logging module

+
+
+
+
+
+dataprofiler.dp_logging.get_child_logger(name)
+

Return logger for the given filepath.

+
+
Parameters
+

name (str) – name of file in need of accessing child logger

+
+
Returns
+

Logger instance for given file

+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.html b/docs/0.10.5/html/dataprofiler.html new file mode 100644 index 000000000..74a59cfe5 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.html @@ -0,0 +1,384 @@ + + + + + + + + + Dataprofiler - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.labelers.base_data_labeler.html b/docs/0.10.5/html/dataprofiler.labelers.base_data_labeler.html new file mode 100644 index 000000000..6fec62428 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.labelers.base_data_labeler.html @@ -0,0 +1,910 @@ + + + + + + + + + Base Data Labeler - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Base Data Labeler

+

Contains abstract classes from which labeler classes will inherit.

+
+
+class dataprofiler.labelers.base_data_labeler.BaseDataLabeler(dirpath: Optional[str] = None, load_options: Optional[dict] = None)
+

Bases: object

+

Parent class for data labeler objects.

+

Initialize DataLabeler class.

+
+
Parameters
+
    +
  • dirpath – path to data labeler

  • +
  • load_options – optional arguments to include for load i.e. class +for model or processors

  • +
+
+
+
+
+help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+property label_mapping: dict
+

Retrieve the label encodings.

+
+
Returns
+

dictionary for associating labels to indexes

+
+
+
+
+
+property reverse_label_mapping: dict
+

Retrieve the index to label encoding.

+
+
Returns
+

dictionary for associating indexes to labels

+
+
+
+
+
+property labels: list
+

Retrieve the label.

+
+
Returns
+

list of labels

+
+
+
+
+
+property preprocessor: data_processing.BaseDataPreprocessor | None
+

Retrieve the data preprocessor.

+
+
Returns
+

returns the preprocessor instance

+
+
+
+
+
+property model: dataprofiler.labelers.base_model.BaseModel
+

Retrieve the data labeler model.

+
+
Returns
+

returns the model instance

+
+
+
+
+
+property postprocessor: data_processing.BaseDataPostprocessor | None
+

Retrieve the data postprocessor.

+
+
Returns
+

returns the postprocessor instance

+
+
+
+
+
+set_params(params: dict) None
+

Allow user to set parameters of pipeline components.

+
+
Done in the following format:
+
params = dict(

preprocessor=dict(…), +model=dict(…), +postprocessor=dict(…)

+
+
+

)

+
+
+

where the key,values pairs for each pipeline component must match +parameters that exist in their components.

+
+
Parameters
+

params (dict) –

dictionary containing a key for a given pipeline +component and its associated value of parameters as such:

+
+

dict(preprocessor=dict(…), model=dict(…), +postprocessor=dict(…))

+
+

+
+
Returns
+

None

+
+
+
+
+
+add_label(label: str, same_as: Optional[str] = None) None
+

Add a label to the data labeler.

+
+
Parameters
+
    +
  • label (str) – new label being added to the data labeler

  • +
  • same_as (str) – label to have the same encoding index as for multi-label +to single encoding index.

  • +
+
+
Returns
+

None

+
+
+
+
+
+set_labels(labels: list | dict) None
+

Set the labels for the data labeler.

+
+
Parameters
+

labels (list or dict) – new labels in either encoding list or dict

+
+
Returns
+

None

+
+
+
+
+
+predict(data: Union[pandas.core.frame.DataFrame, pandas.core.series.Series, numpy.ndarray], batch_size: int = 32, predict_options: Optional[dict] = None, error_on_mismatch: bool = False, verbose: bool = True) dict
+

Predict labels of input data based with the data labeler model.

+
+
Parameters
+
    +
  • data (Union[pd.DataFrame, pd.Series, np.ndarray]) – data to be predicted upon

  • +
  • batch_size (int) – batch size of prediction

  • +
  • predict_options (Dict[str, bool]) – optional parameters to allow for predict as a +dict, i.e. dict(show_confidences=True)

  • +
  • error_on_mismatch (bool) – if true, errors instead of warns on parameter +mismatches in pipeline

  • +
  • verbose (bool) – Flag to determine whether to print status or not

  • +
+
+
Returns
+

predictions

+
+
Return type
+

Dict

+
+
+
+
+
+set_preprocessor(data_processor: dataprofiler.labelers.data_processing.BaseDataPreprocessor) None
+

Set the data preprocessor for the data labeler.

+
+
Parameters
+

data_processor (data_processing.BaseDataPreprocessor) – processor to set as the preprocessor

+
+
Returns
+

None

+
+
+
+
+
+set_model(model: dataprofiler.labelers.base_model.BaseModel) None
+

Set the model for the data labeler.

+
+
Parameters
+

model (base_model.BaseModel) – model to use within the data labeler

+
+
Returns
+

None

+
+
+
+
+
+set_postprocessor(data_processor: dataprofiler.labelers.data_processing.BaseDataPostprocessor) None
+

Set the data postprocessor for the data labeler.

+
+
Parameters
+

data_processor (data_processing.BaseDataPostprocessor) – processor to set as the postprocessor

+
+
Returns
+

None

+
+
+
+
+
+check_pipeline(skip_postprocessor: bool = False, error_on_mismatch: bool = False) None
+

Check whether the processors and models connect together without error.

+
+
Parameters
+
    +
  • skip_postprocessor (bool) – skip checking postprocessor is valid in +pipeline

  • +
  • error_on_mismatch (bool) – if true, errors instead of warns on parameter +mismatches in pipeline

  • +
+
+
Returns
+

None

+
+
+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from the data labeler zoo in the library.

+
+
Parameters
+

name (str) – name of the data labeler.

+
+
Returns
+

DataLabeler class

+
+
Return type
+

BaseDataLabeler

+
+
+
+
+
+classmethod load_from_disk(dirpath: str, load_options: Optional[dict] = None) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from a saved location on disk.

+
+
Parameters
+
    +
  • dirpath (str) – path to data labeler files.

  • +
  • load_options (dict) – optional arguments to include for load i.e. class +for model or processors

  • +
+
+
Returns
+

DataLabeler class

+
+
Return type
+

BaseDataLabeler

+
+
+
+
+
+classmethod load_with_components(preprocessor: dataprofiler.labelers.data_processing.BaseDataPreprocessor, model: dataprofiler.labelers.base_model.BaseModel, postprocessor: dataprofiler.labelers.data_processing.BaseDataPostprocessor) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from a its set of components.

+
+
Parameters
+
+
+
Returns
+

loaded BaseDataLabeler

+
+
Return type
+

BaseDataLabeler

+
+
+
+
+
+save_to_disk(dirpath: str) None
+

Save the data labeler to the specified location.

+
+
Parameters
+

dirpath (str) – location to save the data labeler.

+
+
Returns
+

None

+
+
+
+
+
+
+class dataprofiler.labelers.base_data_labeler.TrainableDataLabeler(dirpath: Optional[str] = None, load_options: Optional[dict] = None)
+

Bases: dataprofiler.labelers.base_data_labeler.BaseDataLabeler

+

Subclass of BaseDataLabeler that can be trained.

+

Initialize DataLabeler class.

+
+
Parameters
+
    +
  • dirpath – path to data labeler

  • +
  • load_options – optional arguments to include for load i.e. class +for model or processors

  • +
+
+
+
+
+fit(x: DataArray, y: DataArray, validation_split: float = 0.2, labels: list | dict | None = None, reset_weights: bool = False, batch_size: int = 32, epochs: int = 1, error_on_mismatch: bool = False) list
+

Fit the data labeler model for the dataset.

+
+
Parameters
+
    +
  • x (Union[pd.DataFrame, pd.Series, np.ndarray]) – samples to fit model

  • +
  • y (Union[pd.DataFrame, pd.Series, np.ndarray]) – labels associated with the samples to fit model

  • +
  • validation_split (float) – split of the data to have as cross-validation +data

  • +
  • labels (Union[list, dict]) – Encoding or number of labels if refit is needed to new +labels

  • +
  • reset_weights (bool) – Flag to determine whether or not to reset the +weights

  • +
  • batch_size (int) – Size of each batch sent to data labeler model

  • +
  • epochs (int) – number of epochs to iterate over the dataset and send to +the model

  • +
  • error_on_mismatch (bool) – if true, errors instead of warns on parameter +mismatches in pipeline

  • +
+
+
Returns
+

model output

+
+
+
+
+
+set_model(model: dataprofiler.labelers.base_model.BaseModel) None
+

Set the model for a trainable data labeler.

+

Model must have a train function to be able to be set.

+
+
Parameters
+

model (base_model.BaseModel) – model to use within the data labeler

+
+
Returns
+

None

+
+
+
+
+
+classmethod load_with_components(preprocessor: dataprofiler.labelers.data_processing.BaseDataPreprocessor, model: dataprofiler.labelers.base_model.BaseModel, postprocessor: dataprofiler.labelers.data_processing.BaseDataPostprocessor) dataprofiler.labelers.base_data_labeler.TrainableDataLabeler
+

Load the data labeler from a its set of components.

+
+
Parameters
+
+
+
Returns
+

loaded TrainableDataLabeler

+
+
Return type
+

TrainableDataLabeler

+
+
+
+
+
+add_label(label: str, same_as: Optional[str] = None) None
+

Add a label to the data labeler.

+
+
Parameters
+
    +
  • label (str) – new label being added to the data labeler

  • +
  • same_as (str) – label to have the same encoding index as for multi-label +to single encoding index.

  • +
+
+
Returns
+

None

+
+
+
+
+
+check_pipeline(skip_postprocessor: bool = False, error_on_mismatch: bool = False) None
+

Check whether the processors and models connect together without error.

+
+
Parameters
+
    +
  • skip_postprocessor (bool) – skip checking postprocessor is valid in +pipeline

  • +
  • error_on_mismatch (bool) – if true, errors instead of warns on parameter +mismatches in pipeline

  • +
+
+
Returns
+

None

+
+
+
+
+
+help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+property label_mapping: dict
+

Retrieve the label encodings.

+
+
Returns
+

dictionary for associating labels to indexes

+
+
+
+
+
+property labels: list
+

Retrieve the label.

+
+
Returns
+

list of labels

+
+
+
+
+
+classmethod load_from_disk(dirpath: str, load_options: Optional[dict] = None) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from a saved location on disk.

+
+
Parameters
+
    +
  • dirpath (str) – path to data labeler files.

  • +
  • load_options (dict) – optional arguments to include for load i.e. class +for model or processors

  • +
+
+
Returns
+

DataLabeler class

+
+
Return type
+

BaseDataLabeler

+
+
+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from the data labeler zoo in the library.

+
+
Parameters
+

name (str) – name of the data labeler.

+
+
Returns
+

DataLabeler class

+
+
Return type
+

BaseDataLabeler

+
+
+
+
+
+property model: dataprofiler.labelers.base_model.BaseModel
+

Retrieve the data labeler model.

+
+
Returns
+

returns the model instance

+
+
+
+
+
+property postprocessor: data_processing.BaseDataPostprocessor | None
+

Retrieve the data postprocessor.

+
+
Returns
+

returns the postprocessor instance

+
+
+
+
+
+predict(data: Union[pandas.core.frame.DataFrame, pandas.core.series.Series, numpy.ndarray], batch_size: int = 32, predict_options: Optional[dict] = None, error_on_mismatch: bool = False, verbose: bool = True) dict
+

Predict labels of input data based with the data labeler model.

+
+
Parameters
+
    +
  • data (Union[pd.DataFrame, pd.Series, np.ndarray]) – data to be predicted upon

  • +
  • batch_size (int) – batch size of prediction

  • +
  • predict_options (Dict[str, bool]) – optional parameters to allow for predict as a +dict, i.e. dict(show_confidences=True)

  • +
  • error_on_mismatch (bool) – if true, errors instead of warns on parameter +mismatches in pipeline

  • +
  • verbose (bool) – Flag to determine whether to print status or not

  • +
+
+
Returns
+

predictions

+
+
Return type
+

Dict

+
+
+
+
+
+property preprocessor: data_processing.BaseDataPreprocessor | None
+

Retrieve the data preprocessor.

+
+
Returns
+

returns the preprocessor instance

+
+
+
+
+
+property reverse_label_mapping: dict
+

Retrieve the index to label encoding.

+
+
Returns
+

dictionary for associating indexes to labels

+
+
+
+
+
+save_to_disk(dirpath: str) None
+

Save the data labeler to the specified location.

+
+
Parameters
+

dirpath (str) – location to save the data labeler.

+
+
Returns
+

None

+
+
+
+
+
+set_labels(labels: list | dict) None
+

Set the labels for the data labeler.

+
+
Parameters
+

labels (list or dict) – new labels in either encoding list or dict

+
+
Returns
+

None

+
+
+
+
+
+set_params(params: dict) None
+

Allow user to set parameters of pipeline components.

+
+
Done in the following format:
+
params = dict(

preprocessor=dict(…), +model=dict(…), +postprocessor=dict(…)

+
+
+

)

+
+
+

where the key,values pairs for each pipeline component must match +parameters that exist in their components.

+
+
Parameters
+

params (dict) –

dictionary containing a key for a given pipeline +component and its associated value of parameters as such:

+
+

dict(preprocessor=dict(…), model=dict(…), +postprocessor=dict(…))

+
+

+
+
Returns
+

None

+
+
+
+
+
+set_postprocessor(data_processor: dataprofiler.labelers.data_processing.BaseDataPostprocessor) None
+

Set the data postprocessor for the data labeler.

+
+
Parameters
+

data_processor (data_processing.BaseDataPostprocessor) – processor to set as the postprocessor

+
+
Returns
+

None

+
+
+
+
+
+set_preprocessor(data_processor: dataprofiler.labelers.data_processing.BaseDataPreprocessor) None
+

Set the data preprocessor for the data labeler.

+
+
Parameters
+

data_processor (data_processing.BaseDataPreprocessor) – processor to set as the preprocessor

+
+
Returns
+

None

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.labelers.base_model.html b/docs/0.10.5/html/dataprofiler.labelers.base_model.html new file mode 100644 index 000000000..11139d6ec --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.labelers.base_model.html @@ -0,0 +1,676 @@ + + + + + + + + + Base Model - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Base Model

+

Contains abstract classes for labeling data.

+
+
+class dataprofiler.labelers.base_model.AutoSubRegistrationMeta(clsname: str, bases: tuple, attrs: dict)
+

Bases: abc.ABCMeta

+

For registering subclasses.

+

Create auto registration object and return new class.

+
+
+mro()
+

Return a type’s method resolution order.

+
+
+
+register(subclass)
+

Register a virtual subclass of an ABC.

+

Returns the subclass, to allow usage as a class decorator.

+
+
+
+
+class dataprofiler.labelers.base_model.BaseModel(label_mapping: list | dict, parameters: dict)
+

Bases: object

+

For labeling data.

+

Initialize Base Model.

+

Only model and model parameters are stored here. +:param label_mapping: label mapping of the model or list of labels to be

+
+

converted into the label mapping

+
+
+
Parameters
+

parameters (dict) – Contains all the appropriate parameters for the model. +Must contain num_labels.

+
+
Returns
+

None

+
+
+
+
+requires_zero_mapping: bool = False
+
+
+
+property label_mapping: dict
+

Return mapping of labels to their encoded values.

+
+
+
+property reverse_label_mapping: dict
+

Return reversed order of current labels.

+

Useful for when needed to extract Labels via indices.

+
+
+
+property labels: list
+

Retrieve the label.

+
+
Returns
+

list of labels

+
+
+
+
+
+property num_labels: int
+

Return max label mapping.

+
+
+
+classmethod get_class(class_name: str) type[BaseModel] | None
+

Get subclasses.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (List[str]) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+add_label(label: str, same_as: str | None = None) None
+

Add a label to the data labeler.

+
+
Parameters
+
    +
  • label (str) – new label being added to the data labeler

  • +
  • same_as (str) – label to have the same encoding index as for multi-label +to single encoding index.

  • +
+
+
Returns
+

None

+
+
+
+
+
+set_label_mapping(label_mapping: list[str] | dict[str, int]) None
+

Set the labels for the model.

+
+
Parameters
+

label_mapping (Union[list, dict]) – label mapping of the model or list of labels to be +converted into the label mapping

+
+
Returns
+

None

+
+
+
+
+
+classmethod help() None
+

Help describe alterable parameters.

+
+
Returns
+

None

+
+
+
+
+
+abstract reset_weights() None
+

Reset the weights of the model.

+
+
Returns
+

None

+
+
+
+
+
+abstract predict(data: Union[pandas.core.frame.DataFrame, pandas.core.series.Series, numpy.ndarray], batch_size: int, show_confidences: bool, verbose: bool) dict
+

Predict the data with the current model.

+
+
Parameters
+
    +
  • data (iterator of data to process) – model input data to predict on

  • +
  • batch_size (int) – number of samples in the batch of data

  • +
  • show_confidences (bool) – whether user wants prediction confidences

  • +
  • verbose (bool) – Flag to determine whether to print status or not

  • +
+
+
Returns
+

char level predictions and confidences

+
+
Return type
+

dict

+
+
+
+
+
+abstract classmethod load_from_disk(dirpath: str) dataprofiler.labelers.base_model.BaseModel
+

Load whole model from disk with weights.

+
+
Parameters
+

dirpath (str) – directory path where you want to load the model from

+
+
Returns
+

loaded model

+
+
Return type
+

BaseModel

+
+
+
+
+
+abstract save_to_disk(dirpath: str) None
+

Save whole model to disk with weights.

+
+
Parameters
+

dirpath (str) – directory path where you want to save the model to

+
+
Returns
+

None

+
+
+
+
+
+
+class dataprofiler.labelers.base_model.BaseTrainableModel(label_mapping: list | dict, parameters: dict)
+

Bases: dataprofiler.labelers.base_model.BaseModel

+

Contains abstract method for training models.

+

Initialize Base Model.

+

Only model and model parameters are stored here. +:param label_mapping: label mapping of the model or list of labels to be

+
+

converted into the label mapping

+
+
+
Parameters
+

parameters (dict) – Contains all the appropriate parameters for the model. +Must contain num_labels.

+
+
Returns
+

None

+
+
+
+
+abstract fit(train_data: DataArray, val_data: DataArray, batch_size: int | None = None, epochs: int | None = None, label_mapping: dict[str, int] | None = None, reset_weights: bool = False, verbose: bool = True) tuple[dict, float | None, dict]
+

Train the current model with the training data and validation data.

+
+
Parameters
+
    +
  • train_data (Union[pd.DataFrame, pd.Series, np.ndarray]) – Training data used to train model

  • +
  • val_data (Union[pd.DataFrame, pd.Series, np.ndarray]) – Validation data used to validate the training

  • +
  • batch_size (int) – Used to determine number of samples in each batch

  • +
  • epochs (int) – Used to determine how many epochs to run

  • +
  • label_mapping (dict) – Mapping of the labels

  • +
  • reset_weights (bool) – Flag to determine whether or not to reset the +model’s weights

  • +
+
+
Returns
+

history, f1, f1_report

+
+
Return type
+

Tuple[dict, float, dict]

+
+
+
+
+
+add_label(label: str, same_as: str | None = None) None
+

Add a label to the data labeler.

+
+
Parameters
+
    +
  • label (str) – new label being added to the data labeler

  • +
  • same_as (str) – label to have the same encoding index as for multi-label +to single encoding index.

  • +
+
+
Returns
+

None

+
+
+
+
+
+classmethod get_class(class_name: str) type[BaseModel] | None
+

Get subclasses.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (List[str]) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod help() None
+

Help describe alterable parameters.

+
+
Returns
+

None

+
+
+
+
+
+property label_mapping: dict
+

Return mapping of labels to their encoded values.

+
+
+
+property labels: list
+

Retrieve the label.

+
+
Returns
+

list of labels

+
+
+
+
+
+abstract classmethod load_from_disk(dirpath: str) dataprofiler.labelers.base_model.BaseModel
+

Load whole model from disk with weights.

+
+
Parameters
+

dirpath (str) – directory path where you want to load the model from

+
+
Returns
+

loaded model

+
+
Return type
+

BaseModel

+
+
+
+
+
+property num_labels: int
+

Return max label mapping.

+
+
+
+abstract predict(data: Union[pandas.core.frame.DataFrame, pandas.core.series.Series, numpy.ndarray], batch_size: int, show_confidences: bool, verbose: bool) dict
+

Predict the data with the current model.

+
+
Parameters
+
    +
  • data (iterator of data to process) – model input data to predict on

  • +
  • batch_size (int) – number of samples in the batch of data

  • +
  • show_confidences (bool) – whether user wants prediction confidences

  • +
  • verbose (bool) – Flag to determine whether to print status or not

  • +
+
+
Returns
+

char level predictions and confidences

+
+
Return type
+

dict

+
+
+
+
+
+requires_zero_mapping: bool = False
+
+
+
+abstract reset_weights() None
+

Reset the weights of the model.

+
+
Returns
+

None

+
+
+
+
+
+property reverse_label_mapping: dict
+

Return reversed order of current labels.

+

Useful for when needed to extract Labels via indices.

+
+
+
+abstract save_to_disk(dirpath: str) None
+

Save whole model to disk with weights.

+
+
Parameters
+

dirpath (str) – directory path where you want to save the model to

+
+
Returns
+

None

+
+
+
+
+
+set_label_mapping(label_mapping: list[str] | dict[str, int]) None
+

Set the labels for the model.

+
+
Parameters
+

label_mapping (Union[list, dict]) – label mapping of the model or list of labels to be +converted into the label mapping

+
+
Returns
+

None

+
+
+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.labelers.char_load_tf_model.html b/docs/0.10.5/html/dataprofiler.labelers.char_load_tf_model.html new file mode 100644 index 000000000..1dfa36427 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.labelers.char_load_tf_model.html @@ -0,0 +1,492 @@ + + + + + + + + + Char Load Tf Model - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Char Load Tf Model

+

Contains class for training data labeler model.

+
+
+class dataprofiler.labelers.char_load_tf_model.CharLoadTFModel(model_path: str, label_mapping: dict, parameters: Optional[dict] = None)
+

Bases: dataprofiler.labelers.base_model.BaseTrainableModel

+

For training data labeler model.

+

Initialize Loadable TF Model.

+
+
Parameters
+
    +
  • model_path (str) – path to model to load

  • +
  • label_mapping (dict) – maps labels to their encoded integers

  • +
  • parameters (dict) –

    Contains all the appropriate parameters for the +model. Must contain num_labels. Other possible parameters are:

    +
    +

    max_length, max_char_encoding_id, dim_embed, size_fc +dropout, size_conv, num_fil, optimizer, default_label

    +
    +

  • +
+
+
Returns
+

None

+
+
+
+
+requires_zero_mapping: bool = False
+
+
+
+set_label_mapping(label_mapping: list[str] | dict[str, int]) None
+

Set the labels for the model.

+
+
Parameters
+

label_mapping (dict) – label mapping of the model

+
+
Returns
+

None

+
+
+
+
+
+save_to_disk(dirpath: str) None
+

Save whole model to disk with weights.

+
+
Parameters
+

dirpath (str) – directory path where you want to save the model to

+
+
Returns
+

None

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.char_load_tf_model.CharLoadTFModel
+

Load whole model from disk with weights.

+
+
Parameters
+

dirpath (str) – directory path where you want to load the model from

+
+
Returns
+

loaded CharLoadTFModel

+
+
Return type
+

CharLoadTFModel

+
+
+
+
+
+reset_weights() None
+

Reset the weights of the model.

+
+
Returns
+

None

+
+
+
+
+
+fit(train_data: DataArray, val_data: DataArray = None, batch_size: int = None, epochs: int = None, label_mapping: dict[str, int] = None, reset_weights: bool = False, verbose: bool = True) tuple[dict, float | None, dict]
+

Train the current model with the training data and validation data.

+
+
Parameters
+
    +
  • train_data (Union[list, np.ndarray]) – Training data used to train model

  • +
  • val_data (Union[list, np.ndarray]) – Validation data used to validate the training

  • +
  • batch_size (int) – Used to determine number of samples in each batch

  • +
  • label_mapping (Union[dict, None]) – maps labels to their encoded integers

  • +
  • reset_weights (bool) – Flag to determine whether to reset the weights or +not

  • +
  • verbose (bool) – Flag to determine whether to print status or not

  • +
+
+
Returns
+

history, f1, f1_report

+
+
Return type
+

Tuple[dict, float, dict]

+
+
+
+
+
+predict(data: Union[pandas.core.frame.DataFrame, pandas.core.series.Series, numpy.ndarray], batch_size: int = 32, show_confidences: bool = False, verbose: bool = True) dict
+

Run model and get predictions.

+
+
Parameters
+
    +
  • data (Union[list, numpy.ndarray]) – text input

  • +
  • batch_size (int) – number of samples in the batch of data

  • +
  • show_confidences – whether user wants prediction confidences

  • +
  • verbose (bool) – Flag to determine whether to print status or not

  • +
+
+
Returns
+

char level predictions and confidences

+
+
Return type
+

dict

+
+
+
+
+
+details() None
+

Print the relevant details of the model.

+

Details include summary, parameters, label mapping.

+
+
+
+add_label(label: str, same_as: str | None = None) None
+

Add a label to the data labeler.

+
+
Parameters
+
    +
  • label (str) – new label being added to the data labeler

  • +
  • same_as (str) – label to have the same encoding index as for multi-label +to single encoding index.

  • +
+
+
Returns
+

None

+
+
+
+
+
+classmethod get_class(class_name: str) type[BaseModel] | None
+

Get subclasses.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (List[str]) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod help() None
+

Help describe alterable parameters.

+
+
Returns
+

None

+
+
+
+
+
+property label_mapping: dict
+

Return mapping of labels to their encoded values.

+
+
+
+property labels: list
+

Retrieve the label.

+
+
Returns
+

list of labels

+
+
+
+
+
+property num_labels: int
+

Return max label mapping.

+
+
+
+property reverse_label_mapping: dict
+

Return reversed order of current labels.

+

Useful for when needed to extract Labels via indices.

+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.labelers.character_level_cnn_model.html b/docs/0.10.5/html/dataprofiler.labelers.character_level_cnn_model.html new file mode 100644 index 000000000..22094eb80 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.labelers.character_level_cnn_model.html @@ -0,0 +1,513 @@ + + + + + + + + + Character Level Cnn Model - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Character Level Cnn Model

+

Contains classes for char data labeling.

+
+
+dataprofiler.labelers.character_level_cnn_model.build_embd_dictionary(filename: str) dict
+

Return a numpy embedding dictionary from embed file with GloVe-like format.

+
+
Parameters
+

filename (str) – Path to the embed file for loading

+
+
+
+
+
+dataprofiler.labelers.character_level_cnn_model.create_glove_char(n_dims: int, source_file: Optional[str] = None) None
+

Embed GloVe chars embeddings from source file to n_dims principal components.

+

Embed in a new file.

+
+
Parameters
+
    +
  • n_dims (int) – Final number of principal component dims of the embeddings

  • +
  • source_file (str) – Location of original embeddings to factor down

  • +
+
+
+
+
+
+class dataprofiler.labelers.character_level_cnn_model.CharacterLevelCnnModel(label_mapping: dict, parameters: Optional[dict] = None)
+

Bases: dataprofiler.labelers.base_model.BaseTrainableModel

+

Class for training char data labeler.

+

Initialize CNN Model.

+

Initialize epoch_id.

+
+
Parameters
+
    +
  • label_mapping (dict) – maps labels to their encoded integers

  • +
  • parameters (dict) –

    Contains all the appropriate parameters for the +model. Must contain num_labels. Other possible parameters are:

    +
    +

    max_length, max_char_encoding_id, dim_embed, size_fc +dropout, size_conv, num_fil, optimizer, default_label

    +
    +

  • +
+
+
Returns
+

None

+
+
+
+
+requires_zero_mapping: bool = True
+
+
+
+set_label_mapping(label_mapping: list[str] | dict[str, int]) None
+

Set the labels for the model.

+
+
Parameters
+

label_mapping (dict) – label mapping of the model

+
+
Returns
+

None

+
+
+
+
+
+save_to_disk(dirpath: str) None
+

Save whole model to disk with weights.

+
+
Parameters
+

dirpath (str) – directory path where you want to save the model to

+
+
Returns
+

None

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.character_level_cnn_model.CharacterLevelCnnModel
+

Load whole model from disk with weights.

+
+
Parameters
+

dirpath (str) – directory path where you want to load the model from

+
+
Returns
+

None

+
+
+
+
+
+reset_weights() None
+

Reset the weights of the model.

+
+
Returns
+

None

+
+
+
+
+
+fit(train_data: DataArray, val_data: DataArray | None = None, batch_size: int = None, epochs: int = None, label_mapping: dict[str, int] = None, reset_weights: bool = False, verbose: bool = True) tuple[dict, float | None, dict]
+

Train the current model with the training data and validation data.

+
+
Parameters
+
    +
  • train_data (Union[list, np.ndarray]) – Training data used to train model

  • +
  • val_data (Union[list, np.ndarray]) – Validation data used to validate the training

  • +
  • batch_size (int) – Used to determine number of samples in each batch

  • +
  • label_mapping (Union[dict, None]) – maps labels to their encoded integers

  • +
  • reset_weights (bool) – Flag to determine whether to reset the weights or +not

  • +
  • verbose (bool) – Flag to determine whether to print status or not

  • +
+
+
Returns
+

history, f1, f1_report

+
+
Return type
+

Tuple[dict, float, dict]

+
+
+
+
+
+predict(data: Union[pandas.core.frame.DataFrame, pandas.core.series.Series, numpy.ndarray], batch_size: int = 32, show_confidences: bool = False, verbose: bool = True) dict
+

Run model and get predictions.

+
+
Parameters
+
    +
  • data (Union[list, numpy.ndarray]) – text input

  • +
  • batch_size (int) – number of samples in the batch of data

  • +
  • show_confidences – whether user wants prediction confidences

  • +
  • verbose (bool) – Flag to determine whether to print status or not

  • +
+
+
Returns
+

char level predictions and confidences

+
+
Return type
+

dict

+
+
+
+
+
+details() None
+

Print the relevant details of the model.

+

Details include summary, parameters, and label mapping.

+
+
+
+add_label(label: str, same_as: str | None = None) None
+

Add a label to the data labeler.

+
+
Parameters
+
    +
  • label (str) – new label being added to the data labeler

  • +
  • same_as (str) – label to have the same encoding index as for multi-label +to single encoding index.

  • +
+
+
Returns
+

None

+
+
+
+
+
+classmethod get_class(class_name: str) type[BaseModel] | None
+

Get subclasses.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (List[str]) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod help() None
+

Help describe alterable parameters.

+
+
Returns
+

None

+
+
+
+
+
+property label_mapping: dict
+

Return mapping of labels to their encoded values.

+
+
+
+property labels: list
+

Retrieve the label.

+
+
Returns
+

list of labels

+
+
+
+
+
+property num_labels: int
+

Return max label mapping.

+
+
+
+property reverse_label_mapping: dict
+

Return reversed order of current labels.

+

Useful for when needed to extract Labels via indices.

+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.labelers.classification_report_utils.html b/docs/0.10.5/html/dataprofiler.labelers.classification_report_utils.html new file mode 100644 index 000000000..7a0cb2f8a --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.labelers.classification_report_utils.html @@ -0,0 +1,452 @@ + + + + + + + + + Classification Report Utils - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Classification Report Utils

+

Contains functions for classification.

+
+
+dataprofiler.labelers.classification_report_utils.convert_confusion_matrix_to_MCM(conf_matrix: list | np.ndarray) np.ndarray
+

Convert a confusion matrix into the MCM format.

+

Format for precision/recall/fscore/ +support computation by sklearn.

+

The format is as specified by sklearn below: +In multilabel confusion matrix \(MCM\), the count of true negatives +is \(MCM_{:,0,0}\), false negatives is \(MCM_{:,1,0}\), +true positives is \(MCM_{:,1,1}\) and false positives is +\(MCM_{:,0,1}\). +Note: this utilizes code/ideology from sklearn.

+
+
Parameters
+

conf_matrix (Union[list, np.ndarray]) – confusion matrix, which is a square matrix describing +false positives and false negatives, true positives and true negatives +for classification

+
+
Returns
+

MCM format for readability by sklearn confusion reports.

+
+
Return type
+

np.ndarray

+
+
+
+
+
+dataprofiler.labelers.classification_report_utils.precision_recall_fscore_support(MCM: np.ndarray, beta: float = 1.0, labels: np.ndarray | None = None, pos_label: str | int = 1, average: str | None = None, warn_for: tuple[str, ...] | set[str] = ('precision', 'recall', 'f-score'), sample_weight: np.ndarray | None = None) tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray | None]
+

Perform same functionality as recision_recall_fscore_support function.

+

Copy of the precision_recall_fscore_support function from sklearn.metrics +with the update to receiving the MCM instead of calculating each time it is +called.

+
+
Parameters
+
    +
  • MCM (array, shape (n_outputs, 2, 2)) – Multi-classification confusion matrix as referenced by the sklearn +metrics module. A 2x2 confusion matrix corresponding to each output in +the input. In multilabel confusion matrix \(MCM\), the count of +true negatives is \(MCM_{:,0,0}\), false negatives is +\(MCM_{:,1,0}\), true positives is \(MCM_{:,1,1}\) and false +positives is \(MCM_{:,0,1}\).

  • +
  • beta (float, 1.0 by default) – The strength of recall versus precision in the F-score.

  • +
  • labels (list, optional) – The set of labels to include when average != 'binary', and their +order if average is None. Labels present in the data can be +excluded, for example to calculate a multiclass average ignoring a +majority negative class, while labels not present in the data will +result in 0 components in a macro average. For multilabel targets, +labels are column indices. By default, all labels in y_true and +y_pred are used in sorted order.

  • +
  • pos_label (str or int, 1 by default) – The class to report if average='binary' and the data is binary. +If the data are multiclass or multilabel, this will be ignored; +setting labels=[pos_label] and average != 'binary' will report +scores for that label only.

  • +
  • average (string, [None (default), 'binary', 'micro', 'macro', 'weighted']) –

    If None, the scores for each class are returned. Otherwise, this +determines the type of averaging performed on the data:

    +
    +
    'binary':

    Only report results for the class specified by pos_label. +This is applicable only if targets (y_{true,pred}) are binary.

    +
    +
    'micro':

    Calculate metrics globally by counting the total true positives, +false negatives and false positives.

    +
    +
    'macro':

    Calculate metrics for each label, and find their unweighted +mean. This does not take label imbalance into account.

    +
    +
    'weighted':

    Calculate metrics for each label, and find their average weighted +by support (the number of true instances for each label). This +alters ‘macro’ to account for label imbalance; it can result in an +F-score that is not between precision and recall.

    +
    +
    +

  • +
  • warn_for (tuple or set, for internal use) – This determines which warnings will be made in the case that this +function is being used to return only one of its metrics.

  • +
  • sample_weight (array-like of shape = [n_samples], optional) – Sample weights.

  • +
+
+
Returns
+

    +
  • precision (float (if average is not None) or array of float, shape = [n_unique_labels])

  • +
  • recall (float (if average is not None) or array of float, , shape = [n_unique_labels])

  • +
  • fbeta_score (float (if average is not None) or array of float, shape = [n_unique_labels])

  • +
  • support (int (if average is not None) or array of int, shape = [n_unique_labels]) – The number of occurrences of each label in y_true.

  • +
+

+
+
+

References

+
+
1
+

Wikipedia entry for the Precision and recall

+
+
2
+

Wikipedia entry for the F1-score

+
+
3
+

Discriminative Methods for Multi-labeled Classification Advances +in Knowledge Discovery and Data Mining (2004), pp. 22-30 by Shantanu +Godbole, Sunita Sarawagi

+
+
+

Notes

+

When true positive + false positive == 0, precision is undefined; +When true positive + false negative == 0, recall is undefined. +In such cases, the metric will be set to 0, as will f-score, and +UndefinedMetricWarning will be raised.

+
+
+
+dataprofiler.labelers.classification_report_utils.classification_report(conf_matrix: np.ndarray, labels: list | np.ndarray | None = None, target_names: list[str] | None = None, sample_weight: np.ndarray | None = None, digits: int = 2, output_dict: bool = False) str | dict
+

Build a text report showing the main classification metrics.

+

Copy of the classification_report function from sklearn.metrics +with the update to receiving the conf_matrix instead of calculating each +time it is called.

+

Read more in the User Guide.

+
+
Parameters
+
    +
  • conf_matrix (array, shape = [n_labels, n_labels]) – confusion matrix, which is a square matrix describing +false positives and false negatives, true positives and true negatives +for classification.

  • +
  • labels (array, shape = [n_labels]) – Optional list of label indices to include in the report.

  • +
  • target_names (list of strings) – Optional display names matching the labels (same order).

  • +
  • sample_weight (array-like of shape = [n_samples], optional) – Sample weights.

  • +
  • digits (int) – Number of digits for formatting output floating point values. +When output_dict is True, this will be ignored and the +returned values will not be rounded.

  • +
  • output_dict (bool (default = False)) – If True, return output as dict

  • +
+
+
Returns
+

report – Text summary of the precision, recall, F1 score for each class. +Dictionary returned if output_dict is True. Dictionary has the +following structure:

+
{'label 1': {'precision':0.5,
+             'recall':1.0,
+             'f1-score':0.67,
+             'support':1},
+ 'label 2': { ... },
+  ...
+}
+
+
+

The reported averages include macro average (averaging the unweighted +mean per label), weighted average (averaging the support-weighted mean +per label), sample average (only for multilabel classification) and +micro average (averaging the total true positives, false negatives and +false positives) it is only shown for multi-label or multi-class +with a subset of classes because it is accuracy otherwise. +See also:func:precision_recall_fscore_support for more details +on averages.

+

Note that in binary classification, recall of the positive class +is also known as “sensitivity”; recall of the negative class is +“specificity”.

+

+
+
Return type
+

string / dict

+
+
+
+

See also

+

precision_recall_fscore_support, confusion_matrix, multilabel_confusion_matrix

+
+
+
+ +
+ +
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.labelers.column_name_model.html b/docs/0.10.5/html/dataprofiler.labelers.column_name_model.html new file mode 100644 index 000000000..d2bdc8fa9 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.labelers.column_name_model.html @@ -0,0 +1,452 @@ + + + + + + + + + Column Name Model - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Column Name Model

+

Contains class for column name data labeling model.

+
+
+class dataprofiler.labelers.column_name_model.ColumnNameModel(label_mapping: dict, parameters: Optional[dict] = None)
+

Bases: dataprofiler.labelers.base_model.BaseModel

+

Class for column name data labeling model.

+

Initialize function for ColumnNameModel.

+
+
Parameters
+

parameters (dict) –

Contains all the appropriate parameters for the model. +Possible parameters are:

+
+

max_length, max_num_chars, dim_embed

+
+

+
+
Returns
+

None

+
+
+
+
+reset_weights() None
+

Reset weights function.

+
+
+
+predict(data: Union[pandas.core.frame.DataFrame, pandas.core.series.Series, numpy.ndarray], batch_size: Optional[int] = None, show_confidences: bool = False, verbose: bool = True) dict
+

Apply the process.cdist for similarity score on input list of strings.

+
+
Parameters
+
    +
  • data (iterator) – list of strings to predict upon

  • +
  • batch_size (N/A) – does not impact this model and should be fixed to not +be required.

  • +
  • show_confidences – Parameter disabled. Confidence values returned +by default.

  • +
  • verbose (bool) – Flag to determine whether to print status or not

  • +
+
+
Returns
+

char level predictions and confidences

+
+
Return type
+

dict

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.column_name_model.ColumnNameModel
+

Load whole model from disk with weights.

+
+
Parameters
+

dirpath (str) – directory path where you want to load the model from

+
+
Returns
+

None

+
+
+
+
+
+save_to_disk(dirpath: str) None
+

Save whole model to disk with weights.

+
+
Parameters
+

dirpath (str) – directory path where you want to save the model to

+
+
Returns
+

None

+
+
+
+
+
+add_label(label: str, same_as: str | None = None) None
+

Add a label to the data labeler.

+
+
Parameters
+
    +
  • label (str) – new label being added to the data labeler

  • +
  • same_as (str) – label to have the same encoding index as for multi-label +to single encoding index.

  • +
+
+
Returns
+

None

+
+
+
+
+
+classmethod get_class(class_name: str) type[BaseModel] | None
+

Get subclasses.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (List[str]) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod help() None
+

Help describe alterable parameters.

+
+
Returns
+

None

+
+
+
+
+
+property label_mapping: dict
+

Return mapping of labels to their encoded values.

+
+
+
+property labels: list
+

Retrieve the label.

+
+
Returns
+

list of labels

+
+
+
+
+
+property num_labels: int
+

Return max label mapping.

+
+
+
+requires_zero_mapping: bool = False
+
+
+
+property reverse_label_mapping: dict
+

Return reversed order of current labels.

+

Useful for when needed to extract Labels via indices.

+
+
+
+set_label_mapping(label_mapping: list[str] | dict[str, int]) None
+

Set the labels for the model.

+
+
Parameters
+

label_mapping (Union[list, dict]) – label mapping of the model or list of labels to be +converted into the label mapping

+
+
Returns
+

None

+
+
+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.labelers.data_labelers.html b/docs/0.10.5/html/dataprofiler.labelers.data_labelers.html new file mode 100644 index 000000000..39ee1dbd1 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.labelers.data_labelers.html @@ -0,0 +1,981 @@ + + + + + + + + + Data Labelers - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Data Labelers

+

Module to train and choose between structured and unstructured data labelers.

+
+
+dataprofiler.labelers.data_labelers.train_structured_labeler(data: None | pd.DataFrame, default_label: int = None, save_dirpath: str = None, epochs: int = 2) TrainableDataLabeler
+

Use provided data to create and save a structured data labeler.

+
+
Parameters
+
    +
  • data (Union[None, pd.DataFrame]) – data to be trained upon

  • +
  • save_dirpath (Union[None, str]) – path to save data labeler

  • +
  • epochs (int) – number of epochs to loop training the data

  • +
+
+
Returns
+

structured data labeler

+
+
Return type
+

TrainableDataLabeler

+
+
+
+
+
+class dataprofiler.labelers.data_labelers.UnstructuredDataLabeler(dirpath: Optional[str] = None, load_options: Optional[dict] = None)
+

Bases: dataprofiler.labelers.base_data_labeler.BaseDataLabeler

+

BaseDataLabeler subclass specified as unstructured with internal variable.

+

Initialize DataLabeler class.

+
+
Parameters
+
    +
  • dirpath – path to data labeler

  • +
  • load_options – optional arguments to include for load i.e. class +for model or processors

  • +
+
+
+
+
+add_label(label: str, same_as: Optional[str] = None) None
+

Add a label to the data labeler.

+
+
Parameters
+
    +
  • label (str) – new label being added to the data labeler

  • +
  • same_as (str) – label to have the same encoding index as for multi-label +to single encoding index.

  • +
+
+
Returns
+

None

+
+
+
+
+
+check_pipeline(skip_postprocessor: bool = False, error_on_mismatch: bool = False) None
+

Check whether the processors and models connect together without error.

+
+
Parameters
+
    +
  • skip_postprocessor (bool) – skip checking postprocessor is valid in +pipeline

  • +
  • error_on_mismatch (bool) – if true, errors instead of warns on parameter +mismatches in pipeline

  • +
+
+
Returns
+

None

+
+
+
+
+
+help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+property label_mapping: dict
+

Retrieve the label encodings.

+
+
Returns
+

dictionary for associating labels to indexes

+
+
+
+
+
+property labels: list
+

Retrieve the label.

+
+
Returns
+

list of labels

+
+
+
+
+
+classmethod load_from_disk(dirpath: str, load_options: Optional[dict] = None) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from a saved location on disk.

+
+
Parameters
+
    +
  • dirpath (str) – path to data labeler files.

  • +
  • load_options (dict) – optional arguments to include for load i.e. class +for model or processors

  • +
+
+
Returns
+

DataLabeler class

+
+
Return type
+

BaseDataLabeler

+
+
+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from the data labeler zoo in the library.

+
+
Parameters
+

name (str) – name of the data labeler.

+
+
Returns
+

DataLabeler class

+
+
Return type
+

BaseDataLabeler

+
+
+
+
+
+classmethod load_with_components(preprocessor: dataprofiler.labelers.data_processing.BaseDataPreprocessor, model: dataprofiler.labelers.base_model.BaseModel, postprocessor: dataprofiler.labelers.data_processing.BaseDataPostprocessor) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from a its set of components.

+
+
Parameters
+
+
+
Returns
+

loaded BaseDataLabeler

+
+
Return type
+

BaseDataLabeler

+
+
+
+
+
+property model: dataprofiler.labelers.base_model.BaseModel
+

Retrieve the data labeler model.

+
+
Returns
+

returns the model instance

+
+
+
+
+
+property postprocessor: data_processing.BaseDataPostprocessor | None
+

Retrieve the data postprocessor.

+
+
Returns
+

returns the postprocessor instance

+
+
+
+
+
+predict(data: Union[pandas.core.frame.DataFrame, pandas.core.series.Series, numpy.ndarray], batch_size: int = 32, predict_options: Optional[dict] = None, error_on_mismatch: bool = False, verbose: bool = True) dict
+

Predict labels of input data based with the data labeler model.

+
+
Parameters
+
    +
  • data (Union[pd.DataFrame, pd.Series, np.ndarray]) – data to be predicted upon

  • +
  • batch_size (int) – batch size of prediction

  • +
  • predict_options (Dict[str, bool]) – optional parameters to allow for predict as a +dict, i.e. dict(show_confidences=True)

  • +
  • error_on_mismatch (bool) – if true, errors instead of warns on parameter +mismatches in pipeline

  • +
  • verbose (bool) – Flag to determine whether to print status or not

  • +
+
+
Returns
+

predictions

+
+
Return type
+

Dict

+
+
+
+
+
+property preprocessor: data_processing.BaseDataPreprocessor | None
+

Retrieve the data preprocessor.

+
+
Returns
+

returns the preprocessor instance

+
+
+
+
+
+property reverse_label_mapping: dict
+

Retrieve the index to label encoding.

+
+
Returns
+

dictionary for associating indexes to labels

+
+
+
+
+
+save_to_disk(dirpath: str) None
+

Save the data labeler to the specified location.

+
+
Parameters
+

dirpath (str) – location to save the data labeler.

+
+
Returns
+

None

+
+
+
+
+
+set_labels(labels: list | dict) None
+

Set the labels for the data labeler.

+
+
Parameters
+

labels (list or dict) – new labels in either encoding list or dict

+
+
Returns
+

None

+
+
+
+
+
+set_model(model: dataprofiler.labelers.base_model.BaseModel) None
+

Set the model for the data labeler.

+
+
Parameters
+

model (base_model.BaseModel) – model to use within the data labeler

+
+
Returns
+

None

+
+
+
+
+
+set_params(params: dict) None
+

Allow user to set parameters of pipeline components.

+
+
Done in the following format:
+
params = dict(

preprocessor=dict(…), +model=dict(…), +postprocessor=dict(…)

+
+
+

)

+
+
+

where the key,values pairs for each pipeline component must match +parameters that exist in their components.

+
+
Parameters
+

params (dict) –

dictionary containing a key for a given pipeline +component and its associated value of parameters as such:

+
+

dict(preprocessor=dict(…), model=dict(…), +postprocessor=dict(…))

+
+

+
+
Returns
+

None

+
+
+
+
+
+set_postprocessor(data_processor: dataprofiler.labelers.data_processing.BaseDataPostprocessor) None
+

Set the data postprocessor for the data labeler.

+
+
Parameters
+

data_processor (data_processing.BaseDataPostprocessor) – processor to set as the postprocessor

+
+
Returns
+

None

+
+
+
+
+
+set_preprocessor(data_processor: dataprofiler.labelers.data_processing.BaseDataPreprocessor) None
+

Set the data preprocessor for the data labeler.

+
+
Parameters
+

data_processor (data_processing.BaseDataPreprocessor) – processor to set as the preprocessor

+
+
Returns
+

None

+
+
+
+
+
+
+class dataprofiler.labelers.data_labelers.StructuredDataLabeler(dirpath: Optional[str] = None, load_options: Optional[dict] = None)
+

Bases: dataprofiler.labelers.base_data_labeler.BaseDataLabeler

+

BaseDataLabeler subclass specified as structured with internal variable.

+

Initialize DataLabeler class.

+
+
Parameters
+
    +
  • dirpath – path to data labeler

  • +
  • load_options – optional arguments to include for load i.e. class +for model or processors

  • +
+
+
+
+
+add_label(label: str, same_as: Optional[str] = None) None
+

Add a label to the data labeler.

+
+
Parameters
+
    +
  • label (str) – new label being added to the data labeler

  • +
  • same_as (str) – label to have the same encoding index as for multi-label +to single encoding index.

  • +
+
+
Returns
+

None

+
+
+
+
+
+check_pipeline(skip_postprocessor: bool = False, error_on_mismatch: bool = False) None
+

Check whether the processors and models connect together without error.

+
+
Parameters
+
    +
  • skip_postprocessor (bool) – skip checking postprocessor is valid in +pipeline

  • +
  • error_on_mismatch (bool) – if true, errors instead of warns on parameter +mismatches in pipeline

  • +
+
+
Returns
+

None

+
+
+
+
+
+help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+property label_mapping: dict
+

Retrieve the label encodings.

+
+
Returns
+

dictionary for associating labels to indexes

+
+
+
+
+
+property labels: list
+

Retrieve the label.

+
+
Returns
+

list of labels

+
+
+
+
+
+classmethod load_from_disk(dirpath: str, load_options: Optional[dict] = None) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from a saved location on disk.

+
+
Parameters
+
    +
  • dirpath (str) – path to data labeler files.

  • +
  • load_options (dict) – optional arguments to include for load i.e. class +for model or processors

  • +
+
+
Returns
+

DataLabeler class

+
+
Return type
+

BaseDataLabeler

+
+
+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from the data labeler zoo in the library.

+
+
Parameters
+

name (str) – name of the data labeler.

+
+
Returns
+

DataLabeler class

+
+
Return type
+

BaseDataLabeler

+
+
+
+
+
+classmethod load_with_components(preprocessor: dataprofiler.labelers.data_processing.BaseDataPreprocessor, model: dataprofiler.labelers.base_model.BaseModel, postprocessor: dataprofiler.labelers.data_processing.BaseDataPostprocessor) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from a its set of components.

+
+
Parameters
+
+
+
Returns
+

loaded BaseDataLabeler

+
+
Return type
+

BaseDataLabeler

+
+
+
+
+
+property model: dataprofiler.labelers.base_model.BaseModel
+

Retrieve the data labeler model.

+
+
Returns
+

returns the model instance

+
+
+
+
+
+property postprocessor: data_processing.BaseDataPostprocessor | None
+

Retrieve the data postprocessor.

+
+
Returns
+

returns the postprocessor instance

+
+
+
+
+
+predict(data: Union[pandas.core.frame.DataFrame, pandas.core.series.Series, numpy.ndarray], batch_size: int = 32, predict_options: Optional[dict] = None, error_on_mismatch: bool = False, verbose: bool = True) dict
+

Predict labels of input data based with the data labeler model.

+
+
Parameters
+
    +
  • data (Union[pd.DataFrame, pd.Series, np.ndarray]) – data to be predicted upon

  • +
  • batch_size (int) – batch size of prediction

  • +
  • predict_options (Dict[str, bool]) – optional parameters to allow for predict as a +dict, i.e. dict(show_confidences=True)

  • +
  • error_on_mismatch (bool) – if true, errors instead of warns on parameter +mismatches in pipeline

  • +
  • verbose (bool) – Flag to determine whether to print status or not

  • +
+
+
Returns
+

predictions

+
+
Return type
+

Dict

+
+
+
+
+
+property preprocessor: data_processing.BaseDataPreprocessor | None
+

Retrieve the data preprocessor.

+
+
Returns
+

returns the preprocessor instance

+
+
+
+
+
+property reverse_label_mapping: dict
+

Retrieve the index to label encoding.

+
+
Returns
+

dictionary for associating indexes to labels

+
+
+
+
+
+save_to_disk(dirpath: str) None
+

Save the data labeler to the specified location.

+
+
Parameters
+

dirpath (str) – location to save the data labeler.

+
+
Returns
+

None

+
+
+
+
+
+set_labels(labels: list | dict) None
+

Set the labels for the data labeler.

+
+
Parameters
+

labels (list or dict) – new labels in either encoding list or dict

+
+
Returns
+

None

+
+
+
+
+
+set_model(model: dataprofiler.labelers.base_model.BaseModel) None
+

Set the model for the data labeler.

+
+
Parameters
+

model (base_model.BaseModel) – model to use within the data labeler

+
+
Returns
+

None

+
+
+
+
+
+set_params(params: dict) None
+

Allow user to set parameters of pipeline components.

+
+
Done in the following format:
+
params = dict(

preprocessor=dict(…), +model=dict(…), +postprocessor=dict(…)

+
+
+

)

+
+
+

where the key,values pairs for each pipeline component must match +parameters that exist in their components.

+
+
Parameters
+

params (dict) –

dictionary containing a key for a given pipeline +component and its associated value of parameters as such:

+
+

dict(preprocessor=dict(…), model=dict(…), +postprocessor=dict(…))

+
+

+
+
Returns
+

None

+
+
+
+
+
+set_postprocessor(data_processor: dataprofiler.labelers.data_processing.BaseDataPostprocessor) None
+

Set the data postprocessor for the data labeler.

+
+
Parameters
+

data_processor (data_processing.BaseDataPostprocessor) – processor to set as the postprocessor

+
+
Returns
+

None

+
+
+
+
+
+set_preprocessor(data_processor: dataprofiler.labelers.data_processing.BaseDataPreprocessor) None
+

Set the data preprocessor for the data labeler.

+
+
Parameters
+

data_processor (data_processing.BaseDataPreprocessor) – processor to set as the preprocessor

+
+
Returns
+

None

+
+
+
+
+
+
+class dataprofiler.labelers.data_labelers.DataLabeler(labeler_type: str, dirpath: Optional[str] = None, load_options: Optional[dict] = None, trainable: bool = False)
+

Bases: object

+

Wrapper class for choosing between structured and unstructured labeler.

+

Create structured and unstructured data labeler objects.

+
+
Parameters
+
    +
  • dirpath (str) – Path to load data labeler

  • +
  • load_options (Dict) – Optional arguments to include for load.

  • +
  • trainable (bool) – variable to dictate whether you want a trainable data +labeler

  • +
+
+
Returns
+

+
+
+
+
+labeler_classes = {'structured': <class 'dataprofiler.labelers.data_labelers.StructuredDataLabeler'>, 'unstructured': <class 'dataprofiler.labelers.data_labelers.UnstructuredDataLabeler'>}
+
+
+
+classmethod load_from_library(name: str, trainable: bool = False) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from the data labeler zoo in the library.

+
+
Parameters
+
    +
  • name (str) – name of the data labeler.

  • +
  • trainable (bool) – variable to dictate whether you want a trainable data +labeler

  • +
+
+
Returns
+

DataLabeler class

+
+
+
+
+
+classmethod load_from_disk(dirpath: str, load_options: Optional[dict] = None, trainable: bool = False) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from a saved location on disk.

+
+
Parameters
+
    +
  • dirpath (str) – path to data labeler files.

  • +
  • load_options (dict) – optional arguments to include for load i.e. class +for model or processors

  • +
  • trainable (bool) – variable to dictate whether you want a trainable data +labeler

  • +
+
+
Returns
+

DataLabeler class

+
+
+
+
+
+classmethod load_with_components(preprocessor: dataprofiler.labelers.data_processing.BaseDataPreprocessor, model: dataprofiler.labelers.base_model.BaseModel, postprocessor: dataprofiler.labelers.data_processing.BaseDataPostprocessor, trainable: bool = False) dataprofiler.labelers.base_data_labeler.BaseDataLabeler
+

Load the data labeler from a its set of components.

+
+
Parameters
+
+
+
Returns
+

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.labelers.data_processing.html b/docs/0.10.5/html/dataprofiler.labelers.data_processing.html new file mode 100644 index 000000000..edd38f334 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.labelers.data_processing.html @@ -0,0 +1,1413 @@ + + + + + + + + + Data Processing - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Data Processing

+

Contains pre-built processors for data labeling/processing.

+
+
+class dataprofiler.labelers.data_processing.AutoSubRegistrationMeta(clsname: str, bases: tuple, attrs: dict)
+

Bases: abc.ABCMeta

+

For registering subclasses.

+

Create AutoSubRegistration object.

+
+
+mro()
+

Return a type’s method resolution order.

+
+
+
+register(subclass)
+

Register a virtual subclass of an ABC.

+

Returns the subclass, to allow usage as a class decorator.

+
+
+
+
+class dataprofiler.labelers.data_processing.BaseDataProcessor(**parameters: Any)
+

Bases: object

+

Abstract Data processing class.

+

Initialize BaseDataProcessor object.

+
+
+processor_type: str
+
+
+
+classmethod get_class(class_name: str) type[BaseDataProcessor] | None
+

Get class of BaseDataProcessor object.

+
+
+
+abstract classmethod help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (list) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+abstract process(*args: Any, **kwargs: Any) Any
+

Process data.

+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.data_processing.Processor
+

Load data processor from a given path on disk.

+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.data_processing.BaseDataProcessor
+

Load data processor from within the library.

+
+
+
+save_to_disk(dirpath: str) None
+

Save data processor to a path on disk.

+
+
+
+
+class dataprofiler.labelers.data_processing.BaseDataPreprocessor(**parameters: Any)
+

Bases: dataprofiler.labelers.data_processing.BaseDataProcessor

+

Abstract Data preprocessing class.

+

Initialize BaseDataPreprocessor object.

+
+
+processor_type: str = 'preprocessor'
+
+
+
+abstract process(data: np.ndarray, labels: np.ndarray | None = None, label_mapping: dict[str, int] | None = None, batch_size: int = 32) Generator[tuple[np.ndarray, np.ndarray] | np.ndarray, None, None] | tuple[np.ndarray, np.ndarray] | np.ndarray
+

Preprocess data.

+
+
+
+classmethod get_class(class_name: str) type[BaseDataProcessor] | None
+

Get class of BaseDataProcessor object.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (list) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+abstract classmethod help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.data_processing.Processor
+

Load data processor from a given path on disk.

+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.data_processing.BaseDataProcessor
+

Load data processor from within the library.

+
+
+
+save_to_disk(dirpath: str) None
+

Save data processor to a path on disk.

+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+
+class dataprofiler.labelers.data_processing.BaseDataPostprocessor(**parameters: Any)
+

Bases: dataprofiler.labelers.data_processing.BaseDataProcessor

+

Abstract Data postprocessing class.

+

Initialize BaseDataPostprocessor object.

+
+
+processor_type: str = 'postprocessor'
+
+
+
+abstract process(data: numpy.ndarray, results: dict, label_mapping: dict) dict
+

Postprocess data.

+
+
+
+classmethod get_class(class_name: str) type[BaseDataProcessor] | None
+

Get class of BaseDataProcessor object.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (list) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+abstract classmethod help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.data_processing.Processor
+

Load data processor from a given path on disk.

+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.data_processing.BaseDataProcessor
+

Load data processor from within the library.

+
+
+
+save_to_disk(dirpath: str) None
+

Save data processor to a path on disk.

+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+
+class dataprofiler.labelers.data_processing.DirectPassPreprocessor
+

Bases: dataprofiler.labelers.data_processing.BaseDataPreprocessor

+

Subclass of BaseDataPreprocessor for preprocessing data.

+

Initialize the DirectPassPreprocessor class.

+
+
+classmethod help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+process(data: np.ndarray, labels: np.ndarray | None = None, label_mapping: dict[str, int] | None = None, batch_size: int = 32) tuple[np.ndarray, np.ndarray] | np.ndarray
+

Preprocess data.

+
+
+
+classmethod get_class(class_name: str) type[BaseDataProcessor] | None
+

Get class of BaseDataProcessor object.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (list) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.data_processing.Processor
+

Load data processor from a given path on disk.

+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.data_processing.BaseDataProcessor
+

Load data processor from within the library.

+
+
+
+processor_type: str = 'preprocessor'
+
+
+
+save_to_disk(dirpath: str) None
+

Save data processor to a path on disk.

+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+
+class dataprofiler.labelers.data_processing.CharPreprocessor(max_length: int = 3400, default_label: str = 'UNKNOWN', pad_label: str = 'PAD', flatten_split: float = 0, flatten_separator: str = ' ', is_separate_at_max_len: bool = False, **kwargs: Any)
+

Bases: dataprofiler.labelers.data_processing.BaseDataPreprocessor

+

Subclass of BaseDataPreprocessor for preprocessing char data.

+

Initialize the CharPreprocessor class.

+
+
Parameters
+
    +
  • max_length (int) – Maximum char length in a sample.

  • +
  • default_label (string (could be int, char, etc.)) – Key for label_mapping that is the default label

  • +
  • pad_label (string (could be int, char, etc.)) – Key for label_mapping that is the pad label

  • +
  • flatten_split (float) – approximate output of split between flattened and +non-flattened characters, value between [0, 1]. When the current +flattened split becomes more than the flatten_split value, any +leftover sample or subsequent samples will be non-flattened until +the current flattened split is below the flatten_split value

  • +
  • flatten_separator (str) – separator used to put between flattened +samples.

  • +
  • is_separate_at_max_len (bool) – if true, separates at max_length, +otherwise at nearest separator

  • +
+
+
+
+
+classmethod help() None
+

Describe alterable parameters.

+

Input data formats. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+process(data: np.ndarray, labels: np.ndarray | None = None, label_mapping: dict[str, int] | None = None, batch_size: int = 32) Generator[tuple[np.ndarray, np.ndarray] | np.ndarray, None, None]
+

Flatten batches of data.

+
+
Parameters
+
    +
  • data (numpy.ndarray) – List of strings to create embeddings for

  • +
  • labels (numpy.ndarray) – labels for each input character

  • +
  • label_mapping (Union[None, dict]) – maps labels to their encoded integers

  • +
  • batch_size (int) – Number of samples in the batch of data

  • +
+
+
Return batch_data
+

A dict containing samples of size batch_size

+
+
Rtype batch_data
+

dicts

+
+
+
+
+
+classmethod get_class(class_name: str) type[BaseDataProcessor] | None
+

Get class of BaseDataProcessor object.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (list) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.data_processing.Processor
+

Load data processor from a given path on disk.

+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.data_processing.BaseDataProcessor
+

Load data processor from within the library.

+
+
+
+processor_type: str = 'preprocessor'
+
+
+
+save_to_disk(dirpath: str) None
+

Save data processor to a path on disk.

+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+
+class dataprofiler.labelers.data_processing.CharEncodedPreprocessor(encoding_map: dict[str, int] | None = None, max_length: int = 5000, default_label: str = 'UNKNOWN', pad_label: str = 'PAD', flatten_split: float = 0, flatten_separator: str = ' ', is_separate_at_max_len: bool = False)
+

Bases: dataprofiler.labelers.data_processing.CharPreprocessor

+

Subclass of CharPreprocessor for preprocessing char encoded data.

+

Initialize the CharEncodedPreprocessor class.

+
+
Parameters
+
    +
  • encoding_map (dict) – char to int encoding map

  • +
  • max_length (int) – Maximum char length in a sample.

  • +
  • default_label (string (could be int, char, etc.)) – Key for label_mapping that is the default label

  • +
  • pad_label (string (could be int, char, etc.)) – Key for label_mapping that is the pad label

  • +
  • flatten_split (float) – approximate output of split between flattened and +non-flattened characters, value between [0, 1]. When the current +flattened split becomes more than the flatten_split value, any +leftover sample or subsequent samples will be non-flattened until +the current flattened split is below the flatten_split value

  • +
  • flatten_separator (str) – separator used to put between flattened +samples.

  • +
  • is_separate_at_max_len (bool) – if true, separates at max_length, +otherwise at nearest separator

  • +
+
+
+
+
+process(data: np.ndarray, labels: np.ndarray | None = None, label_mapping: dict[str, int] | None = None, batch_size: int = 32) Generator[tuple[np.ndarray, np.ndarray] | np.ndarray, None, None]
+

Process structured data for being processed by CharacterLevelCnnModel.

+
+
Parameters
+
    +
  • data (numpy.ndarray) – List of strings to create embeddings for

  • +
  • labels (numpy.ndarray) – labels for each input character

  • +
  • label_mapping (Union[dict, None]) – maps labels to their encoded integers

  • +
  • batch_size (int) – Number of samples in the batch of data

  • +
+
+
Return batch_data
+

A dict containing samples of size batch_size

+
+
Rtype batch_data
+

dict

+
+
+
+
+
+classmethod get_class(class_name: str) type[BaseDataProcessor] | None
+

Get class of BaseDataProcessor object.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (list) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod help() None
+

Describe alterable parameters.

+

Input data formats. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.data_processing.Processor
+

Load data processor from a given path on disk.

+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.data_processing.BaseDataProcessor
+

Load data processor from within the library.

+
+
+
+processor_type: str = 'preprocessor'
+
+
+
+save_to_disk(dirpath: str) None
+

Save data processor to a path on disk.

+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+
+class dataprofiler.labelers.data_processing.CharPostprocessor(default_label: str = 'UNKNOWN', pad_label: str = 'PAD', flatten_separator: str = ' ', use_word_level_argmax: bool = False, output_format: str = 'character_argmax', separators: tuple = (' ', ',', ';', "'", '"', ':', '\n', '\t', '.'), word_level_min_percent: float = 0.75)
+

Bases: dataprofiler.labelers.data_processing.BaseDataPostprocessor

+

Subclass of BaseDataPostprocessor for postprocessing char data.

+

Initialize the CharPostprocessor class.

+
+
Parameters
+
    +
  • default_label (string (could be int, char, etc.)) – Key for label_mapping that is the default label

  • +
  • pad_label (string (could be int, char, etc.)) – Key for label_mapping that is the pad label

  • +
  • flatten_separator (str) – separator used to put between flattened +samples.

  • +
  • use_word_level_argmax (bool) – whether to require the argmax value of +each character in a word to determine the word’s entity

  • +
  • output_format (str) – (character_argmax vs NER) where character_argmax +is a list of encodings for each character in the input text and NER +is in the dict format which specifies start,end,label for each +entity in a sentence

  • +
  • separators (tuple(str)) – list of characters to use for separating words within +the character predictions

  • +
  • word_level_min_percent (float) – threshold on generating dominant +word_level labeling

  • +
+
+
+
+
+classmethod help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+static convert_to_NER_format(predictions: list, label_mapping: dict, default_label: str, pad_label: str) list
+

Convert word level predictions to specified format.

+
+
Parameters
+
    +
  • predictions (list) – predictions

  • +
  • label_mapping (dict) – labels and corresponding integers

  • +
  • default_label (str) – default label in label_mapping

  • +
  • pad_label (str) – pad label in label_mapping

  • +
+
+
Returns
+

formatted predictions

+
+
Return type
+

list

+
+
+
+
+
+static match_sentence_lengths(data: numpy.ndarray, results: dict, flatten_separator: str, inplace: bool = True) dict
+

Convert results from model into same ragged data shapes as original data.

+
+
Parameters
+
    +
  • data (numpy.ndarray) – original input data to the data labeler

  • +
  • results (dict) – dict of model character level predictions and confs

  • +
  • flatten_separator (str) – string which joins to samples together when +flattening

  • +
  • inplace (bool) – flag to modify results in place

  • +
+
+
Returns
+

dict(pred=…) or dict(pred=…, conf=…)

+
+
+
+
+
+process(data: numpy.ndarray, results: dict, label_mapping: dict) dict
+

Conduct processing on data given predictions, label_mapping, and default_label.

+
+
Parameters
+
    +
  • data (Union[np.ndarray, pd.DataFrame]) – original input data to the data labeler

  • +
  • results (dict) – dict of model character level predictions and confs

  • +
  • label_mapping (dict) – labels and corresponding integers

  • +
+
+
Returns
+

dict of predictions and if they exist, confidences

+
+
+
+
+
+classmethod get_class(class_name: str) type[BaseDataProcessor] | None
+

Get class of BaseDataProcessor object.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (list) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.data_processing.Processor
+

Load data processor from a given path on disk.

+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.data_processing.BaseDataProcessor
+

Load data processor from within the library.

+
+
+
+processor_type: str = 'postprocessor'
+
+
+
+save_to_disk(dirpath: str) None
+

Save data processor to a path on disk.

+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+
+class dataprofiler.labelers.data_processing.StructCharPreprocessor(max_length: int = 3400, default_label: str = 'UNKNOWN', pad_label: str = 'PAD', flatten_separator: str = '\x01\x01\x01\x01\x01', is_separate_at_max_len: bool = False)
+

Bases: dataprofiler.labelers.data_processing.CharPreprocessor

+

Subclass of CharPreprocessor for preprocessing struct char data.

+

Initialize the StructCharPreprocessor class.

+
+
Parameters
+
    +
  • max_length (int) – Maximum char length in a sample.

  • +
  • default_label (string (could be int, char, etc.)) – Key for label_mapping that is the default label

  • +
  • pad_label (string (could be int, char, etc.)) – Key for label_mapping that is the pad label

  • +
  • flatten_separator (str) – separator used to put between flattened +samples.

  • +
  • is_separate_at_max_len (bool) – if true, separates at max_length, +otherwise at nearest separator

  • +
+
+
+
+
+classmethod help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for preprocessors.

+
+
Returns
+

None

+
+
+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (list) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+convert_to_unstructured_format(data: np.ndarray, labels: list[str] | npt.NDArray[np.str_] | None) tuple[str, list[tuple[int, int, str]] | None]
+

Convert data samples list to StructCharPreprocessor required input data format.

+
+
Parameters
+
    +
  • data (numpy.ndarray) – list of strings

  • +
  • labels (Optional[Union[List[str], npt.NDArray[np.str_]]]) – labels for each input character

  • +
+
+
Returns
+

data in the following format +text=”<SAMPLE><SEPARATOR><SAMPLE>…”, +entities=[(start=<INT>, end=<INT>, label=”<LABEL>”),

+
+

…(num_samples in data)])

+
+

+
+
Return type
+

Tuple[str, Optional[List[Tuple[int, int, str]]]]

+
+
+
+
+
+process(data: np.ndarray, labels: np.ndarray | None = None, label_mapping: dict[str, int] | None = None, batch_size: int = 32) Generator[tuple[np.ndarray, np.ndarray] | np.ndarray, None, None]
+

Process structured data for being processed by CharacterLevelCnnModel.

+
+
Parameters
+
    +
  • data (numpy.ndarray) – List of strings to create embeddings for

  • +
  • labels (numpy.ndarray) – labels for each input character

  • +
  • label_mapping (Union[dict, None]) – maps labels to their encoded integers

  • +
  • batch_size (int) – Number of samples in the batch of data

  • +
+
+
Return batch_data
+

A dict containing samples of size batch_size

+
+
Rtype batch_data
+

dict

+
+
+
+
+
+classmethod get_class(class_name: str) type[BaseDataProcessor] | None
+

Get class of BaseDataProcessor object.

+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.data_processing.Processor
+

Load data processor from a given path on disk.

+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.data_processing.BaseDataProcessor
+

Load data processor from within the library.

+
+
+
+processor_type: str = 'preprocessor'
+
+
+
+save_to_disk(dirpath: str) None
+

Save data processor to a path on disk.

+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+
+class dataprofiler.labelers.data_processing.StructCharPostprocessor(default_label: str = 'UNKNOWN', pad_label: str = 'PAD', flatten_separator: str = '\x01\x01\x01\x01\x01', is_pred_labels: bool = True, random_state: random.Random | int | list | tuple | None = None)
+

Bases: dataprofiler.labelers.data_processing.BaseDataPostprocessor

+

Subclass of BaseDataPostprocessor for postprocessing struct char data.

+

Initialize the StructCharPostprocessor class.

+
+
Parameters
+
    +
  • default_label (str) – Key for label_mapping that is the default label

  • +
  • pad_label (str) – Key for label_mapping that is the pad label

  • +
  • flatten_separator (str) – separator used to put between flattened +samples.

  • +
  • is_pred_labels (bool) – (default: true) if true, will convert the model +indexes to the label strings given the label_mapping

  • +
  • random_state (random.Random) – random state setting to be used for randomly +selecting a prediction when two labels have equal opportunity for +a given sample.

  • +
+
+
+
+
+classmethod help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+static match_sentence_lengths(data: numpy.ndarray, results: dict, flatten_separator: str, inplace: bool = True) dict
+

Convert results from model into same ragged data shapes as original data.

+
+
Parameters
+
    +
  • data (np.ndarray) – original input data to the data labeler

  • +
  • results (dict) – dict of model character level predictions and confs

  • +
  • flatten_separator (str) – string which joins to samples together when +flattening

  • +
  • inplace (bool) – flag to modify results in place

  • +
+
+
Returns
+

dict(pred=…) or dict(pred=…, conf=…)

+
+
+
+
+
+convert_to_structured_analysis(sentences: numpy.ndarray, results: dict, label_mapping: dict, default_label: str, pad_label: str) dict
+

Convert unstructured results to a structured column analysis.

+

This assumes the column was flattened into a single sample, and takes mode of +all character predictions except for the separator labels. In cases of +tie, chose anything but background, otherwise randomly choose between +the remaining labels.

+
+
Parameters
+
    +
  • sentences (numpy.ndarray) – samples which were predicted upon

  • +
  • results (dict) – character predictions for each sample return from model

  • +
  • label_mapping (dict) – maps labels to their encoded integers

  • +
  • default_label (str) – Key for label_mapping that is the default label

  • +
  • pad_label (str) – Key for label_mapping that is the pad label

  • +
+
+
Returns
+

prediction value for a single column

+
+
+
+
+
+process(data: numpy.ndarray, results: dict, label_mapping: dict) dict
+

Postprocess CharacterLevelCnnModel results when given structured data.

+

Said structured data is processed by StructCharPreprocessor.

+
+
Parameters
+
    +
  • data (Union[numpy.ndarray, pandas.DataFrame]) – original input data to the data labeler

  • +
  • results – dict of model character level predictions and confs

  • +
  • results – dict

  • +
  • label_mapping (dict) – maps labels to their encoded integers

  • +
+
+
Returns
+

dict of predictions and if they exist, confidences

+
+
Return type
+

dict

+
+
+
+
+
+classmethod get_class(class_name: str) type[BaseDataProcessor] | None
+

Get class of BaseDataProcessor object.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (list) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.data_processing.Processor
+

Load data processor from a given path on disk.

+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.data_processing.BaseDataProcessor
+

Load data processor from within the library.

+
+
+
+processor_type: str = 'postprocessor'
+
+
+
+save_to_disk(dirpath: str) None
+

Save data processor to a path on disk.

+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+
+class dataprofiler.labelers.data_processing.RegexPostProcessor(aggregation_func: str = 'split', priority_order: list | np.ndarray | None = None, random_state: random.Random | int | list | tuple | None = None)
+

Bases: dataprofiler.labelers.data_processing.BaseDataPostprocessor

+

Subclass of BaseDataPostprocessor for postprocessing regex data.

+

Initialize the RegexPostProcessor class.

+
+
Parameters
+
    +
  • aggregation_func (str) – aggregation function to apply to regex model +output (split, random, priority)

  • +
  • priority_order (Union[list, numpy.ndarray]) – if priority is set as the aggregation function, +the order in which entities are given priority must be set

  • +
  • random_state (random.Random) – random state setting to be used for randomly +selecting a prediction when two labels have equal opportunity for +a given sample.

  • +
+
+
+
+
+classmethod help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+static priority_prediction(results: dict, entity_priority_order: numpy.ndarray) None
+

Use priority of regex to give entity determination.

+
+
Parameters
+
    +
  • results (dict) – regex from model in format: dict(pred=…, conf=…)

  • +
  • entity_priority_order (np.ndarray) – list of entity priorities (lowest has +higher priority)

  • +
+
+
Returns
+

None

+
+
+
+
+
+static split_prediction(results: dict) None
+

Split the prediction across votes.

+
+
Parameters
+

results (dict) – regex from model in format: dict(pred=…, conf=…)

+
+
Returns
+

None

+
+
+
+
+
+process(data: numpy.ndarray, results: dict, label_mapping: dict) dict
+

Preprocess data.

+
+
+
+classmethod get_class(class_name: str) type[BaseDataProcessor] | None
+

Get class of BaseDataProcessor object.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (list) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.data_processing.Processor
+

Load data processor from a given path on disk.

+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.data_processing.BaseDataProcessor
+

Load data processor from within the library.

+
+
+
+processor_type: str = 'postprocessor'
+
+
+
+save_to_disk(dirpath: str) None
+

Save data processor to a path on disk.

+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+
+class dataprofiler.labelers.data_processing.StructRegexPostProcessor(random_state: random.Random | int | list | tuple | None = None)
+

Bases: dataprofiler.labelers.data_processing.BaseDataPostprocessor

+

Subclass of BaseDataPostprocessor for postprocessing struct regex data.

+

Initialize the RegexPostProcessor class.

+
+
Parameters
+

random_state (random.Random) – random state setting to be used for randomly +selecting a prediction when two labels have equal opportunity for +a given sample.

+
+
+
+
+set_params(**kwargs: Any) None
+

Given kwargs, set the parameters if they exist.

+
+
+
+classmethod help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+process(data: numpy.ndarray, results: dict, label_mapping: dict) dict
+

Preprocess data.

+
+
+
+classmethod get_class(class_name: str) type[BaseDataProcessor] | None
+

Get class of BaseDataProcessor object.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (list) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.data_processing.Processor
+

Load data processor from a given path on disk.

+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.data_processing.BaseDataProcessor
+

Load data processor from within the library.

+
+
+
+processor_type: str = 'postprocessor'
+
+
+
+save_to_disk(dirpath: str) None
+

Save data processor to a path on disk.

+
+
+
+
+class dataprofiler.labelers.data_processing.ColumnNameModelPostprocessor
+

Bases: dataprofiler.labelers.data_processing.BaseDataPostprocessor

+

Subclass of BaseDataPostprocessor for postprocessing regex data.

+

Initialize the ColumnNameModelPostProcessor class.

+
+
+classmethod help() None
+

Describe alterable parameters.

+

Input data formats for preprocessors. +Output data formats for postprocessors.

+
+
Returns
+

None

+
+
+
+
+
+process(data: np.ndarray, results: dict, label_mapping: dict[str, int] | None = None) dict
+

Preprocess data.

+
+
+
+classmethod get_class(class_name: str) type[BaseDataProcessor] | None
+

Get class of BaseDataProcessor object.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (list) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.data_processing.Processor
+

Load data processor from a given path on disk.

+
+
+
+classmethod load_from_library(name: str) dataprofiler.labelers.data_processing.BaseDataProcessor
+

Load data processor from within the library.

+
+
+
+processor_type: str = 'postprocessor'
+
+
+
+save_to_disk(dirpath: str) None
+

Save data processor to a path on disk.

+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.labelers.html b/docs/0.10.5/html/dataprofiler.labelers.html new file mode 100644 index 000000000..26362665b --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.labelers.html @@ -0,0 +1,361 @@ + + + + + + + + + Labelers - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Labelers

+
+

Modules

+
+
+ +

The following will list the built-in models, processors, and data labelers.

+
+
Models:
    +
  1. CharacterLevelCnnModel - character classification of text.

  2. +
  3. RegexModel - character classification of text.

  4. +
+
+
Processors:
+
Preprocessors
    +
  1. CharPreprocessor

  2. +
  3. StructCharPreprocessor

  4. +
  5. DirectPassPreprocessor

  6. +
+
+
PostProcessors
    +
  1. CharPreprocessor

  2. +
  3. StructCharPostprocessor

  4. +
  5. RegexPostProcessor

  6. +
+
+
+
+
Data Labelers:
+
Classes
    +
  1. UnstructuredDataLabeler

  2. +
  3. StructuredDataLabeler

  4. +
+
+
Files to load from disk using BaseDataLabeler.load_from_library(<NAME>)
    +
  1. unstructured_model

  2. +
  3. structured_model

  4. +
  5. regex_model

  6. +
+
+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.labelers.labeler_utils.html b/docs/0.10.5/html/dataprofiler.labelers.labeler_utils.html new file mode 100644 index 000000000..fd088a10f --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.labelers.labeler_utils.html @@ -0,0 +1,2642 @@ + + + + + + + + + Labeler Utils - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Labeler Utils

+

Contains functions for the data labeler.

+
+
+dataprofiler.labelers.labeler_utils.f1_report_dict_to_str(f1_report: dict, label_names: list) str
+

Return the report string from the f1_report dict.

+
+
Example Output:
+
+

precision recall f1-score support

+
+

class 0 0.00 0.00 0.00 1 +class 1 1.00 0.67 0.80 3

+
+

micro avg 0.67 0.50 0.57 4 +macro avg 0.50 0.33 0.40 4

+
+
+

weighted avg 0.75 0.50 0.60 4

+

Note: this is generally taken from the classification_report function +inside sklearn. +:param f1_report: f1 report dictionary from sklearn +:type f1_report: dict +:param label_names: names of labels included in the report +:type label_names: list(str) +:return: string representing f1_report printout +:rtype: str

+
+
+
+dataprofiler.labelers.labeler_utils.evaluate_accuracy(predicted_entities_in_index: list[list[int]], true_entities_in_index: list[list[int]], num_labels: int, entity_rev_dict: dict[int, str], verbose: bool = True, omitted_labels: tuple[str, ...] = ('PAD', 'UNKNOWN'), confusion_matrix_file: str | None = None) tuple[float, dict]
+

Evaluate accuracy from comparing predicted labels with true labels.

+
+
Parameters
+
    +
  • predicted_entities_in_index (list(array(int))) – predicted encoded labels for input +sentences

  • +
  • true_entities_in_index (list(array(int))) – true encoded labels for input sentences

  • +
  • entity_rev_dict (dict([index, entity])) – dictionary to convert indices to entities

  • +
  • verbose (boolean) – print additional information for debugging

  • +
  • omitted_labels (list() of text labels) – labels to omit from the accuracy evaluation

  • +
  • confusion_matrix_file (str) – File name (and dir) for confusion matrix

  • +
+
+
+

:return : f1-score +:rtype: float

+
+
+
+dataprofiler.labelers.labeler_utils.get_tf_layer_index_from_name(model: tf.keras.Model, layer_name: str) int | None
+

Return the index of the layer given the layer name within a tf model.

+
+
Parameters
+
    +
  • model – tf keras model to search

  • +
  • layer_name – name of the layer to find

  • +
+
+
Returns
+

layer index if it exists or None

+
+
+
+
+
+dataprofiler.labelers.labeler_utils.hide_tf_logger_warnings() None
+

Filter out a set of warnings from the tf logger.

+
+
+
+dataprofiler.labelers.labeler_utils.protected_register_keras_serializable(package: str = 'Custom', name: str | None = None) Callable
+

Protect against already registered keras serializable layers.

+

Ensures that if it was already registered, it will not try to +register it again.

+
+
+
+class dataprofiler.labelers.labeler_utils.FBetaScore(*args, **kwargs)
+

Bases: keras.src.metrics.base_metric.Metric

+

Computes F-Beta score.

+

Adapted and slightly modified from https://github.com/tensorflow/addons/blob/v0.12.0/tensorflow_addons/metrics/f_scores.py#L211-L283

+

# Copyright 2019 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the “License”); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# https://github.com/tensorflow/addons/blob/v0.12.0/LICENSE +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an “AS IS” BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ==============================================================================

+

It is the weighted harmonic mean of precision +and recall. Output range is [0, 1]. Works for +both multi-class and multi-label classification. +$$ +F_{beta} = (1 + beta^2) * frac{textrm{precision} * +textrm{precision}}{(beta^2 cdot textrm{precision}) + textrm{recall}} +$$ +:param num_classes: Number of unique classes in the dataset. +:param average: Type of averaging to be performed on data.

+
+

Acceptable values are None, micro, macro and +weighted. Default value is None.

+
+
+
Parameters
+
    +
  • beta – Determines the weight of precision and recall +in harmonic mean. Determines the weight given to the +precision and recall. Default value is 1.

  • +
  • threshold – Elements of y_pred greater than threshold are +converted to be 1, and the rest 0. If threshold is +None, the argmax is converted to 1, and the rest 0.

  • +
  • name – (Optional) String name of the metric instance.

  • +
  • dtype – (Optional) Data type of the metric result.

  • +
+
+
Returns
+

float.

+
+
Return type
+

F-Beta Score

+
+
+

Initialize FBetaScore class.

+
+
+update_state(y_true: tf.Tensor, y_pred: tf.Tensor, sample_weight: tf.Tensor | None = None) None
+

Update state.

+
+
+
+result() tensorflow.python.framework.ops.Tensor
+

Return f1 score.

+
+
+
+get_config() dict
+

Return the serializable config of the metric.

+
+
+
+reset_state() None
+

Reset state.

+
+
+
+property activity_regularizer
+

Optional regularizer function for the output of this layer.

+
+
+
+add_loss(losses, **kwargs)
+

Add loss tensor(s), potentially dependent on layer inputs.

+

Some losses (for instance, activity regularization losses) may be +dependent on the inputs passed when calling a layer. Hence, when reusing +the same layer on different inputs a and b, some entries in +layer.losses may be dependent on a and some on b. This method +automatically keeps track of dependencies.

+

This method can be used inside a subclassed layer or model’s call +function, in which case losses should be a Tensor or list of Tensors.

+

Example:

+

```python +class MyLayer(tf.keras.layers.Layer):

+
+
+
def call(self, inputs):

self.add_loss(tf.abs(tf.reduce_mean(inputs))) +return inputs

+
+
+
+

```

+

The same code works in distributed training: the input to add_loss() +is treated like a regularization loss and averaged across replicas +by the training loop (both built-in Model.fit() and compliant custom +training loops).

+

The add_loss method can also be called directly on a Functional Model +during construction. In this case, any loss Tensors passed to this Model +must be symbolic and be able to be traced back to the model’s Input`s. +These losses become part of the model’s topology and are tracked in +`get_config.

+

Example:

+

`python +inputs = tf.keras.Input(shape=(10,)) +x = tf.keras.layers.Dense(10)(inputs) +outputs = tf.keras.layers.Dense(1)(x) +model = tf.keras.Model(inputs, outputs) +# Activity regularization. +model.add_loss(tf.abs(tf.reduce_mean(x))) +`

+

If this is not the case for your loss (if, for example, your loss +references a Variable of one of the model’s layers), you can wrap your +loss in a zero-argument lambda. These losses are not tracked as part of +the model’s topology since they can’t be serialized.

+

Example:

+

`python +inputs = tf.keras.Input(shape=(10,)) +d = tf.keras.layers.Dense(10) +x = d(inputs) +outputs = tf.keras.layers.Dense(1)(x) +model = tf.keras.Model(inputs, outputs) +# Weight regularization. +model.add_loss(lambda: tf.reduce_mean(d.kernel)) +`

+
+
Parameters
+
    +
  • losses – Loss tensor, or list/tuple of tensors. Rather than tensors, +losses may also be zero-argument callables which create a loss +tensor.

  • +
  • **kwargs – Used for backwards compatibility only.

  • +
+
+
+
+
+
+add_metric(value, name=None, **kwargs)
+

Adds metric tensor to the layer.

+

This method can be used inside the call() method of a subclassed layer +or model.

+

```python +class MyMetricLayer(tf.keras.layers.Layer):

+
+
+
def __init__(self):

super(MyMetricLayer, self).__init__(name=’my_metric_layer’) +self.mean = tf.keras.metrics.Mean(name=’metric_1’)

+
+
def call(self, inputs):

self.add_metric(self.mean(inputs)) +self.add_metric(tf.reduce_sum(inputs), name=’metric_2’) +return inputs

+
+
+
+

```

+

This method can also be called directly on a Functional Model during +construction. In this case, any tensor passed to this Model must +be symbolic and be able to be traced back to the model’s Input`s. These +metrics become part of the model’s topology and are tracked when you +save the model via `save().

+

`python +inputs = tf.keras.Input(shape=(10,)) +x = tf.keras.layers.Dense(10)(inputs) +outputs = tf.keras.layers.Dense(1)(x) +model = tf.keras.Model(inputs, outputs) +model.add_metric(math_ops.reduce_sum(x), name='metric_1') +`

+

Note: Calling add_metric() with the result of a metric object on a +Functional Model, as shown in the example below, is not supported. This +is because we cannot trace the metric result tensor back to the model’s +inputs.

+

`python +inputs = tf.keras.Input(shape=(10,)) +x = tf.keras.layers.Dense(10)(inputs) +outputs = tf.keras.layers.Dense(1)(x) +model = tf.keras.Model(inputs, outputs) +model.add_metric(tf.keras.metrics.Mean()(x), name='metric_1') +`

+
+
Parameters
+
    +
  • value – Metric tensor.

  • +
  • name – String metric name.

  • +
  • **kwargs – Additional keyword arguments for backward compatibility. +Accepted values: +aggregation - When the value tensor provided is not the result +of calling a keras.Metric instance, it will be aggregated by +default using a keras.Metric.Mean.

  • +
+
+
+
+
+
+add_update(updates)
+

Add update op(s), potentially dependent on layer inputs.

+

Weight updates (for instance, the updates of the moving mean and +variance in a BatchNormalization layer) may be dependent on the inputs +passed when calling a layer. Hence, when reusing the same layer on +different inputs a and b, some entries in layer.updates may be +dependent on a and some on b. This method automatically keeps track +of dependencies.

+

This call is ignored when eager execution is enabled (in that case, +variable updates are run on the fly and thus do not need to be tracked +for later execution).

+
+
Parameters
+

updates – Update op, or list/tuple of update ops, or zero-arg callable +that returns an update op. A zero-arg callable should be passed in +order to disable running the updates by setting trainable=False +on this Layer, when executing in Eager mode.

+
+
+
+
+
+add_variable(*args, **kwargs)
+

Deprecated, do NOT use! Alias for add_weight.

+
+
+
+add_weight(name, shape=(), aggregation=VariableAggregationV2.SUM, synchronization=VariableSynchronization.ON_READ, initializer=None, dtype=None)
+

Adds state variable. Only for use by subclasses.

+
+
+
+build(input_shape)
+

Creates the variables of the layer (for subclass implementers).

+

This is a method that implementers of subclasses of Layer or Model +can override if they need a state-creation step in-between +layer instantiation and layer call. It is invoked automatically before +the first execution of call().

+

This is typically used to create the weights of Layer subclasses +(at the discretion of the subclass implementer).

+
+
Parameters
+

input_shape – Instance of TensorShape, or list of instances of +TensorShape if the layer expects a list of inputs +(one instance per input).

+
+
+
+
+
+build_from_config(config)
+

Builds the layer’s states with the supplied config dict.

+

By default, this method calls the build(config[“input_shape”]) method, +which creates weights based on the layer’s input shape in the supplied +config. If your config contains other information needed to load the +layer’s state, you should override this method.

+
+
Parameters
+

config – Dict containing the input shape associated with this layer.

+
+
+
+
+
+call(inputs, *args, **kwargs)
+

This is where the layer’s logic lives.

+

The call() method may not create state (except in its first +invocation, wrapping the creation of variables or other resources in +tf.init_scope()). It is recommended to create state, including +tf.Variable instances and nested Layer instances,

+
+

in __init__(), or in the build() method that is

+
+

called automatically before call() executes for the first time.

+
+
Parameters
+
    +
  • inputs

    Input tensor, or dict/list/tuple of input tensors. +The first positional inputs argument is subject to special rules: +- inputs must be explicitly passed. A layer cannot have zero

    +
    +

    arguments, and inputs cannot be provided via the default value +of a keyword argument.

    +
    +
      +
    • NumPy array or Python scalar values in inputs get cast as +tensors.

    • +
    • Keras mask metadata is only collected from inputs.

    • +
    • Layers are built (build(input_shape) method) +using shape info from inputs only.

    • +
    • input_spec compatibility is only checked against inputs.

    • +
    • Mixed precision input casting is only applied to inputs. +If a layer has tensor arguments in *args or **kwargs, their +casting behavior in mixed precision should be handled manually.

    • +
    • The SavedModel input specification is generated using inputs +only.

    • +
    • Integration with various ecosystem packages like TFMOT, TFLite, +TF.js, etc is only supported for inputs and not for tensors in +positional and keyword arguments.

    • +
    +

  • +
  • *args – Additional positional arguments. May contain tensors, although +this is not recommended, for the reasons above.

  • +
  • **kwargs

    Additional keyword arguments. May contain tensors, although +this is not recommended, for the reasons above. +The following optional keyword arguments are reserved: +- training: Boolean scalar tensor of Python boolean indicating

    +
    +

    whether the call is meant for training or inference.

    +
    +
      +
    • mask: Boolean input mask. If the layer’s call() method takes a +mask argument, its default value will be set to the mask +generated for inputs by the previous layer (if input did come +from a layer that generated a corresponding mask, i.e. if it came +from a Keras layer with masking support).

    • +
    +

  • +
+
+
Returns
+

A tensor or list/tuple of tensors.

+
+
+
+
+
+property compute_dtype
+

The dtype of the layer’s computations.

+

This is equivalent to Layer.dtype_policy.compute_dtype. Unless +mixed precision is used, this is the same as Layer.dtype, the dtype of +the weights.

+

Layers automatically cast their inputs to the compute dtype, which +causes computations and the output to be in the compute dtype as well. +This is done by the base Layer class in Layer.__call__, so you do not +have to insert these casts if implementing your own layer.

+

Layers often perform certain internal computations in higher precision +when compute_dtype is float16 or bfloat16 for numeric stability. The +output will still typically be float16 or bfloat16 in such cases.

+
+
Returns
+

The layer’s compute dtype.

+
+
+
+
+
+compute_mask(inputs, mask=None)
+

Computes an output mask tensor.

+
+
Parameters
+
    +
  • inputs – Tensor or list of tensors.

  • +
  • mask – Tensor or list of tensors.

  • +
+
+
Returns
+

+
None or a tensor (or list of tensors,

one per output tensor of the layer).

+
+
+

+
+
+
+
+
+compute_output_shape(input_shape)
+

Computes the output shape of the layer.

+

This method will cause the layer’s state to be built, if that has not +happened before. This requires that the layer will later be used with +inputs that match the input shape provided here.

+
+
Parameters
+

input_shape – Shape tuple (tuple of integers) or tf.TensorShape, +or structure of shape tuples / tf.TensorShape instances +(one per output tensor of the layer). +Shape tuples can include None for free dimensions, +instead of an integer.

+
+
Returns
+

A tf.TensorShape instance +or structure of tf.TensorShape instances.

+
+
+
+
+
+compute_output_signature(input_signature)
+

Compute the output tensor signature of the layer based on the inputs.

+

Unlike a TensorShape object, a TensorSpec object contains both shape +and dtype information for a tensor. This method allows layers to provide +output dtype information if it is different from the input dtype. +For any layer that doesn’t implement this function, +the framework will fall back to use compute_output_shape, and will +assume that the output dtype matches the input dtype.

+
+
Parameters
+

input_signature – Single TensorSpec or nested structure of TensorSpec +objects, describing a candidate input for the layer.

+
+
Returns
+

+
Single TensorSpec or nested structure of TensorSpec objects,

describing how the layer would transform the provided input.

+
+
+

+
+
Raises
+

TypeError – If input_signature contains a non-TensorSpec object.

+
+
+
+
+
+count_params()
+

Count the total number of scalars composing the weights.

+
+
Returns
+

An integer count.

+
+
Raises
+

ValueError – if the layer isn’t yet built + (in which case its weights aren’t yet defined).

+
+
+
+
+
+property dtype
+

The dtype of the layer weights.

+

This is equivalent to Layer.dtype_policy.variable_dtype. Unless +mixed precision is used, this is the same as Layer.compute_dtype, the +dtype of the layer’s computations.

+
+
+
+property dtype_policy
+

The dtype policy associated with this layer.

+

This is an instance of a tf.keras.mixed_precision.Policy.

+
+
+
+property dynamic
+

Whether the layer is dynamic (eager-only); set in the constructor.

+
+
+
+finalize_state()
+

Finalizes the layers state after updating layer weights.

+

This function can be subclassed in a layer and will be called after +updating a layer weights. It can be overridden to finalize any +additional layer state after a weight update.

+

This function will be called after weights of a layer have been restored +from a loaded model.

+
+
+
+classmethod from_config(config)
+

Creates a layer from its config.

+

This method is the reverse of get_config, +capable of instantiating the same layer from the config +dictionary. It does not handle layer connectivity +(handled by Network), nor weights (handled by set_weights).

+
+
Parameters
+

config – A Python dictionary, typically the +output of get_config.

+
+
Returns
+

A layer instance.

+
+
+
+
+
+get_build_config()
+

Returns a dictionary with the layer’s input shape.

+

This method returns a config dict that can be used by +build_from_config(config) to create all states (e.g. Variables and +Lookup tables) needed by the layer.

+

By default, the config only contains the input shape that the layer +was built with. If you’re writing a custom layer that creates state in +an unusual way, you should override this method to make sure this state +is already created when Keras attempts to load its value upon model +loading.

+
+
Returns
+

A dict containing the input shape associated with the layer.

+
+
+
+
+
+get_input_at(node_index)
+

Retrieves the input tensor(s) of a layer at a given node.

+
+
Parameters
+

node_index – Integer, index of the node +from which to retrieve the attribute. +E.g. node_index=0 will correspond to the +first input node of the layer.

+
+
Returns
+

A tensor (or list of tensors if the layer has multiple inputs).

+
+
Raises
+

RuntimeError – If called in Eager mode.

+
+
+
+
+
+get_input_mask_at(node_index)
+

Retrieves the input mask tensor(s) of a layer at a given node.

+
+
Parameters
+

node_index – Integer, index of the node +from which to retrieve the attribute. +E.g. node_index=0 will correspond to the +first time the layer was called.

+
+
Returns
+

A mask tensor +(or list of tensors if the layer has multiple inputs).

+
+
+
+
+
+get_input_shape_at(node_index)
+

Retrieves the input shape(s) of a layer at a given node.

+
+
Parameters
+

node_index – Integer, index of the node +from which to retrieve the attribute. +E.g. node_index=0 will correspond to the +first time the layer was called.

+
+
Returns
+

A shape tuple +(or list of shape tuples if the layer has multiple inputs).

+
+
Raises
+

RuntimeError – If called in Eager mode.

+
+
+
+
+
+get_output_at(node_index)
+

Retrieves the output tensor(s) of a layer at a given node.

+
+
Parameters
+

node_index – Integer, index of the node +from which to retrieve the attribute. +E.g. node_index=0 will correspond to the +first output node of the layer.

+
+
Returns
+

A tensor (or list of tensors if the layer has multiple outputs).

+
+
Raises
+

RuntimeError – If called in Eager mode.

+
+
+
+
+
+get_output_mask_at(node_index)
+

Retrieves the output mask tensor(s) of a layer at a given node.

+
+
Parameters
+

node_index – Integer, index of the node +from which to retrieve the attribute. +E.g. node_index=0 will correspond to the +first time the layer was called.

+
+
Returns
+

A mask tensor +(or list of tensors if the layer has multiple outputs).

+
+
+
+
+
+get_output_shape_at(node_index)
+

Retrieves the output shape(s) of a layer at a given node.

+
+
Parameters
+

node_index – Integer, index of the node +from which to retrieve the attribute. +E.g. node_index=0 will correspond to the +first time the layer was called.

+
+
Returns
+

A shape tuple +(or list of shape tuples if the layer has multiple outputs).

+
+
Raises
+

RuntimeError – If called in Eager mode.

+
+
+
+
+
+get_weights()
+

Returns the current weights of the layer, as NumPy arrays.

+

The weights of a layer represent the state of the layer. This function +returns both trainable and non-trainable weight values associated with +this layer as a list of NumPy arrays, which can in turn be used to load +state into similarly parameterized layers.

+

For example, a Dense layer returns a list of two values: the kernel +matrix and the bias vector. These can be used to set the weights of +another Dense layer:

+
>>> layer_a = tf.keras.layers.Dense(1,
+...   kernel_initializer=tf.constant_initializer(1.))
+>>> a_out = layer_a(tf.convert_to_tensor([[1., 2., 3.]]))
+>>> layer_a.get_weights()
+[array([[1.],
+       [1.],
+       [1.]], dtype=float32), array([0.], dtype=float32)]
+>>> layer_b = tf.keras.layers.Dense(1,
+...   kernel_initializer=tf.constant_initializer(2.))
+>>> b_out = layer_b(tf.convert_to_tensor([[10., 20., 30.]]))
+>>> layer_b.get_weights()
+[array([[2.],
+       [2.],
+       [2.]], dtype=float32), array([0.], dtype=float32)]
+>>> layer_b.set_weights(layer_a.get_weights())
+>>> layer_b.get_weights()
+[array([[1.],
+       [1.],
+       [1.]], dtype=float32), array([0.], dtype=float32)]
+
+
+
+
Returns
+

Weights values as a list of NumPy arrays.

+
+
+
+
+
+property inbound_nodes
+

Return Functional API nodes upstream of this layer.

+
+
+
+property input
+

Retrieves the input tensor(s) of a layer.

+

Only applicable if the layer has exactly one input, +i.e. if it is connected to one incoming layer.

+
+
Returns
+

Input tensor or list of input tensors.

+
+
Raises
+
    +
  • RuntimeError – If called in Eager mode.

  • +
  • AttributeError – If no inbound nodes are found.

  • +
+
+
+
+
+
+property input_mask
+

Retrieves the input mask tensor(s) of a layer.

+

Only applicable if the layer has exactly one inbound node, +i.e. if it is connected to one incoming layer.

+
+
Returns
+

Input mask tensor (potentially None) or list of input +mask tensors.

+
+
Raises
+
    +
  • AttributeError – if the layer is connected to

  • +
  • more than one incoming layers.

  • +
+
+
+
+
+
+property input_shape
+

Retrieves the input shape(s) of a layer.

+

Only applicable if the layer has exactly one input, +i.e. if it is connected to one incoming layer, or if all inputs +have the same shape.

+
+
Returns
+

Input shape, as an integer shape tuple +(or list of shape tuples, one tuple per input tensor).

+
+
Raises
+
    +
  • AttributeError – if the layer has no defined input_shape.

  • +
  • RuntimeError – if called in Eager mode.

  • +
+
+
+
+
+
+property input_spec
+

InputSpec instance(s) describing the input format for this layer.

+

When you create a layer subclass, you can set self.input_spec to +enable the layer to run input compatibility checks when it is called. +Consider a Conv2D layer: it can only be called on a single input +tensor of rank 4. As such, you can set, in __init__():

+

`python +self.input_spec = tf.keras.layers.InputSpec(ndim=4) +`

+

Now, if you try to call the layer on an input that isn’t rank 4 +(for instance, an input of shape (2,), it will raise a +nicely-formatted error:

+

` +ValueError: Input 0 of layer conv2d is incompatible with the layer: +expected ndim=4, found ndim=1. Full shape received: [2] +`

+

Input checks that can be specified via input_spec include: +- Structure (e.g. a single input, a list of 2 inputs, etc) +- Shape +- Rank (ndim) +- Dtype

+

For more information, see tf.keras.layers.InputSpec.

+
+
Returns
+

A tf.keras.layers.InputSpec instance, or nested structure thereof.

+
+
+
+
+
+load_own_variables(store)
+

Loads the state of the layer.

+

You can override this method to take full control of how the state of +the layer is loaded upon calling keras.models.load_model().

+
+
Parameters
+

store – Dict from which the state of the model will be loaded.

+
+
+
+
+
+property losses
+

List of losses added using the add_loss() API.

+

Variable regularization tensors are created when this property is +accessed, so it is eager safe: accessing losses under a +tf.GradientTape will propagate gradients back to the corresponding +variables.

+

Examples:

+
>>> class MyLayer(tf.keras.layers.Layer):
+...   def call(self, inputs):
+...     self.add_loss(tf.abs(tf.reduce_mean(inputs)))
+...     return inputs
+>>> l = MyLayer()
+>>> l(np.ones((10, 1)))
+>>> l.losses
+[1.0]
+
+
+
>>> inputs = tf.keras.Input(shape=(10,))
+>>> x = tf.keras.layers.Dense(10)(inputs)
+>>> outputs = tf.keras.layers.Dense(1)(x)
+>>> model = tf.keras.Model(inputs, outputs)
+>>> # Activity regularization.
+>>> len(model.losses)
+0
+>>> model.add_loss(tf.abs(tf.reduce_mean(x)))
+>>> len(model.losses)
+1
+
+
+
>>> inputs = tf.keras.Input(shape=(10,))
+>>> d = tf.keras.layers.Dense(10, kernel_initializer='ones')
+>>> x = d(inputs)
+>>> outputs = tf.keras.layers.Dense(1)(x)
+>>> model = tf.keras.Model(inputs, outputs)
+>>> # Weight regularization.
+>>> model.add_loss(lambda: tf.reduce_mean(d.kernel))
+>>> model.losses
+[<tf.Tensor: shape=(), dtype=float32, numpy=1.0>]
+
+
+
+
Returns
+

A list of tensors.

+
+
+
+
+
+merge_state(metrics)
+

Merges the state from one or more metrics.

+

This method can be used by distributed systems to merge the state +computed by different metric instances. Typically the state will be +stored in the form of the metric’s weights. For example, a +tf.keras.metrics.Mean metric contains a list of two weight values: a +total and a count. If there were two instances of a +tf.keras.metrics.Accuracy that each independently aggregated partial +state for an overall accuracy calculation, these two metric’s states +could be combined as follows:

+
>>> m1 = tf.keras.metrics.Accuracy()
+>>> _ = m1.update_state([[1], [2]], [[0], [2]])
+
+
+
>>> m2 = tf.keras.metrics.Accuracy()
+>>> _ = m2.update_state([[3], [4]], [[3], [4]])
+
+
+
>>> m2.merge_state([m1])
+>>> m2.result().numpy()
+0.75
+
+
+
+
Parameters
+

metrics – an iterable of metrics. The metrics must have compatible +state.

+
+
Raises
+

ValueError – If the provided iterable does not contain metrics matching + the metric’s required specifications.

+
+
+
+
+
+property metrics
+

List of metrics added using the add_metric() API.

+

Example:

+
>>> input = tf.keras.layers.Input(shape=(3,))
+>>> d = tf.keras.layers.Dense(2)
+>>> output = d(input)
+>>> d.add_metric(tf.reduce_max(output), name='max')
+>>> d.add_metric(tf.reduce_min(output), name='min')
+>>> [m.name for m in d.metrics]
+['max', 'min']
+
+
+
+
Returns
+

A list of Metric objects.

+
+
+
+
+
+property name
+

Name of the layer (string), set in the constructor.

+
+
+
+property name_scope
+

Returns a tf.name_scope instance for this class.

+
+
+
+property non_trainable_variables
+

Sequence of non-trainable variables owned by this module and its submodules.

+

Note: this method uses reflection to find variables on the current instance +and submodules. For performance reasons you may wish to cache the result +of calling this method if you don’t expect the return value to change.

+
+
Returns
+

A sequence of variables for the current module (sorted by attribute +name) followed by variables from all submodules recursively (breadth +first).

+
+
+
+
+
+property non_trainable_weights
+

List of all non-trainable weights tracked by this layer.

+

Non-trainable weights are not updated during training. They are +expected to be updated manually in call().

+
+
Returns
+

A list of non-trainable variables.

+
+
+
+
+
+property outbound_nodes
+

Return Functional API nodes downstream of this layer.

+
+
+
+property output
+

Retrieves the output tensor(s) of a layer.

+

Only applicable if the layer has exactly one output, +i.e. if it is connected to one incoming layer.

+
+
Returns
+

Output tensor or list of output tensors.

+
+
Raises
+
    +
  • AttributeError – if the layer is connected to more than one incoming + layers.

  • +
  • RuntimeError – if called in Eager mode.

  • +
+
+
+
+
+
+property output_mask
+

Retrieves the output mask tensor(s) of a layer.

+

Only applicable if the layer has exactly one inbound node, +i.e. if it is connected to one incoming layer.

+
+
Returns
+

Output mask tensor (potentially None) or list of output +mask tensors.

+
+
Raises
+
    +
  • AttributeError – if the layer is connected to

  • +
  • more than one incoming layers.

  • +
+
+
+
+
+
+property output_shape
+

Retrieves the output shape(s) of a layer.

+

Only applicable if the layer has one output, +or if all outputs have the same shape.

+
+
Returns
+

Output shape, as an integer shape tuple +(or list of shape tuples, one tuple per output tensor).

+
+
Raises
+
    +
  • AttributeError – if the layer has no defined output shape.

  • +
  • RuntimeError – if called in Eager mode.

  • +
+
+
+
+
+
+reset_states()
+
+
+
+save_own_variables(store)
+

Saves the state of the layer.

+

You can override this method to take full control of how the state of +the layer is saved upon calling model.save().

+
+
Parameters
+

store – Dict where the state of the model will be saved.

+
+
+
+
+
+set_weights(weights)
+

Sets the weights of the layer, from NumPy arrays.

+

The weights of a layer represent the state of the layer. This function +sets the weight values from numpy arrays. The weight values should be +passed in the order they are created by the layer. Note that the layer’s +weights must be instantiated before calling this function, by calling +the layer.

+

For example, a Dense layer returns a list of two values: the kernel +matrix and the bias vector. These can be used to set the weights of +another Dense layer:

+
>>> layer_a = tf.keras.layers.Dense(1,
+...   kernel_initializer=tf.constant_initializer(1.))
+>>> a_out = layer_a(tf.convert_to_tensor([[1., 2., 3.]]))
+>>> layer_a.get_weights()
+[array([[1.],
+       [1.],
+       [1.]], dtype=float32), array([0.], dtype=float32)]
+>>> layer_b = tf.keras.layers.Dense(1,
+...   kernel_initializer=tf.constant_initializer(2.))
+>>> b_out = layer_b(tf.convert_to_tensor([[10., 20., 30.]]))
+>>> layer_b.get_weights()
+[array([[2.],
+       [2.],
+       [2.]], dtype=float32), array([0.], dtype=float32)]
+>>> layer_b.set_weights(layer_a.get_weights())
+>>> layer_b.get_weights()
+[array([[1.],
+       [1.],
+       [1.]], dtype=float32), array([0.], dtype=float32)]
+
+
+
+
Parameters
+

weights – a list of NumPy arrays. The number +of arrays and their shape must match +number of the dimensions of the weights +of the layer (i.e. it should match the +output of get_weights).

+
+
Raises
+

ValueError – If the provided weights list does not match the + layer’s specifications.

+
+
+
+
+
+property stateful
+
+
+
+property submodules
+

Sequence of all sub-modules.

+

Submodules are modules which are properties of this module, or found as +properties of modules which are properties of this module (and so on).

+
>>> a = tf.Module()
+>>> b = tf.Module()
+>>> c = tf.Module()
+>>> a.b = b
+>>> b.c = c
+>>> list(a.submodules) == [b, c]
+True
+>>> list(b.submodules) == [c]
+True
+>>> list(c.submodules) == []
+True
+
+
+
+
Returns
+

A sequence of all submodules.

+
+
+
+
+
+property supports_masking
+

Whether this layer supports computing a mask using compute_mask.

+
+
+
+property trainable
+
+
+
+property trainable_variables
+

Sequence of trainable variables owned by this module and its submodules.

+

Note: this method uses reflection to find variables on the current instance +and submodules. For performance reasons you may wish to cache the result +of calling this method if you don’t expect the return value to change.

+
+
Returns
+

A sequence of variables for the current module (sorted by attribute +name) followed by variables from all submodules recursively (breadth +first).

+
+
+
+
+
+property trainable_weights
+

List of all trainable weights tracked by this layer.

+

Trainable weights are updated via gradient descent during training.

+
+
Returns
+

A list of trainable variables.

+
+
+
+
+
+property updates
+
+
+
+property variable_dtype
+

Alias of Layer.dtype, the dtype of the weights.

+
+
+
+property variables
+

Returns the list of all layer variables/weights.

+

Alias of self.weights.

+

Note: This will not track the weights of nested tf.Modules that are +not themselves Keras layers.

+
+
Returns
+

A list of variables.

+
+
+
+
+
+property weights
+

Returns the list of all layer variables/weights.

+
+
Returns
+

A list of variables.

+
+
+
+
+
+classmethod with_name_scope(method)
+

Decorator to automatically enter the module name scope.

+
>>> class MyModule(tf.Module):
+...   @tf.Module.with_name_scope
+...   def __call__(self, x):
+...     if not hasattr(self, 'w'):
+...       self.w = tf.Variable(tf.random.normal([x.shape[1], 3]))
+...     return tf.matmul(x, self.w)
+
+
+

Using the above module would produce `tf.Variable`s and `tf.Tensor`s whose +names included the module name:

+
>>> mod = MyModule()
+>>> mod(tf.ones([1, 2]))
+<tf.Tensor: shape=(1, 3), dtype=float32, numpy=..., dtype=float32)>
+>>> mod.w
+<tf.Variable 'my_module/Variable:0' shape=(2, 3) dtype=float32,
+numpy=..., dtype=float32)>
+
+
+
+
Parameters
+

method – The method to wrap.

+
+
Returns
+

The original method wrapped such that it enters the module’s name scope.

+
+
+
+
+
+
+class dataprofiler.labelers.labeler_utils.F1Score(*args, **kwargs)
+

Bases: dataprofiler.labelers.labeler_utils.FBetaScore

+

Computes F-1 Score.

+

# Copyright 2019 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the “License”); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# https://github.com/tensorflow/addons/blob/v0.12.0/LICENSE +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an “AS IS” BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ==============================================================================

+

It is the harmonic mean of precision and recall. +Output range is [0, 1]. Works for both multi-class +and multi-label classification. +$$ +F_1 = 2 cdot frac{textrm{precision} +cdot textrm{recall}}{textrm{precision} + textrm{recall}} +$$ +:param num_classes: Number of unique classes in the dataset. +:param average: Type of averaging to be performed on data.

+
+

Acceptable values are None, micro, macro +and weighted. Default value is None.

+
+
+
Parameters
+
    +
  • threshold – Elements of y_pred above threshold are +considered to be 1, and the rest 0. If threshold is +None, the argmax is converted to 1, and the rest 0.

  • +
  • name – (Optional) String name of the metric instance.

  • +
  • dtype – (Optional) Data type of the metric result.

  • +
+
+
Returns
+

float.

+
+
Return type
+

F-1 Score

+
+
+

Initialize F1Score object.

+
+
+property activity_regularizer
+

Optional regularizer function for the output of this layer.

+
+
+
+add_loss(losses, **kwargs)
+

Add loss tensor(s), potentially dependent on layer inputs.

+

Some losses (for instance, activity regularization losses) may be +dependent on the inputs passed when calling a layer. Hence, when reusing +the same layer on different inputs a and b, some entries in +layer.losses may be dependent on a and some on b. This method +automatically keeps track of dependencies.

+

This method can be used inside a subclassed layer or model’s call +function, in which case losses should be a Tensor or list of Tensors.

+

Example:

+

```python +class MyLayer(tf.keras.layers.Layer):

+
+
+
def call(self, inputs):

self.add_loss(tf.abs(tf.reduce_mean(inputs))) +return inputs

+
+
+
+

```

+

The same code works in distributed training: the input to add_loss() +is treated like a regularization loss and averaged across replicas +by the training loop (both built-in Model.fit() and compliant custom +training loops).

+

The add_loss method can also be called directly on a Functional Model +during construction. In this case, any loss Tensors passed to this Model +must be symbolic and be able to be traced back to the model’s Input`s. +These losses become part of the model’s topology and are tracked in +`get_config.

+

Example:

+

`python +inputs = tf.keras.Input(shape=(10,)) +x = tf.keras.layers.Dense(10)(inputs) +outputs = tf.keras.layers.Dense(1)(x) +model = tf.keras.Model(inputs, outputs) +# Activity regularization. +model.add_loss(tf.abs(tf.reduce_mean(x))) +`

+

If this is not the case for your loss (if, for example, your loss +references a Variable of one of the model’s layers), you can wrap your +loss in a zero-argument lambda. These losses are not tracked as part of +the model’s topology since they can’t be serialized.

+

Example:

+

`python +inputs = tf.keras.Input(shape=(10,)) +d = tf.keras.layers.Dense(10) +x = d(inputs) +outputs = tf.keras.layers.Dense(1)(x) +model = tf.keras.Model(inputs, outputs) +# Weight regularization. +model.add_loss(lambda: tf.reduce_mean(d.kernel)) +`

+
+
Parameters
+
    +
  • losses – Loss tensor, or list/tuple of tensors. Rather than tensors, +losses may also be zero-argument callables which create a loss +tensor.

  • +
  • **kwargs – Used for backwards compatibility only.

  • +
+
+
+
+
+
+add_metric(value, name=None, **kwargs)
+

Adds metric tensor to the layer.

+

This method can be used inside the call() method of a subclassed layer +or model.

+

```python +class MyMetricLayer(tf.keras.layers.Layer):

+
+
+
def __init__(self):

super(MyMetricLayer, self).__init__(name=’my_metric_layer’) +self.mean = tf.keras.metrics.Mean(name=’metric_1’)

+
+
def call(self, inputs):

self.add_metric(self.mean(inputs)) +self.add_metric(tf.reduce_sum(inputs), name=’metric_2’) +return inputs

+
+
+
+

```

+

This method can also be called directly on a Functional Model during +construction. In this case, any tensor passed to this Model must +be symbolic and be able to be traced back to the model’s Input`s. These +metrics become part of the model’s topology and are tracked when you +save the model via `save().

+

`python +inputs = tf.keras.Input(shape=(10,)) +x = tf.keras.layers.Dense(10)(inputs) +outputs = tf.keras.layers.Dense(1)(x) +model = tf.keras.Model(inputs, outputs) +model.add_metric(math_ops.reduce_sum(x), name='metric_1') +`

+

Note: Calling add_metric() with the result of a metric object on a +Functional Model, as shown in the example below, is not supported. This +is because we cannot trace the metric result tensor back to the model’s +inputs.

+

`python +inputs = tf.keras.Input(shape=(10,)) +x = tf.keras.layers.Dense(10)(inputs) +outputs = tf.keras.layers.Dense(1)(x) +model = tf.keras.Model(inputs, outputs) +model.add_metric(tf.keras.metrics.Mean()(x), name='metric_1') +`

+
+
Parameters
+
    +
  • value – Metric tensor.

  • +
  • name – String metric name.

  • +
  • **kwargs – Additional keyword arguments for backward compatibility. +Accepted values: +aggregation - When the value tensor provided is not the result +of calling a keras.Metric instance, it will be aggregated by +default using a keras.Metric.Mean.

  • +
+
+
+
+
+
+add_update(updates)
+

Add update op(s), potentially dependent on layer inputs.

+

Weight updates (for instance, the updates of the moving mean and +variance in a BatchNormalization layer) may be dependent on the inputs +passed when calling a layer. Hence, when reusing the same layer on +different inputs a and b, some entries in layer.updates may be +dependent on a and some on b. This method automatically keeps track +of dependencies.

+

This call is ignored when eager execution is enabled (in that case, +variable updates are run on the fly and thus do not need to be tracked +for later execution).

+
+
Parameters
+

updates – Update op, or list/tuple of update ops, or zero-arg callable +that returns an update op. A zero-arg callable should be passed in +order to disable running the updates by setting trainable=False +on this Layer, when executing in Eager mode.

+
+
+
+
+
+add_variable(*args, **kwargs)
+

Deprecated, do NOT use! Alias for add_weight.

+
+
+
+add_weight(name, shape=(), aggregation=VariableAggregationV2.SUM, synchronization=VariableSynchronization.ON_READ, initializer=None, dtype=None)
+

Adds state variable. Only for use by subclasses.

+
+
+
+build(input_shape)
+

Creates the variables of the layer (for subclass implementers).

+

This is a method that implementers of subclasses of Layer or Model +can override if they need a state-creation step in-between +layer instantiation and layer call. It is invoked automatically before +the first execution of call().

+

This is typically used to create the weights of Layer subclasses +(at the discretion of the subclass implementer).

+
+
Parameters
+

input_shape – Instance of TensorShape, or list of instances of +TensorShape if the layer expects a list of inputs +(one instance per input).

+
+
+
+
+
+build_from_config(config)
+

Builds the layer’s states with the supplied config dict.

+

By default, this method calls the build(config[“input_shape”]) method, +which creates weights based on the layer’s input shape in the supplied +config. If your config contains other information needed to load the +layer’s state, you should override this method.

+
+
Parameters
+

config – Dict containing the input shape associated with this layer.

+
+
+
+
+
+call(inputs, *args, **kwargs)
+

This is where the layer’s logic lives.

+

The call() method may not create state (except in its first +invocation, wrapping the creation of variables or other resources in +tf.init_scope()). It is recommended to create state, including +tf.Variable instances and nested Layer instances,

+
+

in __init__(), or in the build() method that is

+
+

called automatically before call() executes for the first time.

+
+
Parameters
+
    +
  • inputs

    Input tensor, or dict/list/tuple of input tensors. +The first positional inputs argument is subject to special rules: +- inputs must be explicitly passed. A layer cannot have zero

    +
    +

    arguments, and inputs cannot be provided via the default value +of a keyword argument.

    +
    +
      +
    • NumPy array or Python scalar values in inputs get cast as +tensors.

    • +
    • Keras mask metadata is only collected from inputs.

    • +
    • Layers are built (build(input_shape) method) +using shape info from inputs only.

    • +
    • input_spec compatibility is only checked against inputs.

    • +
    • Mixed precision input casting is only applied to inputs. +If a layer has tensor arguments in *args or **kwargs, their +casting behavior in mixed precision should be handled manually.

    • +
    • The SavedModel input specification is generated using inputs +only.

    • +
    • Integration with various ecosystem packages like TFMOT, TFLite, +TF.js, etc is only supported for inputs and not for tensors in +positional and keyword arguments.

    • +
    +

  • +
  • *args – Additional positional arguments. May contain tensors, although +this is not recommended, for the reasons above.

  • +
  • **kwargs

    Additional keyword arguments. May contain tensors, although +this is not recommended, for the reasons above. +The following optional keyword arguments are reserved: +- training: Boolean scalar tensor of Python boolean indicating

    +
    +

    whether the call is meant for training or inference.

    +
    +
      +
    • mask: Boolean input mask. If the layer’s call() method takes a +mask argument, its default value will be set to the mask +generated for inputs by the previous layer (if input did come +from a layer that generated a corresponding mask, i.e. if it came +from a Keras layer with masking support).

    • +
    +

  • +
+
+
Returns
+

A tensor or list/tuple of tensors.

+
+
+
+
+
+property compute_dtype
+

The dtype of the layer’s computations.

+

This is equivalent to Layer.dtype_policy.compute_dtype. Unless +mixed precision is used, this is the same as Layer.dtype, the dtype of +the weights.

+

Layers automatically cast their inputs to the compute dtype, which +causes computations and the output to be in the compute dtype as well. +This is done by the base Layer class in Layer.__call__, so you do not +have to insert these casts if implementing your own layer.

+

Layers often perform certain internal computations in higher precision +when compute_dtype is float16 or bfloat16 for numeric stability. The +output will still typically be float16 or bfloat16 in such cases.

+
+
Returns
+

The layer’s compute dtype.

+
+
+
+
+
+compute_mask(inputs, mask=None)
+

Computes an output mask tensor.

+
+
Parameters
+
    +
  • inputs – Tensor or list of tensors.

  • +
  • mask – Tensor or list of tensors.

  • +
+
+
Returns
+

+
None or a tensor (or list of tensors,

one per output tensor of the layer).

+
+
+

+
+
+
+
+
+compute_output_shape(input_shape)
+

Computes the output shape of the layer.

+

This method will cause the layer’s state to be built, if that has not +happened before. This requires that the layer will later be used with +inputs that match the input shape provided here.

+
+
Parameters
+

input_shape – Shape tuple (tuple of integers) or tf.TensorShape, +or structure of shape tuples / tf.TensorShape instances +(one per output tensor of the layer). +Shape tuples can include None for free dimensions, +instead of an integer.

+
+
Returns
+

A tf.TensorShape instance +or structure of tf.TensorShape instances.

+
+
+
+
+
+compute_output_signature(input_signature)
+

Compute the output tensor signature of the layer based on the inputs.

+

Unlike a TensorShape object, a TensorSpec object contains both shape +and dtype information for a tensor. This method allows layers to provide +output dtype information if it is different from the input dtype. +For any layer that doesn’t implement this function, +the framework will fall back to use compute_output_shape, and will +assume that the output dtype matches the input dtype.

+
+
Parameters
+

input_signature – Single TensorSpec or nested structure of TensorSpec +objects, describing a candidate input for the layer.

+
+
Returns
+

+
Single TensorSpec or nested structure of TensorSpec objects,

describing how the layer would transform the provided input.

+
+
+

+
+
Raises
+

TypeError – If input_signature contains a non-TensorSpec object.

+
+
+
+
+
+count_params()
+

Count the total number of scalars composing the weights.

+
+
Returns
+

An integer count.

+
+
Raises
+

ValueError – if the layer isn’t yet built + (in which case its weights aren’t yet defined).

+
+
+
+
+
+property dtype
+

The dtype of the layer weights.

+

This is equivalent to Layer.dtype_policy.variable_dtype. Unless +mixed precision is used, this is the same as Layer.compute_dtype, the +dtype of the layer’s computations.

+
+
+
+property dtype_policy
+

The dtype policy associated with this layer.

+

This is an instance of a tf.keras.mixed_precision.Policy.

+
+
+
+property dynamic
+

Whether the layer is dynamic (eager-only); set in the constructor.

+
+
+
+finalize_state()
+

Finalizes the layers state after updating layer weights.

+

This function can be subclassed in a layer and will be called after +updating a layer weights. It can be overridden to finalize any +additional layer state after a weight update.

+

This function will be called after weights of a layer have been restored +from a loaded model.

+
+
+
+classmethod from_config(config)
+

Creates a layer from its config.

+

This method is the reverse of get_config, +capable of instantiating the same layer from the config +dictionary. It does not handle layer connectivity +(handled by Network), nor weights (handled by set_weights).

+
+
Parameters
+

config – A Python dictionary, typically the +output of get_config.

+
+
Returns
+

A layer instance.

+
+
+
+
+
+get_build_config()
+

Returns a dictionary with the layer’s input shape.

+

This method returns a config dict that can be used by +build_from_config(config) to create all states (e.g. Variables and +Lookup tables) needed by the layer.

+

By default, the config only contains the input shape that the layer +was built with. If you’re writing a custom layer that creates state in +an unusual way, you should override this method to make sure this state +is already created when Keras attempts to load its value upon model +loading.

+
+
Returns
+

A dict containing the input shape associated with the layer.

+
+
+
+
+
+get_input_at(node_index)
+

Retrieves the input tensor(s) of a layer at a given node.

+
+
Parameters
+

node_index – Integer, index of the node +from which to retrieve the attribute. +E.g. node_index=0 will correspond to the +first input node of the layer.

+
+
Returns
+

A tensor (or list of tensors if the layer has multiple inputs).

+
+
Raises
+

RuntimeError – If called in Eager mode.

+
+
+
+
+
+get_input_mask_at(node_index)
+

Retrieves the input mask tensor(s) of a layer at a given node.

+
+
Parameters
+

node_index – Integer, index of the node +from which to retrieve the attribute. +E.g. node_index=0 will correspond to the +first time the layer was called.

+
+
Returns
+

A mask tensor +(or list of tensors if the layer has multiple inputs).

+
+
+
+
+
+get_input_shape_at(node_index)
+

Retrieves the input shape(s) of a layer at a given node.

+
+
Parameters
+

node_index – Integer, index of the node +from which to retrieve the attribute. +E.g. node_index=0 will correspond to the +first time the layer was called.

+
+
Returns
+

A shape tuple +(or list of shape tuples if the layer has multiple inputs).

+
+
Raises
+

RuntimeError – If called in Eager mode.

+
+
+
+
+
+get_output_at(node_index)
+

Retrieves the output tensor(s) of a layer at a given node.

+
+
Parameters
+

node_index – Integer, index of the node +from which to retrieve the attribute. +E.g. node_index=0 will correspond to the +first output node of the layer.

+
+
Returns
+

A tensor (or list of tensors if the layer has multiple outputs).

+
+
Raises
+

RuntimeError – If called in Eager mode.

+
+
+
+
+
+get_output_mask_at(node_index)
+

Retrieves the output mask tensor(s) of a layer at a given node.

+
+
Parameters
+

node_index – Integer, index of the node +from which to retrieve the attribute. +E.g. node_index=0 will correspond to the +first time the layer was called.

+
+
Returns
+

A mask tensor +(or list of tensors if the layer has multiple outputs).

+
+
+
+
+
+get_output_shape_at(node_index)
+

Retrieves the output shape(s) of a layer at a given node.

+
+
Parameters
+

node_index – Integer, index of the node +from which to retrieve the attribute. +E.g. node_index=0 will correspond to the +first time the layer was called.

+
+
Returns
+

A shape tuple +(or list of shape tuples if the layer has multiple outputs).

+
+
Raises
+

RuntimeError – If called in Eager mode.

+
+
+
+
+
+get_weights()
+

Returns the current weights of the layer, as NumPy arrays.

+

The weights of a layer represent the state of the layer. This function +returns both trainable and non-trainable weight values associated with +this layer as a list of NumPy arrays, which can in turn be used to load +state into similarly parameterized layers.

+

For example, a Dense layer returns a list of two values: the kernel +matrix and the bias vector. These can be used to set the weights of +another Dense layer:

+
>>> layer_a = tf.keras.layers.Dense(1,
+...   kernel_initializer=tf.constant_initializer(1.))
+>>> a_out = layer_a(tf.convert_to_tensor([[1., 2., 3.]]))
+>>> layer_a.get_weights()
+[array([[1.],
+       [1.],
+       [1.]], dtype=float32), array([0.], dtype=float32)]
+>>> layer_b = tf.keras.layers.Dense(1,
+...   kernel_initializer=tf.constant_initializer(2.))
+>>> b_out = layer_b(tf.convert_to_tensor([[10., 20., 30.]]))
+>>> layer_b.get_weights()
+[array([[2.],
+       [2.],
+       [2.]], dtype=float32), array([0.], dtype=float32)]
+>>> layer_b.set_weights(layer_a.get_weights())
+>>> layer_b.get_weights()
+[array([[1.],
+       [1.],
+       [1.]], dtype=float32), array([0.], dtype=float32)]
+
+
+
+
Returns
+

Weights values as a list of NumPy arrays.

+
+
+
+
+
+property inbound_nodes
+

Return Functional API nodes upstream of this layer.

+
+
+
+property input
+

Retrieves the input tensor(s) of a layer.

+

Only applicable if the layer has exactly one input, +i.e. if it is connected to one incoming layer.

+
+
Returns
+

Input tensor or list of input tensors.

+
+
Raises
+
    +
  • RuntimeError – If called in Eager mode.

  • +
  • AttributeError – If no inbound nodes are found.

  • +
+
+
+
+
+
+property input_mask
+

Retrieves the input mask tensor(s) of a layer.

+

Only applicable if the layer has exactly one inbound node, +i.e. if it is connected to one incoming layer.

+
+
Returns
+

Input mask tensor (potentially None) or list of input +mask tensors.

+
+
Raises
+
    +
  • AttributeError – if the layer is connected to

  • +
  • more than one incoming layers.

  • +
+
+
+
+
+
+property input_shape
+

Retrieves the input shape(s) of a layer.

+

Only applicable if the layer has exactly one input, +i.e. if it is connected to one incoming layer, or if all inputs +have the same shape.

+
+
Returns
+

Input shape, as an integer shape tuple +(or list of shape tuples, one tuple per input tensor).

+
+
Raises
+
    +
  • AttributeError – if the layer has no defined input_shape.

  • +
  • RuntimeError – if called in Eager mode.

  • +
+
+
+
+
+
+property input_spec
+

InputSpec instance(s) describing the input format for this layer.

+

When you create a layer subclass, you can set self.input_spec to +enable the layer to run input compatibility checks when it is called. +Consider a Conv2D layer: it can only be called on a single input +tensor of rank 4. As such, you can set, in __init__():

+

`python +self.input_spec = tf.keras.layers.InputSpec(ndim=4) +`

+

Now, if you try to call the layer on an input that isn’t rank 4 +(for instance, an input of shape (2,), it will raise a +nicely-formatted error:

+

` +ValueError: Input 0 of layer conv2d is incompatible with the layer: +expected ndim=4, found ndim=1. Full shape received: [2] +`

+

Input checks that can be specified via input_spec include: +- Structure (e.g. a single input, a list of 2 inputs, etc) +- Shape +- Rank (ndim) +- Dtype

+

For more information, see tf.keras.layers.InputSpec.

+
+
Returns
+

A tf.keras.layers.InputSpec instance, or nested structure thereof.

+
+
+
+
+
+load_own_variables(store)
+

Loads the state of the layer.

+

You can override this method to take full control of how the state of +the layer is loaded upon calling keras.models.load_model().

+
+
Parameters
+

store – Dict from which the state of the model will be loaded.

+
+
+
+
+
+property losses
+

List of losses added using the add_loss() API.

+

Variable regularization tensors are created when this property is +accessed, so it is eager safe: accessing losses under a +tf.GradientTape will propagate gradients back to the corresponding +variables.

+

Examples:

+
>>> class MyLayer(tf.keras.layers.Layer):
+...   def call(self, inputs):
+...     self.add_loss(tf.abs(tf.reduce_mean(inputs)))
+...     return inputs
+>>> l = MyLayer()
+>>> l(np.ones((10, 1)))
+>>> l.losses
+[1.0]
+
+
+
>>> inputs = tf.keras.Input(shape=(10,))
+>>> x = tf.keras.layers.Dense(10)(inputs)
+>>> outputs = tf.keras.layers.Dense(1)(x)
+>>> model = tf.keras.Model(inputs, outputs)
+>>> # Activity regularization.
+>>> len(model.losses)
+0
+>>> model.add_loss(tf.abs(tf.reduce_mean(x)))
+>>> len(model.losses)
+1
+
+
+
>>> inputs = tf.keras.Input(shape=(10,))
+>>> d = tf.keras.layers.Dense(10, kernel_initializer='ones')
+>>> x = d(inputs)
+>>> outputs = tf.keras.layers.Dense(1)(x)
+>>> model = tf.keras.Model(inputs, outputs)
+>>> # Weight regularization.
+>>> model.add_loss(lambda: tf.reduce_mean(d.kernel))
+>>> model.losses
+[<tf.Tensor: shape=(), dtype=float32, numpy=1.0>]
+
+
+
+
Returns
+

A list of tensors.

+
+
+
+
+
+merge_state(metrics)
+

Merges the state from one or more metrics.

+

This method can be used by distributed systems to merge the state +computed by different metric instances. Typically the state will be +stored in the form of the metric’s weights. For example, a +tf.keras.metrics.Mean metric contains a list of two weight values: a +total and a count. If there were two instances of a +tf.keras.metrics.Accuracy that each independently aggregated partial +state for an overall accuracy calculation, these two metric’s states +could be combined as follows:

+
>>> m1 = tf.keras.metrics.Accuracy()
+>>> _ = m1.update_state([[1], [2]], [[0], [2]])
+
+
+
>>> m2 = tf.keras.metrics.Accuracy()
+>>> _ = m2.update_state([[3], [4]], [[3], [4]])
+
+
+
>>> m2.merge_state([m1])
+>>> m2.result().numpy()
+0.75
+
+
+
+
Parameters
+

metrics – an iterable of metrics. The metrics must have compatible +state.

+
+
Raises
+

ValueError – If the provided iterable does not contain metrics matching + the metric’s required specifications.

+
+
+
+
+
+property metrics
+

List of metrics added using the add_metric() API.

+

Example:

+
>>> input = tf.keras.layers.Input(shape=(3,))
+>>> d = tf.keras.layers.Dense(2)
+>>> output = d(input)
+>>> d.add_metric(tf.reduce_max(output), name='max')
+>>> d.add_metric(tf.reduce_min(output), name='min')
+>>> [m.name for m in d.metrics]
+['max', 'min']
+
+
+
+
Returns
+

A list of Metric objects.

+
+
+
+
+
+property name
+

Name of the layer (string), set in the constructor.

+
+
+
+property name_scope
+

Returns a tf.name_scope instance for this class.

+
+
+
+property non_trainable_variables
+

Sequence of non-trainable variables owned by this module and its submodules.

+

Note: this method uses reflection to find variables on the current instance +and submodules. For performance reasons you may wish to cache the result +of calling this method if you don’t expect the return value to change.

+
+
Returns
+

A sequence of variables for the current module (sorted by attribute +name) followed by variables from all submodules recursively (breadth +first).

+
+
+
+
+
+property non_trainable_weights
+

List of all non-trainable weights tracked by this layer.

+

Non-trainable weights are not updated during training. They are +expected to be updated manually in call().

+
+
Returns
+

A list of non-trainable variables.

+
+
+
+
+
+property outbound_nodes
+

Return Functional API nodes downstream of this layer.

+
+
+
+property output
+

Retrieves the output tensor(s) of a layer.

+

Only applicable if the layer has exactly one output, +i.e. if it is connected to one incoming layer.

+
+
Returns
+

Output tensor or list of output tensors.

+
+
Raises
+
    +
  • AttributeError – if the layer is connected to more than one incoming + layers.

  • +
  • RuntimeError – if called in Eager mode.

  • +
+
+
+
+
+
+property output_mask
+

Retrieves the output mask tensor(s) of a layer.

+

Only applicable if the layer has exactly one inbound node, +i.e. if it is connected to one incoming layer.

+
+
Returns
+

Output mask tensor (potentially None) or list of output +mask tensors.

+
+
Raises
+
    +
  • AttributeError – if the layer is connected to

  • +
  • more than one incoming layers.

  • +
+
+
+
+
+
+property output_shape
+

Retrieves the output shape(s) of a layer.

+

Only applicable if the layer has one output, +or if all outputs have the same shape.

+
+
Returns
+

Output shape, as an integer shape tuple +(or list of shape tuples, one tuple per output tensor).

+
+
Raises
+
    +
  • AttributeError – if the layer has no defined output shape.

  • +
  • RuntimeError – if called in Eager mode.

  • +
+
+
+
+
+
+reset_state() None
+

Reset state.

+
+
+
+reset_states()
+
+
+
+result() tensorflow.python.framework.ops.Tensor
+

Return f1 score.

+
+
+
+save_own_variables(store)
+

Saves the state of the layer.

+

You can override this method to take full control of how the state of +the layer is saved upon calling model.save().

+
+
Parameters
+

store – Dict where the state of the model will be saved.

+
+
+
+
+
+set_weights(weights)
+

Sets the weights of the layer, from NumPy arrays.

+

The weights of a layer represent the state of the layer. This function +sets the weight values from numpy arrays. The weight values should be +passed in the order they are created by the layer. Note that the layer’s +weights must be instantiated before calling this function, by calling +the layer.

+

For example, a Dense layer returns a list of two values: the kernel +matrix and the bias vector. These can be used to set the weights of +another Dense layer:

+
>>> layer_a = tf.keras.layers.Dense(1,
+...   kernel_initializer=tf.constant_initializer(1.))
+>>> a_out = layer_a(tf.convert_to_tensor([[1., 2., 3.]]))
+>>> layer_a.get_weights()
+[array([[1.],
+       [1.],
+       [1.]], dtype=float32), array([0.], dtype=float32)]
+>>> layer_b = tf.keras.layers.Dense(1,
+...   kernel_initializer=tf.constant_initializer(2.))
+>>> b_out = layer_b(tf.convert_to_tensor([[10., 20., 30.]]))
+>>> layer_b.get_weights()
+[array([[2.],
+       [2.],
+       [2.]], dtype=float32), array([0.], dtype=float32)]
+>>> layer_b.set_weights(layer_a.get_weights())
+>>> layer_b.get_weights()
+[array([[1.],
+       [1.],
+       [1.]], dtype=float32), array([0.], dtype=float32)]
+
+
+
+
Parameters
+

weights – a list of NumPy arrays. The number +of arrays and their shape must match +number of the dimensions of the weights +of the layer (i.e. it should match the +output of get_weights).

+
+
Raises
+

ValueError – If the provided weights list does not match the + layer’s specifications.

+
+
+
+
+
+property stateful
+
+
+
+property submodules
+

Sequence of all sub-modules.

+

Submodules are modules which are properties of this module, or found as +properties of modules which are properties of this module (and so on).

+
>>> a = tf.Module()
+>>> b = tf.Module()
+>>> c = tf.Module()
+>>> a.b = b
+>>> b.c = c
+>>> list(a.submodules) == [b, c]
+True
+>>> list(b.submodules) == [c]
+True
+>>> list(c.submodules) == []
+True
+
+
+
+
Returns
+

A sequence of all submodules.

+
+
+
+
+
+property supports_masking
+

Whether this layer supports computing a mask using compute_mask.

+
+
+
+property trainable
+
+
+
+property trainable_variables
+

Sequence of trainable variables owned by this module and its submodules.

+

Note: this method uses reflection to find variables on the current instance +and submodules. For performance reasons you may wish to cache the result +of calling this method if you don’t expect the return value to change.

+
+
Returns
+

A sequence of variables for the current module (sorted by attribute +name) followed by variables from all submodules recursively (breadth +first).

+
+
+
+
+
+property trainable_weights
+

List of all trainable weights tracked by this layer.

+

Trainable weights are updated via gradient descent during training.

+
+
Returns
+

A list of trainable variables.

+
+
+
+
+
+update_state(y_true: tf.Tensor, y_pred: tf.Tensor, sample_weight: tf.Tensor | None = None) None
+

Update state.

+
+
+
+property updates
+
+
+
+property variable_dtype
+

Alias of Layer.dtype, the dtype of the weights.

+
+
+
+property variables
+

Returns the list of all layer variables/weights.

+

Alias of self.weights.

+

Note: This will not track the weights of nested tf.Modules that are +not themselves Keras layers.

+
+
Returns
+

A list of variables.

+
+
+
+
+
+property weights
+

Returns the list of all layer variables/weights.

+
+
Returns
+

A list of variables.

+
+
+
+
+
+classmethod with_name_scope(method)
+

Decorator to automatically enter the module name scope.

+
>>> class MyModule(tf.Module):
+...   @tf.Module.with_name_scope
+...   def __call__(self, x):
+...     if not hasattr(self, 'w'):
+...       self.w = tf.Variable(tf.random.normal([x.shape[1], 3]))
+...     return tf.matmul(x, self.w)
+
+
+

Using the above module would produce `tf.Variable`s and `tf.Tensor`s whose +names included the module name:

+
>>> mod = MyModule()
+>>> mod(tf.ones([1, 2]))
+<tf.Tensor: shape=(1, 3), dtype=float32, numpy=..., dtype=float32)>
+>>> mod.w
+<tf.Variable 'my_module/Variable:0' shape=(2, 3) dtype=float32,
+numpy=..., dtype=float32)>
+
+
+
+
Parameters
+

method – The method to wrap.

+
+
Returns
+

The original method wrapped such that it enters the module’s name scope.

+
+
+
+
+
+get_config() dict
+

Get configuration.

+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.labelers.regex_model.html b/docs/0.10.5/html/dataprofiler.labelers.regex_model.html new file mode 100644 index 000000000..ef3488781 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.labelers.regex_model.html @@ -0,0 +1,487 @@ + + + + + + + + + Regex Model - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Regex Model

+

Contains class for regex data labeling model.

+
+
+class dataprofiler.labelers.regex_model.RegexModel(label_mapping: dict, parameters: Optional[dict] = None)
+

Bases: dataprofiler.labelers.base_model.BaseModel

+

Class for regex data labeling model.

+

Initialize Regex Model.

+
+
Example regex_patterns:
+
regex_patterns = {
+
“LABEL_1”: [

“LABEL_1_pattern_1”, +“LABEL_1_pattern_2”, +…

+
+
+

], +“LABEL_2”: [

+
+

“LABEL_2_pattern_1”, +“LABEL_2_pattern_2”, +…

+
+
+
+

}

+
+
Example encapsulators:
+
encapsulators = {

‘start’: r’(?<![w.$%-])’, +‘end’: r’(?:(?=(b|[ ]))|(?=[^w%$]([^w]|$))|$)’,

+
+
+

}

+
+
+
+
Parameters
+
    +
  • label_mapping (dict) – maps labels to their encoded integers

  • +
  • parameters (dict) –

    Contains all the appropriate parameters for the model. +Possible parameters are:

    +
    +

    max_length, max_num_chars, dim_embed

    +
    +

  • +
+
+
Returns
+

None

+
+
+
+
+reset_weights() None
+

Reset weights.

+
+
+
+predict(data: Union[pandas.core.frame.DataFrame, pandas.core.series.Series, numpy.ndarray], batch_size: Optional[int] = None, show_confidences: bool = False, verbose: bool = True) dict
+

Apply the regex patterns (within regex_model) to the input_string.

+

Create predictions for all matching patterns. Each pattern has an +associated entity and the predictions of each character within the +string are given a True or False identification for each entity. All +characters not identified by ANY of the regex patterns in the +pattern_dict are considered background characters, and are replaced with +the default_label value.

+
+
Parameters
+
    +
  • data (iterator) – list of strings to predict upon

  • +
  • batch_size (N/A) – does not impact this model and should be fixed to not +be required.

  • +
  • show_confidences – whether user wants prediction confidences

  • +
  • verbose (bool) – Flag to determine whether to print status or not

  • +
+
+
Returns
+

char level predictions and confidences

+
+
Return type
+

dict

+
+
+
+
+
+classmethod load_from_disk(dirpath: str) dataprofiler.labelers.regex_model.RegexModel
+

Load whole model from disk with weights.

+
+
Parameters
+

dirpath (str) – directory path where you want to load the model from

+
+
Returns
+

None

+
+
+
+
+
+save_to_disk(dirpath: str) None
+

Save whole model to disk with weights.

+
+
Parameters
+

dirpath (str) – directory path where you want to save the model to

+
+
Returns
+

None

+
+
+
+
+
+add_label(label: str, same_as: str | None = None) None
+

Add a label to the data labeler.

+
+
Parameters
+
    +
  • label (str) – new label being added to the data labeler

  • +
  • same_as (str) – label to have the same encoding index as for multi-label +to single encoding index.

  • +
+
+
Returns
+

None

+
+
+
+
+
+classmethod get_class(class_name: str) type[BaseModel] | None
+

Get subclasses.

+
+
+
+get_parameters(param_list: list[str] | None = None) dict
+

Return a dict of parameters from the model given a list.

+
+
Parameters
+

param_list (List[str]) – list of parameters to retrieve from the model.

+
+
Returns
+

dict of parameters

+
+
+
+
+
+classmethod help() None
+

Help describe alterable parameters.

+
+
Returns
+

None

+
+
+
+
+
+property label_mapping: dict
+

Return mapping of labels to their encoded values.

+
+
+
+property labels: list
+

Retrieve the label.

+
+
Returns
+

list of labels

+
+
+
+
+
+property num_labels: int
+

Return max label mapping.

+
+
+
+requires_zero_mapping: bool = False
+
+
+
+property reverse_label_mapping: dict
+

Return reversed order of current labels.

+

Useful for when needed to extract Labels via indices.

+
+
+
+set_label_mapping(label_mapping: list[str] | dict[str, int]) None
+

Set the labels for the model.

+
+
Parameters
+

label_mapping (Union[list, dict]) – label mapping of the model or list of labels to be +converted into the label mapping

+
+
Returns
+

None

+
+
+
+
+
+set_params(**kwargs: Any) None
+

Set the parameters if they exist given kwargs.

+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.labelers.utils.html b/docs/0.10.5/html/dataprofiler.labelers.utils.html new file mode 100644 index 000000000..a458cefa7 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.labelers.utils.html @@ -0,0 +1,309 @@ + + + + + + + + + Utils - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Utils

+

Contains functions for checking for installations/dependencies.

+
+
+dataprofiler.labelers.utils.warn_missing_module(labeler_function: str, module_name: str) None
+

Return a warning if a given graph module doesn’t exist.

+
+
Parameters
+
    +
  • labeler_function (str) – Name of the graphing function

  • +
  • module_name (str) – module name that was missing

  • +
+
+
+
+
+
+dataprofiler.labelers.utils.require_module(names: List[str]) Callable
+

Check if a set of modules exists in sys.modules prior to running function.

+

If they do not, give a user a warning and do not run the +function.

+
+
Parameters
+

names (list[str]) – list of module names to check for in sys.modules

+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.base_column_profilers.html b/docs/0.10.5/html/dataprofiler.profilers.base_column_profilers.html new file mode 100644 index 000000000..9e034a785 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.base_column_profilers.html @@ -0,0 +1,458 @@ + + + + + + + + + Base Column Profilers - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Base Column Profilers

+

Contains parent column profiler class.

+
+
+class dataprofiler.profilers.base_column_profilers.BaseColumnProfiler(name: str | None, options: BaseOption | None = None)
+

Bases: Generic[dataprofiler.profilers.base_column_profilers.BaseColumnProfilerT]

+

Abstract class for profiling a column of data.

+

Initialize base class properties for the subclass.

+
+
Parameters
+

name (String) – Name of the dataset

+
+
+
+
+col_type = None
+
+
+
+diff(other_profile: dataprofiler.profilers.base_column_profilers.BaseColumnProfilerT, options: Optional[dict] = None) dict
+

Find the differences for columns.

+
+
Parameters
+

other_profile (BaseColumnProfiler) – profile to find the difference with

+
+
Returns
+

the stat differences

+
+
Return type
+

dict

+
+
+
+
+
+abstract update(df_series: pandas.core.frame.DataFrame) dataprofiler.profilers.base_column_profilers.BaseColumnProfiler
+

Update the profile.

+
+
Parameters
+

df_series (Pandas Dataframe) – Data to profile.

+
+
+
+
+
+abstract property profile: dict
+

Return the profile of the column.

+
+
+
+abstract report(remove_disabled_flag: bool = False) dict
+

Return report.

+
+
Parameters
+

remove_disabled_flag (boolean) – flag to determine if disabled +options should be excluded in the report.

+
+
+
+
+
+classmethod load_from_dict(data: dict[str, Any], config: dict | None = None) BaseColumnProfilerT
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

BaseColumnProfiler

+
+
+
+
+
+
+class dataprofiler.profilers.base_column_profilers.BaseColumnPrimitiveTypeProfiler(name: str | None)
+

Bases: dataprofiler.profilers.base_column_profilers.BaseColumnProfiler[dataprofiler.profilers.base_column_profilers.BaseColumnPrimitiveTypeProfilerT]

+

Abstract class for profiling primative data type for col of data.

+

Initialize base class properties for the subclass.

+
+
Parameters
+

name (String) – Name of the data

+
+
+
+
+sample_size: int
+
+
+
+col_type = None
+
+
+
+diff(other_profile: dataprofiler.profilers.base_column_profilers.BaseColumnProfilerT, options: Optional[dict] = None) dict
+

Find the differences for columns.

+
+
Parameters
+

other_profile (BaseColumnProfiler) – profile to find the difference with

+
+
Returns
+

the stat differences

+
+
Return type
+

dict

+
+
+
+
+
+classmethod load_from_dict(data: dict[str, Any], config: dict | None = None) BaseColumnProfilerT
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

BaseColumnProfiler

+
+
+
+
+
+abstract property profile: dict
+

Return the profile of the column.

+
+
+
+abstract report(remove_disabled_flag: bool = False) dict
+

Return report.

+
+
Parameters
+

remove_disabled_flag (boolean) – flag to determine if disabled +options should be excluded in the report.

+
+
+
+
+
+abstract update(df_series: pandas.core.frame.DataFrame) dataprofiler.profilers.base_column_profilers.BaseColumnProfiler
+

Update the profile.

+
+
Parameters
+

df_series (Pandas Dataframe) – Data to profile.

+
+
+
+
+
+name: str | None
+
+
+
+metadata: dict
+
+
+
+times: dict
+
+
+
+thread_safe: bool
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.categorical_column_profile.html b/docs/0.10.5/html/dataprofiler.profilers.categorical_column_profile.html new file mode 100644 index 000000000..e24dacc18 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.categorical_column_profile.html @@ -0,0 +1,450 @@ + + + + + + + + + Categorical Column Profile - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Categorical Column Profile

+

Contains class for categorical column profiler.

+
+
+class dataprofiler.profilers.categorical_column_profile.CategoricalColumn(name: str | None, options: CategoricalOptions = None)
+

Bases: dataprofiler.profilers.base_column_profilers.BaseColumnProfiler[CategoricalColumn]

+

Categorical column profile subclass of BaseColumnProfiler.

+

Represents a column int the dataset which is a categorical column.

+

Initialize column base properties and itself.

+
+
Parameters
+

name (String) – Name of data

+
+
+
+
+type = 'category'
+
+
+
+property gini_impurity: float | None
+

Return Gini Impurity.

+

Gini Impurity is a way to calculate +likelihood of an incorrect classification of a new instance of +a random variable.

+

G = Σ(i=1; J): P(i) * (1 - P(i)), where i is the category classes. +We are traversing through categories and calculating with the column

+
+
Returns
+

None or Gini Impurity probability

+
+
+
+
+
+property unalikeability: float | None
+

Return Unlikeability.

+

Unikeability checks for “how often observations differ from one another” +Reference: Perry, M. and Kader, G. Variation as Unalikeability. +Teaching Statistics, Vol. 27, No. 2 (2005), pp. 58-60.

+

U = Σ(i=1,n)Σ(j=1,n): (Cij)/(n**2-n) +Cij = 1 if i!=j, 0 if i=j

+
+
Returns
+

None or unlikeability probability

+
+
+
+
+
+diff(other_profile: dataprofiler.profilers.categorical_column_profile.CategoricalColumn, options: Optional[dict] = None) dict
+

Find the differences for CategoricalColumns.

+
+
Parameters
+

other_profile (CategoricalColumn) – profile to find the difference with

+
+
Returns
+

the CategoricalColumn differences

+
+
Return type
+

dict

+
+
+
+
+
+report(remove_disabled_flag: bool = False) dict
+

Return report.

+

This is a private abstract method.

+
+
Parameters
+

remove_disabled_flag (boolean) – flag to determine if disabled +options should be excluded in the report.

+
+
+
+
+
+classmethod load_from_dict(data: dict, config: dict | None = None)
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

CategoricalColumn

+
+
+
+
+
+property profile: dict
+

Return the profile of the column.

+

For categorical_count, it will display the top k categories most +frequently occurred in descending order.

+
+
+
+property categories: list
+

Return categories.

+
+
+
+property categorical_counts: dict
+

Return counts of each category.

+
+
+
+property unique_ratio: float
+

Return ratio of unique categories to sample_size.

+
+
+
+property unique_count: int
+

Return ratio of unique categories to sample_size.

+
+
+
+property is_match: bool
+

Return true if column is categorical.

+
+
+
+col_type = None
+
+
+
+name: str | None
+
+
+
+sample_size: int
+
+
+
+metadata: dict
+
+
+
+times: dict
+
+
+
+thread_safe: bool
+
+
+
+update(df_series: pandas.core.series.Series) dataprofiler.profilers.categorical_column_profile.CategoricalColumn
+

Update the column profile.

+
+
Parameters
+

df_series (pandas.core.series.Series) – Data to profile.

+
+
Returns
+

updated CategoricalColumn

+
+
Return type
+

CategoricalColumn

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.column_profile_compilers.html b/docs/0.10.5/html/dataprofiler.profilers.column_profile_compilers.html new file mode 100644 index 000000000..c46f6a5c0 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.column_profile_compilers.html @@ -0,0 +1,678 @@ + + + + + + + + + Column Profile Compilers - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Column Profile Compilers

+

For generating a report.

+
+
+class dataprofiler.profilers.column_profile_compilers.BaseCompiler(df_series: Optional[pandas.core.series.Series] = None, options: Optional[dataprofiler.profilers.profiler_options.StructuredOptions] = None, pool: Optional[multiprocessing.pool.Pool] = None)
+

Bases: Generic[dataprofiler.profilers.column_profile_compilers.BaseCompilerT]

+

Abstract class for generating a report.

+

Initialize BaseCompiler object.

+
+
+abstract report(remove_disabled_flag: bool = False) dict
+

Return report.

+
+
Parameters
+

remove_disabled_flag (boolean) – flag to determine if disabled options should be excluded in report.

+
+
+
+
+
+property profile: dict
+

Return the profile of the column.

+
+
+
+diff(other: dataprofiler.profilers.column_profile_compilers.BaseCompilerT, options: Optional[dict] = None) dict
+

Find the difference between 2 compilers and returns the report.

+
+
Parameters
+

other (BaseCompiler) – profile compiler finding the difference with this one.

+
+
Returns
+

difference of the profiles

+
+
Return type
+

dict

+
+
+
+
+
+update_profile(df_series: Series, pool: Pool = None) BaseCompiler | None
+

Update the profiles from the data frames.

+
+
Parameters
+
    +
  • df_series (pandas.core.series.Series) – a given column, assume df_series in str

  • +
  • pool (multiprocessing.Pool) – pool to utilized for multiprocessing

  • +
+
+
Returns
+

Self

+
+
Return type
+

BaseCompiler

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseCompiler
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Compiler with attributes populated.

+
+
Return type
+

BaseCompiler

+
+
+
+
+
+
+class dataprofiler.profilers.column_profile_compilers.ColumnPrimitiveTypeProfileCompiler(df_series: Optional[pandas.core.series.Series] = None, options: Optional[dataprofiler.profilers.profiler_options.StructuredOptions] = None, pool: Optional[multiprocessing.pool.Pool] = None)
+

Bases: dataprofiler.profilers.column_profile_compilers.BaseCompiler[ColumnPrimitiveTypeProfileCompiler]

+

For generating ordered column profile reports.

+

Initialize BaseCompiler object.

+
+
+report(remove_disabled_flag: bool = False) dict
+

Return report.

+
+
Parameters
+

remove_disabled_flag (boolean) – flag to determine if disabled options should be excluded in report.

+
+
+
+
+
+property profile: dict
+

Return the profile of the column.

+
+
+
+property selected_data_type: str | None
+

Find the selected data_type in a primitive compiler.

+
+
Returns
+

name of the selected data type

+
+
Return type
+

str

+
+
+
+
+
+diff(other: dataprofiler.profilers.column_profile_compilers.ColumnPrimitiveTypeProfileCompiler, options: Optional[dict] = None) dict
+

Find the difference between 2 compilers and returns the report.

+
+
Parameters
+

other (ColumnPrimitiveTypeProfileCompiler) – profile compiler finding the difference with this one.

+
+
Returns
+

difference of the profiles

+
+
Return type
+

dict

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseCompiler
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Compiler with attributes populated.

+
+
Return type
+

BaseCompiler

+
+
+
+
+
+update_profile(df_series: Series, pool: Pool = None) BaseCompiler | None
+

Update the profiles from the data frames.

+
+
Parameters
+
    +
  • df_series (pandas.core.series.Series) – a given column, assume df_series in str

  • +
  • pool (multiprocessing.Pool) – pool to utilized for multiprocessing

  • +
+
+
Returns
+

Self

+
+
Return type
+

BaseCompiler

+
+
+
+
+
+
+class dataprofiler.profilers.column_profile_compilers.ColumnStatsProfileCompiler(df_series: Optional[pandas.core.series.Series] = None, options: Optional[dataprofiler.profilers.profiler_options.StructuredOptions] = None, pool: Optional[multiprocessing.pool.Pool] = None)
+

Bases: dataprofiler.profilers.column_profile_compilers.BaseCompiler[ColumnStatsProfileCompiler]

+

For generating OrderColumn and CategoricalColumn reports.

+

Initialize BaseCompiler object.

+
+
+report(remove_disabled_flag: bool = False) dict
+

Return report.

+
+
Parameters
+

remove_disabled_flag (boolean) – flag to determine if disabled options should be excluded in report.

+
+
+
+
+
+diff(other: dataprofiler.profilers.column_profile_compilers.ColumnStatsProfileCompiler, options: Optional[dict] = None) dict
+

Find the difference between 2 compilers and returns the report.

+
+
Parameters
+

other (ColumnStatsProfileCompiler) – profile compiler finding the difference with this one.

+
+
Returns
+

difference of the profiles

+
+
Return type
+

dict

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseCompiler
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Compiler with attributes populated.

+
+
Return type
+

BaseCompiler

+
+
+
+
+
+property profile: dict
+

Return the profile of the column.

+
+
+
+update_profile(df_series: Series, pool: Pool = None) BaseCompiler | None
+

Update the profiles from the data frames.

+
+
Parameters
+
    +
  • df_series (pandas.core.series.Series) – a given column, assume df_series in str

  • +
  • pool (multiprocessing.Pool) – pool to utilized for multiprocessing

  • +
+
+
Returns
+

Self

+
+
Return type
+

BaseCompiler

+
+
+
+
+
+
+class dataprofiler.profilers.column_profile_compilers.ColumnDataLabelerCompiler(df_series: Optional[pandas.core.series.Series] = None, options: Optional[dataprofiler.profilers.profiler_options.StructuredOptions] = None, pool: Optional[multiprocessing.pool.Pool] = None)
+

Bases: dataprofiler.profilers.column_profile_compilers.BaseCompiler[ColumnDataLabelerCompiler]

+

For generating DataLabelerColumn report.

+

Initialize BaseCompiler object.

+
+
+report(remove_disabled_flag: bool = False) dict
+

Return report.

+
+
Parameters
+

remove_disabled_flag (boolean) – flag to determine if disabled options should be excluded in report.

+
+
+
+
+
+diff(other: dataprofiler.profilers.column_profile_compilers.ColumnDataLabelerCompiler, options: Optional[dict] = None) dict
+

Find the difference between 2 compilers and return the report.

+
+
Parameters
+
    +
  • other (ColumnDataLabelerCompiler) – profile compiler finding the difference with this one.

  • +
  • options (dict) – options to change results of the difference

  • +
+
+
Returns
+

difference of the profiles

+
+
Return type
+

dict

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseCompiler
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Compiler with attributes populated.

+
+
Return type
+

BaseCompiler

+
+
+
+
+
+property profile: dict
+

Return the profile of the column.

+
+
+
+update_profile(df_series: Series, pool: Pool = None) BaseCompiler | None
+

Update the profiles from the data frames.

+
+
Parameters
+
    +
  • df_series (pandas.core.series.Series) – a given column, assume df_series in str

  • +
  • pool (multiprocessing.Pool) – pool to utilized for multiprocessing

  • +
+
+
Returns
+

Self

+
+
Return type
+

BaseCompiler

+
+
+
+
+
+
+class dataprofiler.profilers.column_profile_compilers.UnstructuredCompiler(df_series: Optional[pandas.core.series.Series] = None, options: Optional[dataprofiler.profilers.profiler_options.StructuredOptions] = None, pool: Optional[multiprocessing.pool.Pool] = None)
+

Bases: dataprofiler.profilers.column_profile_compilers.BaseCompiler[UnstructuredCompiler]

+

For generating TextProfiler and UnstructuredLabelerProfile reports.

+

Initialize BaseCompiler object.

+
+
+report(remove_disabled_flag: bool = False) dict
+

Report profile attrs of class and potentially pop val from self.profile.

+
+
+
+diff(other: dataprofiler.profilers.column_profile_compilers.UnstructuredCompiler, options: Optional[dict] = None) dict
+

Find the difference between 2 compilers and return the report.

+
+
Parameters
+
    +
  • other (UnstructuredCompiler) – profile compiler finding the difference with this one.

  • +
  • options (dict) – options to impact the results of the diff

  • +
+
+
Returns
+

difference of the profiles

+
+
Return type
+

dict

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseCompiler
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Compiler with attributes populated.

+
+
Return type
+

BaseCompiler

+
+
+
+
+
+property profile: dict
+

Return the profile of the column.

+
+
+
+update_profile(df_series: Series, pool: Pool = None) BaseCompiler | None
+

Update the profiles from the data frames.

+
+
Parameters
+
    +
  • df_series (pandas.core.series.Series) – a given column, assume df_series in str

  • +
  • pool (multiprocessing.Pool) – pool to utilized for multiprocessing

  • +
+
+
Returns
+

Self

+
+
Return type
+

BaseCompiler

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.data_labeler_column_profile.html b/docs/0.10.5/html/dataprofiler.profilers.data_labeler_column_profile.html new file mode 100644 index 000000000..7a417e4b6 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.data_labeler_column_profile.html @@ -0,0 +1,447 @@ + + + + + + + + + Data Labeler Column Profile - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Data Labeler Column Profile

+

Contains class for for profiling data labeler col.

+
+
+class dataprofiler.profilers.data_labeler_column_profile.DataLabelerColumn(name: str | None, options: DataLabelerOptions = None)
+

Bases: dataprofiler.profilers.base_column_profilers.BaseColumnProfiler[DataLabelerColumn]

+

Sublass of BaseColumnProfiler for profiling data labeler col.

+

Initialize Data Label profiling for structured datasets.

+
+
Parameters
+
    +
  • name (String) – name of column being profiled

  • +
  • options (DataLabelerOptions) – Options for the data labeler column

  • +
+
+
+
+
+type = 'data_labeler'
+
+
+
+thread_safe: bool
+
+
+
+static assert_equal_conditions(data_labeler: dataprofiler.profilers.data_labeler_column_profile.DataLabelerColumn, data_labeler2: dataprofiler.profilers.data_labeler_column_profile.DataLabelerColumn) None
+

Ensure data labelers have the same values. Raise error otherwise.

+
+
Parameters
+
+
+
Returns
+

None

+
+
+
+
+
+property reverse_label_mapping: dict
+

Return reverse label mapping.

+
+
+
+property possible_data_labels: list
+

Return possible data labels.

+
+
+
+property rank_distribution: dict
+

Return rank distribution.

+
+
+
+property sum_predictions: numpy.ndarray
+

Sum predictions.

+
+
+
+property data_label: str | None
+

Return data labels which best fit data it has seen based on DataLabeler used.

+

Data labels must be within the minimum probability +differential of the top predicted value. If nothing is more than +minimum top label value, it says it could not determine the data label.

+
+
+
+property avg_predictions: dict[str, float] | None
+

Average all sample predictions for each data label.

+
+
+
+property label_representation: dict[str, float] | None
+

Represent label found within the dataset based on ranked voting.

+

When top_k=1, this is simply the distribution of data labels found +within the dataset.

+
+
+
+property profile: dict
+

Return the profile of the column.

+
+
+
+classmethod load_from_dict(data, config: dict | None = None) DataLabelerColumn
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

DataLabelerColumn

+
+
+
+
+
+report(remove_disabled_flag: bool = False) dict
+

Return report.

+

Private abstract method.

+
+
Parameters
+

remove_disabled_flag (boolean) – flag to determine if disabled +options should be excluded in the report.

+
+
+
+
+
+col_type = None
+
+
+
+diff(other_profile: dataprofiler.profilers.data_labeler_column_profile.DataLabelerColumn, options: Optional[dict] = None) dict
+

Generate differences between the orders of two DataLabeler columns.

+
+
Returns
+

Dict containing the differences between orders in their

+
+
+

appropriate output formats +:rtype: dict

+
+
+
+name: str | None
+
+
+
+sample_size: int
+
+
+
+metadata: dict
+
+
+
+times: dict
+
+
+
+update(df_series: pandas.core.series.Series) dataprofiler.profilers.data_labeler_column_profile.DataLabelerColumn
+

Update the column profile.

+
+
Parameters
+

df_series (pandas.core.series.Series) – df series

+
+
Returns
+

updated DataLabelerColumn

+
+
Return type
+

DataLabelerColumn

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.datetime_column_profile.html b/docs/0.10.5/html/dataprofiler.profilers.datetime_column_profile.html new file mode 100644 index 000000000..2c2aba748 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.datetime_column_profile.html @@ -0,0 +1,406 @@ + + + + + + + + + Datetime Column Profile - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Datetime Column Profile

+

Contains class for profiling datetime column.

+
+
+class dataprofiler.profilers.datetime_column_profile.DateTimeColumn(name: str | None, options: DateTimeOptions = None)
+

Bases: dataprofiler.profilers.base_column_profilers.BaseColumnPrimitiveTypeProfiler[DateTimeColumn]

+

Datetime column profile subclass of BaseColumnProfiler.

+

Represents a column int the dataset which is a datetime column.

+

Initialize it and the column base properties.

+
+
Parameters
+
    +
  • name (String) – Name of the data

  • +
  • options (DateTimeOptions) – Options for the datetime column

  • +
+
+
+
+
+type = 'datetime'
+
+
+
+report(remove_disabled_flag: bool = False) dict
+

Return report.

+

Private abstract method.

+
+
Parameters
+

remove_disabled_flag (boolean) – flag to determine if disabled +options should be excluded in the report.

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None)
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

DateTimeColumn

+
+
+
+
+
+property profile: dict
+

Return the profile of the column.

+
+
+
+property data_type_ratio: float | None
+

Calculate the ratio of samples which match this data type.

+
+
Returns
+

ratio of data type

+
+
Return type
+

float

+
+
+
+
+
+diff(other_profile: dataprofiler.profilers.datetime_column_profile.DateTimeColumn, options: Optional[dict] = None) dict
+

Generate differences between max, min, and formats of two DateTime cols.

+
+
Returns
+

Dict containing the differences between max, min, and format in their

+
+
+

appropriate output formats +:rtype: dict

+
+
+
+update(df_series: pandas.core.series.Series) dataprofiler.profilers.datetime_column_profile.DateTimeColumn
+

Update the column profile.

+
+
Parameters
+

df_series (pandas.core.series.Series) – df series

+
+
Returns
+

None

+
+
+
+
+
+col_type = None
+
+
+
+name: str | None
+
+
+
+sample_size: int
+
+
+
+metadata: dict
+
+
+
+times: dict
+
+
+
+thread_safe: bool
+
+
+
+match_count: int
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.float_column_profile.html b/docs/0.10.5/html/dataprofiler.profilers.float_column_profile.html new file mode 100644 index 000000000..ab8324f38 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.float_column_profile.html @@ -0,0 +1,547 @@ + + + + + + + + + Float Column Profile - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Float Column Profile

+

Float profile analysis for individual col within structured profiling.

+
+
+class dataprofiler.profilers.float_column_profile.FloatColumn(name: str | None, options: FloatOptions = None)
+

Bases: dataprofiler.profilers.numerical_column_stats.NumericStatsMixin[FloatColumn], dataprofiler.profilers.base_column_profilers.BaseColumnPrimitiveTypeProfiler[FloatColumn]

+

Float column profile mixin with numerical stats.

+

Represents a column in the dataset which is a float column.

+

Initialize column base properties and itself.

+
+
Parameters
+
    +
  • name (String) – Name of the data

  • +
  • options (FloatOptions) – Options for the float column

  • +
+
+
+
+
+type: str | None = 'float'
+
+
+
+diff(other_profile: dataprofiler.profilers.float_column_profile.FloatColumn, options: Optional[dict] = None) dict
+

Find the differences for FloatColumns.

+
+
Parameters
+

other_profile (FloatColumn) – profile to find the difference with

+
+
Returns
+

the FloatColumn differences

+
+
Return type
+

dict

+
+
+
+
+
+report(remove_disabled_flag: bool = False) dict
+

Report profile attribute of class; potentially pop val from self.profile.

+
+
+
+classmethod load_from_dict(data, config: dict | None = None)
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

FloatColumn

+
+
+
+
+
+property profile: dict
+

Return the profile of the column.

+
+
Returns
+

+
+
+
+
+
+property precision: dict[str, float | None]
+

Report statistics on the significant figures of each element in the data.

+
+
Returns
+

Precision statistics

+
+
Return type
+

dict

+
+
+
+
+
+property data_type_ratio: float | None
+

Calculate the ratio of samples which match this data type.

+
+
Returns
+

ratio of data type

+
+
Return type
+

float

+
+
+
+
+
+col_type = None
+
+
+
+static is_float(x: str) bool
+

Return True if x is float.

+

For “0.80” this function returns True +For “1.00” this function returns True +For “1” this function returns True

+
+
Parameters
+

x (str) – string to test

+
+
Returns
+

if is float or not

+
+
Return type
+

bool

+
+
+
+
+
+static is_int(x: str) bool
+

Return True if x is integer.

+

For “0.80” This function returns False +For “1.00” This function returns True +For “1” this function returns True

+
+
Parameters
+

x (str) – string to test

+
+
Returns
+

if is integer or not

+
+
Return type
+

bool

+
+
+
+
+
+property kurtosis: float | np.float64
+

Return kurtosis value.

+
+
+
+property mean: float | np.float64
+

Return mean value.

+
+
+
+property median: float
+

Estimate the median of the data.

+
+
Returns
+

the median

+
+
Return type
+

float

+
+
+
+
+
+property median_abs_deviation: float | np.float64
+

Get median absolute deviation estimated from the histogram of the data.

+
+

Subtract bin edges from the median value +Fold the histogram to positive and negative parts around zero +Impose the two bin edges from the two histogram +Calculate the counts for the two histograms with the imposed bin edges +Superimpose the counts from the two histograms +Interpolate the median absolute deviation from the superimposed counts

+
+
+
Returns
+

median absolute deviation

+
+
+
+
+
+property mode: list
+

Find an estimate for the mode[s] of the data.

+
+
Returns
+

the mode(s) of the data

+
+
Return type
+

list(float)

+
+
+
+
+
+static np_type_to_type(val: Any) Any
+

Convert numpy variables to base python type variables.

+
+
Parameters
+

val (numpy type or base type) – value to check & change

+
+
Return val
+

base python type

+
+
Rtype val
+

int or float

+
+
+
+
+
+property skewness: float | np.float64
+

Return skewness value.

+
+
+
+property stddev: float | np.float64
+

Return stddev value.

+
+
+
+update(df_series: pandas.core.series.Series) dataprofiler.profilers.float_column_profile.FloatColumn
+

Update the column profile.

+
+
Parameters
+

df_series (pandas.core.series.Series) – df series

+
+
Returns
+

updated FloatColumn

+
+
Return type
+

FloatColumn

+
+
+
+
+
+property variance: float | np.float64
+

Return variance.

+
+
+
+name: str | None
+
+
+
+sample_size: int
+
+
+
+metadata: dict
+
+
+
+times: dict
+
+
+
+thread_safe: bool
+
+
+
+match_count: int
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.graph_profiler.html b/docs/0.10.5/html/dataprofiler.profilers.graph_profiler.html new file mode 100644 index 000000000..e68d6ef1a --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.graph_profiler.html @@ -0,0 +1,383 @@ + + + + + + + + + Graph Profiler - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Graph Profiler

+

Class and functions to calculate and profile properties of graph data.

+
+
+class dataprofiler.profilers.graph_profiler.GraphProfiler(data: nx.Graph | GraphData, options: ProfilerOptions = None)
+

Bases: object

+

GraphProfiler class.

+

Creates a profile describing a graph dataset +Statistical properties of graph

+

Initialize Graph Profiler.

+
+
Parameters
+
+
+
+
+
+times: dict
+

Properties

+
+
+
+property profile: dict
+

Return the profile of the graph.

+
+
Returns
+

the profile of the graph in data

+
+
+
+
+
+diff(other_profile: dataprofiler.profilers.graph_profiler.GraphProfiler, options: Optional[dict] = None) dict
+

Find the differences for two graph profiles.

+
+
Parameters
+
    +
  • other_profile (GraphProfiler) – profile to find the difference with

  • +
  • options (dict) – options for diff output

  • +
+
+
Returns
+

the difference between profiles

+
+
Return type
+

dict

+
+
+
+
+
+report(remove_disabled_flag: bool = False) dict
+

Report on profile attribute of the class.

+

Pop value from self.profile if key not in self.__calculations

+
+
+
+update(graph: networkx.classes.graph.Graph) dataprofiler.profilers.graph_profiler.GraphProfiler
+

Update the graph profile.

+
+
Parameters
+

data (NetworkX Graph) – networkx graph

+
+
Returns
+

None

+
+
+
+
+
+save(filepath: Optional[str] = None) None
+

Save profiler to disk.

+
+
Parameters
+

filepath (String) – Path of file to save to

+
+
Returns
+

None

+
+
+
+
+
+classmethod load(filepath: str) dataprofiler.profilers.graph_profiler.GraphProfiler
+

Load profiler from disk.

+
+
Parameters
+

filepath (String) – Path of file to load from

+
+
Returns
+

GraphProfiler being loaded

+
+
Return type
+

GraphProfiler

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.helpers.html b/docs/0.10.5/html/dataprofiler.profilers.helpers.html new file mode 100644 index 000000000..668b1bdd6 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.helpers.html @@ -0,0 +1,334 @@ + + + + + + + + + Helpers - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Helpers

+
+

Modules

+
+
+ +

This package provides helper functions for generating reports.

+
+
+dataprofiler.profilers.helpers.calculate_quantiles(num_quantile_groups: int, quantiles: dict) dict
+

Calculate and return quantiles.

+
+
Parameters
+
    +
  • num_quantile_groups (int) – number of quantile groups

  • +
  • quantiles (dict[int, int]) – original quantiles

  • +
+
+
Returns
+

calculated quantiles

+
+
Return type
+

dict[int, int]

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.helpers.report_helpers.html b/docs/0.10.5/html/dataprofiler.profilers.helpers.report_helpers.html new file mode 100644 index 000000000..55740d02c --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.helpers.report_helpers.html @@ -0,0 +1,325 @@ + + + + + + + + + Report Helpers - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Report Helpers

+

Contains helper functions for generating report.

+
+
+dataprofiler.profilers.helpers.report_helpers.calculate_quantiles(num_quantile_groups: int, quantiles: dict) dict
+

Calculate and return quantiles.

+
+
Parameters
+
    +
  • num_quantile_groups (int) – number of quantile groups

  • +
  • quantiles (dict[int, int]) – original quantiles

  • +
+
+
Returns
+

calculated quantiles

+
+
Return type
+

dict[int, int]

+
+
+
+
+
+dataprofiler.profilers.helpers.report_helpers.flat_dict(od: dict, separator: str = '_', key: str = '') dict
+

Flatten nested dictionary.

+

Each level is collapsed and +joined with the specified seperator.

+
+
Parameters
+
    +
  • od (dict) – dictionary or dictionary-like object

  • +
  • seperator (str) – character(s) joining successive levels

  • +
  • key (str) – concatenated keys

  • +
+
+
Returns
+

unnested dictionary

+
+
Return type
+

dict

+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.histogram_utils.html b/docs/0.10.5/html/dataprofiler.profilers.histogram_utils.html new file mode 100644 index 000000000..4f369477a --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.histogram_utils.html @@ -0,0 +1,288 @@ + + + + + + + + + Histogram Utils - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+ + +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.html b/docs/0.10.5/html/dataprofiler.profilers.html new file mode 100644 index 000000000..f664c0398 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.html @@ -0,0 +1,342 @@ + + + + + + + + + Profilers - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.int_column_profile.html b/docs/0.10.5/html/dataprofiler.profilers.int_column_profile.html new file mode 100644 index 000000000..5a5af4516 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.int_column_profile.html @@ -0,0 +1,540 @@ + + + + + + + + + Int Column Profile - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Int Column Profile

+

Int profile analysis for individual col within structured profiling.

+
+
+class dataprofiler.profilers.int_column_profile.IntColumn(name: str | None, options: IntOptions = None)
+

Bases: dataprofiler.profilers.numerical_column_stats.NumericStatsMixin[IntColumn], dataprofiler.profilers.base_column_profilers.BaseColumnPrimitiveTypeProfiler[IntColumn]

+

Integer column profile mixin with of numerical stats.

+

Represents a column in the dataset which is an integer column.

+

Initialize column base properties and itself.

+
+
Parameters
+
    +
  • name (String) – Name of the data

  • +
  • options (IntOptions) – Options for the integer column

  • +
+
+
+
+
+type: str | None = 'int'
+
+
+
+report(remove_disabled_flag: bool = False) dict
+

Return the report.

+
+
Parameters
+

remove_disabled_flag (boolean) – flag to determine if disabled +options should be excluded in the report.

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None)
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

IntColumn

+
+
+
+
+
+property profile: dict
+

Return the profile of the column.

+
+
Returns
+

+
+
+
+
+
+property data_type_ratio: float | None
+

Calculate the ratio of samples which match this data type.

+
+
Returns
+

ratio of data type

+
+
Return type
+

float

+
+
+
+
+
+update(df_series: pandas.core.series.Series) dataprofiler.profilers.int_column_profile.IntColumn
+

Update the column profile.

+
+
Parameters
+

df_series (pandas.core.series.Series) – df series

+
+
Returns
+

updated IntColumn

+
+
Return type
+

IntColumn

+
+
+
+
+
+col_type = None
+
+
+
+diff(other_profile: dataprofiler.profilers.numerical_column_stats.NumericStatsMixinT, options: Optional[dict] = None) dict
+

Find the differences for several numerical stats.

+
+
Parameters
+

other_profile (NumericStatsMixin Profile) – profile to find the difference with

+
+
Returns
+

the numerical stats differences

+
+
Return type
+

dict

+
+
+
+
+
+static is_float(x: str) bool
+

Return True if x is float.

+

For “0.80” this function returns True +For “1.00” this function returns True +For “1” this function returns True

+
+
Parameters
+

x (str) – string to test

+
+
Returns
+

if is float or not

+
+
Return type
+

bool

+
+
+
+
+
+static is_int(x: str) bool
+

Return True if x is integer.

+

For “0.80” This function returns False +For “1.00” This function returns True +For “1” this function returns True

+
+
Parameters
+

x (str) – string to test

+
+
Returns
+

if is integer or not

+
+
Return type
+

bool

+
+
+
+
+
+property kurtosis: float | np.float64
+

Return kurtosis value.

+
+
+
+property mean: float | np.float64
+

Return mean value.

+
+
+
+property median: float
+

Estimate the median of the data.

+
+
Returns
+

the median

+
+
Return type
+

float

+
+
+
+
+
+property median_abs_deviation: float | np.float64
+

Get median absolute deviation estimated from the histogram of the data.

+
+

Subtract bin edges from the median value +Fold the histogram to positive and negative parts around zero +Impose the two bin edges from the two histogram +Calculate the counts for the two histograms with the imposed bin edges +Superimpose the counts from the two histograms +Interpolate the median absolute deviation from the superimposed counts

+
+
+
Returns
+

median absolute deviation

+
+
+
+
+
+property mode: list
+

Find an estimate for the mode[s] of the data.

+
+
Returns
+

the mode(s) of the data

+
+
Return type
+

list(float)

+
+
+
+
+
+static np_type_to_type(val: Any) Any
+

Convert numpy variables to base python type variables.

+
+
Parameters
+

val (numpy type or base type) – value to check & change

+
+
Return val
+

base python type

+
+
Rtype val
+

int or float

+
+
+
+
+
+property skewness: float | np.float64
+

Return skewness value.

+
+
+
+property stddev: float | np.float64
+

Return stddev value.

+
+
+
+property variance: float | np.float64
+

Return variance.

+
+
+
+name: str | None
+
+
+
+sample_size: int
+
+
+
+metadata: dict
+
+
+
+times: dict
+
+
+
+thread_safe: bool
+
+
+
+match_count: int
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.json_decoder.html b/docs/0.10.5/html/dataprofiler.profilers.json_decoder.html new file mode 100644 index 000000000..980aa8b8d --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.json_decoder.html @@ -0,0 +1,547 @@ + + + + + + + + + JSON Decoder - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

JSON Decoder

+

Contains methods to decode components of a Profiler.

+
+
+dataprofiler.profilers.json_decoder.get_column_profiler_class(class_name: str) type[BaseColumnProfiler]
+

Use name of class to return default-constructed version of that class.

+
+
Raises ValueError if class_name is not name of a subclass of

BaseColumnProfiler.

+
+
+
+
Parameters
+

class_name (str representing name of class) – name of BaseColumnProfiler subclass retrieved by +calling type(instance).__name__

+
+
Returns
+

subclass of BaseColumnProfiler object

+
+
+
+
+
+dataprofiler.profilers.json_decoder.get_compiler_class(class_name: str) type[col_pro_compiler.BaseCompiler]
+

Use name of class to return default-constructed version of that class.

+
+
Raises ValueError if class_name is not name of a subclass of

BaseCompiler.

+
+
+
+
Parameters
+

class_name (str representing name of class) – name of BaseCompiler subclass retrieved by +calling type(instance).__name__

+
+
Returns
+

subclass of BaseCompiler object

+
+
+
+
+
+dataprofiler.profilers.json_decoder.get_option_class(class_name: str) type[BaseOption]
+

Use name of class to return default-constructed version of that class.

+
+
Raises ValueError if class_name is not name of a subclass of

BaseOptions.

+
+
+
+
Parameters
+

class_name (str representing name of class) – name of BaseOptions subclass retrieved by +calling type(instance).__name__

+
+
Returns
+

subclass of BaseOptions object

+
+
+
+
+
+dataprofiler.profilers.json_decoder.get_profiler_class(class_name: str) type[BaseProfiler]
+

Use name of class to return default-constructed version of that class.

+
+
Raises ValueError if class_name is not name of a subclass of

BaseProfiler.

+
+
+
+
Parameters
+

class_name (str representing name of class) – name of BaseProfiler subclass retrieved by +calling type(instance).__name__

+
+
Raises
+

ValueError if the profiler class does not exist

+
+
Returns
+

subclass of BaseProfiler object

+
+
+
+
+
+dataprofiler.profilers.json_decoder.get_structured_col_profiler_class(class_name: str) type[StructuredColProfiler]
+

Use name of class to return default-constructed version of that class.

+
+
Raises ValueError if class_name is not name of a subclass of

StructuredColProfiler.

+
+
+
+
Parameters
+

class_name (str representing name of class) – name of StructuredColProfiler subclass retrieved by +calling type(instance).__name__

+
+
Returns
+

subclass of StructuredColProfiler object

+
+
+
+
+
+dataprofiler.profilers.json_decoder.load_column_profile(serialized_json: dict, config: dict | None = None) BaseColumnProfiler
+

Construct subclass of BaseColumnProfiler given a serialized JSON.

+
+
Expected format of serialized_json (see json_encoder):
+
{

“class”: <str name of class that was serialized> +“data”: {

+
+

<attr1>: <value1> +<attr2>: <value2> +…

+
+

}

+
+
+

}

+
+
+
+
Parameters
+
    +
  • serialized_json (a dict that was created by calling json.loads on +a JSON representation using the custom encoder) – JSON representation of column profiler that was +serialized using the custom encoder in profilers.json_encoder

  • +
  • config (Dict | None) – config for overriding data params when loading from dict

  • +
+
+
Returns
+

subclass of BaseColumnProfiler that has been deserialized from +JSON

+
+
+
+
+
+dataprofiler.profilers.json_decoder.load_compiler(serialized_json: dict, config: dict | None = None) col_pro_compiler.BaseCompiler
+

Construct subclass of BaseCompiler given a serialized JSON.

+
+
Expected format of serialized_json (see json_encoder):
+
{

“class”: <str name of class that was serialized> +“data”: {

+
+

<attr1>: <value1> +<attr2>: <value2> +…

+
+

}

+
+
+

}

+
+
+
+
Parameters
+
    +
  • serialized_json (a dict that was created by calling json.loads on +a JSON representation using the custom encoder) – JSON representation of profile compiler that was +serialized using the custom encoder in profilers.json_encoder

  • +
  • config (Dict | None) – config for overriding data params when loading from dict

  • +
+
+
Returns
+

subclass of BaseCompiler that has been deserialized from +JSON

+
+
+
+
+
+dataprofiler.profilers.json_decoder.load_option(serialized_json: dict, config: dict | None = None) BaseOption
+

Construct subclass of BaseOption given a serialized JSON.

+
+
Expected format of serialized_json (see json_encoder):
+
{

“class”: <str name of class that was serialized> +“data”: {

+
+

<attr1>: <value1> +<attr2>: <value2> +…

+
+

}

+
+
+

}

+
+
+
+
Parameters
+
    +
  • serialized_json (a dict that was created by calling json.loads on +a JSON representation using the custom encoder) – JSON representation of option that was +serialized using the custom encoder in profilers.json_encoder

  • +
  • config (Dict | None) – config for overriding data params when loading from dict

  • +
+
+
Returns
+

subclass of BaseOption that has been deserialized from +JSON

+
+
+
+
+
+dataprofiler.profilers.json_decoder.load_profiler(serialized_json: dict, config=None) BaseProfiler
+

Construct subclass of BaseProfiler given a serialized JSON.

+
+
Expected format of serialized_json (see json_encoder):
+
{

“class”: <str name of class that was serialized> +“data”: {

+
+

<attr1>: <value1> +<attr2>: <value2> +…

+
+

}

+
+
+

}

+
+
+
+
Parameters
+
    +
  • serialized_json (a dict that was created by calling json.loads on +a JSON representation using the custom encoder) – JSON representation of column profiler that was +serialized using the custom encoder in profilers.json_encoder

  • +
  • config (Dict | None) – config for overriding data params when loading from dict

  • +
+
+
Returns
+

subclass of BaseProfiler that has been deserialized from +JSON

+
+
+
+
+
+dataprofiler.profilers.json_decoder.load_structured_col_profiler(serialized_json: dict, config: dict | None = None) StructuredColProfiler
+

Construct subclass of BaseProfiler given a serialized JSON.

+
+
Expected format of serialized_json (see json_encoder):
+
{

“class”: <str name of class that was serialized> +“data”: {

+
+

<attr1>: <value1> +<attr2>: <value2> +…

+
+

}

+
+
+

}

+
+
+
+
Parameters
+
    +
  • serialized_json (a dict that was created by calling json.loads on +a JSON representation using the custom encoder) – JSON representation of column profiler that was +serialized using the custom encoder in profilers.json_encoder

  • +
  • config (Dict | None) – config for overriding data params when loading from dict

  • +
+
+
Returns
+

subclass of BaseCompiler that has been deserialized from +JSON

+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.json_encoder.html b/docs/0.10.5/html/dataprofiler.profilers.json_encoder.html new file mode 100644 index 000000000..6d0250cfa --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.json_encoder.html @@ -0,0 +1,364 @@ + + + + + + + + + JSON Encoder - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

JSON Encoder

+

Contains ProfilerEncoder class.

+
+
+class dataprofiler.profilers.json_encoder.ProfileEncoder(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)
+

Bases: json.encoder.JSONEncoder

+

JSONify profiler objects and it subclasses and contents.

+

Constructor for JSONEncoder, with sensible defaults.

+

If skipkeys is false, then it is a TypeError to attempt +encoding of keys that are not str, int, float or None. If +skipkeys is True, such items are simply skipped.

+

If ensure_ascii is true, the output is guaranteed to be str +objects with all incoming non-ASCII characters escaped. If +ensure_ascii is false, the output can contain non-ASCII characters.

+

If check_circular is true, then lists, dicts, and custom encoded +objects will be checked for circular references during encoding to +prevent an infinite recursion (which would cause an RecursionError). +Otherwise, no such check takes place.

+

If allow_nan is true, then NaN, Infinity, and -Infinity will be +encoded as such. This behavior is not JSON specification compliant, +but is consistent with most JavaScript based encoders and decoders. +Otherwise, it will be a ValueError to encode such floats.

+

If sort_keys is true, then the output of dictionaries will be +sorted by key; this is useful for regression tests to ensure +that JSON serializations can be compared on a day-to-day basis.

+

If indent is a non-negative integer, then JSON array +elements and object members will be pretty-printed with that +indent level. An indent level of 0 will only insert newlines. +None is the most compact representation.

+

If specified, separators should be an (item_separator, key_separator) +tuple. The default is (’, ‘, ‘: ‘) if indent is None and +(‘,’, ‘: ‘) otherwise. To get the most compact JSON representation, +you should specify (‘,’, ‘:’) to eliminate whitespace.

+

If specified, default is a function that gets called for objects +that can’t otherwise be serialized. It should return a JSON encodable +version of the object or raise a TypeError.

+
+
+default(to_serialize)
+

Specify how an object should be serialized.

+
+
Parameters
+

to_serialize (a BaseColumnProfile object) – an object to be serialized

+
+
Raises
+

NotImplementedError

+
+
Returns
+

a datatype serializble by json.JSONEncoder

+
+
+
+
+
+encode(o)
+

Return a JSON string representation of a Python data structure.

+
>>> from json.encoder import JSONEncoder
+>>> JSONEncoder().encode({"foo": ["bar", "baz"]})
+'{"foo": ["bar", "baz"]}'
+
+
+
+
+
+item_separator = ', '
+
+
+
+iterencode(o, _one_shot=False)
+

Encode the given object and yield each string +representation as available.

+

For example:

+
for chunk in JSONEncoder().iterencode(bigobject):
+    mysocket.write(chunk)
+
+
+
+
+
+key_separator = ': '
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.numerical_column_stats.html b/docs/0.10.5/html/dataprofiler.profilers.numerical_column_stats.html new file mode 100644 index 000000000..f970bd576 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.numerical_column_stats.html @@ -0,0 +1,536 @@ + + + + + + + + + Numerical Column Stats - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Numerical Column Stats

+

Build model for dataset by identifying col type along with its respective params.

+
+
+class dataprofiler.profilers.numerical_column_stats.abstractstaticmethod(function: Callable)
+

Bases: staticmethod

+

For making function an abstract method.

+

Initialize abstract static method.

+
+
+
+class dataprofiler.profilers.numerical_column_stats.NumericStatsMixin(options: Optional[dataprofiler.profilers.profiler_options.NumericalOptions] = None)
+

Bases: dataprofiler.profilers.base_column_profilers.BaseColumnProfiler[dataprofiler.profilers.numerical_column_stats.NumericStatsMixinT]

+

Abstract numerical column profile subclass of BaseColumnProfiler.

+

Represents column in the dataset which is a text column. +Has Subclasses itself.

+

Initialize column base properties and itself.

+
+
Parameters
+

options (NumericalOptions) – Options for the numerical stats.

+
+
+
+
+type: str | None = None
+
+
+
+profile() dict
+

Return profile of the column.

+
+
Returns
+

+
+
+
+
+
+report(remove_disabled_flag: bool = False) dict
+

Call the profile and remove the disabled columns from profile’s report.

+
+

“Disabled column” is defined as a column +that is not present in self.__calculations but is present +in the self.profile.

+
+
+
Variables
+

remove_disabled_flag – true/false value to tell the code to remove +values missing in __calculations

+
+
Returns
+

Profile object pop’d based on values missing from __calculations

+
+
Return type
+

Profile

+
+
+
+
+
+diff(other_profile: dataprofiler.profilers.numerical_column_stats.NumericStatsMixinT, options: Optional[dict] = None) dict
+

Find the differences for several numerical stats.

+
+
Parameters
+

other_profile (NumericStatsMixin Profile) – profile to find the difference with

+
+
Returns
+

the numerical stats differences

+
+
Return type
+

dict

+
+
+
+
+
+property mean: float | np.float64
+

Return mean value.

+
+
+
+property mode: list
+

Find an estimate for the mode[s] of the data.

+
+
Returns
+

the mode(s) of the data

+
+
Return type
+

list(float)

+
+
+
+
+
+property median: float
+

Estimate the median of the data.

+
+
Returns
+

the median

+
+
Return type
+

float

+
+
+
+
+
+property variance: float | np.float64
+

Return variance.

+
+
+
+property stddev: float | np.float64
+

Return stddev value.

+
+
+
+property skewness: float | np.float64
+

Return skewness value.

+
+
+
+property kurtosis: float | np.float64
+

Return kurtosis value.

+
+
+
+property median_abs_deviation: float | np.float64
+

Get median absolute deviation estimated from the histogram of the data.

+
+

Subtract bin edges from the median value +Fold the histogram to positive and negative parts around zero +Impose the two bin edges from the two histogram +Calculate the counts for the two histograms with the imposed bin edges +Superimpose the counts from the two histograms +Interpolate the median absolute deviation from the superimposed counts

+
+
+
Returns
+

median absolute deviation

+
+
+
+
+
+col_type = None
+
+
+
+classmethod load_from_dict(data: dict[str, Any], config: dict | None = None) BaseColumnProfilerT
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

BaseColumnProfiler

+
+
+
+
+
+name: str | None
+
+
+
+sample_size: int
+
+
+
+metadata: dict
+
+
+
+times: dict
+
+
+
+thread_safe: bool
+
+
+
+abstract update(df_series: pandas.core.series.Series) dataprofiler.profilers.numerical_column_stats.NumericStatsMixin
+

Update the numerical profile properties with an uncleaned dataset.

+
+
Parameters
+

df_series (pandas.core.series.Series) – df series with nulls removed

+
+
Returns
+

None

+
+
+
+
+
+static is_float(x: str) bool
+

Return True if x is float.

+

For “0.80” this function returns True +For “1.00” this function returns True +For “1” this function returns True

+
+
Parameters
+

x (str) – string to test

+
+
Returns
+

if is float or not

+
+
Return type
+

bool

+
+
+
+
+
+static is_int(x: str) bool
+

Return True if x is integer.

+

For “0.80” This function returns False +For “1.00” This function returns True +For “1” this function returns True

+
+
Parameters
+

x (str) – string to test

+
+
Returns
+

if is integer or not

+
+
Return type
+

bool

+
+
+
+
+
+static np_type_to_type(val: Any) Any
+

Convert numpy variables to base python type variables.

+
+
Parameters
+

val (numpy type or base type) – value to check & change

+
+
Return val
+

base python type

+
+
Rtype val
+

int or float

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.order_column_profile.html b/docs/0.10.5/html/dataprofiler.profilers.order_column_profile.html new file mode 100644 index 000000000..cd6449b57 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.order_column_profile.html @@ -0,0 +1,402 @@ + + + + + + + + + Order Column Profile - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Order Column Profile

+

Index profile analysis for individual col within structured profiling.

+
+
+class dataprofiler.profilers.order_column_profile.Comparable(*args, **kwargs)
+

Bases: Protocol

+

Protocol for ensuring comparable types, in this case both floats or strings.

+
+
+
+class dataprofiler.profilers.order_column_profile.OrderColumn(name: str | None, options: OrderOptions = None)
+

Bases: dataprofiler.profilers.base_column_profilers.BaseColumnProfiler[OrderColumn]

+

Index column profile subclass of BaseColumnProfiler.

+

Represents a column in the dataset which is an index column.

+

Initialize column base properties and self.

+
+
Parameters
+
    +
  • name (String) – Name of the data

  • +
  • options (OrderOptions) – Options for the Order column

  • +
+
+
+
+
+type = 'order'
+
+
+
+report(remove_disabled_flag: bool = False) dict
+

Private abstract method for returning report.

+
+
Parameters
+

remove_disabled_flag (boolean) – flag to determine if disabled +options should be excluded in the report.

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None)
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – options for loading column profiler params from dictionary

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

CategoricalColumn

+
+
+
+
+
+property profile: dict
+

Property for profile. Returns the profile of the column.

+
+
Returns
+

+
+
+
+
+
+diff(other_profile: dataprofiler.profilers.order_column_profile.OrderColumn, options: Optional[dict] = None) dict
+

Generate the differences between the orders of two OrderColumns.

+
+
Returns
+

Dict containing the differences between orders in their

+
+
+

appropriate output formats +:rtype: dict

+
+
+
+update(df_series: pandas.core.series.Series) dataprofiler.profilers.order_column_profile.OrderColumn
+

Update the column profile.

+
+
Parameters
+

df_series (pandas.core.series.Series) – df series

+
+
Returns
+

updated OrderColumn

+
+
Return type
+

OrderColumn

+
+
+
+
+
+col_type = None
+
+
+
+name: str | None
+
+
+
+sample_size: int
+
+
+
+metadata: dict
+
+
+
+times: dict
+
+
+
+thread_safe: bool
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.profile_builder.html b/docs/0.10.5/html/dataprofiler.profilers.profile_builder.html new file mode 100644 index 000000000..4b47b9412 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.profile_builder.html @@ -0,0 +1,892 @@ + + + + + + + + + Profile Builder - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Profile Builder

+

Build model for dataset by identifying col type along with its respective params.

+
+
+class dataprofiler.profilers.profile_builder.StructuredColProfiler(df_series: Optional[pandas.core.series.Series] = None, sample_size: Optional[int] = None, min_sample_size: int = 5000, sampling_ratio: float = 0.2, min_true_samples: int = 0, sample_ids: Optional[numpy.ndarray] = None, pool: Optional[multiprocessing.pool.Pool] = None, column_index: Optional[int] = None, options: Optional[dataprofiler.profilers.profiler_options.StructuredOptions] = None)
+

Bases: object

+

For profiling structured data columns.

+

Instantiate the StructuredColProfiler class for a given column.

+
+
Parameters
+
    +
  • df_series (pandas.core.series.Series) – Data to be profiled

  • +
  • sample_size (int) – Number of samples to use in generating profile

  • +
  • min_true_samples (int) – Minimum number of samples required for the +profiler

  • +
  • sample_ids (list(list)) – Randomized list of sample indices

  • +
  • pool (multiprocessing.Pool) – pool utilized for multiprocessing

  • +
  • column_index (int) – index of the given column

  • +
  • options (StructuredOptions Object) – Options for the structured profiler.

  • +
+
+
+
+
+update_column_profilers(clean_sampled_df: pandas.core.series.Series, pool: Optional[multiprocessing.pool.Pool] = None) None
+

Calculate type statistics and label dataset.

+
+
Parameters
+
    +
  • clean_sampled_df (Pandas.Series) – sampled series with none types dropped

  • +
  • pool (multiprocessing.pool) – pool utilized for multiprocessing

  • +
+
+
+
+
+
+diff(other_profile: dataprofiler.profilers.profile_builder.StructuredColProfiler, options: Optional[dict] = None) dict
+

Find the difference between 2 StructuredCols and return the report.

+
+
Parameters
+
    +
  • other_profile (StructuredColProfiler) – Structured col finding the difference with this +one.

  • +
  • options (dict) – options to change results of the difference

  • +
+
+
Returns
+

difference of the structured column

+
+
Return type
+

dict

+
+
+
+
+
+report(remove_disabled_flag: bool = False) collections.OrderedDict
+

Return profile.

+
+
+
+classmethod load_from_dict(data, config: dict | None = None) StructuredColProfiler
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading structured column profiler

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

StructuredColProfiler

+
+
+
+
+
+property profile: dict
+

Return a report.

+
+
+
+update_profile(df_series: pandas.core.series.Series, sample_size: Optional[int] = None, min_true_samples: Optional[int] = None, sample_ids: Optional[numpy.ndarray] = None, pool: Optional[multiprocessing.pool.Pool] = None) None
+

Update the column profiler.

+
+
Parameters
+
    +
  • df_series (pandas.core.series.Series) – Data to be profiled

  • +
  • sample_size (int) – Number of samples to use in generating profile

  • +
  • min_true_samples (int) – Minimum number of samples required for the +profiler

  • +
  • sample_ids (list(list)) – Randomized list of sample indices

  • +
  • pool (multiprocessing.Pool) – pool utilized for multiprocessing

  • +
+
+
+
+
+
+static clean_data_and_get_base_stats(df_series: pd.Series, sample_size: int, null_values: dict[str, re.RegexFlag | int] = None, min_true_samples: int = None, sample_ids: np.ndarray | list[list[int]] | None = None) tuple[pd.Series, dict]
+

Identify null characters and return them in a dictionary.

+

Remove any nulls in column.

+
+
Parameters
+
    +
  • df_series (pandas.core.series.Series) – a given column

  • +
  • sample_size (int) – Number of samples to use in generating the profile

  • +
  • null_values (Dict[str, Union[re.RegexFlag, int]]) – Dictionary mapping null values to regex flag where +the key represents the null value to remove from the data and the +flag represents the regex flag to apply

  • +
  • min_true_samples (int) – Minimum number of samples required for the +profiler

  • +
  • sample_ids (list(list)) – Randomized list of sample indices

  • +
+
+
Returns
+

updated column with null removed and dictionary of null +parameters

+
+
Return type
+

pd.Series, dict

+
+
+
+
+
+
+class dataprofiler.profilers.profile_builder.BaseProfiler(data: Data | None, samples_per_update: int = None, min_true_samples: int = 0, options: BaseOption = None)
+

Bases: object

+

Abstract class for profiling data.

+

Instantiate the BaseProfiler class.

+
+
Parameters
+
    +
  • data (Data class object) – Data to be profiled

  • +
  • samples_per_update (int) – Number of samples to use in generating +profile

  • +
  • min_true_samples (int) – Minimum number of samples required for the +profiler

  • +
  • options (ProfilerOptions Object) – Options for the profiler.

  • +
+
+
Returns
+

Profiler

+
+
+
+
+diff(other_profile: dataprofiler.profilers.profile_builder.BaseProfiler, options: Optional[dict] = None) dict
+

Find the difference of two profiles.

+
+
Parameters
+

other_profile (BaseProfiler) – profile being added to this one.

+
+
Returns
+

diff of the two profiles

+
+
Return type
+

dict

+
+
+
+
+
+property profile: BaseCompiler | list[StructuredColProfiler]
+

Return the stored profiles for the given profiler.

+
+
Returns
+

BaseCompiler | list[StructuredColProfiler]

+
+
+
+
+
+report(report_options: Optional[dict] = None) dict
+

Return profile report based on all profiled data fed into the profiler.

+
+
User can specify the output_formats: (pretty, compact, serializable, flat).
+
Pretty: floats are rounded to four decimal places, and lists are

shortened.

+
+
Compact: Similar to pretty, but removes detailed statistics such as

runtimes, label probabilities, index locations of null types, +etc.

+
+
+

Serializable: Output is json serializable and not prettified +Flat: Nested output is returned as a flattened dictionary

+
+
+
+
Variables
+

report_options – optional format changes to the report +dict(output_format=<FORMAT>)

+
+
Returns
+

dictionary report

+
+
Return type
+

dict

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseProfilerT
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for overriding data params when loading from dict

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

BaseProfiler

+
+
+
+
+
+update_profile(data: data_readers.base_data.BaseData | pd.DataFrame | pd.Series, sample_size: int = None, min_true_samples: int = None) None
+

Update the profile for data provided.

+

User can specify the sample size to profile the data with. +Additionally, the user can specify the +minimum number of non-null samples to profile.

+
+
Parameters
+
    +
  • data (Union[data_readers.base_data.BaseData, pandas.DataFrame, +pandas.Series]) – data to be profiled

  • +
  • sample_size (int) – number of samples to profile from the data

  • +
  • min_true_samples (int) – minimum number of non-null samples to profile

  • +
+
+
Returns
+

None

+
+
+
+
+
+save(filepath: Optional[str] = None, save_method: str = 'pickle') None
+

Save profiler to disk.

+
+
Parameters
+
    +
  • filepath (String) – Path of file to save to

  • +
  • save_method (String) – The desired saving method (must be “pickle” or “json”)

  • +
+
+
Returns
+

None

+
+
+
+
+
+classmethod load(filepath: str, load_method: str | None = None) BaseProfiler
+

Load profiler from disk.

+
+
Parameters
+
    +
  • filepath (String) – Path of file to load from

  • +
  • load_method (Optional[String]) – The desired loading method, default = None

  • +
+
+
Returns
+

Profiler being loaded, StructuredProfiler or +UnstructuredProfiler

+
+
Return type
+

BaseProfiler

+
+
+
+
+
+
+class dataprofiler.profilers.profile_builder.UnstructuredProfiler(data: dataprofiler.data_readers.data.Data, samples_per_update: Optional[int] = None, min_true_samples: int = 0, options: Optional[dataprofiler.profilers.profiler_options.BaseOption] = None)
+

Bases: dataprofiler.profilers.profile_builder.BaseProfiler

+

For profiling unstructured data.

+

Instantiate the UnstructuredProfiler class.

+
+
Parameters
+
    +
  • data (Data class object) – Data to be profiled

  • +
  • samples_per_update (int) – Number of samples to use in generating +profile

  • +
  • min_true_samples (int) – Minimum number of samples required for the +profiler

  • +
  • options (ProfilerOptions Object) – Options for the profiler.

  • +
+
+
Returns
+

UnstructuredProfiler

+
+
+
+
+diff(other_profile: UnstructuredProfiler, options: dict | None = None) dict
+

Find difference between 2 unstuctured profiles and return the report.

+
+
Parameters
+
    +
  • other_profile (UnstructuredProfiler) – profile finding the difference with this one.

  • +
  • options (dict) – options to impact the results of the diff

  • +
+
+
Returns
+

difference of the profiles

+
+
Return type
+

dict

+
+
+
+
+
+property profile: dataprofiler.profilers.column_profile_compilers.BaseCompiler
+

Return the stored profiles for the given profiler.

+
+
Returns
+

BaseCompiler

+
+
+
+
+
+report(report_options: Optional[dict] = None) dict
+

Return unstructured report based on all profiled data fed into profiler.

+
+
User can specify the output_formats: (pretty, compact, serializable, flat).
+
Pretty: floats are rounded to four decimal places, and lists are

shortened.

+
+
Compact: Similar to pretty, but removes detailed statistics such as

runtimes, label probabilities, index locations of null types, +etc.

+
+
+

Serializable: Output is json serializable and not prettified +Flat: Nested output is returned as a flattened dictionary

+
+
+
+
Variables
+

report_options – optional format changes to the report +dict(output_format=<FORMAT>)

+
+
Returns
+

dictionary report

+
+
Return type
+

dict

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None)
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading profiler params from dictionary

  • +
+
+
Raises
+

NotImplementedError

+
+
+
+
+
+save(filepath: Optional[str] = None, save_method: str = 'pickle') None
+

Save profiler to disk.

+
+
Parameters
+
    +
  • filepath (String) – Path of file to save to

  • +
  • save_method (String) – The desired saving method (“pickle” | “json”)

  • +
+
+
Returns
+

None

+
+
+
+
+
+classmethod load(filepath: str, load_method: str | None = None) BaseProfiler
+

Load profiler from disk.

+
+
Parameters
+
    +
  • filepath (String) – Path of file to load from

  • +
  • load_method (Optional[String]) – The desired loading method, default = None

  • +
+
+
Returns
+

Profiler being loaded, StructuredProfiler or +UnstructuredProfiler

+
+
Return type
+

BaseProfiler

+
+
+
+
+
+update_profile(data: data_readers.base_data.BaseData | pd.DataFrame | pd.Series, sample_size: int = None, min_true_samples: int = None) None
+

Update the profile for data provided.

+

User can specify the sample size to profile the data with. +Additionally, the user can specify the +minimum number of non-null samples to profile.

+
+
Parameters
+
    +
  • data (Union[data_readers.base_data.BaseData, pandas.DataFrame, +pandas.Series]) – data to be profiled

  • +
  • sample_size (int) – number of samples to profile from the data

  • +
  • min_true_samples (int) – minimum number of non-null samples to profile

  • +
+
+
Returns
+

None

+
+
+
+
+
+
+class dataprofiler.profilers.profile_builder.StructuredProfiler(data: dataprofiler.data_readers.data.Data, samples_per_update: Optional[int] = None, min_true_samples: int = 0, options: Optional[dataprofiler.profilers.profiler_options.BaseOption] = None)
+

Bases: dataprofiler.profilers.profile_builder.BaseProfiler

+

For profiling structured data.

+

Instantiate the StructuredProfiler class.

+
+
Parameters
+
    +
  • data (Data class object) – Data to be profiled

  • +
  • samples_per_update (int) – Number of samples to use in generating +profile

  • +
  • min_true_samples (int) – Minimum number of samples required for the +profiler

  • +
  • options (ProfilerOptions Object) – Options for the profiler.

  • +
+
+
Returns
+

StructuredProfiler

+
+
+
+
+diff(other_profile: StructuredProfiler, options: dict | None = None) dict
+

Find the difference between 2 Profiles and return the report.

+
+
Parameters
+
    +
  • other_profile (StructuredProfiler) – profile finding the difference with this one

  • +
  • options (dict) – options to change results of the difference

  • +
+
+
Returns
+

difference of the profiles

+
+
Return type
+

dict

+
+
+
+
+
+property profile: list
+

Return the stored profiles for the given profiler.

+
+
Returns
+

list[StructuredColProfiler]

+
+
+
+
+
+report(report_options: Optional[dict] = None) dict
+

Return a report.

+
+
+
+classmethod load_from_dict(data, config: dict | None = None) StructuredProfiler
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading profiler params from dictionary

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

StructuredProfiler

+
+
+
+
+
+save(filepath: Optional[str] = None, save_method: str = 'pickle') None
+

Save profiler to disk.

+
+
Parameters
+
    +
  • filepath (String) – Path of file to save to

  • +
  • save_method (String) – The desired saving method (must be “pickle” or “json”)

  • +
+
+
Returns
+

None

+
+
+
+
+
+classmethod load(filepath: str, load_method: str | None = None) BaseProfiler
+

Load profiler from disk.

+
+
Parameters
+
    +
  • filepath (String) – Path of file to load from

  • +
  • load_method (Optional[String]) – The desired loading method, default = None

  • +
+
+
Returns
+

Profiler being loaded, StructuredProfiler or +UnstructuredProfiler

+
+
Return type
+

BaseProfiler

+
+
+
+
+
+update_profile(data: data_readers.base_data.BaseData | pd.DataFrame | pd.Series, sample_size: int = None, min_true_samples: int = None) None
+

Update the profile for data provided.

+

User can specify the sample size to profile the data with. +Additionally, the user can specify the +minimum number of non-null samples to profile.

+
+
Parameters
+
    +
  • data (Union[data_readers.base_data.BaseData, pandas.DataFrame, +pandas.Series]) – data to be profiled

  • +
  • sample_size (int) – number of samples to profile from the data

  • +
  • min_true_samples (int) – minimum number of non-null samples to profile

  • +
+
+
Returns
+

None

+
+
+
+
+
+
+class dataprofiler.profilers.profile_builder.Profiler(data: Data, samples_per_update: int = None, min_true_samples: int = 0, options: ProfilerOptions = None, profiler_type: str = None)
+

Bases: object

+

For profiling data.

+

Instantiate Structured and Unstructured Profilers.

+

This is a factory class.

+
+
Parameters
+
    +
  • data (Data class object) – Data to be profiled, type allowed depends on the +profiler_type

  • +
  • samples_per_update (int) – Number of samples to use to generate profile

  • +
  • min_true_samples (int) – Min number of samples required for the profiler

  • +
  • options (ProfilerOptions Object) – Options for the profiler.

  • +
  • profiler_type (str) – Type of Profiler (“graph”/”structured”/”unstructured”)

  • +
+
+
Returns
+

Union[GraphProfiler, StructuredProfiler, UnstructuredProfiler]

+
+
+
+
+classmethod load(filepath: str, load_method: str | None = None) BaseProfiler
+

Load profiler from disk.

+
+
Parameters
+
    +
  • filepath (String) – Path of file to load from

  • +
  • load_method (Optional[String]) – The desired loading method, default = “None”

  • +
+
+
Returns
+

Profiler being loaded, StructuredProfiler or +UnstructuredProfiler

+
+
Return type
+

BaseProfiler

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.profiler_options.html b/docs/0.10.5/html/dataprofiler.profilers.profiler_options.html new file mode 100644 index 000000000..b650891ad --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.profiler_options.html @@ -0,0 +1,2396 @@ + + + + + + + + + Profiler Options - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Profiler Options

+

Specify the options when running the data profiler.

+
+
+class dataprofiler.profilers.profiler_options.BaseOption
+

Bases: Generic[dataprofiler.profilers.profiler_options.BaseOptionT]

+

For configuring options.

+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.BooleanOption(is_enabled: bool = True)
+

Bases: dataprofiler.profilers.profiler_options.BaseOption[dataprofiler.profilers.profiler_options.BooleanOptionT]

+

For setting Boolean options.

+

Initialize Boolean option.

+
+
Variables
+

is_enabled (bool) – boolean option to enable/disable the option.

+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.HistogramAndQuantilesOption(is_enabled: bool = True, bin_count_or_method: str | int | list[str] = 'auto', num_quantiles: int = 1000)
+

Bases: dataprofiler.profilers.profiler_options.BooleanOption[HistogramAndQuantilesOption]

+

For setting histogram options.

+

Initialize Options for histograms.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable the option.

  • +
  • bin_count_or_method (Union[str, int, list(str)]) – bin count or the method with which to +calculate histograms

  • +
  • num_quantiles (int) – number of quantiles

  • +
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.ModeOption(is_enabled: bool = True, max_k_modes: int = 5)
+

Bases: dataprofiler.profilers.profiler_options.BooleanOption[ModeOption]

+

For setting mode estimation options.

+

Initialize Options for mode estimation.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable the option.

  • +
  • max_k_modes (int) – the max number of modes to return, if applicable

  • +
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.BaseInspectorOptions(is_enabled: bool = True)
+

Bases: dataprofiler.profilers.profiler_options.BooleanOption[dataprofiler.profilers.profiler_options.BaseInspectorOptionsT]

+

For setting Base options.

+

Initialize Base options for all the columns.

+
+
Variables
+

is_enabled (bool) – boolean option to enable/disable the column.

+
+
+
+
+is_prop_enabled(prop: str) bool
+

Check to see if a property is enabled or not and returns boolean.

+
+
Parameters
+

prop (String) – The option to check if it is enabled

+
+
Returns
+

Whether or not the property is enabled

+
+
Return type
+

Boolean

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.NumericalOptions
+

Bases: dataprofiler.profilers.profiler_options.BaseInspectorOptions[dataprofiler.profilers.profiler_options.NumericalOptionsT]

+

For configuring options for Numerican Stats Mixin.

+

Initialize Options for the Numerical Stats Mixin.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable the column.

  • +
  • min (BooleanOption) – boolean option to enable/disable min

  • +
  • max (BooleanOption) – boolean option to enable/disable max

  • +
  • mode (ModeOption) – option to enable/disable mode and set return count

  • +
  • median (BooleanOption) – option to enable/disable median

  • +
  • sum (BooleanOption) – boolean option to enable/disable sum

  • +
  • variance (BooleanOption) – boolean option to enable/disable variance

  • +
  • skewness (BooleanOption) – boolean option to enable/disable skewness

  • +
  • kurtosis (BooleanOption) – boolean option to enable/disable kurtosis

  • +
  • histogram_and_quantiles (BooleanOption) – boolean option to enable/disable +histogram_and_quantiles

  • +
+
+
+

:ivar bias_correction : boolean option to enable/disable existence of bias +:vartype bias_correction: BooleanOption +:ivar num_zeros: boolean option to enable/disable num_zeros +:vartype num_zeros: BooleanOption +:ivar num_negatives: boolean option to enable/disable num_negatives +:vartype num_negatives: BooleanOption +:ivar is_numeric_stats_enabled: boolean to enable/disable all numeric

+
+

stats

+
+
+
+
+
+property is_numeric_stats_enabled: bool
+

Return the state of numeric stats being enabled / disabled.

+

If any numeric stats property is enabled it will return True, +otherwise it will return False.

+
+
Returns
+

true if any numeric stats property is enabled, otherwise false

+
+
Rtype bool
+

+
+
+
+
+property properties: dict
+

Include is_enabled.

+

is_enabled: Turns on or off the column.

+
+
+
+is_prop_enabled(prop: str) bool
+

Check to see if a property is enabled or not and returns boolean.

+
+
Parameters
+

prop (String) – The option to check if it is enabled

+
+
Returns
+

Whether or not the property is enabled

+
+
Return type
+

Boolean

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.IntOptions
+

Bases: dataprofiler.profilers.profiler_options.NumericalOptions[IntOptions]

+

For configuring options for Int Column.

+

Initialize Options for the Int Column.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable the column.

  • +
  • min (BooleanOption) – boolean option to enable/disable min

  • +
  • max (BooleanOption) – boolean option to enable/disable max

  • +
  • mode (ModeOption) – option to enable/disable mode and set return count

  • +
  • median (BooleanOption) – option to enable/disable median

  • +
  • sum (BooleanOption) – boolean option to enable/disable sum

  • +
  • variance (BooleanOption) – boolean option to enable/disable variance

  • +
  • skewness (BooleanOption) – boolean option to enable/disable skewness

  • +
  • kurtosis (BooleanOption) – boolean option to enable/disable kurtosis

  • +
  • histogram_and_quantiles (BooleanOption) – boolean option to enable/disable +histogram_and_quantiles

  • +
+
+
+

:ivar bias_correction : boolean option to enable/disable existence of bias +:vartype bias_correction: BooleanOption +:ivar num_zeros: boolean option to enable/disable num_zeros +:vartype num_zeros: BooleanOption +:ivar num_negatives: boolean option to enable/disable num_negatives +:vartype num_negatives: BooleanOption +:ivar is_numeric_stats_enabled: boolean to enable/disable all numeric

+
+

stats

+
+
+
+
+
+property is_numeric_stats_enabled: bool
+

Return the state of numeric stats being enabled / disabled.

+

If any numeric stats property is enabled it will return True, +otherwise it will return False.

+
+
Returns
+

true if any numeric stats property is enabled, otherwise false

+
+
Rtype bool
+

+
+
+
+
+is_prop_enabled(prop: str) bool
+

Check to see if a property is enabled or not and returns boolean.

+
+
Parameters
+

prop (String) – The option to check if it is enabled

+
+
Returns
+

Whether or not the property is enabled

+
+
Return type
+

Boolean

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Include is_enabled.

+

is_enabled: Turns on or off the column.

+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.PrecisionOptions(is_enabled: bool = True, sample_ratio: Optional[float] = None)
+

Bases: dataprofiler.profilers.profiler_options.BooleanOption[PrecisionOptions]

+

For configuring options for precision.

+

Initialize Options for precision.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable the column.

  • +
  • sample_ratio (float) – float option to determine ratio of valid +float samples in determining percision. +This ratio will override any defaults.

  • +
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.FloatOptions
+

Bases: dataprofiler.profilers.profiler_options.NumericalOptions[FloatOptions]

+

For configuring options for Float Column.

+

Initialize Options for the Float Column.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable the column.

  • +
  • min (BooleanOption) – boolean option to enable/disable min

  • +
  • max (BooleanOption) – boolean option to enable/disable max

  • +
  • mode (ModeOption) – option to enable/disable mode and set return count

  • +
  • median (BooleanOption) – option to enable/disable median

  • +
  • sum (BooleanOption) – boolean option to enable/disable sum

  • +
  • variance (BooleanOption) – boolean option to enable/disable variance

  • +
  • skewness (BooleanOption) – boolean option to enable/disable skewness

  • +
  • kurtosis (BooleanOption) – boolean option to enable/disable kurtosis

  • +
  • histogram_and_quantiles (BooleanOption) – boolean option to enable/disable +histogram_and_quantiles

  • +
+
+
+

:ivar bias_correction : boolean option to enable/disable existence of bias +:vartype bias_correction: BooleanOption +:ivar num_zeros: boolean option to enable/disable num_zeros +:vartype num_zeros: BooleanOption +:ivar num_negatives: boolean option to enable/disable num_negatives +:vartype num_negatives: BooleanOption +:ivar is_numeric_stats_enabled: boolean to enable/disable all numeric

+
+

stats

+
+
+
+
+
+property is_numeric_stats_enabled: bool
+

Return the state of numeric stats being enabled / disabled.

+

If any numeric stats property is enabled it will return True, +otherwise it will return False.

+
+
Returns
+

true if any numeric stats property is enabled, otherwise false

+
+
Rtype bool
+

+
+
+
+
+is_prop_enabled(prop: str) bool
+

Check to see if a property is enabled or not and returns boolean.

+
+
Parameters
+

prop (String) – The option to check if it is enabled

+
+
Returns
+

Whether or not the property is enabled

+
+
Return type
+

Boolean

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Include is_enabled.

+

is_enabled: Turns on or off the column.

+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.TextOptions
+

Bases: dataprofiler.profilers.profiler_options.NumericalOptions[TextOptions]

+

For configuring options for Text Column.

+

Initialize Options for the Text Column.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable the column.

  • +
  • vocab (BooleanOption) – boolean option to enable/disable vocab

  • +
  • min (BooleanOption) – boolean option to enable/disable min

  • +
  • max (BooleanOption) – boolean option to enable/disable max

  • +
  • mode (ModeOption) – option to enable/disable mode and set return count

  • +
  • median (BooleanOption) – option to enable/disable median

  • +
  • sum (BooleanOption) – boolean option to enable/disable sum

  • +
  • variance (BooleanOption) – boolean option to enable/disable variance

  • +
  • skewness (BooleanOption) – boolean option to enable/disable skewness

  • +
  • kurtosis (BooleanOption) – boolean option to enable/disable kurtosis

  • +
+
+
+

:ivar bias_correction : boolean option to enable/disable existence of bias +:vartype bias_correction: BooleanOption +:ivar histogram_and_quantiles: boolean option to enable/disable

+
+

histogram_and_quantiles

+
+
+
Variables
+
    +
  • num_zeros (BooleanOption) – boolean option to enable/disable num_zeros

  • +
  • num_negatives (BooleanOption) – boolean option to enable/disable num_negatives

  • +
  • is_numeric_stats_enabled (bool) – boolean to enable/disable all numeric +stats

  • +
+
+
+
+
+property is_numeric_stats_enabled: bool
+

Return the state of numeric stats being enabled / disabled.

+

If any numeric stats property is enabled it will return True, otherwise +it will return False. Although it seems redundant, this method is needed +in order for the function below, the setter function +also called is_numeric_stats_enabled, to properly work.

+
+
Returns
+

true if any numeric stats property is enabled, otherwise false

+
+
Rtype bool
+

+
+
+
+
+is_prop_enabled(prop: str) bool
+

Check to see if a property is enabled or not and returns boolean.

+
+
Parameters
+

prop (String) – The option to check if it is enabled

+
+
Returns
+

Whether or not the property is enabled

+
+
Return type
+

Boolean

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Include is_enabled.

+

is_enabled: Turns on or off the column.

+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.DateTimeOptions
+

Bases: dataprofiler.profilers.profiler_options.BaseInspectorOptions[DateTimeOptions]

+

For configuring options for Datetime Column.

+

Initialize Options for the Datetime Column.

+
+
Variables
+

is_enabled (bool) – boolean option to enable/disable the column.

+
+
+
+
+is_prop_enabled(prop: str) bool
+

Check to see if a property is enabled or not and returns boolean.

+
+
Parameters
+

prop (String) – The option to check if it is enabled

+
+
Returns
+

Whether or not the property is enabled

+
+
Return type
+

Boolean

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.OrderOptions
+

Bases: dataprofiler.profilers.profiler_options.BaseInspectorOptions[OrderOptions]

+

For configuring options for Order Column.

+

Initialize options for the Order Column.

+
+
Variables
+

is_enabled (bool) – boolean option to enable/disable the column.

+
+
+
+
+is_prop_enabled(prop: str) bool
+

Check to see if a property is enabled or not and returns boolean.

+
+
Parameters
+

prop (String) – The option to check if it is enabled

+
+
Returns
+

Whether or not the property is enabled

+
+
Return type
+

Boolean

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.CategoricalOptions(is_enabled: bool = True, top_k_categories: int | None = None, max_sample_size_to_check_stop_condition: int | None = None, stop_condition_unique_value_ratio: float | None = None, cms: bool = False, cms_confidence: float | None = 0.95, cms_relative_error: float | None = 0.01, cms_max_num_heavy_hitters: int | None = 5000)
+

Bases: dataprofiler.profilers.profiler_options.BaseInspectorOptions[CategoricalOptions]

+

For configuring options Categorical Column.

+

Initialize options for the Categorical Column.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable the column.

  • +
  • top_k_categories ([None, int]) – number of categories to be displayed when called

  • +
  • max_sample_size_to_check_stop_condition ([None, int]) – The maximum sample size +before categorical stop conditions are checked

  • +
  • stop_condition_unique_value_ratio ([None, float]) – The highest ratio of unique +values to dataset size that is to be considered a categorical type

  • +
  • cms (bool) – boolean option for using count min sketch

  • +
  • cms_confidence ([None, float]) – defines the number of hashes used in CMS. +eg. confidence = 1 - failure probability, default 0.95

  • +
  • cms_relative_error ([None, float]) – defines the number of buckets used in CMS, +default 0.01

  • +
  • cms_max_num_heavy_hitters – value used to define

  • +
+
+
+

the threshold for minimum frequency required by a category to be counted +:vartype cms_max_num_heavy_hitters: [None, int]

+
+
+is_prop_enabled(prop: str) bool
+

Check to see if a property is enabled or not and returns boolean.

+
+
Parameters
+

prop (String) – The option to check if it is enabled

+
+
Returns
+

Whether or not the property is enabled

+
+
Return type
+

Boolean

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.CorrelationOptions(is_enabled: bool = False, columns: Optional[list] = None)
+

Bases: dataprofiler.profilers.profiler_options.BaseInspectorOptions[CorrelationOptions]

+

For configuring options for Correlation between Columns.

+

Initialize options for the Correlation between Columns.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable.

  • +
  • columns (list()) – Columns considered to calculate correlation

  • +
+
+
+
+
+is_prop_enabled(prop: str) bool
+

Check to see if a property is enabled or not and returns boolean.

+
+
Parameters
+

prop (String) – The option to check if it is enabled

+
+
Returns
+

Whether or not the property is enabled

+
+
Return type
+

Boolean

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.HyperLogLogOptions(seed: int = 0, register_count: int = 15)
+

Bases: dataprofiler.profilers.profiler_options.BaseOption[HyperLogLogOptions]

+

Options for alternative method of gathering unique row count.

+

Initialize options for the hyperloglog method of gathering unique row count.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable.

  • +
  • seed (int) – seed used to set HLL hashing function

  • +
  • register_count (int) – number of registers is equal to 2^register_count

  • +
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.UniqueCountOptions(is_enabled: bool = True, hashing_method: str = 'full')
+

Bases: dataprofiler.profilers.profiler_options.BooleanOption[UniqueCountOptions]

+

For configuring options for unique row count.

+

Initialize options for unique row counts.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable.

  • +
  • hashing_method (str) – property to specify row hashing method (“full” | “hll”)

  • +
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.RowStatisticsOptions(is_enabled: bool = True, unique_count: bool = True, null_count: bool = True)
+

Bases: dataprofiler.profilers.profiler_options.BooleanOption[RowStatisticsOptions]

+

For configuring options for row statistics.

+

Initialize options for row statistics.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable.

  • +
  • unique_count (bool) – boolean option to enable/disable unique_count

  • +
+
+
+

ivar null_count: boolean option to enable/disable null_count +:vartype null_count: bool

+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.DataLabelerOptions
+

Bases: dataprofiler.profilers.profiler_options.BaseInspectorOptions[DataLabelerOptions]

+

For configuring options for Data Labeler Column.

+

Initialize options for the Data Labeler Column.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable the column.

  • +
  • data_labeler_dirpath (str) – String to load data labeler

  • +
  • max_sample_size (BaseDataLabeler) – Int to decide sample size

  • +
  • data_labeler_object – DataLabeler object used in profiler

  • +
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) DataLabelerOptions
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

DataLabelerOptions

+
+
+
+
+
+is_prop_enabled(prop: str) bool
+

Check to see if a property is enabled or not and returns boolean.

+
+
Parameters
+

prop (String) – The option to check if it is enabled

+
+
Returns
+

Whether or not the property is enabled

+
+
Return type
+

Boolean

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.TextProfilerOptions(is_enabled: bool = True, is_case_sensitive: bool = True, stop_words: Optional[set] = None, top_k_chars: Optional[int] = None, top_k_words: Optional[int] = None)
+

Bases: dataprofiler.profilers.profiler_options.BaseInspectorOptions[TextProfilerOptions]

+

For configuring options for text profiler.

+

Construct the TextProfilerOption object with default values.

+
+
Variables
+
    +
  • is_enabled (bool) – boolean option to enable/disable the option.

  • +
  • is_case_sensitive (bool) – option set for case sensitivity.

  • +
  • stop_words (Union[None, list(str)]) – option set for stop words.

  • +
  • top_k_chars (Union[None, int]) – option set for number of top common characters.

  • +
  • top_k_words (Union[None, int]) – option set for number of top common words.

  • +
  • words (BooleanOption) – option set for word update.

  • +
  • vocab (BooleanOption) – option set for vocab update.

  • +
+
+
+
+
+is_prop_enabled(prop: str) bool
+

Check to see if a property is enabled or not and returns boolean.

+
+
Parameters
+

prop (String) – The option to check if it is enabled

+
+
Returns
+

Whether or not the property is enabled

+
+
Return type
+

Boolean

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.StructuredOptions(null_values: dict[str, re.RegexFlag | int] = None, column_null_values: dict[int, dict[str, re.RegexFlag | int]] = None, sampling_ratio: float = 0.2)
+

Bases: dataprofiler.profilers.profiler_options.BaseOption[StructuredOptions]

+

For configuring options for structured profiler.

+

Construct the StructuredOptions object with default values.

+
+
Parameters
+
    +
  • null_values – null values we input.

  • +
  • column_null_values – column level null values we input.

  • +
+
+
Variables
+
    +
  • int (IntOptions) – option set for int profiling.

  • +
  • float (FloatOptions) – option set for float profiling.

  • +
  • datetime (DateTimeOptions) – option set for datetime profiling.

  • +
  • text (TextOptions) – option set for text profiling.

  • +
  • order (OrderOptions) – option set for order profiling.

  • +
  • category (CategoricalOptions) – option set for category profiling.

  • +
  • data_labeler (DataLabelerOptions) – option set for data_labeler profiling.

  • +
  • correlation (CorrelationOptions) – option set for correlation profiling.

  • +
  • chi2_homogeneity (BooleanOption()) – option set for chi2_homogeneity matrix

  • +
  • row_statistics (BooleanOption()) – option set for row statistics calculations

  • +
  • null_replication_metrics (BooleanOptions) – option set for metrics +calculation for replicating nan vals

  • +
  • null_values (Union[None, dict]) – option set for defined null values

  • +
  • sampling_ratio (Union[None, float]) – What ratio of the input data to sample. +Float value > 0 and <= 1

  • +
+
+
+
+
+property enabled_profiles: list
+

Return a list of the enabled profilers for columns.

+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.UnstructuredOptions
+

Bases: dataprofiler.profilers.profiler_options.BaseOption[UnstructuredOptions]

+

For configuring options for unstructured profiler.

+

Construct the UnstructuredOptions object with default values.

+
+
Variables
+
+
+
+
+
+property enabled_profiles: list
+

Return a list of the enabled profilers.

+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+set(options: dict) None
+

Set all the options.

+

Send in a dict that contains all of or a subset of +the appropriate options. Set the values of the options. Will raise error +if the formatting is improper.

+
+
Parameters
+

options (dict) – dict containing the options you want to set.

+
+
Returns
+

None

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+
+class dataprofiler.profilers.profiler_options.ProfilerOptions(presets: Optional[str] = None)
+

Bases: dataprofiler.profilers.profiler_options.BaseOption[ProfilerOptions]

+

For configuring options for profiler.

+

Initialize the ProfilerOptions object.

+
+
Variables
+
    +
  • structured_options (StructuredOptions) – option set for structured dataset profiling.

  • +
  • unstructured_options (UnstructuredOptions) – option set for unstructured dataset profiling.

  • +
  • presets (Optional[str]) – A pre-configured mapping of a string name to group of options: +“complete”, “data_types”, “numeric_stats_disabled”, +and “lower_memory_sketching”. Default: None

  • +
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None) BaseOption
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config to override loading options params from dictionary

  • +
+
+
Returns
+

Options with attributes populated.

+
+
Return type
+

BaseOption

+
+
+
+
+
+property properties: dict
+

Return a copy of the option properties.

+
+
Returns
+

dictionary of the option’s properties attr: value

+
+
Return type
+

dict

+
+
+
+
+
+validate(raise_error: bool = True) list[str] | None
+

Validate the options do not conflict and cause errors.

+

Raises error/warning if so.

+
+
Parameters
+

raise_error (bool) – Flag that raises errors if true. Returns errors if +false.

+
+
Returns
+

list of errors (if raise_error is false)

+
+
Return type
+

list(str)

+
+
+
+
+
+set(options: dict) None
+

Overwrite BaseOption.set.

+

We do this because the type (unstructured/structured) may +need to be specified if the same options exist within both +self.structured_options and self.unstructured_options

+
+
Parameters
+

options (dict) – Dictionary of options to set

+
+
Return
+

None

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.profiler_utils.html b/docs/0.10.5/html/dataprofiler.profilers.profiler_utils.html new file mode 100644 index 000000000..10d6eda37 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.profiler_utils.html @@ -0,0 +1,825 @@ + + + + + + + + + Profiler Utils - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Profiler Utils

+

Contains functions for profilers.

+
+
+dataprofiler.profilers.profiler_utils.recursive_dict_update(d: dict, update_d: dict) dict
+

Recursive updates nested dictionaries. Updating d with update_d.

+
+
Parameters
+
    +
  • d – dict which gets updated with update_d

  • +
  • update_d – dict to update d with

  • +
+
+
Returns
+

updated dict

+
+
+
+
+
+class dataprofiler.profilers.profiler_utils.KeyDict
+

Bases: collections.defaultdict

+

Helper class for sample_in_chunks.

+

Allows keys that are missing to become the values for that key. +From: +https://www.drmaciver.com/2018/01/lazy-fisher-yates-shuffling-for-precise-rejection-sampling/

+
+
+clear() None.  Remove all items from D.
+
+
+
+copy() a shallow copy of D.
+
+
+
+default_factory
+

Factory for default value called by __missing__().

+
+
+
+fromkeys(value=None, /)
+

Create a new dictionary with keys from iterable and values set to value.

+
+
+
+get(key, default=None, /)
+

Return the value for key if key is in the dictionary, else default.

+
+
+
+items() a set-like object providing a view on D’s items
+
+
+
+keys() a set-like object providing a view on D’s keys
+
+
+
+pop(k[, d]) v, remove specified key and return the corresponding value.
+

If key is not found, default is returned if given, otherwise KeyError is raised

+
+
+
+popitem()
+

Remove and return a (key, value) pair as a 2-tuple.

+

Pairs are returned in LIFO (last-in, first-out) order. +Raises KeyError if the dict is empty.

+
+
+
+setdefault(key, default=None, /)
+

Insert key with a value of default if key is not in the dictionary.

+

Return the value for key if key is in the dictionary, else default.

+
+
+
+update([E, ]**F) None.  Update D from dict/iterable E and F.
+

If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] +If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v +In either case, this is followed by: for k in F: D[k] = F[k]

+
+
+
+values() an object providing a view on D’s values
+
+
+
+
+dataprofiler.profilers.profiler_utils.shuffle_in_chunks(data_length: int, chunk_size: int) Generator[list, None, Any]
+

Create shuffled indexes in chunks.

+

This reduces the cost of having to create all indexes, +but only of that what is needed. +Initial Code idea from: +https://www.drmaciver.com/2018/01/lazy-fisher-yates-shuffling-for-precise-rejection-sampling/

+
+
Parameters
+
    +
  • data_length – length of data to be shuffled

  • +
  • chunk_size – size of shuffled chunks

  • +
+
+
Returns
+

list of shuffled indices of chunk size

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.warn_on_profile(col_profile: str, e: Exception) None
+

Return a warning if a given profile errors (tensorflow typically).

+
+
Parameters
+
    +
  • col_profile (str) – Name of the column profile

  • +
  • e (Exception) – Error message from profiler error

  • +
+
+
+
+
+
+dataprofiler.profilers.profiler_utils.partition(data: list, chunk_size: int) Generator[list, None, Any]
+

Create a generator which returns data in specified chunk size.

+
+
Parameters
+
    +
  • data (list, dataframe, etc) – list, dataframe, etc

  • +
  • chunk_size (int) – size of partition to return

  • +
+
+
+
+
+
+dataprofiler.profilers.profiler_utils.auto_multiprocess_toggle(data: pandas.core.frame.DataFrame, num_rows_threshold: int = 750000, num_cols_threshold: int = 20) bool
+

Automate multiprocessing toggle depending on dataset sizes.

+
+
Parameters
+
    +
  • data (pandas.DataFrame) – a dataset

  • +
  • num_rows_threshold (int) – threshold for number of rows to +use multiprocess

  • +
  • num_cols_threshold (int) – threshold for number of columns +to use multiprocess

  • +
+
+
Returns
+

recommended option.multiprocess.is_enabled value

+
+
Return type
+

bool

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.suggest_pool_size(data_size: int = None, cols: int = None) int | None
+

Suggest the pool size based on resources.

+
+
Parameters
+
    +
  • data_size (int) – size of the dataset

  • +
  • cols (int) – columns of the dataset

  • +
+
+
Return suggested_pool_size
+

suggested pool size

+
+
Rtype suggested_pool_size
+

int

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.generate_pool(max_pool_size: int = None, data_size: int = None, cols: int = None) tuple[Pool | None, int | None]
+

Generate a multiprocessing pool to allocate functions too.

+
+
Parameters
+
    +
  • max_pool_size (Union[int, None]) – Max number of processes assigned to the pool

  • +
  • data_size (int) – size of the dataset

  • +
  • cols (int) – columns of the dataset

  • +
+
+
Return pool
+

Multiprocessing pool to allocate processes to

+
+
Rtype pool
+

Multiproessing.Pool

+
+
Return cpu_count
+

Number of processes (cpu bound) to utilize

+
+
Rtype cpu_count
+

int

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.overlap(x1: int | Any, x2: int | Any, y1: int | Any, y2: int | Any) bool
+

Return True iff [x1:x2] overlaps with [y1:y2].

+
+
+
+dataprofiler.profilers.profiler_utils.add_nested_dictionaries(first_dict: dict, second_dict: dict) dict
+

Merge two dictionaries together and add values together.

+
+
Parameters
+
    +
  • first_dict (dict) – dictionary to be merged

  • +
  • second_dict (dict) – dictionary to be merged

  • +
+
+
Returns
+

merged dictionary

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.biased_skew(df_series: pandas.core.series.Series) numpy.float64
+

Calculate the biased estimator for skewness of the given data.

+
+
The definition is formalized as g_1 here:

https://en.wikipedia.org/wiki/Skewness#Sample_skewness

+
+
+
+
Parameters
+

df_series (pandas Series) – data to get skewness of, assuming floats

+
+
Returns
+

biased skewness

+
+
Return type
+

np.float64

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.biased_kurt(df_series: pandas.core.series.Series) numpy.float64
+

Calculate the biased estimator for kurtosis of the given data.

+
+
The definition is formalized as g_2 here:

https://en.wikipedia.org/wiki/Kurtosis#A_natural_but_biased_estimator

+
+
+
+
Parameters
+

df_series (pandas Series) – data to get kurtosis of, assuming floats

+
+
Returns
+

biased kurtosis

+
+
Return type
+

np.float64

+
+
+
+
+
+class dataprofiler.profilers.profiler_utils.Subtractable(*args, **kwargs)
+

Bases: Protocol

+

Protocol for annotating subtractable types.

+
+
+
+dataprofiler.profilers.profiler_utils.find_diff_of_numbers(stat1: int | float | np.float64 | np.int64 | None, stat2: int | float | np.float64 | np.int64 | None) Any
+
+dataprofiler.profilers.profiler_utils.find_diff_of_numbers(stat1: T | None, stat2: T | None) Any
+

Find the difference between two stats.

+

If there is no difference, return “unchanged”. +For ints/floats, returns stat1 - stat2.

+
+
Parameters
+
    +
  • stat1 (Union[int, float, np.float64, np.int64, None]) – the first statistical input

  • +
  • stat2 (Union[int, float, np.float64, np.int64, None]) – the second statistical input

  • +
+
+
Returns
+

the difference of the stats

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.find_diff_of_strings_and_bools(stat1: str | bool | None, stat2: str | bool | None) list[str | bool | None] | str
+

Find the difference between two stats.

+

If there is no difference, return “unchanged”. +For strings and bools, return list containing [stat1, stat2].

+
+
Parameters
+
    +
  • stat1 (Union[str, bool]) – the first statistical input

  • +
  • stat2 (Union[str, bool]) – the second statistical input

  • +
+
+
Returns
+

the difference of the stats

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.find_diff_of_lists_and_sets(stat1: list | set | None, stat2: list | set | None) list[list | set | None] | str
+

Find the difference between two stats.

+

If there is no difference, return +“unchanged”. Remove duplicates and returns [unique values of stat1, +shared values, unique values of stat2].

+
+
Parameters
+
    +
  • stat1 (Union[list, set]) – the first statistical input

  • +
  • stat2 (Union[list, set]) – the second statistical input

  • +
+
+
Returns
+

the difference of the stats

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.find_diff_of_dates(stat1: datetime.datetime | None, stat2: datetime.datetime | None) list | str | None
+

Find the difference between two dates.

+

If there is no difference, return +“unchanged”. For dates, return the difference in time.

+

Because only days can be stored as negative values internally +for timedelta objects, the output for these negative values is +less readable due to the combination of signs in the default +output. This returns a readable output for timedelta that +accounts for potential negative differences.

+
+
Parameters
+
    +
  • stat1 (datetime.datetime object) – the first statistical input

  • +
  • stat2 (datetime.datetime object) – the second statistical input

  • +
+
+
Returns
+

difference in stats

+
+
Return type
+

Union[List, str]

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.find_diff_of_dicts(dict1: dict | None, dict2: dict | None) dict | str
+

Find the difference between two dicts.

+

For each key in each dict, +return “unchanged” if there’s no difference, otherwise return +the difference. Assume that if the two dictionaries share the +same key, their values are the same type.

+
+
Parameters
+
    +
  • dict1 (dict) – the first dict

  • +
  • dict2 (dict) – the second dict

  • +
+
+
Returns
+

Difference in the keys of each dict

+
+
Return type
+

dict

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.find_diff_of_matrices(matrix1: np.ndarray | None, matrix2: np.ndarray | None) np.ndarray | str | None
+

Find the difference between two matrices.

+
+
Parameters
+
    +
  • matrix1 (list(list(float))) – the first matrix

  • +
  • matrix2 (list(list(float))) – the second matrix

  • +
+
+
Returns
+

Difference in the matrix

+
+
Return type
+

list(list(float))

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.find_diff_of_dicts_with_diff_keys(dict1: dict | None, dict2: dict | None) list[dict] | str
+

Find the difference between two dicts.

+

For each key in each dict, +return “unchanged” if there’s no difference, otherwise return +the difference. Assume that if the two dictionaries share the +same key, their values are the same type.

+
+
Parameters
+
    +
  • dict1 (dict) – the first dict

  • +
  • dict2 (dict) – the second dict

  • +
+
+
Returns
+

Difference in the keys of each dict

+
+
Return type
+

list

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.get_memory_size(data: list | np.ndarray | DataFrame, unit: str = 'M') float
+

Get memory size of the input data.

+
+
Parameters
+
    +
  • data (Union[list, numpy.array, pandas.DataFrame]) – list or array of data

  • +
  • unit (string) – memory size unit (B, K, M, or G)

  • +
+
+
Returns
+

memory size of the input data

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.method_timeit(method: Optional[Callable] = None, name: Optional[str] = None) Callable
+

Measure execution time of provided method.

+

Record time into times dictionary.

+
+
Parameters
+
    +
  • method (Callable) – method to time

  • +
  • name (str) – key argument for the times dictionary

  • +
+
+
+
+
+
+dataprofiler.profilers.profiler_utils.perform_chi_squared_test_for_homogeneity(categories1: dict, sample_size1: int, categories2: dict, sample_size2: int) dict[str, int | float | None]
+

Perform a Chi Squared test for homogeneity between two groups.

+
+
Parameters
+
    +
  • categories1 (dict) – Categories and respective counts of the first group

  • +
  • sample_size1 (int) – Number of samples in first group

  • +
  • categories2 (dict) – Categories and respective counts of the second group

  • +
  • sample_size2 (int) – Number of samples in second group

  • +
+
+
Returns
+

Results of the chi squared test

+
+
Return type
+

dict

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.chunk(lst: list, size: int) Iterator[tuple]
+

Chunk things out.

+
+
Parameters
+
    +
  • lst (list) – List to chunk

  • +
  • size (int) – Size of each chunk

  • +
+
+
Returns
+

Iterator that produces tuples of each chunk

+
+
Return type
+

Iterator[Tuple]

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.merge(top_profile: profile_builder.BaseProfiler, other_profile: profile_builder.BaseProfiler = None) profile_builder.BaseProfiler
+

Merge two Profiles.

+
+
Parameters
+
    +
  • top_profile (Profile) – First profile

  • +
  • other_profile (Profile) – Second profile

  • +
+
+
Returns
+

Merge of two profile objects

+
+
Return type
+

Profile

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.merge_profile_list(list_of_profiles: list[profile_builder.BaseProfiler], pool_count: int = 5) profile_builder.BaseProfiler
+

Merge list of profiles into a single profile.

+
+
Parameters
+
    +
  • list_of_profiles (list) – Categories and respective counts of the second group

  • +
  • pool_count (int) – Number of samples in second group

  • +
+
+
Returns
+

Single profile that is the merge of all profiles in the +list_of_profiles list.

+
+
Return type
+

Profile

+
+
+
+
+
+dataprofiler.profilers.profiler_utils.reload_labeler_from_options_or_get_new(data_labeler_load_attr: dict, config: dict | None = None) BaseDataLabeler | None
+

If required by the load_attr load a data labeler, but reuse from config if possible.

+
+
Parameters
+
    +
  • data_labeler_load_attr (dict[string, dict]) – dictionary with attributes and values.

  • +
  • config (dict[string, dict]) – config for loading classes to reuse an existing labeler

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

DataLabelerOptions

+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.text_column_profile.html b/docs/0.10.5/html/dataprofiler.profilers.text_column_profile.html new file mode 100644 index 000000000..d0ed0b990 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.text_column_profile.html @@ -0,0 +1,588 @@ + + + + + + + + + Text Column Profile - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Text Column Profile

+

Text profile analysis for individual col within structured profiling..

+
+
+class dataprofiler.profilers.text_column_profile.TextColumn(name: str | None, options: TextOptions = None)
+

Bases: dataprofiler.profilers.numerical_column_stats.NumericStatsMixin[TextColumn], dataprofiler.profilers.base_column_profilers.BaseColumnPrimitiveTypeProfiler[TextColumn]

+

Text column profile subclass of BaseColumnProfiler.

+

Represents a column in the dataset which is a text column.

+

Initialize column base properties and itself.

+
+
Parameters
+
    +
  • name (String) – Name of the data

  • +
  • options (TextOptions) – Options for the Text column

  • +
+
+
+
+
+type: str | None = 'text'
+
+
+
+report(remove_disabled_flag: bool = False) dict
+

Report profile attribute of class; potentially pop val from self.profile.

+
+
+
+property profile: dict
+

Return the profile of the column.

+
+
Returns
+

+
+
+
+
+
+diff(other_profile: dataprofiler.profilers.text_column_profile.TextColumn, options: Optional[dict] = None) dict
+

Find the differences for text columns.

+
+
Parameters
+

other_profile (TextColumn Profile) – profile to find the difference with

+
+
Returns
+

the text columns differences

+
+
Return type
+

dict

+
+
+
+
+
+property data_type_ratio: float | None
+

Calculate the ratio of samples which match this data type.

+

NOTE: all values can be considered string so always returns 1 in this +case.

+
+
Returns
+

ratio of data type

+
+
Return type
+

float

+
+
+
+
+
+update(df_series: pandas.core.series.Series) dataprofiler.profilers.text_column_profile.TextColumn
+

Update the column profile.

+
+
Parameters
+

df_series (pandas.core.series.Series) – df series

+
+
Returns
+

updated TextColumn

+
+
Return type
+

TextColumn

+
+
+
+
+
+classmethod load_from_dict(data, config: dict | None = None)
+

Parse attribute from json dictionary into self.

+
+
Parameters
+
    +
  • data (dict[string, Any]) – dictionary with attributes and values.

  • +
  • config (Dict | None) – config for loading column profiler params from dictionary

  • +
+
+
Returns
+

Profiler with attributes populated.

+
+
Return type
+

TextColumn

+
+
+
+
+
+col_type = None
+
+
+
+static is_float(x: str) bool
+

Return True if x is float.

+

For “0.80” this function returns True +For “1.00” this function returns True +For “1” this function returns True

+
+
Parameters
+

x (str) – string to test

+
+
Returns
+

if is float or not

+
+
Return type
+

bool

+
+
+
+
+
+static is_int(x: str) bool
+

Return True if x is integer.

+

For “0.80” This function returns False +For “1.00” This function returns True +For “1” this function returns True

+
+
Parameters
+

x (str) – string to test

+
+
Returns
+

if is integer or not

+
+
Return type
+

bool

+
+
+
+
+
+property kurtosis: float | np.float64
+

Return kurtosis value.

+
+
+
+property mean: float | np.float64
+

Return mean value.

+
+
+
+property median: float
+

Estimate the median of the data.

+
+
Returns
+

the median

+
+
Return type
+

float

+
+
+
+
+
+property median_abs_deviation: float | np.float64
+

Get median absolute deviation estimated from the histogram of the data.

+
+

Subtract bin edges from the median value +Fold the histogram to positive and negative parts around zero +Impose the two bin edges from the two histogram +Calculate the counts for the two histograms with the imposed bin edges +Superimpose the counts from the two histograms +Interpolate the median absolute deviation from the superimposed counts

+
+
+
Returns
+

median absolute deviation

+
+
+
+
+
+property mode: list
+

Find an estimate for the mode[s] of the data.

+
+
Returns
+

the mode(s) of the data

+
+
Return type
+

list(float)

+
+
+
+
+
+static np_type_to_type(val: Any) Any
+

Convert numpy variables to base python type variables.

+
+
Parameters
+

val (numpy type or base type) – value to check & change

+
+
Return val
+

base python type

+
+
Rtype val
+

int or float

+
+
+
+
+
+property skewness: float | np.float64
+

Return skewness value.

+
+
+
+property stddev: float | np.float64
+

Return stddev value.

+
+
+
+property variance: float | np.float64
+

Return variance.

+
+
+
+min: int | float | np.float64 | np.int64 | None
+
+
+
+max: int | float | np.float64 | np.int64 | None
+
+
+
+sum: int | float | np.float64 | np.int64
+
+
+
+max_histogram_bin: int
+
+
+
+min_histogram_bin: int
+
+
+
+histogram_bin_method_names: list[str]
+
+
+
+histogram_selection: str | None
+
+
+
+user_set_histogram_bin: int | None
+
+
+
+bias_correction: bool
+
+
+
+num_zeros: int | np.int64
+
+
+
+num_negatives: int | np.int64
+
+
+
+histogram_methods: dict
+
+
+
+quantiles: list[float] | None
+
+
+
+match_count: int
+
+
+
+name: str | None
+
+
+
+sample_size: int
+
+
+
+metadata: dict
+
+
+
+times: dict
+
+
+
+thread_safe: bool
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.unstructured_labeler_profile.html b/docs/0.10.5/html/dataprofiler.profilers.unstructured_labeler_profile.html new file mode 100644 index 000000000..9e853cb73 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.unstructured_labeler_profile.html @@ -0,0 +1,348 @@ + + + + + + + + + Unstructured Labeler Profile - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Unstructured Labeler Profile

+

Profile analysis for applying labels within unstructured profiling.

+
+
+class dataprofiler.profilers.unstructured_labeler_profile.UnstructuredLabelerProfile(data_labeler_dirpath: Optional[str] = None, options: Optional[dataprofiler.profilers.profiler_options.DataLabelerOptions] = None)
+

Bases: object

+

Profiles and labels unstructured data.

+

Initialize of Data Label profiling for unstructured datasets.

+
+
Parameters
+
    +
  • data_labeler_dirpath (String) – Directory path to the data labeler

  • +
  • options (DataLabelerOptions) – Options for the data labeler column

  • +
+
+
+
+
+type = 'data_labeler'
+
+
+
+report(remove_disabled_flag: bool = False) dict
+

Return profile object.

+
+
Parameters
+

remove_disabled_flag (boolean) – flag to determine if disabled options +should be excluded in report.

+
+
+
+
+
+diff(other_profile: dataprofiler.profilers.unstructured_labeler_profile.UnstructuredLabelerProfile, options: Optional[dict] = None) dict
+

Find the differences for two unstructured labeler profiles.

+
+
Parameters
+
    +
  • other_profile (UnstructuredLabelerProfile) – profile to find the difference with

  • +
  • options (dict) – options for diff output

  • +
+
+
Returns
+

the difference between entity counts/percentages

+
+
Return type
+

dict

+
+
+
+
+
+property label_encoding: list
+

Return list of labels.

+
+
+
+update(df_series: pandas.core.series.Series) None
+

Update profile.

+
+
+
+property profile: dict
+

Return a profile.

+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.unstructured_text_profile.html b/docs/0.10.5/html/dataprofiler.profilers.unstructured_text_profile.html new file mode 100644 index 000000000..0a52d766b --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.unstructured_text_profile.html @@ -0,0 +1,356 @@ + + + + + + + + + Unstructured Text Profile - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Unstructured Text Profile

+

For profiling unstructured text data.

+
+
+class dataprofiler.profilers.unstructured_text_profile.TextProfiler(name: str | None, options: TextProfilerOptions = None)
+

Bases: object

+

Profiles text data.

+

Initialize TextProfiler object.

+
+
Parameters
+
    +
  • name (String) – Name of the data

  • +
  • options (TextProfilerOptions) – Options for the Text Profiler

  • +
+
+
+
+
+type = 'text'
+
+
+
+diff(other_profile: dataprofiler.profilers.unstructured_text_profile.TextProfiler, options: Optional[dict] = None) dict
+

Find the differences for two unstructured text profiles.

+
+
Parameters
+
    +
  • other_profile (TextProfiler) – profile to find the difference with

  • +
  • options (dict) – options for diff output

  • +
+
+
Returns
+

the difference between profiles

+
+
Return type
+

dict

+
+
+
+
+
+report(remove_disabled_flag: bool = False) dict
+

Report profile attribute of class; potentially pop val from self.profile.

+
+
+
+property profile: dict
+

Return the profile of the column.

+
+
Returns
+

profile of the column

+
+
Return type
+

dict

+
+
+
+
+
+update(data: pandas.core.series.Series) dataprofiler.profilers.unstructured_text_profile.TextProfiler
+

Update the column profile.

+
+
Parameters
+

data (pandas.core.series.Series) – df series

+
+
Returns
+

updated TextProfiler

+
+
Return type
+

TextProfiler

+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.profilers.utils.html b/docs/0.10.5/html/dataprofiler.profilers.utils.html new file mode 100644 index 000000000..cdccfda91 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.profilers.utils.html @@ -0,0 +1,265 @@ + + + + + + + + + Utils - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Utils

+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.reports.graphs.html b/docs/0.10.5/html/dataprofiler.reports.graphs.html new file mode 100644 index 000000000..5cad9e329 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.reports.graphs.html @@ -0,0 +1,266 @@ + + + + + + + + + Graphs - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Graphs

+

Contains functions for generating graph data report.

+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.reports.html b/docs/0.10.5/html/dataprofiler.reports.html new file mode 100644 index 000000000..fd514fe96 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.reports.html @@ -0,0 +1,298 @@ + + + + + + + + + Reports - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Reports

+
+

Modules

+
+
+
+ +
+

Package for generating reports.

+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.reports.utils.html b/docs/0.10.5/html/dataprofiler.reports.utils.html new file mode 100644 index 000000000..228993cef --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.reports.utils.html @@ -0,0 +1,291 @@ + + + + + + + + + Utils - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Utils

+

Contains functions for checking for installations/dependencies.

+
+
+dataprofiler.reports.utils.warn_missing_module(graph_func: str, module_name: str) None
+

Return a warning if a given graph module doesn’t exist.

+
+
Parameters
+
    +
  • graph_func (str) – Name of the graphing function

  • +
  • module_name (str) – module name that was missing

  • +
+
+
+
+
+
+dataprofiler.reports.utils.require_module(names: List[str]) Callable[[dataprofiler.reports.utils.F], dataprofiler.reports.utils.F]
+

Check if a set of modules exists in sys.modules prior to running function.

+

If they do not, give a user a warning and do not run the +function.

+
+
Parameters
+

names (list[str]) – list of module names to check for in sys.modules

+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.rng_utils.html b/docs/0.10.5/html/dataprofiler.rng_utils.html new file mode 100644 index 000000000..c75842355 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.rng_utils.html @@ -0,0 +1,271 @@ + + + + + + + + + Rng Utils - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Rng Utils

+

Create a random number generator using a manual seed DATAPROFILER_SEED.

+
+
+dataprofiler.rng_utils.get_random_number_generator() numpy.random._generator.Generator
+

Create a random number generator using a manual seed DATAPROFILER_SEED.

+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.settings.html b/docs/0.10.5/html/dataprofiler.settings.html new file mode 100644 index 000000000..c85759935 --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.settings.html @@ -0,0 +1,266 @@ + + + + + + + + + Settings - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Settings

+

Configure settings for dataprofiler.

+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.validators.base_validators.html b/docs/0.10.5/html/dataprofiler.validators.base_validators.html new file mode 100644 index 000000000..59b5fe8fe --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.validators.base_validators.html @@ -0,0 +1,362 @@ + + + + + + + + + Base Validators - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Base Validators

+

Build model for dataset by identifying col type along with its respective params.

+
+
+dataprofiler.validators.base_validators.is_in_range(x: str | int | float, config: dict) bool
+

Check to see x is in the range of the config.

+
+
Parameters
+
    +
  • x (int/float) – number

  • +
  • config (dict) – configuration

  • +
+
+
Returns
+

bool

+
+
+
+
+
+dataprofiler.validators.base_validators.is_in_list(x: str | int | float, config: dict) bool
+

Check to see x is in the config list.

+
+
Parameters
+
    +
  • x (string) – item

  • +
  • config (dict) – configuration

  • +
+
+
Returns
+

bool

+
+
+
+
+
+class dataprofiler.validators.base_validators.Validator
+

Bases: object

+

For validating a data set.

+

Initialize Validator object.

+
+
+validate(data: pd.DataFrame | dd.DataFrame, config: dict) None
+

Validate a data set.

+

No option for validating a partial data set.

+

Set configuration on run not on instantiation of the class such that +you have the option to run multiple times with different configurations +without having to also reinstantiate the class.

+
+
Parameters
+
    +
  • data (DataFrame Dask/Pandas) – The data to be processed by the validator. Processing +occurs in a column-wise fashion.

  • +
  • config (dict) – configuration for how the validator should +run across the given data. Validator will only run over columns +specified in the configuration.

  • +
+
+
Example
+

This is an example of the config:

+
config = {
+        <column_name>: {
+                range: {
+                    'start': 1,
+                    'end':2
+                },
+                list: [1,2,3]
+            }
+        }
+
+
+
+
+
+
+
+get() dict
+

Get the results of the validation run.

+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.validators.html b/docs/0.10.5/html/dataprofiler.validators.html new file mode 100644 index 000000000..ee3d0251c --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.validators.html @@ -0,0 +1,315 @@ + + + + + + + + + Validators - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Validators

+
+

Modules

+
+
+ +

Package for identifying cols.

+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/dataprofiler.version.html b/docs/0.10.5/html/dataprofiler.version.html new file mode 100644 index 000000000..d7794adef --- /dev/null +++ b/docs/0.10.5/html/dataprofiler.version.html @@ -0,0 +1,266 @@ + + + + + + + + + Version - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Version

+

File contains the version number for the package.

+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/examples.html b/docs/0.10.5/html/examples.html new file mode 100644 index 000000000..48377e8c1 --- /dev/null +++ b/docs/0.10.5/html/examples.html @@ -0,0 +1,427 @@ + + + + + + + + + Examples - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Examples

+

These examples provide a more in-depth look into the details of the Data Profiler library.

+
+

Basics

+
+ +
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/genindex.html b/docs/0.10.5/html/genindex.html new file mode 100644 index 000000000..55f39a49a --- /dev/null +++ b/docs/0.10.5/html/genindex.html @@ -0,0 +1,3431 @@ + + + + + + + Index - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + +
+

Index

+
A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W
+
+
+

A

+ + + +
+
+ +
+

B

+ + + +
+
+ +
+

C

+ + + +
+
+ +
+

D

+ + + +
+
+ +
+

E

+ + + +
+
+ +
+

F

+ + + +
+
+ +
+

G

+ + + +
+
+ +
+

H

+ + + +
+
+ +
+

I

+ + + +
+
+ +
+

J

+ + + +
+
+ +
+

K

+ + + +
+
+ +
+

L

+ + + +
+
+ +
+

M

+ + + +
+
+ +
+

N

+ + + +
+
+ +
+

O

+ + + +
+
+ +
+

P

+ + + +
+
+ +
+

Q

+ + + +
+
+ +
+

R

+ + + +
+
+ +
+

S

+ + + +
+
+ +
+

T

+ + + +
+
+ +
+

U

+ + + +
+
+ +
+

V

+ + + +
+
+ +
+

W

+ + + +
+
+ + +
+
+ + + + + +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/graph_data_demo.html b/docs/0.10.5/html/graph_data_demo.html new file mode 100644 index 000000000..d89332efc --- /dev/null +++ b/docs/0.10.5/html/graph_data_demo.html @@ -0,0 +1,709 @@ + + + + + + + + + Graph Pipeline Demo - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + + +

View this notebook on GitHub

+
+

Graph Pipeline Demo

+

DataProfiler can also load and profile graph datasets. Similarly to the rest of DataProfiler profilers, this is split into two components: - GraphData - GraphProfiler

+

We will demo the use of this graph pipeline.

+

First, let’s import the libraries needed for this example.

+
+
[ ]:
+
+
+
+import os
+import sys
+import pprint
+
+try:
+    sys.path.insert(0, '..')
+    import dataprofiler as dp
+except ImportError:
+    import dataprofiler as dp
+
+data_path = "../dataprofiler/tests/data"
+
+
+
+

We now input our dataset into the generic DataProfiler pipeline:

+
+
[ ]:
+
+
+
+data = dp.Data(os.path.join(data_path, "csv/graph_data_csv_identify.csv"))
+profile = dp.Profiler(data)
+
+report = profile.report()
+
+pp = pprint.PrettyPrinter(sort_dicts=False, compact=True)
+pp.pprint(report)
+
+
+
+

We notice that the Data class automatically detected the input file as graph data. The GraphData class is able to differentiate between tabular and graph csv data. After Data matches the input file as graph data, GraphData does the necessary work to load the csv data into a NetworkX Graph.

+

Profiler runs GraphProfiler when graph data is input (or when data_type="graph" is specified). The report() function outputs the profile for the user.

+
+

Profile

+

The profile skeleton looks like this:

+
profile = {
+    "num_nodes": ...,
+    "num_edges": ...,
+    "categorical_attributes": ...,
+    "continuous_attributes": ...,
+    "avg_node_degree": ...,
+    "global_max_component_size": ...,
+    "continuous_distribution": ...,
+    "categorical_distribution": ...,
+    "times": ...,
+}
+
+
+

Description of properties in profile: - num_nodes: number of nodes in the graph - num_edges: number of edges in the graph - categorical_attributes: list of categorical edge attributes - continuous_attributes: list of continuous edge attributes - avg_node_degree: average degree of nodes in the graph - global_max_component_size: size of largest global max component in the graph - continuous_distribution: dictionary of statistical properties for each continuous attribute +- categorical_distribution: dictionary of statistical properties for each categorical attribute

+

The continuous_distribution and categorical_distribution dictionaries list statistical properties for each edge attribute in the graph:

+
continuous_distribution = {
+    "name": ...,
+    "scale": ...,
+    "properties": ...,
+}
+
+
+
categorical_distribution = {
+    "bin_counts": ...,
+    "bin_edges": ...,
+}
+
+
+

Description of each attribute: - Continuous distribution: - name: name of the distribution - scale: negative log likelihood used to scale distributions and compare them in GraphProfiler - properties: list of distribution props - Categorical distribution: - bin_counts: histogram bin counts - bin_edges: histogram bin edges

+

properties lists the following distribution properties: [optional: shape, loc, scale, mean, variance, skew, kurtosis]. The list can be either 6 length or 7 length depending on the distribution (extra shape parameter): - 6 length: norm, uniform, expon, logistic - 7 length: gamma, lognorm - gamma: shape=a (float) - lognorm: shape=s (float)

+

For more information on shape parameters a and s: https://docs.scipy.org/doc/scipy/tutorial/stats.html#shape-parameters

+
+
+

Saving and Loading a Profile

+

Below you will see an example of how a Graph Profile can be saved and loaded again.

+
+
[ ]:
+
+
+
+# The default save filepath is profile-<datetime>.pkl
+profile.save(filepath="profile.pkl")
+
+new_profile = dp.GraphProfiler.load("profile.pkl")
+new_report = new_profile.report()
+
+
+
+
+
[ ]:
+
+
+
+pp.pprint(report)
+
+
+
+
+
+

Difference in Data

+

If we wanted to ensure that this new profile was the same as the previous profile that we loaded, we could compare them using the diff functionality.

+
+
[ ]:
+
+
+
+diff = profile.diff(new_profile)
+
+
+
+
+
[ ]:
+
+
+
+pp.pprint(diff)
+
+
+
+

Another use for diff might be to provide differences between training and testing profiles as shown in the cell below. We will use the profile above as the training profile and create a new profile to represent the testing profile

+
+
[ ]:
+
+
+
+training_profile = profile
+
+testing_data = dp.Data(os.path.join(data_path, "csv/graph-differentiator-input-positive.csv"))
+testing_profile = dp.Profiler(testing_data)
+
+test_train_diff = training_profile.diff(testing_profile)
+
+
+
+

Below you can observe the difference between the two profiles.

+
+
[ ]:
+
+
+
+pp.pprint(test_train_diff)
+
+
+
+
+
+

Conclusion

+

We have shown the graph pipeline in the DataProfiler. It works similarly to the current DataProfiler implementation.

+
+
+ +
+ +
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/graph_data_demo.ipynb b/docs/0.10.5/html/graph_data_demo.ipynb new file mode 100644 index 000000000..088612872 --- /dev/null +++ b/docs/0.10.5/html/graph_data_demo.ipynb @@ -0,0 +1,271 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Graph Pipeline Demo" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "DataProfiler can also load and profile graph datasets. Similarly to the rest of DataProfiler profilers, this is split into two components:\n", + "- GraphData\n", + "- GraphProfiler\n", + "\n", + "We will demo the use of this graph pipeline.\n", + "\n", + "First, let's import the libraries needed for this example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import pprint\n", + "\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " import dataprofiler as dp\n", + "\n", + "data_path = \"../dataprofiler/tests/data\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now input our dataset into the generic DataProfiler pipeline:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data = dp.Data(os.path.join(data_path, \"csv/graph_data_csv_identify.csv\"))\n", + "profile = dp.Profiler(data)\n", + "\n", + "report = profile.report()\n", + "\n", + "pp = pprint.PrettyPrinter(sort_dicts=False, compact=True)\n", + "pp.pprint(report)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We notice that the `Data` class automatically detected the input file as graph data. The `GraphData` class is able to differentiate between tabular and graph csv data. After `Data` matches the input file as graph data, `GraphData` does the necessary work to load the csv data into a NetworkX Graph. \n", + "\n", + "`Profiler` runs `GraphProfiler` when graph data is input (or when `data_type=\"graph\"` is specified). The `report()` function outputs the profile for the user." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Profile" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The profile skeleton looks like this:\n", + "```\n", + "profile = {\n", + " \"num_nodes\": ...,\n", + " \"num_edges\": ...,\n", + " \"categorical_attributes\": ...,\n", + " \"continuous_attributes\": ...,\n", + " \"avg_node_degree\": ...,\n", + " \"global_max_component_size\": ...,\n", + " \"continuous_distribution\": ...,\n", + " \"categorical_distribution\": ...,\n", + " \"times\": ...,\n", + "}\n", + "```\n", + "\n", + "Description of properties in profile:\n", + "- `num_nodes`: number of nodes in the graph\n", + "- `num_edges`: number of edges in the graph\n", + "- `categorical_attributes`: list of categorical edge attributes\n", + "- `continuous_attributes`: list of continuous edge attributes\n", + "- `avg_node_degree`: average degree of nodes in the graph\n", + "- `global_max_component_size`: size of largest global max component in the graph\n", + "- `continuous_distribution`: dictionary of statistical properties for each continuous attribute\n", + "- `categorical_distribution`: dictionary of statistical properties for each categorical attribute\n", + "\n", + "The `continuous_distribution` and `categorical_distribution` dictionaries list statistical properties for each edge attribute in the graph:\n", + "```\n", + "continuous_distribution = {\n", + " \"name\": ...,\n", + " \"scale\": ...,\n", + " \"properties\": ...,\n", + "}\n", + "```\n", + "```\n", + "categorical_distribution = {\n", + " \"bin_counts\": ...,\n", + " \"bin_edges\": ...,\n", + "}\n", + "```\n", + "Description of each attribute:\n", + "- Continuous distribution:\n", + " - `name`: name of the distribution\n", + " - `scale`: negative log likelihood used to scale distributions and compare them in `GraphProfiler`\n", + " - `properties`: list of distribution props\n", + "- Categorical distribution:\n", + " - `bin_counts`: histogram bin counts\n", + " - `bin_edges`: histogram bin edges\n", + "\n", + "`properties` lists the following distribution properties: [optional: shape, loc, scale, mean, variance, skew, kurtosis]. The list can be either 6 length or 7 length depending on the distribution (extra shape parameter):\n", + "- 6 length: norm, uniform, expon, logistic\n", + "- 7 length: gamma, lognorm\n", + " - gamma: shape=`a` (float)\n", + " - lognorm: shape=`s` (float)\n", + " \n", + "For more information on shape parameters `a` and `s`: https://docs.scipy.org/doc/scipy/tutorial/stats.html#shape-parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Saving and Loading a Profile\n", + "Below you will see an example of how a Graph Profile can be saved and loaded again." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# The default save filepath is profile-.pkl\n", + "profile.save(filepath=\"profile.pkl\")\n", + "\n", + "new_profile = dp.GraphProfiler.load(\"profile.pkl\")\n", + "new_report = new_profile.report()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pp.pprint(report)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Difference in Data\n", + "If we wanted to ensure that this new profile was the same as the previous profile that we loaded, we could compare them using the diff functionality." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "diff = profile.diff(new_profile)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pp.pprint(diff)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another use for diff might be to provide differences between training and testing profiles as shown in the cell below.\n", + "We will use the profile above as the training profile and create a new profile to represent the testing profile" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "training_profile = profile\n", + "\n", + "testing_data = dp.Data(os.path.join(data_path, \"csv/graph-differentiator-input-positive.csv\"))\n", + "testing_profile = dp.Profiler(testing_data)\n", + "\n", + "test_train_diff = training_profile.diff(testing_profile)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Below you can observe the difference between the two profiles." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pp.pprint(test_train_diff)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Conclusion" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have shown the graph pipeline in the DataProfiler. It works similarly to the current DataProfiler implementation." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/0.10.5/html/graphs.html b/docs/0.10.5/html/graphs.html new file mode 100644 index 000000000..2bf0b706e --- /dev/null +++ b/docs/0.10.5/html/graphs.html @@ -0,0 +1,488 @@ + + + + + + + + + Graphs - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Graphs

+
+

Graph Your Data

+

We can plot some of our data as seaborn histogram plots. Below will demonstrate how to do so and provide examples.

+

The following plots are currently available to work directly with your profilers:

+
+
    +
  • histogram (numeric columns only)

  • +
  • missing values matrix

  • +
+
+

Below shows how to do so with examples.

+
+

What we need to import

+
from dataprofiler.reports import graphs
+
+
+

The main functions that is used to plot histograms are in graphs. You will also need the `dataprofiler[reports]` requirement to be installed:

+
pip install 'dataprofiler[reports]'
+
+
+
+
+

Plotting from a StructuredProfiler class

+

With a StructuredProfiler class variable, we can specify what columns we want to be plotted, and plot them into histograms.

+
graphs.plot_histograms(profiler, column_names, column_inds)
+
+
+

These are what the variables mean:

+
+
    +
  • profiler - StructuredProfiler class variable that contains the data we want

  • +
  • columns - (Optional) The list of IntColumn or FloatColumn names we want to specifically plot. If specified, column_inds cannot be specified.

  • +
  • column_inds - (Optional) The list of IntColumn or FloatColumn indexes we want to specifically plot. If specified, column_names cannot be specified.

  • +
+
+

Additionally, we can also plot the missing values matrix for a StructuredProfiler:

+
graphs.plot_missing_values_matrix(profiler, ax, title)
+
+
+

These are what the variables mean:

+
+
    +
  • profiler - StructuredProfiler class variable that contains the data we want

  • +
  • ax - (Optional) MatPlotLib Axes to plot the matrix within.

  • +
  • title - (Optional) The title of the axes we want to define.

  • +
+
+
+
+

Plotting an individual IntColumn or FloatColumn

+

With a column’s Int or Float profile, we can plot their respective histograms.

+
graphs.plot_col_histogram(column, axes, title)
+
+
+

These are what the variables mean:

+
+
    +
  • column - The IntColumn or FloatColumn we want to plot

  • +
  • axes - (Optional) The MatPlotLib Axes to plot the histogram within.

  • +
  • title - (Optional) The title of the axes we want to define.

  • +
+
+

Additionally, we can also plot the missing values bargraph for any column profile:

+
graphs.plot_col_missing_values(profiler, ax, title)
+
+
+

These are what the variables mean:

+
+
    +
  • profiler - The StructuredColProfiler we want to plot

  • +
  • ax - (Optional) MatPlotLib Axes to plot the matrix within.

  • +
  • title - (Optional) The title of the axes we want to define.

  • +
+
+
+
+

Examples

+
+

Histograms

+
    +
  1. This example demonstrates how we can take a StructuredProfiler class and plot histograms of the specified columns.

  2. +
+
import dataprofiler as dp
+from dataprofiler.reports import graphs
+
+
+data = [[1, 'a', 1.0],
+        [2, 'b', 2.2],
+        [3, 'c', 3.5],
+        [None, 'd', 10.0]]
+profiler = dp.StructuredProfiler(data)
+
+# This will plot all IntColumn and FloatColumn as histograms (The first and last column).
+fig = graphs.plot_histograms(profiler)
+fig.show()
+
+# This will only plot the specified column, 0.
+columns_names = [0]
+fig = graphs.plot_histograms(profiler, columns_names)
+fig.show()
+
+
+First Histogram Example Image +Second Histogram Example Image +
    +
  1. This example demonstrates how we can plot a low level profiler.

  2. +
+
import pandas as pd
+
+from dataprofiler.profilers import IntColumn
+from dataprofiler.reports import graphs
+
+
+data = pd.Series([1, 2, 3], dtype=str)
+profiler = IntColumn('example')
+profiler.update(data)
+
+# Plot the axes
+ax = graphs.plot_col_histogram(profiler)
+
+# get and show the figure of the plotted histogram
+fig = ax.get_figure()
+fig.show()
+
+
+Histogram Column Only Example Image +
+
+

Missing Values Matrix

+
    +
  1. This example demonstrates how we can take a StructuredProfiler class and plot a missing values matrix.

  2. +
+
import dataprofiler as dp
+from dataprofiler.reports import graphs
+
+
+data = pd.DataFrame(
+    [[None, '', 1.0, '1/2/2021'],
+     [3, None, 3.5, ''],
+     [1, None, 1.0, '2/5/2020'],
+     [None, 1, 10.0, '3/5/2020']],
+    columns=['integer', 'str', 'float', 'datetime'],
+    dtype=object
+)
+profiler = dp.StructuredProfiler(data)
+
+# This will plot the missing values matrix for all columns.
+fig = graphs.plot_missing_values_matrix(profiler)
+fig.show()
+
+
+Missing Values Matrix Example Image +
    +
  1. This example demonstrates how we can plot barchart of a column’s missing values.

  2. +
+
import pandas as pd
+
+from dataprofiler.profilers.profile_builder import StructuredColProfiler
+from dataprofiler.reports import graphs
+
+
+data = pd.Series([1, 2, 3, None, None, 4], name='example', dtype=str)
+profiler = StructuredColProfiler(data)
+
+# Plot the axes, can be a list of multiple columns
+ax = graphs.plot_col_missing_values([profiler])
+
+# get and show the figure of the plotted histogram
+fig = ax.get_figure()
+fig.show()
+
+
+Missing Values Column Only Example Image +
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/index.html b/docs/0.10.5/html/index.html new file mode 100644 index 000000000..cfee16638 --- /dev/null +++ b/docs/0.10.5/html/index.html @@ -0,0 +1,746 @@ + + + + + + + + + Home - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Data Profiler | What’s in your data?

+
+

Purpose

+

The DataProfiler is a Python library designed to make data analysis, monitoring and sensitive data detection easy.

+

Loading Data with a single command, the library automatically formats & loads files into a DataFrame. Profiling the Data, the library identifies the schema, statistics, entities and more. Data Profiles can then be used in downstream applications or reports.

+

The Data Profiler comes with a cutting edge pre-trained deep learning model, used to efficiently identify sensitive data (or PII). If customization is needed, it’s easy to add new entities to the existing pre-trained model or insert a new pipeline for entity recognition.

+

The best part? Getting started only takes a few lines of code (Example CSV):

+
import json
+from dataprofiler import Data, Profiler
+
+data = Data("your_file.csv") # Auto-Detect & Load: CSV, AVRO, Parquet, JSON, Text
+print(data.data.head(5)) # Access data directly via a compatible Pandas DataFrame
+
+profile = Profiler(data) # Calculate Statistics, Entity Recognition, etc
+readable_report = profile.report(report_options={"output_format":"pretty"})
+print(json.dumps(readable_report, indent=4))
+
+
+

To install the full package from pypi:

+
pip install DataProfiler[ml]
+
+
+

If the ML requirements are too strict (say, you don’t want to install tensorflow), you can install a slimmer package. The slimmer package disables the default sensitive data detection / entity recognition (labler)

+

Install from pypi:

+
pip install DataProfiler
+
+
+

If you have suggestions or find a bug, please open an issue.

+

Visit the API to explore Data Profiler’s terminology.

+
+
+

What is a Data Profile?

+

In the case of this library, a data profile is a dictionary containing statistics and predictions about the underlying dataset. There are “global statistics” or global_stats, which contain dataset level data and there are “column/row level statistics” or data_stats (each column is a new key-value entry).

+

The format for a structured profile is below:

+
"global_stats": {
+    "samples_used": int,
+    "column_count": int,
+    "row_count": int,
+    "row_has_null_ratio": float,
+    "row_is_null_ratio": float,
+    "unique_row_ratio": float,
+    "duplicate_row_count": int,
+    "file_type": string,
+    "encoding": string,
+    "correlation_matrix": list[list[int]], (*)
+    "chi2_matrix": list[list[float]],
+    "profile_schema": dict[string, list[int]]
+},
+"data_stats": [
+    {
+        "column_name": string,
+        "data_type": string,
+        "data_label": string,
+        "categorical": bool,
+        "order": string,
+        "samples": list[str],
+        "statistics": {
+            "sample_size": int,
+            "null_count": int,
+            "null_types": list[string],
+            "null_types_index": dict[string, list[int]],
+            "data_type_representation": dict[string, list[string]],
+            "min": [null, float],
+            "max": [null, float],
+            "sum": float,
+            "mode": list[float],
+            "median": float,
+            "median_absolute_deviation": float,
+            "mean": float,
+            "variance": float,
+            "stddev": float,
+            "skewness": float,
+            "kurtosis": float,
+            "num_zeros": int,
+            "num_negatives": int,
+            "histogram": {
+                "bin_counts": list[int],
+                "bin_edges": list[float],
+            },
+            "quantiles": {
+                int: float
+            },
+            "vocab": list[char],
+            "avg_predictions": dict[string, float],
+            "data_label_representation": dict[string, float],
+            "categories": list[str],
+            "unique_count": int,
+            "unique_ratio": float,
+            "categorical_count": dict[string, int],
+            "gini_impurity": float,
+            "unalikeability": float,
+            "precision": {
+                'min': int,
+                'max': int,
+                'mean': float,
+                'var': float,
+                'std': float,
+                'sample_size': int,
+                'margin_of_error': float,
+                'confidence_level': float
+            },
+            "times": dict[string, float],
+            "format": string
+        },
+        "null_replication_metrics": {
+            "class_prior": list[int],
+            "class_sum": list[list[int]],
+            "class_mean": list[list[int]]
+        }
+    }
+]
+
+
+

(*) Currently the correlation matrix update is toggled off. It will be reset in a later update. Users can still use it as desired with the is_enable option set to True.

+

The format for an unstructured profile is below:

+
"global_stats": {
+    "samples_used": int,
+    "empty_line_count": int,
+    "file_type": string,
+    "encoding": string,
+    "memory_size": float, # in MB
+},
+"data_stats": {
+    "data_label": {
+        "entity_counts": {
+            "word_level": dict[string, int],
+            "true_char_level": dict[string, int],
+            "postprocess_char_level": dict[string, int]
+        },
+        "entity_percentages": {
+            "word_level": dict[string, float],
+            "true_char_level": dict[string, float],
+            "postprocess_char_level": dict[string, float]
+        },
+        "times": dict[string, float]
+    },
+    "statistics": {
+        "vocab": list[char],
+        "vocab_count": dict[string, int],
+        "words": list[string],
+        "word_count": dict[string, int],
+        "times": dict[string, float]
+    }
+}
+
+
+

The format for a graph profile is below:

+
"num_nodes": int,
+"num_edges": int,
+"categorical_attributes": list[string],
+"continuous_attributes": list[string],
+"avg_node_degree": float,
+"global_max_component_size": int,
+"continuous_distribution": {
+    "<attribute_1>": {
+        "name": string,
+        "scale": float,
+        "properties": list[float, np.array]
+    },
+    "<attribute_2>": None,
+},
+"categorical_distribution": {
+    "<attribute_1>": None,
+    "<attribute_2>": {
+        "bin_counts": list[int],
+        "bin_edges": list[float]
+    },
+},
+"times": dict[string, float]
+
+
+
+

Supported Data Formats

+
    +
  • Any delimited file (CSV, TSV, etc.)

  • +
  • JSON object

  • +
  • Avro file

  • +
  • Parquet file

  • +
  • Text file

  • +
  • Pandas DataFrame

  • +
  • A URL that points to one of the supported file types above

  • +
+
+
+

Data Labels

+

Data Labels are determined per cell for structured data (column/row when the profiler is used) or at the character level for unstructured data.

+
    +
  • UNKNOWN

  • +
  • ADDRESS

  • +
  • BAN (bank account number, 10-18 digits)

  • +
  • CREDIT_CARD

  • +
  • EMAIL_ADDRESS

  • +
  • UUID

  • +
  • HASH_OR_KEY (md5, sha1, sha256, random hash, etc.)

  • +
  • IPV4

  • +
  • IPV6

  • +
  • MAC_ADDRESS

  • +
  • PERSON

  • +
  • PHONE_NUMBER

  • +
  • SSN

  • +
  • URL

  • +
  • US_STATE

  • +
  • DRIVERS_LICENSE

  • +
  • DATE

  • +
  • TIME

  • +
  • DATETIME

  • +
  • INTEGER

  • +
  • FLOAT

  • +
  • QUANTITY

  • +
  • ORDINAL

  • +
+
+
+
+

Get Started

+
+

Load a File

+

The profiler should automatically identify the file type and load the data into a Data Class.

+

Along with other attributtes the Data class enables structured data to be accessed via a valid Pandas DataFrame.

+
# Load a csv file, return a CSVData object
+csv_data = Data('your_file.csv')
+
+# Print the first 10 rows of the csv file
+print(csv_data.data.head(10))
+
+# Load a parquet file, return a ParquetData object
+parquet_data = Data('your_file.parquet')
+
+# Sort the data by the name column
+parquet_data.data.sort_values(by='name', inplace=True)
+
+# Print the sorted first 10 rows of the parquet data
+print(parquet_data.data.head(10))
+
+
+

If the file type is not automatically identified (rare), you can specify them +specifically, see section Data Readers.

+
+
+

Profile a File

+

Example uses a CSV file for example, but CSV, JSON, Avro, Parquet or Text should also work.

+
import json
+from dataprofiler import Data, Profiler
+
+# Load file (CSV should be automatically identified)
+data = Data("your_file.csv")
+
+# Profile the dataset
+profile = Profiler(data)
+
+# Generate a report and use json to prettify.
+report  = profile.report(report_options={"output_format":"pretty"})
+
+# Print the report
+print(json.dumps(report, indent=4))
+
+
+
+
+

Updating Profiles

+

Currently, the data profiler is equipped to update its profile in batches.

+
import json
+from dataprofiler import Data, Profiler
+
+# Load and profile a CSV file
+data = Data("your_file.csv")
+profile = Profiler(data)
+
+# Update the profile with new data:
+new_data = Data("new_data.csv")
+profile.update_profile(new_data)
+
+# Print the report using json to prettify.
+report  = profile.report(report_options={"output_format":"pretty"})
+print(json.dumps(report, indent=4))
+
+
+
+
+

Merging Profiles

+

If you have two files with the same schema (but different data), it is possible to merge the two profiles together via an addition operator.

+

This also enables profiles to be determined in a distributed manner.

+
import json
+from dataprofiler import Data, Profiler
+
+# Load a CSV file with a schema
+data1 = Data("file_a.csv")
+profile1 = Profiler(data)
+
+# Load another CSV file with the same schema
+data2 = Data("file_b.csv")
+profile2 = Profiler(data)
+
+profile3 = profile1 + profile2
+
+# Print the report using json to prettify.
+report  = profile3.report(report_options={"output_format":"pretty"})
+print(json.dumps(report, indent=4))
+
+
+
+
+

Profile a Pandas DataFrame

+
import pandas as pd
+import dataprofiler as dp
+import json
+
+my_dataframe = pd.DataFrame([[1, 2.0],[1, 2.2],[-1, 3]])
+profile = dp.Profiler(my_dataframe)
+
+# print the report using json to prettify.
+report = profile.report(report_options={"output_format":"pretty"})
+print(json.dumps(report, indent=4))
+
+# read a specified column, in this case it is labeled 0:
+print(json.dumps(report["data stats"][0], indent=4))
+
+
+
+
+

Unstructured Profiler

+

In addition to the structured profiler, the Data Profiler provides unstructured +profiling for the TextData object or string. Unstructured profiling also works +with list(string), pd.Series(string) or pd.DataFrame(string) given profiler_type +option specified as unstructured. Below is an example of unstructured profile +with a text file.

+
import dataprofiler as dp
+import json
+my_text = dp.Data('text_file.txt')
+profile = dp.Profiler(my_text)
+
+# print the report using json to prettify.
+report = profile.report(report_options={"output_format":"pretty"})
+print(json.dumps(report, indent=4))
+
+
+

Another example of unstructured profile with pd.Series of string is given as below

+
import dataprofiler as dp
+import pandas as pd
+import json
+
+text_data = pd.Series(['first string', 'second string'])
+profile = dp.Profiler(text_data, profiler_type="unstructured")
+
+# print the report using json to prettify.
+report = profile.report(report_options={"output_format":"pretty"})
+print(json.dumps(report, indent=4))
+
+
+
+
+

Graph Profiler

+

DataProfiler also provides the ability to profile graph data from a csv file. Below is an example of the graph profiler with a graph data csv file:

+
import dataprofiler as dp
+import pprint
+
+my_graph = dp.Data('graph_file.csv')
+profile = dp.Profiler(my_graph)
+
+# print the report using pretty print (json dump does not work on numpy array values inside dict)
+report = profile.report()
+printer = pprint.PrettyPrinter(sort_dicts=False, compact=True)
+printer.pprint(report)
+
+
+
+
+

Specifying a Filetype or Delimiter

+

Example of specifying a CSV data type, with a , delimiter. +In addition, it utilizes only the first 10,000 rows.

+
import json
+import os
+from dataprofiler import Data, Profiler
+from dataprofiler.data_readers.csv_data import CSVData
+
+# Load a CSV file, with "," as the delimiter
+data = CSVData("your_file.csv", options={"delimiter": ","})
+
+# Split the data, such that only the first 10,000 rows are used
+data = data.data[0:10000]
+
+# Read in profile and print results
+profile = Profiler(data)
+print(json.dumps(profile.report(report_options={"output_format":"pretty"}), indent=4))
+
+
+
+
+
+
+
+
+
+
+
+

Versions

+ +
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/install.html b/docs/0.10.5/html/install.html new file mode 100644 index 000000000..59a1e52a5 --- /dev/null +++ b/docs/0.10.5/html/install.html @@ -0,0 +1,392 @@ + + + + + + + + + Install - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Install

+

To install the full package from pypi:

+
pip install DataProfiler[ml]
+
+
+

If the ML requirements are too strict (say, you don’t want to install +tensorflow), you can install a slimmer package. The slimmer package disables +the default sensitive data detection / entity recognition (labler)

+

Install from pypi:

+
pip install DataProfiler
+
+
+
+

Snappy Installation

+

This is required to profile parquet/avro datasets

+

MacOS (intel chip) with homebrew:

+
brew install snappy && CPPFLAGS="-I/usr/local/include -L/usr/local/lib" pip install python-snappy
+
+
+

MacOS (apple chip) with homebrew:

+
brew install snappy && CPPFLAGS="-I/opt/homebrew/include -L/opt/homebrew/lib" pip install python-snappy
+
+
+

Linux install:

+
sudo apt-get -y install libsnappy-dev
+
+
+
+
+

Build From Scratch

+

NOTE: Installation for python3

+

virtualenv install:

+
python3 -m pip install virtualenv
+
+
+

Setup virtual env:

+
python3 -m virtualenv --python=python3 venv3
+source venv3/bin/activate
+
+
+

Install requirements:

+
pip3 install -r requirements.txt
+
+
+

Install labeler dependencies:

+
pip3 install -r requirements-ml.txt
+
+
+

Install via the repo – Build setup.py and install locally:

+
python3 setup.py sdist bdist bdist_wheel
+pip3 install dist/DataProfiler*-py3-none-any.whl
+
+
+

If you see:

+
ERROR: Double requirement given:dataprofiler==X.Y.Z from dataprofiler/dist/DataProfiler-X.Y.Z-py3-none-any.whl (already in dataprofiler==X2.Y2.Z2 from dataprofiler/dist/DataProfiler-X2.Y2.Z2-py3-none-any.whl, name='dataprofiler')
+
+
+

This means that you have multiple versions of the DataProfiler distribution +in the dist folder. +To resolve, either remove the older one or delete the folder and rerun the steps +above.

+

Install via github:

+
pip3 install git+https://github.com/capitalone/dataprofiler.git#egg=dataprofiler
+
+
+
+
+

Testing

+

For testing, install test requirements:

+
pip3 install -r requirements-test.txt
+
+
+

To run all unit tests, use:

+
DATAPROFILER_SEED=0 python3 -m unittest discover -p "test*.py"
+
+
+

To run file of unit tests, use form:

+
DATAPROFILER_SEED=0 python3 -m unittest discover -p test_profile_builder.py
+
+
+

To run a file with Pytest use:

+
DATAPROFILER_SEED=0 pytest dataprofiler/tests/data_readers/test_csv_data.py -v
+
+
+

To run individual of unit test, use form:

+
DATAPROFILER_SEED=0 python3 -m unittest dataprofiler.tests.profilers.test_profile_builder.TestProfiler
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/labeler.html b/docs/0.10.5/html/labeler.html new file mode 100644 index 000000000..1b645e416 --- /dev/null +++ b/docs/0.10.5/html/labeler.html @@ -0,0 +1,957 @@ + + + + + + + + + Sensitive Data Detection with the Labeler - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + + +

View this notebook on GitHub

+
+

Sensitive Data Detection with the Labeler

+

In this example, we utilize the Labeler component of the Data Profiler to detect the sensitive information for both structured and unstructured data. In addition, we show how to train the Labeler on some specific dataset with different list of entities.

+

First, let’s dive into what the Labeler is.

+
+

What is the Labeler

+

The Labeler is a pipeline designed to make building, training, and predictions with ML models quick and easy. There are 3 major components to the Labeler: the preprocessor, the model, and the postprocessor.

+

alt text

+

Each component can be switched out individually to suit your needs. As you might expect, the preprocessor takes in raw data and prepares it for the model, the model performs the prediction or training, and the postprocessor takes prediction results and turns them into human-readable results.

+

Now let’s run some examples. Start by importing all the requirements.

+
+
[ ]:
+
+
+
+import os
+import sys
+import json
+import pandas as pd
+
+try:
+    sys.path.insert(0, '..')
+    import dataprofiler as dp
+except ImportError:
+    import dataprofiler as dp
+
+# remove extra tf loggin
+import tensorflow as tf
+tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
+
+
+
+
+
+

Structured Data Prediction

+

We’ll use the aws honeypot dataset in the test folder for this example. First, look at the data using the Data Reader class of the Data Profiler. This dataset is from the US department of educations, found here!

+
+
[ ]:
+
+
+
+data = dp.Data("../dataprofiler/tests/data/csv/SchoolDataSmall.csv")
+df_data = data.data
+df_data.head()
+
+
+
+

We can directly predict the labels of a structured dataset on the cell level.

+
+
[ ]:
+
+
+
+labeler = dp.DataLabeler(labeler_type='structured')
+
+# print out the labels and label mapping
+print("Labels: {}".format(labeler.labels))
+print("\n")
+print("Label Mapping: {}".format(labeler.label_mapping))
+print("\n")
+
+# make predictions and get labels for each cell going row by row
+# predict options are model dependent and the default model can show prediction confidences
+predictions = labeler.predict(data, predict_options={"show_confidences": True})
+
+# display prediction results
+print("Predictions: {}".format(predictions['pred']))
+print("\n")
+
+# display confidence results
+print("Confidences: {}".format(predictions['conf']))
+
+
+
+

The profiler uses the Labeler to perform column by column predictions. The data contains 11 columns, each of which has data label. Next, we will use the Labeler of the Data Profiler to predict the label for each column in this tabular dataset. Since we are only going to demo the labeling functionality, other options of the Data Profiler are disabled to keep this quick.

+
+
[ ]:
+
+
+
+# helper functions for printing results
+
+def get_structured_results(results):
+    """Helper function to get data labels for each column."""
+    columns = []
+    predictions = []
+    samples = []
+    for col in results['data_stats']:
+        columns.append(col['column_name'])
+        predictions.append(col['data_label'])
+        samples.append(col['samples'])
+
+    df_results = pd.DataFrame({'Column': columns, 'Prediction': predictions, 'Sample': samples})
+    return df_results
+
+def get_unstructured_results(data, results):
+    """Helper function to get data labels for each labeled piece of text."""
+    labeled_data = []
+    for pred in results['pred'][0]:
+        labeled_data.append([data[0][pred[0]:pred[1]], pred[2]])
+    label_df = pd.DataFrame(labeled_data, columns=['Text', 'Labels'])
+    return label_df
+
+
+pd.set_option('display.width', 100)
+
+
+
+
+
[ ]:
+
+
+
+# set options to only run the labeler
+profile_options = dp.ProfilerOptions()
+profile_options.set({"structured_options.text.is_enabled": False,
+                     "int.is_enabled": False,
+                     "float.is_enabled": False,
+                     "order.is_enabled": False,
+                     "category.is_enabled": False,
+                     "chi2_homogeneity.is_enabled": False,
+                     "datetime.is_enabled": False,})
+
+profile = dp.Profiler(data, options=profile_options)
+
+results = profile.report()
+print(get_structured_results(results))
+
+
+
+

In this example, the results show that the Data Profiler is able to detect integers, URLs, address, and floats appropriately. Unknown is typically strings of text, which is appropriate for those columns.

+
+
+

Unstructured Data Prediction

+

Besides structured data, the Labeler detects the sensitive information on the unstructured text. We use a sample of spam email in Enron email dataset for this demo. As above, we start investigating the content of the given email sample.

+
+
[ ]:
+
+
+
+# load data
+data = "Message-ID: <11111111.1111111111111.JavaMail.evans@thyme>\n" + \
+        "Date: Fri, 10 Aug 2005 11:31:37 -0700 (PDT)\n" + \
+        "From: w..smith@company.com\n" + \
+        "To: john.smith@company.com\n" + \
+        "Subject: RE: ABC\n" + \
+        "Mime-Version: 1.0\n" + \
+        "Content-Type: text/plain; charset=us-ascii\n" + \
+        "Content-Transfer-Encoding: 7bit\n" + \
+        "X-From: Smith, Mary W. </O=ENRON/OU=NA/CN=RECIPIENTS/CN=SSMITH>\n" + \
+        "X-To: Smith, John </O=ENRON/OU=NA/CN=RECIPIENTS/CN=JSMITH>\n" + \
+        "X-cc: \n" + \
+        "X-bcc: \n" + \
+        "X-Folder: \SSMITH (Non-Privileged)\Sent Items\n" + \
+        "X-Origin: Smith-S\n" + \
+        "X-FileName: SSMITH (Non-Privileged).pst\n\n" + \
+        "All I ever saw was the e-mail from the office.\n\n" + \
+        "Mary\n\n" + \
+        "-----Original Message-----\n" + \
+        "From:   Smith, John  \n" + \
+        "Sent:   Friday, August 10, 2005 13:07 PM\n" + \
+        "To:     Smith, Mary W.\n" + \
+        "Subject:        ABC\n\n" + \
+        "Have you heard any more regarding the ABC sale? I guess that means that " + \
+        "it's no big deal here, but you think they would have send something.\n\n\n" + \
+        "John Smith\n" + \
+        "123-456-7890\n"
+
+# convert string data to list to feed into the labeler
+data = [data]
+
+
+
+

By default, the Labeler predicts the results at the character level for unstructured text.

+
+
[ ]:
+
+
+
+labeler = dp.DataLabeler(labeler_type='unstructured')
+
+# make predictions and get labels per character
+predictions = labeler.predict(data)
+
+# display results
+print(predictions['pred'])
+
+
+
+

In addition to the character-level result, the Labeler provides the results at the word level following the standard NER (Named Entity Recognition), e.g., utilized by spaCy.

+
+
[ ]:
+
+
+
+# convert prediction to word format and ner format
+# Set the output to the NER format (start position, end position, label)
+labeler.set_params(
+    { 'postprocessor': { 'output_format':'ner', 'use_word_level_argmax':True } }
+)
+
+# make predictions and get labels per character
+predictions = labeler.predict(data)
+
+# display results
+print('\n')
+print('=======================Prediction======================\n')
+for pred in predictions['pred'][0]:
+    print('{}: {}'.format(data[0][pred[0]: pred[1]], pred[2]))
+    print('--------------------------------------------------------')
+
+
+
+

Here, the Labeler is able to identify sensitive information such as datetime, email address, person names, and phone number in an email sample.

+
+
+

Train the Labeler from Scratch

+

The Labeler can be trained from scratch with a new list of labels. Below, we show an example of training the Labeler on a dataset with labels given as the columns of that dataset. For brevity’s sake, let’s only train a few epochs with a subset of a dataset.

+
+
[ ]:
+
+
+
+data = dp.Data("../dataprofiler/tests/data/csv/SchoolDataSmall.csv")
+df = data.data[["OPEID6", "INSTURL", "SEARCH_STRING"]]
+df.head()
+
+# split data to training and test set
+split_ratio = 0.2
+df = df.sample(frac=1).reset_index(drop=True)
+data_train = df[:int((1 - split_ratio) * len(df))]
+data_test = df[int((1 - split_ratio) * len(df)):]
+
+# train a new labeler with column names as labels
+if not os.path.exists('data_labeler_saved'):
+    os.makedirs('data_labeler_saved')
+
+labeler = dp.train_structured_labeler(
+    data=data_train,
+    save_dirpath="data_labeler_saved",
+    epochs=10,
+    default_label="OPEID6"
+)
+
+
+
+
+

The trained Labeler is then used by the Data Profiler to provide the prediction on the new dataset.

+
+
[ ]:
+
+
+
+# predict with the labeler object
+profile_options.set({'structured_options.data_labeler.data_labeler_object': labeler})
+profile = dp.Profiler(data_test, options=profile_options)
+
+# get the prediction from the data profiler
+results = profile.report()
+print(get_structured_results(results))
+
+
+
+

Another way to use the trained Labeler is through the directory path of the saved labeler.

+
+
[ ]:
+
+
+
+# predict with the labeler loaded from path
+profile_options.set({'structured_options.data_labeler.data_labeler_dirpath': 'data_labeler_saved'})
+profile = dp.Profiler(data_test, options=profile_options)
+
+# get the prediction from the data profiler
+results = profile.report()
+print(get_structured_results(results))
+
+
+
+
+
+

Transfer Learning a Labeler

+

Instead of training a model from scratch, we can also transfer learn to improve the model and/or extend the labels. Again for brevity’s sake, let’s only train a few epochs with a small dataset at the cost of accuracy.

+
+
[ ]:
+
+
+
+data = dp.Data("../dataprofiler/tests/data/csv/SchoolDataSmall.csv")
+df_data = data.data[["OPEID6", "INSTURL", "SEARCH_STRING"]]
+
+
+# prep data
+df_data = df_data.reset_index(drop=True).melt()
+df_data.columns = [1, 0]  # labels=1, values=0 in that order
+df_data = df_data.astype(str)
+new_labels = df_data[1].unique().tolist()
+
+# load structured Labeler w/ trainable set to True
+labeler = dp.DataLabeler(labeler_type='structured', trainable=True)
+
+# Reconstruct the model to add each new label
+for label in new_labels:
+    labeler.add_label(label)
+
+# this will use transfer learning to retrain the labeler on your new
+# dataset and labels.
+# Setting labels with a list of labels or label mapping will overwrite the existing labels with new ones
+# Setting the reset_weights parameter to false allows transfer learning to occur
+model_results = labeler.fit(x=df_data[0], y=df_data[1], validation_split=0.2,
+                                 epochs=10, labels=None, reset_weights=False)
+
+
+
+

Let’s display the training results of the last epoch:

+
+
[ ]:
+
+
+
+print("{:16s}  Precision  Recall  F1-score  Support".format(""))
+for item in model_results[-1][2]:
+    print("{:16s}  {:4.3f}      {:4.3f}   {:4.3f}     {:7.0f}".format(item,
+                                                                      model_results[-1][2][item]["precision"],
+                                                                      model_results[-1][2][item]["recall"],
+                                                                      model_results[-1][2][item]["f1-score"],
+                                                                      model_results[-1][2][item]["support"]))
+
+
+
+

It is now trained to detect additional labels! The model results here show all the labels training accuracy. Since only new labels existed in the dataset, only the new labels are given accuracy scores. Keep in mind this is a small dataset for brevity’s sake and that real training would involve more samples and better results.

+
+
+

Saving and Loading a Labeler

+

The Labeler can easily be saved or loaded with one simple line.

+
+
[ ]:
+
+
+
+# Ensure save directory exists
+if not os.path.exists('my_labeler'):
+    os.makedirs('my_labeler')
+
+# Saving the labeler
+labeler.save_to_disk("my_labeler")
+
+# Loading the labeler
+labeler = dp.DataLabeler(labeler_type='structured', dirpath="my_labeler")
+
+
+
+
+
+

Building a Labeler from the Ground Up

+

As mentioned earlier, the labeler is comprised of three components, and each of the compenents can be created and interchanged in the the labeler pipeline.

+
+
[ ]:
+
+
+
+import random
+from dataprofiler.labelers.character_level_cnn_model import \
+    CharacterLevelCnnModel
+from dataprofiler.labelers.data_processing import \
+    StructCharPreprocessor, StructCharPostprocessor
+
+model = CharacterLevelCnnModel({"PAD":0, "UNKNOWN":1, "Test_Label":2})
+preprocessor = StructCharPreprocessor()
+postprocessor = StructCharPostprocessor()
+
+labeler = dp.DataLabeler(labeler_type='structured')
+labeler.set_preprocessor(preprocessor)
+labeler.set_model(model)
+labeler.set_postprocessor(postprocessor)
+
+# check for basic compatibility between the processors and the model
+labeler.check_pipeline()
+
+# Optionally set the parameters
+parameters={
+    'preprocessor':{
+        'max_length': 100,
+    },
+    'model':{
+        'max_length': 100,
+    },
+    'postprocessor':{
+        'random_state': random.Random(1)
+    }
+}
+labeler.set_params(parameters)
+
+labeler.help()
+
+
+
+

The components can each be created if you inherit the BaseModel and BaseProcessor for the model and processors, respectively. More info can be found about coding your own components in the Labeler section of the documentation. In summary, the Data Profiler open source library can be used to scan sensitive information in both structured and unstructured data with different file types. It supports multiple input formats and output formats at word and +character levels. Users can also train the labeler on their own datasets.

+
+
+ +
+ +
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/labeler.ipynb b/docs/0.10.5/html/labeler.ipynb new file mode 100644 index 000000000..af31b68c5 --- /dev/null +++ b/docs/0.10.5/html/labeler.ipynb @@ -0,0 +1,650 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "spoken-reunion", + "metadata": {}, + "source": [ + "# Sensitive Data Detection with the Labeler" + ] + }, + { + "cell_type": "markdown", + "id": "interesting-bidder", + "metadata": {}, + "source": [ + "In this example, we utilize the Labeler component of the Data Profiler to detect the sensitive information for both structured and unstructured data. In addition, we show how to train the Labeler on some specific dataset with different list of entities.\n", + "\n", + "First, let's dive into what the Labeler is." + ] + }, + { + "cell_type": "markdown", + "id": "1965b83b", + "metadata": {}, + "source": [ + "## What is the Labeler" + ] + }, + { + "cell_type": "markdown", + "id": "388c643f", + "metadata": {}, + "source": [ + "The Labeler is a pipeline designed to make building, training, and predictions with ML models quick and easy. There are 3 major components to the Labeler: the preprocessor, the model, and the postprocessor." + ] + }, + { + "cell_type": "markdown", + "id": "e5d0aeb4", + "metadata": {}, + "source": [ + "![alt text](DL-Flowchart.png \"Title\")" + ] + }, + { + "cell_type": "markdown", + "id": "550323c7", + "metadata": {}, + "source": [ + "Each component can be switched out individually to suit your needs. As you might expect, the preprocessor takes in raw data and prepares it for the model, the model performs the prediction or training, and the postprocessor takes prediction results and turns them into human-readable results. \n", + "\n", + "Now let's run some examples. Start by importing all the requirements." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "scientific-stevens", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "import pandas as pd\n", + "\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " import dataprofiler as dp\n", + "\n", + "# remove extra tf loggin\n", + "import tensorflow as tf\n", + "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)" + ] + }, + { + "cell_type": "markdown", + "id": "5125b215", + "metadata": {}, + "source": [ + "## Structured Data Prediction" + ] + }, + { + "cell_type": "markdown", + "id": "wicked-devon", + "metadata": {}, + "source": [ + "We'll use the aws honeypot dataset in the test folder for this example. First, look at the data using the Data Reader class of the Data Profiler. This dataset is from the US department of educations, [found here!](https://data.ed.gov/dataset/college-scorecard-all-data-files-through-6-2020/resources?resource=823ac095-bdfc-41b0-b508-4e8fc3110082)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "adjusted-native", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "data = dp.Data(\"../dataprofiler/tests/data/csv/SchoolDataSmall.csv\")\n", + "df_data = data.data\n", + "df_data.head()" + ] + }, + { + "cell_type": "markdown", + "id": "ab6ccf8a", + "metadata": {}, + "source": [ + "We can directly predict the labels of a structured dataset on the cell level." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19529af4", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "labeler = dp.DataLabeler(labeler_type='structured')\n", + "\n", + "# print out the labels and label mapping\n", + "print(\"Labels: {}\".format(labeler.labels)) \n", + "print(\"\\n\")\n", + "print(\"Label Mapping: {}\".format(labeler.label_mapping))\n", + "print(\"\\n\")\n", + "\n", + "# make predictions and get labels for each cell going row by row\n", + "# predict options are model dependent and the default model can show prediction confidences\n", + "predictions = labeler.predict(data, predict_options={\"show_confidences\": True})\n", + "\n", + "# display prediction results\n", + "print(\"Predictions: {}\".format(predictions['pred']))\n", + "print(\"\\n\")\n", + "\n", + "# display confidence results\n", + "print(\"Confidences: {}\".format(predictions['conf']))" + ] + }, + { + "cell_type": "markdown", + "id": "2af72e2c", + "metadata": {}, + "source": [ + "The profiler uses the Labeler to perform column by column predictions. The data contains 11 columns, each of which has data label. Next, we will use the Labeler of the Data Profiler to predict the label for each column in this tabular dataset. Since we are only going to demo the labeling functionality, other options of the Data Profiler are disabled to keep this quick." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d6cb9d7e-149a-4cfe-86f8-76c47c57aeea", + "metadata": {}, + "outputs": [], + "source": [ + "# helper functions for printing results\n", + "\n", + "def get_structured_results(results):\n", + " \"\"\"Helper function to get data labels for each column.\"\"\"\n", + " columns = []\n", + " predictions = []\n", + " samples = []\n", + " for col in results['data_stats']:\n", + " columns.append(col['column_name'])\n", + " predictions.append(col['data_label'])\n", + " samples.append(col['samples'])\n", + "\n", + " df_results = pd.DataFrame({'Column': columns, 'Prediction': predictions, 'Sample': samples})\n", + " return df_results\n", + "\n", + "def get_unstructured_results(data, results):\n", + " \"\"\"Helper function to get data labels for each labeled piece of text.\"\"\"\n", + " labeled_data = []\n", + " for pred in results['pred'][0]:\n", + " labeled_data.append([data[0][pred[0]:pred[1]], pred[2]])\n", + " label_df = pd.DataFrame(labeled_data, columns=['Text', 'Labels'])\n", + " return label_df\n", + " \n", + "\n", + "pd.set_option('display.width', 100)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "secret-million", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# set options to only run the labeler\n", + "profile_options = dp.ProfilerOptions()\n", + "profile_options.set({\"structured_options.text.is_enabled\": False, \n", + " \"int.is_enabled\": False, \n", + " \"float.is_enabled\": False, \n", + " \"order.is_enabled\": False, \n", + " \"category.is_enabled\": False, \n", + " \"chi2_homogeneity.is_enabled\": False,\n", + " \"datetime.is_enabled\": False,})\n", + "\n", + "profile = dp.Profiler(data, options=profile_options)\n", + "\n", + "results = profile.report() \n", + "print(get_structured_results(results))" + ] + }, + { + "cell_type": "markdown", + "id": "fatty-louisville", + "metadata": {}, + "source": [ + "In this example, the results show that the Data Profiler is able to detect integers, URLs, address, and floats appropriately. Unknown is typically strings of text, which is appropriate for those columns." + ] + }, + { + "cell_type": "markdown", + "id": "unavailable-diploma", + "metadata": {}, + "source": [ + "## Unstructured Data Prediction" + ] + }, + { + "cell_type": "markdown", + "id": "metallic-coaching", + "metadata": {}, + "source": [ + "Besides structured data, the Labeler detects the sensitive information on the unstructured text. We use a sample of spam email in Enron email dataset for this demo. As above, we start investigating the content of the given email sample." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "unauthorized-lounge", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# load data\n", + "data = \"Message-ID: <11111111.1111111111111.JavaMail.evans@thyme>\\n\" + \\\n", + " \"Date: Fri, 10 Aug 2005 11:31:37 -0700 (PDT)\\n\" + \\\n", + " \"From: w..smith@company.com\\n\" + \\\n", + " \"To: john.smith@company.com\\n\" + \\\n", + " \"Subject: RE: ABC\\n\" + \\\n", + " \"Mime-Version: 1.0\\n\" + \\\n", + " \"Content-Type: text/plain; charset=us-ascii\\n\" + \\\n", + " \"Content-Transfer-Encoding: 7bit\\n\" + \\\n", + " \"X-From: Smith, Mary W. \\n\" + \\\n", + " \"X-To: Smith, John \\n\" + \\\n", + " \"X-cc: \\n\" + \\\n", + " \"X-bcc: \\n\" + \\\n", + " \"X-Folder: \\SSMITH (Non-Privileged)\\Sent Items\\n\" + \\\n", + " \"X-Origin: Smith-S\\n\" + \\\n", + " \"X-FileName: SSMITH (Non-Privileged).pst\\n\\n\" + \\\n", + " \"All I ever saw was the e-mail from the office.\\n\\n\" + \\\n", + " \"Mary\\n\\n\" + \\\n", + " \"-----Original Message-----\\n\" + \\\n", + " \"From: Smith, John \\n\" + \\\n", + " \"Sent: Friday, August 10, 2005 13:07 PM\\n\" + \\\n", + " \"To: Smith, Mary W.\\n\" + \\\n", + " \"Subject: ABC\\n\\n\" + \\\n", + " \"Have you heard any more regarding the ABC sale? I guess that means that \" + \\\n", + " \"it's no big deal here, but you think they would have send something.\\n\\n\\n\" + \\\n", + " \"John Smith\\n\" + \\\n", + " \"123-456-7890\\n\"\n", + "\n", + "# convert string data to list to feed into the labeler\n", + "data = [data]" + ] + }, + { + "cell_type": "markdown", + "id": "concerned-segment", + "metadata": {}, + "source": [ + "By default, the Labeler predicts the results at the character level for unstructured text." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "junior-acrobat", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "labeler = dp.DataLabeler(labeler_type='unstructured')\n", + "\n", + "# make predictions and get labels per character\n", + "predictions = labeler.predict(data)\n", + "\n", + "# display results\n", + "print(predictions['pred'])" + ] + }, + { + "cell_type": "markdown", + "id": "individual-diabetes", + "metadata": {}, + "source": [ + "In addition to the character-level result, the Labeler provides the results at the word level following the standard NER (Named Entity Recognition), e.g., utilized by spaCy. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "optical-universe", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# convert prediction to word format and ner format\n", + "# Set the output to the NER format (start position, end position, label)\n", + "labeler.set_params(\n", + " { 'postprocessor': { 'output_format':'ner', 'use_word_level_argmax':True } } \n", + ")\n", + "\n", + "# make predictions and get labels per character\n", + "predictions = labeler.predict(data)\n", + "\n", + "# display results\n", + "print('\\n')\n", + "print('=======================Prediction======================\\n')\n", + "for pred in predictions['pred'][0]:\n", + " print('{}: {}'.format(data[0][pred[0]: pred[1]], pred[2]))\n", + " print('--------------------------------------------------------')" + ] + }, + { + "cell_type": "markdown", + "id": "behavioral-tourism", + "metadata": {}, + "source": [ + "Here, the Labeler is able to identify sensitive information such as datetime, email address, person names, and phone number in an email sample. " + ] + }, + { + "cell_type": "markdown", + "id": "nasty-disney", + "metadata": {}, + "source": [ + "## Train the Labeler from Scratch" + ] + }, + { + "cell_type": "markdown", + "id": "destroyed-twist", + "metadata": {}, + "source": [ + "The Labeler can be trained from scratch with a new list of labels. Below, we show an example of training the Labeler on a dataset with labels given as the columns of that dataset. For brevity's sake, let's only train a few epochs with a subset of a dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "utility-evaluation", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "data = dp.Data(\"../dataprofiler/tests/data/csv/SchoolDataSmall.csv\")\n", + "df = data.data[[\"OPEID6\", \"INSTURL\", \"SEARCH_STRING\"]]\n", + "df.head()\n", + "\n", + "# split data to training and test set\n", + "split_ratio = 0.2\n", + "df = df.sample(frac=1).reset_index(drop=True)\n", + "data_train = df[:int((1 - split_ratio) * len(df))]\n", + "data_test = df[int((1 - split_ratio) * len(df)):]\n", + "\n", + "# train a new labeler with column names as labels\n", + "if not os.path.exists('data_labeler_saved'):\n", + " os.makedirs('data_labeler_saved')\n", + "\n", + "labeler = dp.train_structured_labeler(\n", + " data=data_train,\n", + " save_dirpath=\"data_labeler_saved\",\n", + " epochs=10,\n", + " default_label=\"OPEID6\"\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "utility-torture", + "metadata": {}, + "source": [ + "The trained Labeler is then used by the Data Profiler to provide the prediction on the new dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "answering-panel", + "metadata": {}, + "outputs": [], + "source": [ + "# predict with the labeler object\n", + "profile_options.set({'structured_options.data_labeler.data_labeler_object': labeler})\n", + "profile = dp.Profiler(data_test, options=profile_options)\n", + "\n", + "# get the prediction from the data profiler\n", + "results = profile.report()\n", + "print(get_structured_results(results))" + ] + }, + { + "cell_type": "markdown", + "id": "polish-stand", + "metadata": {}, + "source": [ + "Another way to use the trained Labeler is through the directory path of the saved labeler." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "industrial-characterization", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# predict with the labeler loaded from path\n", + "profile_options.set({'structured_options.data_labeler.data_labeler_dirpath': 'data_labeler_saved'})\n", + "profile = dp.Profiler(data_test, options=profile_options)\n", + "\n", + "# get the prediction from the data profiler\n", + "results = profile.report()\n", + "print(get_structured_results(results))" + ] + }, + { + "cell_type": "markdown", + "id": "2acedba0", + "metadata": {}, + "source": [ + "## Transfer Learning a Labeler" + ] + }, + { + "cell_type": "markdown", + "id": "2f15fb1f", + "metadata": {}, + "source": [ + "Instead of training a model from scratch, we can also transfer learn to improve the model and/or extend the labels. Again for brevity's sake, let's only train a few epochs with a small dataset at the cost of accuracy." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0104c374", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "data = dp.Data(\"../dataprofiler/tests/data/csv/SchoolDataSmall.csv\")\n", + "df_data = data.data[[\"OPEID6\", \"INSTURL\", \"SEARCH_STRING\"]]\n", + "\n", + "\n", + "# prep data\n", + "df_data = df_data.reset_index(drop=True).melt()\n", + "df_data.columns = [1, 0] # labels=1, values=0 in that order\n", + "df_data = df_data.astype(str)\n", + "new_labels = df_data[1].unique().tolist()\n", + "\n", + "# load structured Labeler w/ trainable set to True\n", + "labeler = dp.DataLabeler(labeler_type='structured', trainable=True)\n", + "\n", + "# Reconstruct the model to add each new label\n", + "for label in new_labels:\n", + " labeler.add_label(label)\n", + "\n", + "# this will use transfer learning to retrain the labeler on your new\n", + "# dataset and labels.\n", + "# Setting labels with a list of labels or label mapping will overwrite the existing labels with new ones\n", + "# Setting the reset_weights parameter to false allows transfer learning to occur\n", + "model_results = labeler.fit(x=df_data[0], y=df_data[1], validation_split=0.2, \n", + " epochs=10, labels=None, reset_weights=False)" + ] + }, + { + "cell_type": "markdown", + "id": "ae78745f", + "metadata": {}, + "source": [ + "Let's display the training results of the last epoch:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b764aa8c", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "print(\"{:16s} Precision Recall F1-score Support\".format(\"\"))\n", + "for item in model_results[-1][2]:\n", + " print(\"{:16s} {:4.3f} {:4.3f} {:4.3f} {:7.0f}\".format(item,\n", + " model_results[-1][2][item][\"precision\"],\n", + " model_results[-1][2][item][\"recall\"],\n", + " model_results[-1][2][item][\"f1-score\"],\n", + " model_results[-1][2][item][\"support\"]))" + ] + }, + { + "cell_type": "markdown", + "id": "44009522", + "metadata": {}, + "source": [ + "It is now trained to detect additional labels! The model results here show all the labels training accuracy. Since only new labels existed in the dataset, only the new labels are given accuracy scores. Keep in mind this is a small dataset for brevity's sake and that real training would involve more samples and better results." + ] + }, + { + "cell_type": "markdown", + "id": "e110ee1c", + "metadata": {}, + "source": [ + "## Saving and Loading a Labeler" + ] + }, + { + "cell_type": "markdown", + "id": "c484d193", + "metadata": {}, + "source": [ + "The Labeler can easily be saved or loaded with one simple line." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4d8684fa", + "metadata": {}, + "outputs": [], + "source": [ + "# Ensure save directory exists\n", + "if not os.path.exists('my_labeler'):\n", + " os.makedirs('my_labeler')\n", + "\n", + "# Saving the labeler\n", + "labeler.save_to_disk(\"my_labeler\")\n", + "\n", + "# Loading the labeler\n", + "labeler = dp.DataLabeler(labeler_type='structured', dirpath=\"my_labeler\")" + ] + }, + { + "cell_type": "markdown", + "id": "8d36dec8", + "metadata": {}, + "source": [ + "## Building a Labeler from the Ground Up" + ] + }, + { + "cell_type": "markdown", + "id": "59346d2b", + "metadata": {}, + "source": [ + "As mentioned earlier, the labeler is comprised of three components, and each of the compenents can be created and interchanged in the the labeler pipeline." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6506ef97", + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "from dataprofiler.labelers.character_level_cnn_model import \\\n", + " CharacterLevelCnnModel\n", + "from dataprofiler.labelers.data_processing import \\\n", + " StructCharPreprocessor, StructCharPostprocessor\n", + "\n", + "model = CharacterLevelCnnModel({\"PAD\":0, \"UNKNOWN\":1, \"Test_Label\":2})\n", + "preprocessor = StructCharPreprocessor()\n", + "postprocessor = StructCharPostprocessor()\n", + "\n", + "labeler = dp.DataLabeler(labeler_type='structured')\n", + "labeler.set_preprocessor(preprocessor)\n", + "labeler.set_model(model)\n", + "labeler.set_postprocessor(postprocessor)\n", + "\n", + "# check for basic compatibility between the processors and the model\n", + "labeler.check_pipeline()\n", + "\n", + "# Optionally set the parameters\n", + "parameters={\n", + " 'preprocessor':{\n", + " 'max_length': 100,\n", + " },\n", + " 'model':{\n", + " 'max_length': 100,\n", + " },\n", + " 'postprocessor':{\n", + " 'random_state': random.Random(1)\n", + " }\n", + "} \n", + "labeler.set_params(parameters)\n", + "\n", + "labeler.help()" + ] + }, + { + "cell_type": "markdown", + "id": "5f020d7f", + "metadata": {}, + "source": [ + "The components can each be created if you inherit the BaseModel and BaseProcessor for the model and processors, respectively. More info can be found about coding your own components in the Labeler section of the [documentation]( https://capitalone.github.io/dataprofiler). In summary, the Data Profiler open source library can be used to scan sensitive information in both structured and unstructured data with different file types. It supports multiple input formats and output formats at word and character levels. Users can also train the labeler on their own datasets." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/html/merge_profile_list.html b/docs/0.10.5/html/merge_profile_list.html new file mode 100644 index 000000000..4f7ef4b59 --- /dev/null +++ b/docs/0.10.5/html/merge_profile_list.html @@ -0,0 +1,638 @@ + + + + + + + + + Merge List of Profiles - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + + +

View this notebook on GitHub

+
+

Merge List of Profiles

+

This is an example of a new utils in the dataprofiler for distributed merging of profile objects. This assumes the user is providing a list of profile objects to the utils function for merging all the profiles together.

+
+

Imports

+

Let’s start by importing the necessary packages…

+
+
[ ]:
+
+
+
+import os
+import sys
+import json
+
+import pandas as pd
+import tensorflow as tf
+
+try:
+    sys.path.insert(0, '..')
+    import dataprofiler as dp
+    from dataprofiler.profilers.profiler_utils import merge_profile_list
+except ImportError:
+    import dataprofiler as dp
+    from dataprofiler.profilers.profiler_utils import merge_profile_list
+
+# remove extra tf loggin
+tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
+
+
+
+
+
+

Setup the Data and Profiler

+

This section shows the basic example of the Data Profiler.

+
    +
  1. Instantiate a Pandas dataframe with dummy data

  2. +
  3. Pass the dataframe to the Profiler and instantiate two separate profilers in a list

  4. +
+
+
[ ]:
+
+
+
+d = {'col1': [1, 2], 'col2': [3, 4]}
+df = pd.DataFrame(data=d)
+
+list_of_profiles = [dp.Profiler(df), dp.Profiler(df)]
+
+
+
+

Take a look at the list of profiles…

+
+
[ ]:
+
+
+
+list_of_profiles
+
+
+
+
+
+

Run Merge on List of Profiles

+

Now let’s merge the list of profiles into a single_profile

+
+
[ ]:
+
+
+
+single_profile = merge_profile_list(list_of_profiles=list_of_profiles)
+
+
+
+

And check out the .report on the single profile:

+
+
[ ]:
+
+
+
+single_profile.report()
+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/merge_profile_list.ipynb b/docs/0.10.5/html/merge_profile_list.ipynb new file mode 100644 index 000000000..7a6d8005a --- /dev/null +++ b/docs/0.10.5/html/merge_profile_list.ipynb @@ -0,0 +1,159 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "60af5256", + "metadata": {}, + "source": [ + "# Merge List of Profiles\n", + "\n", + "This is an example of a new utils in the dataprofiler for distributed merging of profile objects. This assumes the user is providing a list of profile objects to the utils function for merging all the profiles together." + ] + }, + { + "cell_type": "markdown", + "id": "7eee37ff", + "metadata": {}, + "source": [ + "## Imports\n", + "\n", + "Let's start by importing the necessary packages..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f0d27009", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "\n", + "import pandas as pd\n", + "import tensorflow as tf\n", + "\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + " from dataprofiler.profilers.profiler_utils import merge_profile_list\n", + "except ImportError:\n", + " import dataprofiler as dp\n", + " from dataprofiler.profilers.profiler_utils import merge_profile_list\n", + "\n", + "# remove extra tf loggin\n", + "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)" + ] + }, + { + "cell_type": "markdown", + "id": "b4369e64", + "metadata": {}, + "source": [ + "## Setup the Data and Profiler" + ] + }, + { + "cell_type": "markdown", + "id": "410c3c4d", + "metadata": {}, + "source": [ + "This section shows the basic example of the Data Profiler. \n", + "\n", + "1. Instantiate a Pandas dataframe with dummy data\n", + "2. Pass the dataframe to the `Profiler` and instantiate two separate profilers in a list" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3567c82", + "metadata": {}, + "outputs": [], + "source": [ + "d = {'col1': [1, 2], 'col2': [3, 4]}\n", + "df = pd.DataFrame(data=d)\n", + "\n", + "list_of_profiles = [dp.Profiler(df), dp.Profiler(df)]" + ] + }, + { + "cell_type": "markdown", + "id": "350502eb", + "metadata": {}, + "source": [ + "Take a look at the list of profiles... " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b649db32", + "metadata": {}, + "outputs": [], + "source": [ + "list_of_profiles" + ] + }, + { + "cell_type": "markdown", + "id": "4ed4fc12", + "metadata": {}, + "source": [ + "## Run Merge on List of Profiles\n", + "\n", + "Now let's merge the list of profiles into a `single_profile`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4a636047", + "metadata": {}, + "outputs": [], + "source": [ + "single_profile = merge_profile_list(list_of_profiles=list_of_profiles)" + ] + }, + { + "cell_type": "markdown", + "id": "0aa88720", + "metadata": {}, + "source": [ + "And check out the `.report` on the single profile:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34059c21", + "metadata": {}, + "outputs": [], + "source": [ + "single_profile.report()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "dataprofiler", + "language": "python", + "name": "dataprofiler" + }, + "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.7.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/html/modules.html b/docs/0.10.5/html/modules.html new file mode 100644 index 000000000..db47e67e2 --- /dev/null +++ b/docs/0.10.5/html/modules.html @@ -0,0 +1,299 @@ + + + + + + + + + dataprofiler - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+ + +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/objects.inv b/docs/0.10.5/html/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..30e28b373e80a861c12da7faf14a224a2ed0cd7a GIT binary patch literal 29194 zcmYhiV~{Rg6D`=bZQHhOoVMMkZQHhO+qSz;+qP|E`u*;miTPFWRPCzB^<-q`+PQKQ z6DZl4ncKJ#nA^CR*f`lbxD&XTI5?Wy+7K{75fdml*jktvIdKt)7&saH_si7W%EaOK zf$INR#6`eB$H+j(`g=#&%!I(f#M;2z#@NJxz}A$&$;{l5;J@_*zgHt$YdZ%MM@JK5 z0%u2ao4*7eR_2CuP;To}-CGHp91Ub{JMxI8Yo^?e@#j|??UrrvUtn07y#{QIMOuX}{H_tHAJ zk;s*qM>2E2pWY5S;jDZoICs8qV}e257dlBn=&EdV3jl2pTm71s0SZ9_9sT>sX zsJUFAbFzywm8b8b*q@wtv@Kl-Jk!Zl`B-O+?GAYbr{q+82t0zbvR8WyLNBR3kLUac3CDqX}&@6v(VJl5jJ;GfMB>qK>CMZ5qsingoEfSJ`naIqp*p(=In$; z060Pk2hdSDMP3K;J*-exb9(hVrh7OFPH;rF`97hyZKwV1All>>upu{$-huZ!r1^PV zsHR01rlk%#PnKCd1v_5;>DJAhgJYrF1N-5l)V#b5JDk3E6U2Y@psPBYM^qe&&|hyf zTdaO_l2;^@Ax=SupPWRVDo=F0Pn&yTm+*X?JMpI4DHh1s8c=O5In`HxnpulO#f%OA z&L4libix8cKpIk!K|p^}PYSKF%4t+;j*VsO>Z_tkE=7rxWeajH=tKTM#8-}5qJJyr zFkX2_!N1zku3KxuEHcW@g;Y--)JUleBjH|NNxSUWoXu!t<{FQ}zA&R~N4X)xuN1%>-gSz$It&{vikg;lKus zXX)(-GZ6(F6hTHl=$r5d622|f&Mk}m<8R9k6|gGft8gPOq5d$((sX#kADD?OILu^3 zn4r)p=#YS66L8?X4$>ouAiskI3qk<<@@9rGILH=&zA+Xp01>AKS^zRC@Q^`E z;=iv5Y)Rr#`h}CeJYJu;d_J^wbp&laJRoTsKGg(cV}v9SWHz6-!A{sbUW!}daC*j@ zb$ihv*vvqEoG=(YWn*&#=rLX70fImKYp=M zmI~}Fn+TXFsN9CZprf!l{dHR-b^5p0ff@|Rc7>W8>YKM{NGk?e&|tARw*h+v;05|) zWr&m*6%Rsu%K`OFCMWyiibAP1Y7Sxf7PKFB@x8n}jmux~_moz<>ve-xewyC`Fyq4R zL5YQv=y&w55?y@*0lQ$k2>Pq`?7s-wo_-OScq?v!tNkKKJO4!>1>DCOmG_Ile*qni zSN9#LAVgBH&c#0UZ@}oKa#B>(a>@I|#J)V*#Ei5{MNUqKoQV+u)`U7(Zhh7z$Meka zSzeC1DlPiCwa1{vq0j+zB|f!o82d@#V-kNv+_=+s8@)k^Jq2r)$ykRtz!Wv6TGig? z@CTw6HrHw%FT>7ZsPM;zi*+pIP7R7)1oTBFM>p)urITb}RZgV+okM*P&Rq2F`0P;+ zTXX)E!fkE1?x6l)xm(r4J8M4XPUNx1B=}5fg|W%tf;!QALyNG4A~7ARZO~?pz3$R@ z6oP?Kz3u!geP1H70yCp=q!9a@=-sENb&vFl=op6SCB?!nd^Hp7Cu!}2qtJ`mmk<#% zS~PPHs@{1Q#ltAFdsP{52^>ZZbh&>6N{DBz(PhGK}<7-5Z0v4 zMgmE}Qid?rvIVUK(#AP$K8#%}O&cs#LP&>Z3EjY_}(bzJ#w6`Gchy#WT$T7*dEHc1rx1*=5 zIrmT)%q@S5=PS*{sK34q9U03>Q!3YXV-Ch2(-Ea7Axa$QsO}xWogis=X5KiQ&WwB{ zbcT-oScZkGg_}5GrfpjKM1OPuXC=fmV9BQJIssyMujzInJh5?^N`pzT6VUsVjUIqf z^y731N-(O`$Pi#RsI~9!JPiPs1bTvsapqW85kp+u*$qlOB99^DxT}Kw&cLI0weC*4 z-R_Un^jYdbuLC2XXbUjx^ksGZm|_%n4GiQ^%w#5!rvQ`zP==xOSx`W+cj8Bx1IdR* z!DJPy1jG~+t^7ij6nA+IDMhh^3;HEce#$N7q=Mu|6 zO0D!#%G714BO%rv?`=Qyw*TR8r;rl)F{`6Yqc|yx8==xI7S==J{miWf!a|)@35iFr zln@SxV+C%8Pzr6lR%0F^dC#XEBP7gYghVQtTiwIxmPZYVHz}vQ1+}xVaSio|gm8il zIW6ZG9QK*=>K?TlxcKlGH>^-pG;EM}IWw`BFn(kl!T!sUOD>cCLN_GBA_^?uSHE21 zE2}b1t+27efAo_OE=2@`UEk4nTD^2&Df@U1d%d}vIGQ=pe%#_W&iuK37M5BV3Tvfz z`*6$6m0OFysmw6>^dK~_?)rO;8OI!sLB=7EIe;CQjV)5w zXM%(<3ggxkJDiJG?k7^$c;5$LOc%%%QswX1cNXc#cY%(By|Dm38k~Cw0~yWVcIN-h zu(>Rz(%lqRR>sD`@viM@2kl2_VyFEXhB^w81Cd!5S+5~5zlISdv2#TL7XcnRl8XRu z3&c?p3z)s?{(`{OMmYw+#lv^}>WboY+I~Z^yBo&~$8}%iibHHC-oYiBw*{79H){rFF3@HIDJjtgDu;z)gC&TFhV`2R z;z(FFnL_9|Hki{{nj@ShM^{LNLX65 zAn<0Oj1lnG_bS)FMa$Yk+CX&rtp!GL0cq4>ZdtPTL0BYn+lJ)lN#&vmt`SRT z$GJqh5g)(y7UABn6#{dL*t6E-%b2s$-P>}o;yEr|BCBHWY3 zI4^*39iFuL=m1N%aX;t#4;G2zDp(YI(?D#LCy0m8pGTBTCfDy z*?OxjTJ3lt>0p?nl!q2y%EO{5JQrb`&OYX2?=E(iF2OYTI1VB;;4MVSuc_In3vEc- zU<$7C`^ zdSY>hz3*FFP57uAfm-8NF%y{oe1z!9i3)4NZZJ| zNUz|tkquYhou3OP?`;;2P=V`kxZ)8(j-~!~hD%g*?u7^}=5jiU5COImnBzEWhKNw# z!M5Lv={rqN1M6_7e9Qzb80W~6vb&WQE5 zix69A?1P(g!J<>sLfN9LAgNnmTY-3@h7GXl+)UEG(}xX^gmZYIKMDooo3jMKPxOrf ztX^1E6?~-JLr29^vOh#W49-3*0D_P{%IZ*gt>D~~b2221sw!(@erb`pGFKun(B)d@ zIQP>Oom6$?1y!e#qLN8zrFP<-v$pKwn&utY9m!i8*1{IIyxwO z79=i_P*+}rF=e8J9HX7X*{W1`_s*lBqV)59^>~*Px8U85O-%>j(ewkLO}JJLPJ%yz z6uW=DiO-~Wg(!h@wO4BWk-;65sD|x)f%-w6*>LJDot3knYabxdl+qqZzA=LXoJ2z* zOE{s5a+)wa1@$D4ggTO#WO#ocDB8~3UW82DFv~B#hN;FL5)Er5FUT@_V^`!~v=Z=` zDvr3qxrb=SHHSZ`rUwq9q#8bX9VC~?KI<5#9gsvpvIH*0lvFxgx>>aqoNO~mxu|SE z>(#&^P9~WztKmGIyqrDd{3l!ZqUoB0 z2#H2})*vFSuABgJwVsWJK=L^DUAP+K-@YbdfFsRgsALbAJgvD!LkFqZ*NY5doVWR7 z5H3L{iIzT2|01n}tN$Cz0s>TIk@5@Fqmy%@W3M@XqNvb%v3th9NJcTJHFpb6dk z1r^nGuioBe_ssfcpOsDE+t-&W(+2LzLs{J|Yt?!|lj}lG)6!2B9;yl8k2yN(r^dLn z)tO;`%G>iZNuJM~m0}EFH!Jl!&%tL{ZsRZVsm9u>Y4?$IGm+B$86RZ`OA*=`+`oU_ zdl`2zZi`rM5pI=*vhBZTh11n;)FjlyT+Xyp09hn_Ste284Q3TmIbVf=YOQa<|MW)A zUO4!N==w8oqGCLQLHUl|drV7sU()%I*w>iu)C8x!nfynaRB=9FkqG^m__>dm==GR4|imLatq%5TAb_vrqejEx-$C5kN323Lz8%TyRMGpWe` z-0n_jdnS+DO$*%bKiv|SQBTi}E?*8j4Jn%nb{bQ8 z=0r4%MLZl)@qamL+1ABHo=$zgwNwqjn<}Remf9$r5|&siljV>2QWfs{10;*SmSZKG zyqaUBn}ktfrOURm!{{EFSJcw@(#Wy1Uu*x{-$-umUzXKWJ&{%1N;BCV4~!LU+)wA( zgPfkX9S`^muXTSVQ}G4OWX-U?X9>X56=fMB9EY+(uo;HGf;J?8zY=Eyec*&9XQQy; z+lBn+W+S<`$l81%BM8=VqeRQhWMi4s#$h9**vfZ9bxY1@@#xhyPbFhgYMUo|WJ`{l zHNzblcG=9}J;jnGHWIAbWv>GMeD(PsIoq?#duAw^?d#PeGnZq+3%zEcO{v~ohAZ+{ z_;SPJSJ-lumRW+Y3?F=E6XQ9I)B34SBmw_PJ>f~_|XoUPD; zS>1*H%3))C`?Gm0#icmJBS}q{rmr{TI0<6D0cQ)0L-d}u3_KX^yk1p06mJTD<9Fnag+8mn7Fv>hk2?T9{ptOywLaF%HbRUgo>|Q(vcU9V7;&ikD95qawser34iG*PP zM*>WHU9hq|gpfs6+`fFRXE*$U!~zLr6y$Z29FEUt0(m^9_R@3QZC)^m9ehruqzQn3 zC(;<)Fav!&U=fhd>km4(o{pl4%_Z2Fp<{mGL2eViKx{yqQQ-r_hHS(-fA{Ixu{M~$W=>u< z%uS%LRi<{(eQ%SuW4AJr9>Az-4T~w zpOTo974mVh_71v!LL_^Gb&QMxwvv;dAyh^#%7u#0oVg9C^r#sEFM{av?veZ9#FmMJ zTV5bQF0vfp<60FS4-J@-)}&rc6neDlmPn6(GYM%j30jJUCLEU}2yKiPR!H{^n}05s;;)ApN)8)*g3q>QvcaLh__a8bwOmF!z|0 zY5#R{>}#J{O(Af|pOfuB5i`mRYCETBp}d_mx01e1Upz(2XR4g57Btp0+6b8G5^IHs z50AF_cNH{vD`RaXZI`}Lw;VQ>U;f}t{6qDOi#%5%r{Znbp(95Qp3Pukas=yXX!E%` zpp~^HHag&w1mCaaQ?P6Jx7a?)Z(8&q@8B=H{iVRjn0=JMP@z4H0B!6jBOu=SaQ`T{ zoBeNZi9Y^PAc!WOMq*2NU=W%7^E+U5)Y2ZP#)(EG@8IT-jL#0Jy^V0>IRrSKOF)2- zybTEWFs!}co}#yhg0Y(#9txU=3ke0qw}+XY+dzo)whtcJi)}6h?$UnGTCTco3w!4A z5nRtSz|tO9{JwP42>htM|-3_Qg0X(It#HcfunYj9b|e8G3Nk6nf)44NV@k*fKv(~jC%)lt=UDSO?KlJI^ek_HO{+5tW|>~HEJrP z4>UkoT3jL<9PR>?f(ppp7P(`Iu)@gY-vnzGxA&$|wlvF(C343XY~=@@!q0-5S`~g^R82elBexzRGz%XTIT72C`xS z`6a)Y*M#+OWtZcYlRn zUrHS)xo=6$?rpUHB6$DpX&@3^(83hl0Z=20V;w|gvNloVw?(8~Q)X52R)Z87)i!JuTHT1eNyG#^;(Ve0kMQ%#$L{Ha5Z$RP3#O zbt6;$=G2=f=bc?OrMt5ACrQn6;8{iI=CJv-zM9NqRQYJxEo3p``4p9VP*1Yxs?UEJ z#;E$%6HuxRtU%Gl5R~%(VvbP42EHwkO~@{;-9xS|w1GF$VU4Sws<3 z`e9j}zmFyc{a|exBLig9nrj00`b+vvLk&FlA)?zuQeZ7P@D zo#i+`uEi3~!`F6pFBZP&;Y`MLbWi(4bsILtuv!!KGO5j)-XJ&DdIU<`X(xJ&P8pYW zCIn41o(GKJ!@gr|VMx1$HXYmz&)=JXu$UZtQrt3w@7mmgr{TwGNVpRd5n_5q7*yAF zJ?Q=F49b~ZDVdlqm_XSN{r42A!>^ zFzM#RYdoi@eJ?8Ka8y>bM9w$;?WneUFUFD11{mtD?PF;C0 za#bRytVyFqIa2!fYNV1aLE~mfTDfFx02B{aH$HtyW4N)$^|KoHSCxMb@JY#M$;V8= zq%CgT76^sJZwb0m{w)~jJYhu^@W;539Ha6-f#`Wgbfj0u@r~7l@i=T;UFGl0QhP#l zv6(KVRr%Vt=EHt)c|8Gk;M{8;m5!4|Y&_-(^B#O%yh{_>@w6Vnz4RqxBtLU+ns z$#PC6LvUn0fqh`V7b-U#&#mw(VxRp^PmDf*4=7~-qM=ZmFIunO#!FlYR?Y*yWPhVZ zZt^V3?a4@?-(W8T9_;o};l5&&pf@pN2&m*mK1Q2uv7{e=J{};>UGfCR=_`EkXx+XC zn&Sfb9G>1EF}wLFehnQ`7Qm;kV2Ib9cWlFXMSvdw5fHo27bznQ|93EN7+{3l>{viw z-cn-xpW;;vF%-$t2J;8(+ounV-K-^twM$jQ#MCY{!VA9rFuUwa7wm@7Fp)w@ybODm z^E8{$3p(d7mW;oWqU+VrwrCv8DMK78EdN)itI{Q9L_vintw+GCAYp``izcs!-<}I) zmVb(?>E2LYEw{|1Ow0M`dp5R|?vk~;Xg0*y-@Y|cKUf_zO50!0Gg{qWbptGE3c_yb zcLklKt)nLqYWv45prHjSWRWhY%;SKcMAd9rq4O~5av9q7A@a%eW;b^IM>|cxfI;ipq4+~LsZ;IfI`drjwCBco zM>=2bxMwB$Y4@5OdtxXMk+fvzKAk5c^yyHCeB}#0Om*z@GCg_9yGCM_|KwgK$nJSa z7X+7lJ4?%S7VOJZ@#}lSE>A9PXI2D5)Gi`5MV@($d!9_dKlPDQ@MiSL0g z*2TV$B`f^Zz{2h-vPF@F(%whuN$9$|5$vpbivhWOU(3y%^1ZO4*Aas|Ps5A!6=tae z36@5KPO)DK?e5kK?8$0iO>0d%N19qU`>B1}++MI>~9LrUd zJ*pB`V{^=3%3~ELwro@5MqU{+9*q>Ow}it0brxieilw;{Ss2?6G(m3SQ{VZjr2`>WrxNOT zVkFCD4*W6Kvckv+B@{u~XdV{fMpxXzzzy5K5cK?R#Nzdo{Wc6 zLMt8ovUIM#sk|x9CsseeF!4?4z4}glwSKwtY&UzfWL}L8Nwz-W@3+a;8H8p94f6UGaRwcYh11nlPf0O*d%9E;?+j znY~V}iL(MeFmamztP5Un$_ZVlZV?pk_DUtuGBlnT)l5|Iy zH&yYjZoc1I6~iP{FF7wFW>oK~CCq(=)AmpeO|JIkzLigbKa9eFzey}pLxHt1ptB~A z$%&$@$ufG2zwv9O-!)ymGgVr&3pWcYryTbcO=)K!>2X+-Y>6wIY8lSTo3T6H+PmXM zj&%Lf+;YO(mrz}=yrZ`nBDm_BDL3D4eaDKU_lXIr+L9WSb4U# z9mTSgjlh-fSqb%f%WRGyp66bn;Wf#3uh+81iVKCcVx&&)+&fr!O(}nc+JfZedye>% zN_EgOypMq=qB+%W%SZJDU=3G{k&NxO=x4m6Gs^=7c>-E59?koX^=ayiugbePY^UJh zuCB9HC#?plCszuVsn0{Sx&BXO1Sy-R5UF=+?_#pO$mMcahy(xE#lxry&Fp!DC|-6& zPa0jB8EQHD(g|Vh(|C!!iZ17uc&g9m!GkC4$n4EVQY>ibwRWLRGM*lFf+&sc!A=(y zAsg(`_rc!54K|w2{rg5TD}wVvLGHS*Ek!c6AOTjWgTu>snWefwmgHDRu`2)L(;C@g zjY=55D@7i+MElh-U_BJb9D5mVi5(984nq6-ejX_iSG5fw*7P$XBLnyoa_sn&>LGe~ zGTgKZ0~xXfH9jgl)TAs868L#eu>m|6AiSf1>zstwn6+)}dD>^&R_^w;*5eaInpQKN2NHAnxrx^*KT$PuFM1^qZAp!EZ^F-PNZBhh| zptXt2K<5r2=a`5?w>)3-OF0q)1Gp1<@Wb4dHz9xoc2}(Pnz;}7$QPb8vh_kKYH~b8K}$ybo(GF zk0$USnfYtG-Gd}PQPsn^Y`R3vL5UJyjaI2rCX?Mt_1u@j=A01-07b>l1N!5oL7e%_ zBhM#vumdOMt5_g?7^vTGNpcXJi(I+nZG`Y1&W$qhC6~>zi#l zt`)TCo%d=k>edV3xF|))ja(wp-=BPDqDFlfJRUOPX{%jRA%r`ONh@m+7#T6}z?85( zCe!Vc%Q}8IRCalE zkmvT%{>Y)*^}0shx*g(#NClW3duI2)qty$qu;CbVt}n`|&QH8Pvbp}86QYFqdgfa^ zhX@&AqJuI{{OtQEND5$K2A0FvxLIc@ydmY{KaZa80pG$re%K zccw9Zr~q%~)fzUnP$g*hZ13>o`xO_5IsMm8VV~GB&frvSwG-&7?Drcg_hO~b$c-_k z?*tu@A*Lc<$h`ip1%`k}1jw82&Lh+tjSG;;; zizW|Q*%jW(Sf&DI;j=dIv@$*}D%pIoXCGKovNSx(=gejlCE42V?dEJ1b^3hWQ!_YRgAdk;}S2=-tw@#Q!tNyIW#v zEk@BjZC@X>;Fab=(<>Ggs>Y4QR#MjJ#HA8y;&dKe?pTv>Z!_M=hr|Jf@EzE z%^i~;cg+U&8?V0x`rBbAbzJaK?w>M%0i|^RHy@NX6>+wC@Z^@Hhwc9thIO9G@zwIh z>qSx5nkx6ex=k2zOk8E_`z|Xr6xr)wGz6K$>+Ei{HLLmJLBOUR#Uy&(qua^nvhnf&n32j!2Wr#mte+$r22n-4M5FcpHZZ@82H zHxpW9CR+a{kM%PkeLb)|bO7NYBZt7u3Xev^?9vQSBPRd!0*?p%^xTXgBKuty)~7u{ zF8bzhvHd|Ksq;Z78$Ku{gmA)1<;75>e>_gYL@5hnlx3+0&u^uIRCs`|<)!4%dG4jM zEJ*lml%?>9%WuaeG9)XMMpUf|R1P4)S(YEKwz+1u(4zNv?4!^2+g$zIN#Tbb3s0kb zFaovwE#U)ibtOO{`!V0d00NMH28HBIYYd4>Zz0#*l4e8P`ici9nSNqI^<+C<>wBU^ zoq`2T{o=x{QzOW!;ZeDaXp(*jm`+$S#r z>w+_PjTVPY;h1;eg_2G7ZIdG9z?k3>LJ&NK`lzG@VEFhEB5)N707?khW?76m;ZU0{a6NIh!9se{FzFh<)h;b5 zjU7HkCQb6U+{u;GZM$2fpbK1-( zV;1cr`pL_>HvmjXtceic`AZAFAs9^YSWk#J;HF#L-)-d>tfNI7^3oL_9(1uLHc=vv zKRs*W>U|D&ic-2c)Gr)WgcN=_w@1ahK*D%e0X)hkHNyM&C|408fXNi zDwYA3`@Gk%#JfGs^GTg$>MqcXkR+zmFzQ2bIGiKF)uQrW6FlfoMnGjdpuwVoqbn8O zMVF7Pl%B0HgKQ9q4}Hdom0mWz%J@V`>At<1KgTYPE<+Jk|h+r5G1T6t0y9;Mhe&B(gvb3Hf%nRui{Dt zIn=r7EnyNuJsERIIT6Jb&T2Mn9DZqnO9xSPSQH2g&aR~~YSQK(b4z)8iRp}z(!q3hv4FwGg<6*zzn zh;kk@S*mZ6rdlAOlCWj1rknya9X3{k1W{h{rT0rV!sg0?<9Kq?IB@+Kr9Wcb9EGkM z*1=$T)R4(emaJ%CbE+xa?lxb0oO&Qshj8b5P1Iz94hv)l;(HkFek9{ z13Dx?-Eg@;4ounhNezZbxW!ujf8%~c=hu&EJy3>r#H9y28h4MIx2IV$_1d6DcDs#C z`xBrJfFMN#JnV9nST;!l==3rUh!Cd_uOg^M(I><>q435To7oVaY+hPaMHj*@Y}Zk~ z5~)Nb-;U{Sa>yjW$2IzmKw9&Nl>L|C&m@Bl;Oivl@qVx23BlZBQR692#!?Ut6j(EL z<0yp@VKAbywKQ1)CmJjPh@5%h6li>$L8xS~^=ErUU3RWQhHPjBUQ_e5p+nJ%q9P#> ze>kC6>NvAy@4~8vrtfLIgo-^M8xY6yWC3V5AI3lgSwxGYiP)PQkg`db%)_MMP1enh ziX6Wo3Mh%JNid6pV_z2&1O;Vm#u8+ue>NNB*l6R+BeFv0-9jZLtRsLm>TLxar^N(S zHe55Vav!*q>UAB5t}GTLDz>a`haa{)-|~a##nCUh?F`-|_{?MUiP)n;jHGUg9QAxy zk6teWM6z}peDc@oO8^+D$}qU=$msPG<9EHDR(qhz+JMLu0w0>PWrHD=?gA%j!Tye? zSPhru8N;OdLc!s2?yXq-XN3@9zuoR_H&lT`;MLXPPZH^(WSBrL$q;4}1J6+|RRx=nCH1&@5P zOMxe_7>#()9tb0#L8aDBzeIn!RG&`Dt@Y5{aXNMf5IWcRYC zhEa0!<1t|dqpCo5LC#*P5^x8Ye)}B74zFrEUnQWqv{l)6F5f)}Q zV;mK>{Ikz^!FzYsLIafVOj^8bzKoq~bjq@-WA3s17Cko=c%RiWYNwS-M1a+yew5Ej zdH4EM^;#5&){etUMvC1Ihn8#pv7Z*%QH0}Jojd#&r?c$1mgjE6PTjT84Z3ca!?ieE z<3+u;P#?cF?4*|GY{O3DB=QHzFVc6KYvIpz2cJYAx8dBZy!}19pO#ut{&vUeX<2;O z<^LV&G&5^Z2Xa_pbF;J~p6Mv5K!xo~BWCa+RWVhFG^$r)hx^OgsqCDnles_CAK3|p zdUbzY)py-URrgWISk0F<)iEe-?hC!A%b*2xMp)EDC5p3Xyx%)Yoywp4P(tT3w)fV> zUrMy1zZBYv@6yjYk4Sgi^AXS*`|@^{g!|T0p)pdM8q~aIs$v&i6O{R}XuU_!#TD53 zn6q@|LD$H{Pu#m&hi1iX_vH4{>1Kr~>-1kqyh45h;ES;Mt%)r$lD$#bB32G0P6Vw! zAfzKbqrf%(AvBv%Zt4wH(pz@F#e@*OevsKzuUf1ke-Ew;4mX8yA%IyTEdAwaasN~Z8 zac>hA8uKzz1$JxYAVYL^VPr`4;UV*UqG@MuCKms&UmY{-EjKO;d4QUZdLc=NZ zWCjN3*&~52GA<-UXz#r>=Gs$2<=t1N6PQ#YyiEfCzPG-!RMY+oNk_tDzbv2Jl)(OL zf+MmWS{G)xAf~sNTR08Aj85-(wuK>%=nraT`M0pgywX&{Reu@E{C$+otcX!8H*Gcw zUf!D4kTDYP|6lD^x^D`C%O|1H>MF1OIHoc!W7)bL^b5U;Yfb<$-c|J$nm5#W5IoDv zv-p{O)@ziuHz+MIKJ=p96{alEhwBJKOrjq|0#nWkz<#`>rI3ts$JT_$wB~`;+f1eS zC9o=9?Ryk_^Fb5^CUicJ<`0<2p+L^@iW2CVSUj%bfA-EP+Ccv51thq#U8)29Q<`=B zr41x6Q4bM3ZF+g&^TI;dUc-zu1|v^mL107)NUGJ8ZWyd6S)8>|prr7PbjMY(0dkie z>I!Ipm4@o9Bw0@v5|50dAY4I6R4wyE7{m?$xXQ}?YEXfWCfejfl!Qjq=1wgw1bK8! zP)cBg)W8GfQ2%n@;dI#=(uU<o zIk8}by(bEI|3?|}eB#P<=Zz1$I9F7#0#F)S!MF;33BzztofYh@!D7(K72}CavJ)25 z*4Vp-{)EjDvQt>oIMQ4|=PezJ;4<}1oF;|jppF-MFz3aRD_unyhe&loi1Bob9Mm6y z;e-PsRf(S6f9et{k2r?t4g0eY>JtN&g+z@XYDiF?mjGO0XBFpF?%j1sRZnC=N}|L0 zN@DCJfwNh3QizzIuR&T0*8-I6K^b9P?ZzQI?LejhGzBbKvoolVyT9y`NsM2SK^;K` z8PPwfF$lG$lm}7NyaWOa`j<|U$GQ3Fvk?_B5s`(HgL9erqBdzG&cMK+fh>rK=tr3M zllc(vDlf**K(fsSnuSYZJvsF`(+MyjO0YxU<^siy{DcSo2*mUMc8ExhU!Y#g3%-W( zeeyVR`Nrh&_d=m>5{I74fjoE0au|x_ac01wj?akSiVVEsFmky3@7jz$}O%@uL)->`rG?zrIx?B6LPk4ikv^D!c?#GO+P{F0~`$$&K9eQJG&UM1Fz1-ju2P z=AbjNG`CO5R1IRZ09X_eC_+-c97ic?jbjZOP_(Xab zQtd=2hLmA$uoPSSu|E~?TMqKh9XbF01d*OM$jm3>gMM}TeG}woqxr*7nY9;09>UTc z6nexpfXK{?ez1Yv#`9|vGuERp10_DBt@+EsGdedlf+arKFhjJB7!M&$(df$%{Kcdw z9)dxh;*&uk_)7$!V$MO5kq_`GKCQZo6&_xkHJm14mp&)(q^Kmtw!nzwm-E!u6ioi0 z@H;@REs`bOCUhs~?}L;FcY)$zKxH~+%H_d6=ZKSu^=EtRm=&ycju|VCjtL9Wlo1<_ z_?R9H)>tHdT7wP8C8OHUi8L?XG{o=;kDcAWg7_fOl&@ir&4$cSRcH!h>T>Xs*=8GX zUQ~>DPupnFK2!rt02$X`nK_cSwB8Y_GUs-2=`#E)Ph0ej2JpxV(sO)SGcEwOVQp}o z_i?hnC?JZu0dp{<^>i&j1s>8Fq!A>#Fbs1bgawkbh#5G#P_7ZE63_75%oJFx)}9$K zj0y>k-dS-;^dZA}$C0igAxAVDkuVvNQIauro+~O{+?qPiINbER>5AIs+IUG=2zM__ z@}O?eYrG&hgr&kgVOrx7XS^&hq~>3_Swajb^>5Td$?Ja%YoBXj;h|Jq=)nFLDKa-4 z7`+@>MA|OL;WwB zNHBh*sR8DH(R7Uc8%+{i|BI$%pWkT84E&9z3B0YAnef6_>)ijGSHe7D$(gQ{pdC>5 zvSq3yvSr*vo+j{d+0tB2ctksVx#rnQD}jy~-K6w)bgSh*R~Bcmd)~Bwo=FM(W(&?C z8?7=fCcg0#$Lmh(DXB6{;@nC1{~i++GET`%JGRpP=RwF4d)-d!Y7aw2@t%{Gr$zUZ zs}v4g{-MSQ08jg?h_E%{9Ic@BZ0JQX39>bqLEGLMMQ}nL$YacWms_A_Qo=-s7DPLF zdTm0&$|Og)o9=Qp*2gZzX&#{~RZt6Jl0>g>MAIKC33Srvrp7n~ZcV@p29TV}!Ka~X zL7-`ze1XHzP}kg$-qx(M@A&_iVlg$s#j((Q%ht#9+%^0g1dIzf<>>DmHLI<9%FW9P z*G_Lo`f1p&7Lnq2u*1x#R&!34h#k_om4PTZd%!6jLKgUYK1lTUEN?GA1&GKR1zpeh zi|ic{JWM#D(q6BuUJG+&6^adz;iP!(?$0z^6jc`V|d5W z_Iq4_cs~!=5jpa=!ER>y+cAg;2K*IK@R0wvokX~s^=}U!-rK#?%z^{CZsjlw50h&x zkMdT*izKH4GELK+w+~x8DMbcEhXSKU7(Y1oYL8I=1el6_?cf`9Oo@^n;S43^0J6{D z)doFaQq;k|+lk^oDQY$XyQuUF$=@%ZJhB-9p@E$xOd2x0&@^n&-G-6GX}F%cWMC}m+{7onkn-|vT}f?(dt&rTV;i;R#9 zg}g0H!4&xK+%}!&crj^-a~h4En9MR~ffnU?xY&oP&BD(q@ndt?K&QgZ&gO8A_GcB6 zVhtU<#wO1DD8kZyT{1!>yvU7&L;|Pz+n-Y&pMy-xRF{D(yU$l*5pOSJ(O%7o0fjs! zLkk6N#&3Jqg{y2r=`H~K{X80b7V=%b-z|~-Ctu@xI9)%hsAE#3XyE4HfFy-kJdW{x z8y!EP#BOUqKh)3z2l7vs!rRubS48*os2WSABmX>?7Xc5T{c=1MQN|Erg zGWrZbB8iL9zd2-RZx?@Z(FP^!7b@AEt}gHnF=}9vHi$6GXvirkO6KQudz)RHI5n#@ zIsIjNEYf)Ytd6De$Q$_Ujd2iiVt?*e{Boqn=-A7#$^V>5ho2P(bv-0h1SPm4+2Ite z$USr;`j8cW{F54n*Wgd-ZY+!U)exKu3bEf4obN`XH*Twg!E@i{)?Y=8rvkDZ30XwN*jNx69h!5jLW5xq&T~yNk{-X|mrg=Nvsag#RfE zhdnT-5#H_9^9x z?VJ|g1awObDI)gLg4pWq+uE8;WyR$1RCq;Wh-PhAP}XJ)-l*j2=4+VknB_1)} zXrt42GY@lrgZ^SF(<`)#&zu=I0X7+llLm$Sau&R9s*nqsxGHm&3>*8u(j^i5a&dF4 z`*j2agHH-7sJxKLFsV_&60%U2(2$0%L8onTbKGxXgg&d|sm^j-9fauD)i4|Hgy6br zJKM`j(}n|GhYU|5wIyYIHO2xsJuYRvzK@O2XMlLQMu%M~J(<3bou&3iOG|p22(O7( zC24oZHuND5eY-Ot$_xezw?~FAy$z!?c`Z5C#O@Nm%11r*n!bh;?|&tSaT-B2*3G+( z<(P}gix#FFdt-Yu$==>?y`AzEagp{wg8-xQ9)aWiZ3bvYG3k^oO(_5fvqcSwwU$>V z(leoPIFU?#5&CDRdu7}l2#5*WA9pC~JmC@N=ierVSNfC+*GGz<>f;A;U00|@0zMK{ z9L?t5v?Cm{j)Nj)GPk|QrHb~l@>s5ARp_jv=um35n%x3AA>1MZ@@IC|CHGtgqhz*G zHpi-NZ9OZZO;BO%UABPly!jFKSbP)zcuT4gFqxz~>97oJJ?I`3{XTukaEs{jm(M`0 zmH0Cs7VeVE%%`UBni9M4okIWq#`(MBP!L4L;9fKSjf_wgtnH7cBdUt~qA1DPH94D0 zy@y85KEB+ECy$2H@m?TX8J0_~uRRuBjIa$_}wqS6A93MmHMv~f~YZ8U~xa;3% z5Cbs`*%~^(2#tb^>`xov--$9IbR^AYhgccRt*h^w@$0&F^eChyct#5|q*+f>(=bQH z{qUEmO8iYd8-if%G_7jUAD~vzFPi($Z6^{pcCE`A;Jtz6p1PZVt85M8Tl166qt<)N z>%wO!_Z|v0SwR~rtGf$J_HNjpw3WV~3S}OBD#*Ie0w4W8czquh5ArnX!~3`==4Ph( z6ifjEY)L!Y3DnVRFLeN8NU)uP;w>k8i<4vYRhSLBdqn_()zZG&j^dm!-v0(N=TIM? z7&(=|7qNez+7Nb(KG`hClT*Jn+NofV#HiI&gVY0)hbG$aBsIcgs zuH!rbe@$_CjVBDqT;7NH7ot%_Bj$2RZbhr_IGOPhxBC3K@7~Q6b$X>x{LoQ zrrJ3JjWV%~e&|idIB72(YB@z-N2wNJZ$g0FH?bD$8aD{A^-R^;b{MOu1PC)Uh&4K0 z?Tn7saZrXzIXeDM94dsUc=c^7NjfrEFY8%pMGAKt=bd#9PqgU6t@Xd24xaT`*uDvHPj3o2jYCUF7(6e7(1Hui{lA zfwl+k;iHRSR|I@Hc{y|lH}JKt`MqF4i$vd+HZGeG0A1c}WKPQJPk#7n1GJi@4onBz8$JgY~mvIT|!a{4Oh1 z2frEDIjt3x9^xdJ^`e6%7$K%OS$7zWMEp0nm$Qj6e$xgjOghIa0OaNyGZ_fx8n}};_Y;RV?<)f_@AZN1@Zvedw>A1`B%cV@@-G6ownMvc(!$h^kY*VDs_4EYx;DVI6 zCz!j7xh1|doWjR$zSJhWy>kx`U-o@FQ6X$P*gd_naoHwui81v=F>7{rxO&&-x-?+Q zs^iLW91x?IojAzJb<^U;2Mf=vpeMxVur&WTMeHdenKLNADH-KAU6j z$xKc#YsYf8n~Evty{-|l=!jh5wrbB!Ej#F#{#$RhzO85|VC2MPrVGN6cG%^Hm`TN) zb5uz0K9*Cwia|506Y-d4%_#QkqVIEm7*)@Ea4@<2QtAyCL_9_(>DjbJKuyS z2Xsy7O-u^+97v0uM#Q}R+Lx9TX#?zyMXAPU_SLVta<;j;qjw(hx8>Z=cG7U0J5Xrw zCf*<;4p;K@8vE`>lhZXO)~D5HJfbZO%XWxDKQBC1x8~Fp9F~zEh(1#%e-B~f(>05f zl;jmsD`d7nW#Y>7C%l86lcGr8E!b9Gl-10gouJ~7TCy@4`mD1~Z*&*EMmP4oV?W>rpBFg7dd@n1+N}-99DyQZ~TuKTaAk2(` z%Z#AS4%ti2YkX?9&LAvNLeY)H6*Rc+>pYwHqcb@9~M0 z(Q{mj7t;*Lc1z>p{if&q=g;<=j$5(`3?R0XihLLoZc@yd}mfehtT=rQ?>ABM+m3h0!9$YmG0zCi z?Jy?%_>MUMO>OMv8@3h3nsjDznRrqnEzAY2(v)Vp@XgtP5#m$hn9d}#0zy@6vgXLH z9x~08ovjH>Xsl+0hMNk^Iie1?YLI zaaj|T*my{`d#K^px*f0!Ffirj4W&hHXomz3hh!h?2t{_mQk`A!jsm z6Z6WS^u-7QkM7-fPs(`J0As&>h*z;$o~p+q0=%ve5)SEJ)wh4$xZWT(svFVNb2vZ9 z3+{uyLtUe2slBg$9@tW&$v@9`H@PK7oeBAU6+nago#s?yV$ZejgGEn>IIGFVMVOgS zi$$J(2PwhD#T*$bN~bkx0~KU#ujKV1rmu`u_}}Pl^=K6U9xaB)pOsLu;9Zs2OmWj7 zx^PT4z;|3{OGp?f7x6`h^{MFnl1pbWM=loa=!}6*L?b=SK;PyiqFZ=h z9J#WNdXhRV%p& zB=a^bF$o`xXLzAh$4m|+v9X1?q9a}k+T=LfBRA?pI-UOO>s&e`0}(S*Tb_~W4Plfo zEfK-eaz_KK<6Tv)t-H&gpaEd)2wtiEUDZB=AIsty{-U@I8kKDeK3dG0> zVb(E*aSop>x@qa4#D$0OQkayBc(!Fs;`8_n0+xv?!e>3^7@bj(Ltrx&X$lKIl zGJmeb2OUM7-`044^m`WA%x-Ww3ytQfCUVB`QRm%-B>;<>-Ni6Z_4`4{&||8y2>!*m zqQph5v@`gq*?=Hqg^?l)?8Hn>#zHQhE*-I$^N@n6qeIV`y=6@5i zpmDG={%^{OGYbt(MT6V7_*1njBq2PE6iuKgdTKH!axiMr$iXb261s|pH~|GtX}1}X zKWMj%^Xp#ZFujW|7paygqudY;rz}pItoRag85K;(wm2(0J|}UoD81}Z;V@)YrNt1+ zWXGwzD7)pWq=GFoAxDFcno1Op7iNm=tte4xHkN=H>d6QdrnB{!q&9{gJDg9kt1a(# zh*oN-;?qt+r2zrz7xKl@ZFFB1I-0DY5OJ2SXH-^Tzd`m(fweK-59`3EgZvWo3?zfzpEbNLhucjOyj4-+h&0d@Rm-d@OjY zdNd8fo@IyKbVtu;1{xtHvJuOp)co3c4z6pZSe$i<)H6hw$#+nMsSS!}cm5C-&@ZnQ zmdT8#R)FFYP)%>)(8!Nxkx1qh&_7)Grji@aXivc_U>bDCE(J&IzS3ggbqeu^Cl*EQ zbfBsoyaix5ve}3g&r7}-sR}uSCdd?p9sSAW`4YX?`Rzy#V3z;J15upJu+iTHmhBD^ zH5pD+0hHj{UOW9GA$z~z_)qeR6R#}cBf`Auf|bwmcF9qS5Pr$T(J*`KYYcdKs8<;_ zA=joaoOPOsp{N!<fEk*4w@FW?6#!!HxHhQ&kT4b# zc;r_XJojvEUd<%SsAuw86FG>ZyB-{;YxbM5#k?8VLFBJM!g_&T#HY*bg{LxV0HIIa zGGwvd^Pec#^0Wj1ws+iTc5bQ{t<8k9nl@7xSOnCjDA3*^n;c?;2#zZ$;%o0&y2Dn` z3;_~qVMsppNsu9`2*g$r*BzVs1}2X4qS89JAm$5VrSFOMx|rhhykjnMgyVfSu+QP8E6$f4(5MM`4-VO0G1nlI+Z^Q=3kuB9B-09AVvZt=qLd$^VV= z>tAbN1pzI)?7~+UituDfjlm)MA)Qk_n#l5x%pkKp`aC9Vc24%RX>kpW)~cXb+T?M$ ze>600YZ@XGn5KTMCu~APP?Z$sN!1n0FR^F)ihSenl+mp%eY?fXA&B4FWGGnbN-{I; z)FJVeM_e+NOxwqi3K2((y&rePhVtl$kXOSL)wjh+JjmY=fe1|N$trsf8Wha z()KS;4jnD2@JqhW@j4t~s!D?t2y-Ua{UnwfONC8xfqF(j;(kJ27Ez7v^)M^&=|Y#0 zB%-8u_D!QIXZyHG(Mejx{+A82+^Br80B}wBh$+PoY(}|XQt;bzjC{5_Dpq2CP-U-e zIMRASOp0h~rSck^L*#Vy4-W+q!}t8+G5L^qnN&^pDWy|4vCxo1_-GPN?P86dQan!W z=`Pf4Elmr7dDLvXEkiiP9GY(!HgHp|AeNAFStNWHiIBrJ?S;ZBY}&m@*I5JKXj0C0 z_mLunboCatA^)$J5}l9CbRM$?F>2SzCbI_o{{*bpG?T7ngsg4-Jc&5#vd3kph&jJI z@*`(UF`^<74M@r$RWE3RFXP(7~0Pt8Uz$}?ke7Xw9 zm)K+)LC(7}JW?y8Zq#_#@0{zZs4*N78^1@sVsrW>#f5XQCW-H;rH2!&i8>#a{DrU7 zM2n~@v0nYUvGQ0GI*j6{Ui8E?{bG3xhGmij}s4lgYN7&-|O|2@@5L|)b}$to{d zw)|Q@cM>Uka2`vEIhP!}W3g$#c|?yxwlh}!608NzGakYaO9O+J@W_b2jG$dp;wVNSKJ)1mPuSiT{0Q6hu(<%qm1gCn zX(MS^GM~bu;112^I?0GWY4eN5{NwD2Y^N80UIZkfLLq0d5J{T7DsP>{_jP)77&zmh9-^&KvR{%RIYs+ zk-+9NrSO2Kj7`fp<}p_nCu*vG5%GSwDhVBy!vC+zRCo{-D14{^|Enmf54fUm0{^Qh zTo<^aV4K1JDjEWs6rLPt`>&$TB01g>B$NMDv}?iM*m)jgC3K&-0_i|6GYs#K+j|FW z&1w5Dl$LIz&a>Gcg#U#CbgzFK0c`y*l=#X7*){W#-am zdH|Py6u}H<%8Rih6n^(TeK0et_;lpRX!qqRjp^(6Qo*Nn=?D~qdNLGs_j^MYBdi|! zhumM7p9cPccqWa4ol2SU#4kdINA-4ND6^6>)Hb;F?i)n~?Z@P$3FTwUFEJ+%?O15v zBzYjLdnFT~q?lbI35EM*xlv*Z^v6)37-cEcHUU*HA33G6I(mfYO4!&5`@_d;?qlo= z<&n{%^K)+JEyJ@mYGR`VQ-z%mSR7`yWmWJLM2yP;#c&f2*e*}DE2u-mn#Rxs9u~Rd z5*1_zIQ>xtAKkBH6EZ7QoAV7*q9n>|<<7{9lRj#At(B?IaJ8>XZBzRu0?MCJ zv@zsZFEtwXB_Qy;#;)CIQ9_EsrlQ^jR5ZhFOHLUNPS;cP$<_U?1rfT(BZ2ZIIJ6%Cdm20;@5%$IZU#P*C}|ZEv$?t2@Ob`e z(Nte%LC106oCIII>nDs%3I>tg(W$dwqiLDR zGxAR_IL0he6x}~wlv0$dA&Bia1RFJR4?e|U-agsUn#St0k1gW$aK20a_eCHuYShvS zX-Qc?KsZ5idQ|=ie1jiPRY;n}m?JteUiBmx!^Y5~=-GQcvU~pC^p_d7*xrjfL6ZJ8 zeUH5+K8t9;%rlZeM0;?>K9VFO{VU8dgUq1RL$7r{NZNRnQIJ>uO~i*n-IJjsXmS)2 zT`MKIP2^z-EvwRPb73^U4T*qF(1H@EW;Byfj7-faSlVrEp)`VAOINU#{j8%&tLCu; zW-EnSokgY9;!ytZK!2gcx8j~_1X!On_kMaKchDO;6f<)B{=e&k#hBk#q?V+_Fvg-h9|^DP zdk~rPO2ub>ubIz_AE&Y6N#=JC$`FiBJ94`2wq0B!0lc)@d!xw4N=6TgpUVP8jOn(>Z@diML6-qR-temv4u&hO-b z5eD^b;kYml&k@n|gzaztpVPu^c2w6$N2aQl`-4FqW0nnL_DZv91DHw_cGPV73I^VA z%hO}NB|D2IoRAZS;ItyCx{#4nZ$xgS7b)~$Wc_6-xx|DZKv&cCqItf(_rfYMRJF7< z751QN`webNi;Uhk{^xhYjVNuoV~QAt8@2NaOgWp~e}Nk%7$uldWf8#My6u{*Zc6w< ziPvCb}*DYFu)&!`ktpI^x(b@Q`&5 z?u-a%d|{L1)0NB-i0JgK2{=|9AaIVLV<~7&=$ZU2B8SQkmse_itiq2tI@20iF@PD_ za967U4^~zPT^IaEg2U?hx)QJ}p&&~ima*9BB}xykpN%GggzZ0iof*mz^^ZkvWZG>o z=d@~iX0;>|)V-jVRq#{X(PSEVDO5{l+6gH?b7?bD#AjS~-|RHczGE>99n6hOgPDo1 zU~p2q;x>7W0+~>_ z)uluUlB+)-q zmUrU+?5>h35Kmh@z>L1%mMQXoIFUWT3)4`bKE2xL_UcmVrE@Z|Fu+HbLB)<*B$rjv z-|33MXrxqkqF+(%xG2^*Gg!OxQm57@(EY#lFS}_q(XwCkmC72=e1$IzN$mK~b%L@E z<}sC)0;&0gicK?}n2ybcBD>Gjvo8{jqzWP^GdCr$VM{N&VFdp=%4?=V|32k5btC@! z);zh-=Kp3<%#ozvtca&a7fNu5B-oJd7@)dL(y$314s(&2GQ{)L9BA5~r1%h~hiXWT zoX8vDdUqmOv5E3%g!9X9`{egQ8EUnEYG-mo)MQUdgx4q<|hy!Y>NEQ5vkoWgxZsFHL2ZaIO< zHLpl)V}~@?B22z`+oZ`goe|3hrsbxBsw$ZHtSJ|>V!#9-tTVjRz}?>_e%2GLR9@JJ zpWY#G*Ou6_cz_FXv6M)J=UTmFl@o%gFiQ;d&ec?^ojGPYq$vs>2#y+=p+Y-*>}+uf zq95wJ!YQMMjkH$K9XTcebq663bs@;n%l~I3}=FvnsKGtqs zNo|Hp1>t6=i=Ep&bOmCsCBQgF$NR|zFMGk*-}v2p4jbqX z!PUDezZ~KYQVcgXek}D3nDQ-cG{1qV_HBN#TrB1Forc; z!(GP>g33y>*O~JNbz-=Tn}aER&!DpsQ5Em^X0MLduVV@Wq zzVf4uRGP5`y{o`Ua$W+SBz529AD0bwl{AXXX1)gdM-?mv;>?fkT+*mM-$vHVf6eMz zx*nKb%(=PNU=j}PW8$Du_9%!(!i2JaRC;SDJ9jirdj+~rH7Q+hfEur!W)v4)M?)5C z*PCC9dyKaV3d6j(F_V8jJNmUS%3;?yiB*q1W=!AuK4U_tU%PMJy0bouxl}6B+a|pj zdWrWriBrxPOWgUgmODS*DACT{eP9J$J_pANN>{@k(uoy7t$pP?wkY z6pI>1ii6v4&SQM*e%)(Ho-8mSwOyVBM)g;GH!n`r2e{<%4{ut9+?7rWM+8o{09I38 zA6{i2PYD;n2|0}kv@V#~)CuT33Gv|z>C9#Lu8VQ0-;yPMtw!|gS@x|Nr0H+G_;_k7 zyrBqG|I!dG2|N$2zY;*pnJD1fHkhdhu1K2 zS;chXoGNoIp<1Fw4~%KgUY_~}`X-u}{u~i`L%J3?v(OR}%*D>R$jQ3&6+&FgdV$v0 zLUn7&|5{?TCHCxxWb3QueSHbRb0f2^KmW*idmF=3k^d|qw{M^!d5(XK+51XEn=6wS zI;9l&Nf217iIHmQ(x#xCroB(8#^_%$+gE&+6S zYxn9E&0%QWqV48?vYK4_Yrf{Yo{GC+##@PRab1I9P+y%B-E7zuht1*?mO)RW&0}+w zT}j7j8B$-4r)o7ThX3D_(tnj8QVs2Q{nxSDr;WW<9^$pes7pI<$%8gn!<~YIl8t)T zaUW~asr&kJ434lH?K<6_N!EqmC>B!xOms+T~5dVXm-5Qds>w=*+5fc|Wj4 zb4I^=4nnJX?ngTdzu}FT(dK+#m1pgVWAuj+=S=ru*1bMz2A_U3==a9^{0+0kMZxJQ zgW18qAB4{rN2(w1Y9FL^Z=@N9#f$dA|nTKx}w1(QtL0LWYo|;id;c;RUP0A&+PwHDY zuLWAOig__6mSSN=4l~>R$idA%!0)GdFW#pBebaERey);zGd@4?5z|o2ZX(0z^qmfD z_uqg1vW0wa!R0luH2?tU_J*v^n)@R8!=cn9fAZ3Abb}u6n{C@ZuBzG?=dsj#=i%;? zRv%sK%J`I|Iu%(5~>2#ZGTjZTx@U7luA4P;AqSu$X)=Bu1w^i}d7X!)@`T)1smZ<0A%xuwyo z)~fT+V@|dB!*MxD;xnXLCSq0WPU3e%o1i8eE7vkj|ILe9!{u7G;9F&u?`93x?dQAk z=c8?Po62gr&}F?q#^pKBO)a-yxOc@(*<+x>kM8{96ipb9>L9<3FEa&g0_&3w(?7YB zv*mx>o}Bk)Z_6oJs;_@KLS=VSa=ujEGu|j7(eBFK7K+@<{oaRsO$n2fcBw; zzM=QIw(Sg#l>_I$bHk#(rxojQ&ZrQcVXHWUI z&n~zEwp{iVcUtVU{bdS_aC_^KFG(1Go{XRI*ItwjG*q{$L-Er$@SAK72dylk#yVh5P*L&acycpaDHh>p-pgNmCZKq;lz3#0q zJ*Ubti{{UH3|sv+N4OhpwXcoR13I7H)ayd4amt}EIj=}ZzDQ$6UTx@3>DXN3tccT1 zV@PQ=lT!vsZ{EY1QEfs}UT{U_heh^ECFv1i4Tsj=oZAW~} zo#$Wc4(}dtpcsbhBuTXY@It%l^^6hVjz7aja{ZeB!ZcL9F(ygwos{qCoZb~_|(Nu8h%7nIio z)l(oR59k;(qp*R_24xjS`WB1f_=oN{avvTMsS(6>p(KaF7YZ2ILe^8FJDdqNHZio{ z=x$HTZI*A_yl}TGbnQ0td?nC6G1&_k(p(BA1>eTbeUls8Y+ur|1sh3+(^yZD(l&-N z+A`R&oRmSaHKheV=KfexWuZOm=N#4cWt`7Iymh}_T{1f5)prQcvUXt^RaK3KMd`Ir z4V&$5D0}#eCvDV@J2FAB`!%uDA#Nq)v{+mmJ2~_)bXW)e_GZ^@(Nbumzkeh+IQNab zGK&WLi@6I)xKO`t@~*wo$!R>+ST>)s*!O*uL%#ID>a}tpa3*PzmnELVALHVeopte6 zPyd-7oaO$b2;0MbrS{iPer~DhzI)93a}&Yrcv*sUx!k$*QN0RBhuYnTg^i@$XQS;o4bLjMH zkT-qhv!+L;6;rsKdinae2DRWye%l9PW?#^!Wfdw}M8&`iOda_JDq!bC2+c4I`c@l? z;w!zcby{;KCt>%4XPHDQuld5Ss2RyP+>9NTa(hqgK&%0CrH?G^x*WmDDk>E)56o{l*8`S ztiNuY?AGJ0Y(_0mrGHYiBBo%|j%COETpJ)(Kw^SNAjlsbbxbi$J@nVUU_VaWF$oLB z3NPN)YxqD0iK-CJeU1NHM*kEGKhzJ3NsNDg32ARh;WGv0O}QcRn;>*8l&B#lA@{LG z!ZTBlA;cl@;d06U-F^9uXvhK;+MkpOVPe;eMW*020c8>{{Q+fB>k)$7*JtfH=G_0_ zAnPGg3uPe`@N$2>!EO#1{MnekDd!#2nv{w@EbeZY@yU23g(49KX- z8P4CSApoH(^ofj`-^c6X9C=t*7VhX*+GOCdfD&x zt|I!@!-W2;Z)J`-@Cx@TJ$ACYGad??II8U;1L)zqDLKJR@V+0x5XbVKb>}GF>@0P4_orn7Z_3Z;~u zcuA+FT%k;it631hU1*S5o0;gbLJG}9D@$R@*QlCp6z5baIw4FdcL7kj8(tdlo^Y&2 zk07g06kDs*w)wNME}Ssa5$u4zkb3=H+1i2Vcjd*`)yJ!SYs`WUa2%ieWHQ}aj`Pw} z{W=|Stl1d8wr+7xTxlTWWVn9=$KR(jt$)9@$8(~oPPA69?1zt`)BD}bo; z@j~vp;=WWR{jtw_1T;y}^6C@^K_023`jKJ4t;t z=iVw>Q;Z3W;cLX{+i*kjP4Vac#RdP<%SdMO_m+p<3>Qc|8qh@p5lkp?xcBbtJV5i+ zA=d3DOlBj!qrdoSZ2LXTkMqYwL*Z3RuEAUJaiuK@QJv7|_3RTn3N!te!?SXNVTX=Pq#)*M(e@4} zBbpk`U)}W{9`!$HTV0fEKM*IMVd?{kV}u*k>JpiLVV&ha4EH@98RKaCDJeo4e|G&^ z&Snr;1Ew_^NLT8%oWxH~r&<4+$W8}tq2DhT)zUB?deJVtXeCss?Vqz)J+~e$BK7oa zJ_-Zo&oi{vw0V24JEb>zK1+nRg_+L*%419PYgK0Tn4ewGilifUh@k+N!!RW+y5Welx+(D literal 0 HcmV?d00001 diff --git a/docs/0.10.5/html/overview.html b/docs/0.10.5/html/overview.html new file mode 100644 index 000000000..2befc2f1f --- /dev/null +++ b/docs/0.10.5/html/overview.html @@ -0,0 +1,849 @@ + + + + + + + + + Data Profiler - What’s in your data? - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + + +

View this notebook on GitHub

+
+

Data Profiler - What’s in your data?

+

This introductory jupyter notebook demonstrates the basic usages of the Data Profiler. The library is designed to easily detect sensitive data and gather statistics on your datasets with just several lines of code. The Data Profiler can handle several different data types including: CSV (or any delimited file), JSON, Parquet, AVRO, and text. Additionally, there are a plethora of options to customize your profile. This library also has the ability to update profiles from multiple batches of large +datasets, or merge multiple profiles. In particular, this example covers the followings:

+
    +
  • Basic usage of the Data Profiler

  • +
  • The data reader class

  • +
  • Profiler options

  • +
  • Updating profiles and merging profiles

  • +
+

First, let’s import the libraries needed for this example.

+
+
[ ]:
+
+
+
+import os
+import sys
+import json
+import pandas as pd
+import matplotlib.pyplot as plt
+sys.path.insert(0, '..')
+import dataprofiler as dp
+
+data_path = "../dataprofiler/tests/data"
+
+
+
+
+

Basic Usage of the Data Profiler

+

This section shows the basic example of the Data Profiler. A CSV dataset is read using the data reader, then the Data object is given to the Data Profiler to detect sensitive data and obtain the statistics.

+
+
[ ]:
+
+
+
+# use data reader to read input data
+data = dp.Data(os.path.join(data_path, "csv/aws_honeypot_marx_geo.csv"))
+print(data.data.head())
+
+# run data profiler and get the report
+profile = dp.Profiler(data)
+report  = profile.report(report_options={"output_format":"compact"})
+
+# print the report
+print(json.dumps(report, indent=4))
+
+
+
+

The report includes global_stats and data_stats for the given dataset. The former contains overall properties of the data such as number of rows/columns, null ratio, duplicate ratio, while the latter contains specific properties and statistics for each column such as detected data label, min, max, mean, variance, etc. In this example, the compact format of the report is used to shorten the full list of the results. To get more results related to detailed predictions at the entity +level from the Data Labeler component or histogram results, the format pretty should be used.

+
+
+

Data reader class

+

DataProfiler can detect multiple file types including CSV (or any delimited file), JSON, Parquet, AVRO, and text. The example below shows that it successfully detects data types from multiple categories regardless of the file extensions.

+
+
[ ]:
+
+
+
+# use data reader to read input data with different file types
+csv_files = [
+    "csv/aws_honeypot_marx_geo.csv",
+    "csv/all-strings-skip-header-author.csv", # csv files with the author/description on the first line
+    "csv/sparse-first-and-last-column-empty-first-row.txt", # csv file with the .txt extension
+]
+json_files = [
+    "json/complex_nested.json",
+    "json/honeypot_intentially_mislabeled_file.csv", # json file with the .csv extension
+]
+parquet_files = [
+    "parquet/nation.dict.parquet",
+    "parquet/nation.plain.intentionally_mislabled_file.csv", # parquet file with the .csv extension
+]
+avro_files = [
+    "avro/userdata1.avro",
+    "avro/userdata1_intentionally_mislabled_file.json", # avro file with the .json extension
+]
+text_files = [
+    "txt/discussion_reddit.txt",
+]
+
+all_files = {
+    "csv": csv_files,
+    "json": json_files,
+    "parquet": parquet_files,
+    "avro": avro_files,
+    "text": text_files
+}
+
+for file_type in all_files:
+    print(file_type)
+    for file in all_files[file_type]:
+        data = dp.Data(os.path.join(data_path, file))
+        print("{:<85} {:<15}".format(file, data.data_type))
+    print("\n")
+
+
+
+

The Data class detects the file type and uses one of the following classes: CSVData, JSONData, ParquetData, AVROData, TextData. Users can call these specific classes directly if desired. For example, below we provide a collection of data with different types, each of them is processed by the corresponding data class.

+
+
[ ]:
+
+
+
+# use individual data reader classes
+from dataprofiler.data_readers.csv_data import CSVData
+from dataprofiler.data_readers.json_data import JSONData
+from dataprofiler.data_readers.parquet_data import ParquetData
+from dataprofiler.data_readers.avro_data import AVROData
+from dataprofiler.data_readers.text_data import TextData
+
+csv_files = "csv/aws_honeypot_marx_geo.csv"
+json_files = "json/complex_nested.json"
+parquet_files = "parquet/nation.dict.parquet"
+avro_files = "avro/userdata1.avro"
+text_files = "txt/discussion_reddit.txt"
+
+all_files = {
+    "csv": [csv_files, CSVData],
+    "json": [json_files, JSONData],
+    "parquet": [parquet_files, ParquetData],
+    "avro": [avro_files, AVROData],
+    "text": [text_files, TextData],
+}
+
+for file_type in all_files:
+    file, data_reader = all_files[file_type]
+    data = data_reader(os.path.join(data_path, file))
+    print("File name {}\n".format(file))
+    if file_type == "text":
+        print(data.data[0][:1000]) # print the first 1000 characters
+    else:
+        print(data.data)
+    print('===============================================================================')
+
+
+
+

In addition to reading the input data from multiple file types, the Data Profiler allows the input data as a dataframe.

+
+
[ ]:
+
+
+
+# run data profiler and get the report
+my_dataframe = pd.DataFrame([[1, 2.0],[1, 2.2],[-1, 3]], columns=["col_int", "col_float"])
+profile = dp.Profiler(my_dataframe)
+report  = profile.report(report_options={"output_format":"compact"})
+
+# Print the report
+print(json.dumps(report, indent=4))
+
+
+
+
+
+

Structured Profiler vs. Unstructured Profiler

+

The profiler will infer what type of statistics to generate (structured or unstructured) based on the input. However, you can explicitly specify profile type as well. Here is an example of the the profiler explicitly calling the structured profile and the unstructured profile.

+
+
[ ]:
+
+
+
+# Using the structured profiler
+data = dp.Data(os.path.join(data_path, "csv/aws_honeypot_marx_geo.csv"))
+profile = dp.Profiler(data, profiler_type='structured')
+
+report = profile.report(report_options={"output_format": "pretty"})
+print(json.dumps(report, indent=4))
+
+# Using the unstructured profiler
+my_dataframe = pd.DataFrame([["Sample1"],["Sample2"],["Sample3"]], columns=["Text_Samples"])
+profile = dp.Profiler(my_dataframe, profiler_type='unstructured')
+
+report  = profile.report(report_options={"output_format":"pretty"})
+print(json.dumps(report, indent=4))
+
+
+
+
+
+

Profiler options

+

The Data Profiler can enable/disable statistics and modify features through profiler options. For example, if the users only want the statistics information, they may turn off the Data Labeler functionality. Below, let’s remove the histogram and data labeler component while running Data Profiler.

+
+
[ ]:
+
+
+
+profile_options = dp.ProfilerOptions()
+profile_options.set({"histogram_and_quantiles.is_enabled": False,
+                     "median_abs_deviation.is_enabled": False,
+                     "median.is_enabled": False,
+                     "mode.is_enabled": False,
+                     "data_labeler.is_enabled": False,})
+
+profile = dp.Profiler(my_dataframe, options=profile_options)
+report  = profile.report(report_options={"output_format":"pretty"})
+
+# Print the report
+print(json.dumps(report, indent=4))
+
+
+
+

Besides toggling on and off features, other options like the data labeler sample size or histogram bin method can be directly set and validated as shown here:

+
+
[ ]:
+
+
+
+profile_options = dp.ProfilerOptions()
+profile_options.structured_options.data_labeler.sample_size = 1
+profile_options.structured_options.int.histogram_and_quantiles.bin_count_or_method = "rice"
+# An error will raise if the options are set incorrectly.
+profile_options.validate()
+
+profile = dp.Profiler(my_dataframe, options=profile_options)
+report  = profile.report(report_options={"output_format":"pretty"})
+
+# Print the report
+print(json.dumps(report, indent=4))
+
+
+
+
+
+

Update profiles

+

One of the interesting features of the Data Profiler is the ability to update profiles from batches of data, which allows for data streaming usage. In this section, the original dataset is separated into two batches with equal size. Each batch is then updated with Data Profiler sequentially.

+

After the update, we expect the resulted profiles give the same statistics as the profiles updated from the full dataset. We will verify that through some properties in global_stats of the profiles including column_count, row_count, row_is_null_ratio, duplicate_row_count.

+
+
[ ]:
+
+
+
+# read the input data and devide it into two equal halves
+data = dp.Data(os.path.join(data_path, "csv/aws_honeypot_marx_geo.csv"))
+df = data.data
+df1 = df.iloc[:int(len(df)/2)]
+df2 = df.iloc[int(len(df)/2):]
+
+# Update the profile with the first half
+profile = dp.Profiler(df1)
+
+# Update the profile with the second half
+profile.update_profile(df2)
+
+# Update profile with the full dataset
+profile_full = dp.Profiler(df)
+
+report  = profile.report(report_options={"output_format":"compact"})
+report_full  = profile_full.report(report_options={"output_format":"compact"})
+
+# print the report
+print(json.dumps(report, indent=4))
+print(json.dumps(report_full, indent=4))
+
+
+
+

You can see that the profiles are exactly the same whether they are broken into several updates or not.

+
+
+

Merge profiles

+

In addition to the profile update, Data Profiler provides the merging functionality which allows users to combine the profiles updated from multiple locations. This enables Data Profiler to be used in a distributed computing environment. Below, we assume that the two aforementioned halves of the original dataset come from two different machines. Each of them is then updated with the Data Profiler on the same machine, then the resulted profiles are merged.

+

As with the profile update, we expect the merged profiles give the same statistics as the profiles updated from the full dataset.

+
+
[ ]:
+
+
+
+# Update the profile with the first half
+profile1 = dp.Profiler(df1)
+
+# Update the profile with the second half
+profile2 = dp.Profiler(df2)
+
+# merge profiles
+profile_merge = profile1 + profile2
+
+# check results of the merged profile
+report_merge  = profile.report(report_options={"output_format":"compact"})
+
+# print the report
+print(json.dumps(report_merge, indent=4))
+print(json.dumps(report_full, indent=4))
+
+
+
+

You can see that the profiles are exactly the same!

+
+
+

Conclusion

+

We have walked through some basic examples of Data Profiler usage, with different input data types and profiling options. We also work with update and merging functionality of the Data Profiler, which make it applicable for data streaming and distributed environment. Interested users can try with different datasets and functionalities as desired.

+
+
+ +
+ +
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/overview.ipynb b/docs/0.10.5/html/overview.ipynb new file mode 100644 index 000000000..d5e77abe4 --- /dev/null +++ b/docs/0.10.5/html/overview.ipynb @@ -0,0 +1,470 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fc2826d9", + "metadata": {}, + "source": [ + "# Data Profiler - What's in your data?" + ] + }, + { + "cell_type": "markdown", + "id": "b997522b", + "metadata": {}, + "source": [ + "This introductory jupyter notebook demonstrates the basic usages of the Data Profiler. The library is designed to easily detect sensitive data and gather statistics on your datasets with just several lines of code. The Data Profiler can handle several different data types including: CSV (or any delimited file), JSON, Parquet, AVRO, and text. Additionally, there are a plethora of options to customize your profile. This library also has the ability to update profiles from multiple batches of large datasets, or merge multiple profiles. In particular, this example covers the followings:\n", + "\n", + "- Basic usage of the Data Profiler\n", + "- The data reader class\n", + "- Profiler options\n", + "- Updating profiles and merging profiles\n", + "\n", + "First, let's import the libraries needed for this example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ef404c84", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "sys.path.insert(0, '..')\n", + "import dataprofiler as dp\n", + "\n", + "data_path = \"../dataprofiler/tests/data\"" + ] + }, + { + "cell_type": "markdown", + "id": "f51971e3", + "metadata": {}, + "source": [ + "## Basic Usage of the Data Profiler" + ] + }, + { + "cell_type": "markdown", + "id": "639e66d3", + "metadata": {}, + "source": [ + "This section shows the basic example of the Data Profiler. A CSV dataset is read using the data reader, then the Data object is given to the Data Profiler to detect sensitive data and obtain the statistics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5379c45c", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "# use data reader to read input data\n", + "data = dp.Data(os.path.join(data_path, \"csv/aws_honeypot_marx_geo.csv\"))\n", + "print(data.data.head())\n", + "\n", + "# run data profiler and get the report\n", + "profile = dp.Profiler(data)\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "\n", + "# print the report\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "57fe2827", + "metadata": {}, + "source": [ + "The report includes `global_stats` and `data_stats` for the given dataset. The former contains overall properties of the data such as number of rows/columns, null ratio, duplicate ratio, while the latter contains specific properties and statistics for each column such as detected data label, min, max, mean, variance, etc. In this example, the `compact` format of the report is used to shorten the full list of the results. To get more results related to detailed predictions at the entity level from the Data Labeler component or histogram results, the format `pretty` should be used." + ] + }, + { + "cell_type": "markdown", + "id": "74027cfd", + "metadata": {}, + "source": [ + "## Data reader class" + ] + }, + { + "cell_type": "markdown", + "id": "41364888", + "metadata": {}, + "source": [ + "DataProfiler can detect multiple file types including CSV (or any delimited file), JSON, Parquet, AVRO, and text. The example below shows that it successfully detects data types from multiple categories regardless of the file extensions." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "823829f4", + "metadata": {}, + "outputs": [], + "source": [ + "# use data reader to read input data with different file types\n", + "csv_files = [\n", + " \"csv/aws_honeypot_marx_geo.csv\",\n", + " \"csv/all-strings-skip-header-author.csv\", # csv files with the author/description on the first line\n", + " \"csv/sparse-first-and-last-column-empty-first-row.txt\", # csv file with the .txt extension\n", + "]\n", + "json_files = [\n", + " \"json/complex_nested.json\",\n", + " \"json/honeypot_intentially_mislabeled_file.csv\", # json file with the .csv extension\n", + "]\n", + "parquet_files = [\n", + " \"parquet/nation.dict.parquet\",\n", + " \"parquet/nation.plain.intentionally_mislabled_file.csv\", # parquet file with the .csv extension\n", + "]\n", + "avro_files = [\n", + " \"avro/userdata1.avro\",\n", + " \"avro/userdata1_intentionally_mislabled_file.json\", # avro file with the .json extension\n", + "]\n", + "text_files = [\n", + " \"txt/discussion_reddit.txt\",\n", + "]\n", + "\n", + "all_files = {\n", + " \"csv\": csv_files,\n", + " \"json\": json_files,\n", + " \"parquet\": parquet_files,\n", + " \"avro\": avro_files,\n", + " \"text\": text_files\n", + "}\n", + "\n", + "for file_type in all_files:\n", + " print(file_type)\n", + " for file in all_files[file_type]:\n", + " data = dp.Data(os.path.join(data_path, file))\n", + " print(\"{:<85} {:<15}\".format(file, data.data_type))\n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "3f9d7e02", + "metadata": {}, + "source": [ + "The `Data` class detects the file type and uses one of the following classes: `CSVData`, `JSONData`, `ParquetData`, `AVROData`, `TextData`. Users can call these specific classes directly if desired. For example, below we provide a collection of data with different types, each of them is processed by the corresponding data class." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "831e68a3", + "metadata": {}, + "outputs": [], + "source": [ + "# use individual data reader classes\n", + "from dataprofiler.data_readers.csv_data import CSVData\n", + "from dataprofiler.data_readers.json_data import JSONData\n", + "from dataprofiler.data_readers.parquet_data import ParquetData\n", + "from dataprofiler.data_readers.avro_data import AVROData\n", + "from dataprofiler.data_readers.text_data import TextData\n", + "\n", + "csv_files = \"csv/aws_honeypot_marx_geo.csv\"\n", + "json_files = \"json/complex_nested.json\"\n", + "parquet_files = \"parquet/nation.dict.parquet\"\n", + "avro_files = \"avro/userdata1.avro\"\n", + "text_files = \"txt/discussion_reddit.txt\"\n", + "\n", + "all_files = {\n", + " \"csv\": [csv_files, CSVData],\n", + " \"json\": [json_files, JSONData],\n", + " \"parquet\": [parquet_files, ParquetData],\n", + " \"avro\": [avro_files, AVROData],\n", + " \"text\": [text_files, TextData],\n", + "}\n", + "\n", + "for file_type in all_files:\n", + " file, data_reader = all_files[file_type]\n", + " data = data_reader(os.path.join(data_path, file))\n", + " print(\"File name {}\\n\".format(file))\n", + " if file_type == \"text\":\n", + " print(data.data[0][:1000]) # print the first 1000 characters\n", + " else:\n", + " print(data.data)\n", + " print('===============================================================================')" + ] + }, + { + "cell_type": "markdown", + "id": "572df0a8", + "metadata": {}, + "source": [ + "In addition to reading the input data from multiple file types, the Data Profiler allows the input data as a dataframe." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df87ab83", + "metadata": {}, + "outputs": [], + "source": [ + "# run data profiler and get the report\n", + "my_dataframe = pd.DataFrame([[1, 2.0],[1, 2.2],[-1, 3]], columns=[\"col_int\", \"col_float\"])\n", + "profile = dp.Profiler(my_dataframe)\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "\n", + "# Print the report\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "84a06312", + "metadata": {}, + "source": [ + "## Structured Profiler vs. Unstructured Profiler" + ] + }, + { + "cell_type": "markdown", + "id": "4c0ea925", + "metadata": {}, + "source": [ + "The profiler will infer what type of statistics to generate (structured or unstructured) based on the input. However, you can explicitly specify profile type as well. Here is an example of the the profiler explicitly calling the structured profile and the unstructured profile." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5f4565d8", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "# Using the structured profiler\n", + "data = dp.Data(os.path.join(data_path, \"csv/aws_honeypot_marx_geo.csv\"))\n", + "profile = dp.Profiler(data, profiler_type='structured')\n", + "\n", + "report = profile.report(report_options={\"output_format\": \"pretty\"})\n", + "print(json.dumps(report, indent=4))\n", + "\n", + "# Using the unstructured profiler\n", + "my_dataframe = pd.DataFrame([[\"Sample1\"],[\"Sample2\"],[\"Sample3\"]], columns=[\"Text_Samples\"])\n", + "profile = dp.Profiler(my_dataframe, profiler_type='unstructured')\n", + "\n", + "report = profile.report(report_options={\"output_format\":\"pretty\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "b16648ba", + "metadata": {}, + "source": [ + "## Profiler options" + ] + }, + { + "cell_type": "markdown", + "id": "8b0cc8ad", + "metadata": {}, + "source": [ + "The Data Profiler can enable/disable statistics and modify features through profiler options. For example, if the users only want the statistics information, they may turn off the Data Labeler functionality. Below, let's remove the histogram and data labeler component while running Data Profiler." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bbac3a2c", + "metadata": {}, + "outputs": [], + "source": [ + "profile_options = dp.ProfilerOptions()\n", + "profile_options.set({\"histogram_and_quantiles.is_enabled\": False,\n", + " \"median_abs_deviation.is_enabled\": False,\n", + " \"median.is_enabled\": False,\n", + " \"mode.is_enabled\": False,\n", + " \"data_labeler.is_enabled\": False,})\n", + "\n", + "profile = dp.Profiler(my_dataframe, options=profile_options)\n", + "report = profile.report(report_options={\"output_format\":\"pretty\"})\n", + "\n", + "# Print the report\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "590ca50b", + "metadata": {}, + "source": [ + "Besides toggling on and off features, other options like the data labeler sample size or histogram bin method can be directly set and validated as shown here:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ed21bc1", + "metadata": {}, + "outputs": [], + "source": [ + "profile_options = dp.ProfilerOptions()\n", + "profile_options.structured_options.data_labeler.sample_size = 1\n", + "profile_options.structured_options.int.histogram_and_quantiles.bin_count_or_method = \"rice\"\n", + "# An error will raise if the options are set incorrectly.\n", + "profile_options.validate()\n", + "\n", + "profile = dp.Profiler(my_dataframe, options=profile_options)\n", + "report = profile.report(report_options={\"output_format\":\"pretty\"})\n", + "\n", + "# Print the report\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "9f690616", + "metadata": {}, + "source": [ + "## Update profiles" + ] + }, + { + "cell_type": "markdown", + "id": "965f8c85", + "metadata": {}, + "source": [ + "One of the interesting features of the Data Profiler is the ability to update profiles from batches of data, which allows for data streaming usage. In this section, the original dataset is separated into two batches with equal size. Each batch is then updated with Data Profiler sequentially. \n", + "\n", + "After the update, we expect the resulted profiles give the same statistics as the profiles updated from the full dataset. We will verify that through some properties in `global_stats` of the profiles including `column_count`, `row_count`, `row_is_null_ratio`, `duplicate_row_count`. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34ac4346", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# read the input data and devide it into two equal halves\n", + "data = dp.Data(os.path.join(data_path, \"csv/aws_honeypot_marx_geo.csv\"))\n", + "df = data.data\n", + "df1 = df.iloc[:int(len(df)/2)]\n", + "df2 = df.iloc[int(len(df)/2):]\n", + "\n", + "# Update the profile with the first half\n", + "profile = dp.Profiler(df1)\n", + "\n", + "# Update the profile with the second half\n", + "profile.update_profile(df2)\n", + "\n", + "# Update profile with the full dataset\n", + "profile_full = dp.Profiler(df)\n", + "\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "report_full = profile_full.report(report_options={\"output_format\":\"compact\"})\n", + "\n", + "# print the report\n", + "print(json.dumps(report, indent=4))\n", + "print(json.dumps(report_full, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "b41ee2bf", + "metadata": {}, + "source": [ + "You can see that the profiles are exactly the same whether they are broken into several updates or not." + ] + }, + { + "cell_type": "markdown", + "id": "c547f051", + "metadata": {}, + "source": [ + "## Merge profiles" + ] + }, + { + "cell_type": "markdown", + "id": "a5292962", + "metadata": {}, + "source": [ + "In addition to the profile update, Data Profiler provides the merging functionality which allows users to combine the profiles updated from multiple locations. This enables Data Profiler to be used in a distributed computing environment. Below, we assume that the two aforementioned halves of the original dataset come from two different machines. Each of them is then updated with the Data Profiler on the same machine, then the resulted profiles are merged.\n", + "\n", + "As with the profile update, we expect the merged profiles give the same statistics as the profiles updated from the full dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a565b8d1", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Update the profile with the first half\n", + "profile1 = dp.Profiler(df1)\n", + "\n", + "# Update the profile with the second half\n", + "profile2 = dp.Profiler(df2)\n", + "\n", + "# merge profiles\n", + "profile_merge = profile1 + profile2\n", + "\n", + "# check results of the merged profile\n", + "report_merge = profile.report(report_options={\"output_format\":\"compact\"})\n", + "\n", + "# print the report\n", + "print(json.dumps(report_merge, indent=4))\n", + "print(json.dumps(report_full, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "b77fac3f", + "metadata": {}, + "source": [ + "You can see that the profiles are exactly the same!" + ] + }, + { + "cell_type": "markdown", + "id": "c644ee42", + "metadata": {}, + "source": [ + "## Conclusion\n", + "\n", + "We have walked through some basic examples of Data Profiler usage, with different input data types and profiling options. We also work with update and merging functionality of the Data Profiler, which make it applicable for data streaming and distributed environment. Interested users can try with different datasets and functionalities as desired." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/html/popmon_dp_loader_example.html b/docs/0.10.5/html/popmon_dp_loader_example.html new file mode 100644 index 000000000..0adacb12a --- /dev/null +++ b/docs/0.10.5/html/popmon_dp_loader_example.html @@ -0,0 +1,804 @@ + + + + + + + + + Dataloader with Popmon Reports - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + + +

View this notebook on GitHub

+
+

Dataloader with Popmon Reports

+

This demo is to cover the usage of popmon with the dataloader from the dataprofiler

+

This demo covers the followings:

+
- How to install popmon
+- Comparison of the dynamic dataloader from dataprofiler to the
+    standard dataloader used in pandas
+- Popmon's usage example using both dataloaders
+- Dataprofiler's examples using both dataloaders
+- Usage of the pm_stability_report function (popmon reports)
+
+
+
+

How to Install Popmon

+

To install popmon you can use the command below:

+

pip3 install popmon

+

From here, we can import the libararies needed for this demo.

+
+
[ ]:
+
+
+
+import os
+import sys
+try:
+    sys.path.insert(0, '..')
+    import dataprofiler as dp
+except ImportError:
+    import dataprofiler as dp
+import pandas as pd
+import popmon  # noqa
+
+
+
+
+
+

Comparison of Dataloaders

+

First, we have the original pandas dataloading which works for specific file types. This is good for if the data format is known ahead of time but is less useful for more dynamic cases.

+
+
[ ]:
+
+
+
+def popmon_dataloader(path, time_index):
+    # Load pm dataframe (Can only read csvs unless reader option is changed)
+    if not time_index is None:
+        pm_data = pd.read_csv(path, parse_dates=[time_index])
+    else:
+        time_index = True
+        pm_data = pd.read_csv(path)
+    return pm_data
+
+
+
+

Next, we have the dataprofiler’s dataloader. This allows for the dynamic loading of different data formats which is super useful when the data format is not know ahead of time. This is intended to be an improvement on the dataloader standardly used in pandas.

+
+
[ ]:
+
+
+
+def dp_dataloader(path):
+    # Datalaoder from dataprofiler used
+    dp_data = dp.Data(path)
+
+    # Profiler used to ensure proper label for datetime even
+    # when null values exist
+    profiler_options = dp.ProfilerOptions()
+    profiler_options.set({'*.is_enabled': False,  # Runs first disabling all options in profiler
+                          '*.datetime.is_enabled': True})
+    profile = dp.Profiler(dp_data, options=profiler_options)
+
+    # convert any time/datetime types from strings to actual datatime type
+    for ind, col in enumerate(dp_data.data.columns):
+        if profile.profile[ind].profile.get('data_type') == 'datetime':
+            dp_data.data[col] = pd.to_datetime(dp_data.data[col])
+
+    return dp_data.data
+
+
+
+
+
+

Popmon’s usage example using both dataloaders

+

Next, we’ll download a dataset from the resources component

+
+
[ ]:
+
+
+
+import gzip
+import shutil
+popmon_tutorial_data = popmon.resources.data("flight_delays.csv.gz")
+with gzip.open(popmon_tutorial_data, 'rb') as f_in:
+    with open('./flight_delays.csv', 'wb') as f_out:
+        shutil.copyfileobj(f_in, f_out)
+
+
+
+

Finally we read in the data with popmon and print the report to a file

+
+
[ ]:
+
+
+
+# Default csv from popmon example
+path = "./flight_delays.csv"
+time_index = "DATE"
+report_output_dir = "./popmon_output/flight_delays_full"
+if not os.path.exists(report_output_dir):
+    os.makedirs(report_output_dir)
+
+
+
+
+
+
[ ]:
+
+
+
+pm_data = popmon_dataloader(path, time_index)
+
+report_pm_loader = pm_data.pm_stability_report(
+    time_axis=time_index,
+    time_width="1w",
+    time_offset="2015-07-02",
+    extended_report=False,
+    pull_rules={"*_pull": [10, 7, -7, -10]},
+)
+
+# Save popmon reports
+report_pm_loader.to_file(os.path.join(report_output_dir, "popmon_loader_report.html"))
+print("Report printed at:", os.path.join(report_output_dir, "popmon_loader_report.html"))
+
+
+
+

We then do the same for the dataprofiler loader

+
+
[ ]:
+
+
+
+dp_dataframe = dp_dataloader(path)
+# Generate pm report using dp dataloader
+report_dp_loader = dp_dataframe.pm_stability_report(
+    time_axis=time_index,
+    time_width="1w",
+    time_offset="2015-07-02",
+    extended_report=False,
+    pull_rules={"*_pull": [10, 7, -7, -10]},
+)
+
+# Save popmon reports
+report_dp_loader.to_file(os.path.join(report_output_dir, "dataprofiler_loader_report.html"))
+print("Report printed at:", os.path.join(report_output_dir, "dataprofiler_loader_report.html"))
+
+
+
+
+
+

Examples of data

+

Next, We’ll use some data from the test files of the data profiler to compare the dynamic loading of the dataprofiler’s data loader to that of the standard pandas approach.

+
+
+

Dataprofiler’s examples using both dataloaders

+

To execute this properly, simply choose one of the 3 examples below and then run the report generation below.

+
+
[ ]:
+
+
+
+# Default csv from popmon example (mini version)
+path = "../dataprofiler/tests/data/csv/flight_delays.csv"
+time_index = "DATE"
+report_output_dir = "./popmon_output/flight_delays_mini"
+
+
+
+
+
[ ]:
+
+
+
+# Random csv from dataprofiler tests
+path = "../dataprofiler/tests/data/csv/aws_honeypot_marx_geo.csv"
+time_index = "datetime"
+report_output_dir = "./popmon_output/aws_honeypot_marx_geo"
+
+
+
+
+
[ ]:
+
+
+
+# Random json file from dataprofiler tests
+path = "../dataprofiler/tests/data/json/math.json"
+
+time_index = "data.9"
+report_output_dir = "./popmon_output/math"
+
+
+
+

Run the block below to create an output directory for your popmon reports.

+
+
[ ]:
+
+
+
+if not os.path.exists(report_output_dir):
+    os.makedirs(report_output_dir)
+dp_dataframe = dp_dataloader(path)
+
+
+
+
+
+

Report comparison

+

We generate reports using different sets of data from the dataprofiler and pandas below using dataprofiler’s dataloader and popmons report generator

+

The dataprofiler’s dataloader can seemlessly switch between data formats and generate reports with the exact same code in place.

+
+
[ ]:
+
+
+
+# Generate pm report using dp dataloader
+report_dp_loader = dp_dataframe.pm_stability_report(
+    time_axis=time_index,
+    time_width="1w",
+    time_offset="2015-07-02",
+    extended_report=False,
+    pull_rules={"*_pull": [10, 7, -7, -10]},
+)
+
+
+
+

If the dataloaders are valid, you can see the reports and compare them at the output directory specified in the printout below each report generation block (the two code blocks below).

+
+
[ ]:
+
+
+
+# Save dp reports
+report_dp_loader.to_file(os.path.join(report_output_dir, "dataprofiler_loader_report.html"))
+print("Report printed at:", os.path.join(report_output_dir, "dataprofiler_loader_report.html"))
+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/popmon_dp_loader_example.ipynb b/docs/0.10.5/html/popmon_dp_loader_example.ipynb new file mode 100644 index 000000000..3ddb267da --- /dev/null +++ b/docs/0.10.5/html/popmon_dp_loader_example.ipynb @@ -0,0 +1,416 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7f0cceea", + "metadata": {}, + "source": [ + "# Dataloader with Popmon Reports" + ] + }, + { + "cell_type": "markdown", + "id": "9e79d9c5", + "metadata": {}, + "source": [ + "This demo is to cover the usage of popmon with the dataloader from the dataprofiler\n", + "\n", + "This demo covers the followings:\n", + "\n", + " - How to install popmon\n", + " - Comparison of the dynamic dataloader from dataprofiler to the \n", + " standard dataloader used in pandas\n", + " - Popmon's usage example using both dataloaders\n", + " - Dataprofiler's examples using both dataloaders\n", + " - Usage of the pm_stability_report function (popmon reports)\n" + ] + }, + { + "cell_type": "markdown", + "id": "aec2198a", + "metadata": {}, + "source": [ + "## How to Install Popmon\n", + "To install popmon you can use the command below:" + ] + }, + { + "cell_type": "markdown", + "id": "4383ed2a", + "metadata": {}, + "source": [ + "`pip3 install popmon`\n" + ] + }, + { + "cell_type": "markdown", + "id": "91dedc34", + "metadata": {}, + "source": [ + "From here, we can import the libararies needed for this demo." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2adec556", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " import dataprofiler as dp\n", + "import pandas as pd\n", + "import popmon # noqa" + ] + }, + { + "cell_type": "markdown", + "id": "2ed532ec", + "metadata": {}, + "source": [ + "## Comparison of Dataloaders" + ] + }, + { + "cell_type": "markdown", + "id": "cccbf4cd", + "metadata": {}, + "source": [ + "First, we have the original pandas dataloading which works for specific file types. \n", + "This is good for if the data format is known ahead of time but is less useful for more dynamic cases." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "96e9ff89", + "metadata": {}, + "outputs": [], + "source": [ + "def popmon_dataloader(path, time_index):\n", + " # Load pm dataframe (Can only read csvs unless reader option is changed)\n", + " if not time_index is None:\n", + " pm_data = pd.read_csv(path, parse_dates=[time_index])\n", + " else:\n", + " time_index = True\n", + " pm_data = pd.read_csv(path)\n", + " return pm_data" + ] + }, + { + "cell_type": "markdown", + "id": "16dfbe10", + "metadata": {}, + "source": [ + "Next, we have the dataprofiler's dataloader. This allows for the dynamic loading of different data formats which is super useful when the data format is not know ahead of time.\n", + "This is intended to be an improvement on the dataloader standardly used in pandas." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "07481259", + "metadata": {}, + "outputs": [], + "source": [ + "def dp_dataloader(path):\n", + " # Datalaoder from dataprofiler used\n", + " dp_data = dp.Data(path)\n", + " \n", + " # Profiler used to ensure proper label for datetime even \n", + " # when null values exist\n", + " profiler_options = dp.ProfilerOptions()\n", + " profiler_options.set({'*.is_enabled': False, # Runs first disabling all options in profiler\n", + " '*.datetime.is_enabled': True})\n", + " profile = dp.Profiler(dp_data, options=profiler_options)\n", + "\n", + " # convert any time/datetime types from strings to actual datatime type\n", + " for ind, col in enumerate(dp_data.data.columns):\n", + " if profile.profile[ind].profile.get('data_type') == 'datetime':\n", + " dp_data.data[col] = pd.to_datetime(dp_data.data[col])\n", + "\n", + " return dp_data.data" + ] + }, + { + "cell_type": "markdown", + "id": "69a8ea9b", + "metadata": {}, + "source": [ + "## Popmon's usage example using both dataloaders" + ] + }, + { + "cell_type": "markdown", + "id": "ff914ca7", + "metadata": {}, + "source": [ + "Next, we'll download a dataset from the resources component" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bff33da8", + "metadata": {}, + "outputs": [], + "source": [ + "import gzip\n", + "import shutil\n", + "popmon_tutorial_data = popmon.resources.data(\"flight_delays.csv.gz\")\n", + "with gzip.open(popmon_tutorial_data, 'rb') as f_in:\n", + " with open('./flight_delays.csv', 'wb') as f_out:\n", + " shutil.copyfileobj(f_in, f_out)" + ] + }, + { + "cell_type": "markdown", + "id": "19222c4a", + "metadata": {}, + "source": [ + "Finally we read in the data with popmon and print the report to a file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0090a2f3", + "metadata": {}, + "outputs": [], + "source": [ + "# Default csv from popmon example\n", + "path = \"./flight_delays.csv\"\n", + "time_index = \"DATE\"\n", + "report_output_dir = \"./popmon_output/flight_delays_full\"\n", + "if not os.path.exists(report_output_dir):\n", + " os.makedirs(report_output_dir)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0abcd9b", + "metadata": {}, + "outputs": [], + "source": [ + "pm_data = popmon_dataloader(path, time_index)\n", + "\n", + "report_pm_loader = pm_data.pm_stability_report(\n", + " time_axis=time_index,\n", + " time_width=\"1w\",\n", + " time_offset=\"2015-07-02\",\n", + " extended_report=False,\n", + " pull_rules={\"*_pull\": [10, 7, -7, -10]},\n", + ")\n", + "\n", + "# Save popmon reports\n", + "report_pm_loader.to_file(os.path.join(report_output_dir, \"popmon_loader_report.html\"))\n", + "print(\"Report printed at:\", os.path.join(report_output_dir, \"popmon_loader_report.html\"))" + ] + }, + { + "cell_type": "markdown", + "id": "2303b5cf", + "metadata": {}, + "source": [ + "We then do the same for the dataprofiler loader" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f2854383", + "metadata": {}, + "outputs": [], + "source": [ + "dp_dataframe = dp_dataloader(path)\n", + "# Generate pm report using dp dataloader\n", + "report_dp_loader = dp_dataframe.pm_stability_report(\n", + " time_axis=time_index,\n", + " time_width=\"1w\",\n", + " time_offset=\"2015-07-02\",\n", + " extended_report=False,\n", + " pull_rules={\"*_pull\": [10, 7, -7, -10]},\n", + ")\n", + "\n", + "# Save popmon reports\n", + "report_dp_loader.to_file(os.path.join(report_output_dir, \"dataprofiler_loader_report.html\"))\n", + "print(\"Report printed at:\", os.path.join(report_output_dir, \"dataprofiler_loader_report.html\"))" + ] + }, + { + "cell_type": "markdown", + "id": "8cc4e5f3", + "metadata": {}, + "source": [ + "## Examples of data\n", + "Next, We'll use some data from the test files of the data profiler to compare the dynamic loading of the dataprofiler's data loader to that of the standard pandas approach. \n" + ] + }, + { + "cell_type": "markdown", + "id": "352eaeea", + "metadata": {}, + "source": [ + "## Dataprofiler's examples using both dataloaders" + ] + }, + { + "cell_type": "markdown", + "id": "e99af913", + "metadata": {}, + "source": [ + "To execute this properly, simply choose one of the 3 examples below and then run the report generation below." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "80eb601d", + "metadata": {}, + "outputs": [], + "source": [ + "# Default csv from popmon example (mini version)\n", + "path = \"../dataprofiler/tests/data/csv/flight_delays.csv\"\n", + "time_index = \"DATE\"\n", + "report_output_dir = \"./popmon_output/flight_delays_mini\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c127288", + "metadata": {}, + "outputs": [], + "source": [ + "# Random csv from dataprofiler tests\n", + "path = \"../dataprofiler/tests/data/csv/aws_honeypot_marx_geo.csv\"\n", + "time_index = \"datetime\"\n", + "report_output_dir = \"./popmon_output/aws_honeypot_marx_geo\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6cd5c385", + "metadata": {}, + "outputs": [], + "source": [ + "# Random json file from dataprofiler tests\n", + "path = \"../dataprofiler/tests/data/json/math.json\"\n", + "\n", + "time_index = \"data.9\"\n", + "report_output_dir = \"./popmon_output/math\"" + ] + }, + { + "cell_type": "markdown", + "id": "ec860cb7", + "metadata": {}, + "source": [ + "Run the block below to create an output directory for your popmon reports." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cf21835c", + "metadata": {}, + "outputs": [], + "source": [ + "if not os.path.exists(report_output_dir):\n", + " os.makedirs(report_output_dir)\n", + "dp_dataframe = dp_dataloader(path)" + ] + }, + { + "cell_type": "markdown", + "id": "479975a5", + "metadata": {}, + "source": [ + "## Report comparison" + ] + }, + { + "cell_type": "markdown", + "id": "02a355e7", + "metadata": {}, + "source": [ + "We generate reports using different sets of data from the dataprofiler and pandas below using dataprofiler's dataloader and popmons report generator\n" + ] + }, + { + "cell_type": "markdown", + "id": "6ce69145", + "metadata": {}, + "source": [ + "The dataprofiler's dataloader can seemlessly switch between data formats and generate reports with the exact same code in place." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a0dcb405", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Generate pm report using dp dataloader\n", + "report_dp_loader = dp_dataframe.pm_stability_report(\n", + " time_axis=time_index,\n", + " time_width=\"1w\",\n", + " time_offset=\"2015-07-02\",\n", + " extended_report=False,\n", + " pull_rules={\"*_pull\": [10, 7, -7, -10]},\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "9eb0035c", + "metadata": {}, + "source": [ + "If the dataloaders are valid, you can see the reports and compare them at the output directory specified in the printout below each report generation block (the two code blocks below)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "efe7d8d6", + "metadata": {}, + "outputs": [], + "source": [ + "# Save dp reports\n", + "report_dp_loader.to_file(os.path.join(report_output_dir, \"dataprofiler_loader_report.html\"))\n", + "print(\"Report printed at:\", os.path.join(report_output_dir, \"dataprofiler_loader_report.html\"))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/html/profiler.html b/docs/0.10.5/html/profiler.html new file mode 100644 index 000000000..03720ad47 --- /dev/null +++ b/docs/0.10.5/html/profiler.html @@ -0,0 +1,1410 @@ + + + + + + + + + Profiler - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Profiler

+
+

Profile Your Data

+

Profiling your data is easy. Just use the data reader, send the data to the +profiler, and print out the report.

+
import json
+from dataprofiler import Data, Profiler
+
+data = Data("your_file.csv") # Auto-Detect & Load: CSV, AVRO, Parquet, JSON, Text
+
+profile = Profiler(data) # Calculate Statistics, Entity Recognition, etc
+
+readable_report = profile.report(report_options={"output_format": "pretty"})
+print(json.dumps(readable_report, indent=4))
+
+
+

If the data is structured, the profile will return global statistics as well as +column by column statistics. The vast amount of statistics are listed on the +intro page.

+
+

Load a File

+

The profiler should automatically identify the file type and load the data into a Data Class.

+

Along with other attributtes the Data class enables structured data to be accessed via a valid Pandas DataFrame.

+
# Load a csv file, return a CSVData object
+csv_data = Data('your_file.csv')
+
+# Print the first 10 rows of the csv file
+print(csv_data.data.head(10))
+
+# Load a parquet file, return a ParquetData object
+parquet_data = Data('your_file.parquet')
+
+# Sort the data by the name column
+parquet_data.data.sort_values(by='name', inplace=True)
+
+# Print the sorted first 10 rows of the parquet data
+print(parquet_data.data.head(10))
+
+
+

If the file type is not automatically identified (rare), you can specify them +specifically, see section Data Readers.

+
+
+

Profile a File

+

Example uses a CSV file for example, but CSV, JSON, Avro or Parquet should also work.

+
import json
+from dataprofiler import Data, Profiler
+
+# Load file (CSV should be automatically identified)
+data = Data("your_file.csv")
+
+# Profile the dataset
+profile = Profiler(data)
+
+# Generate a report and use json to prettify.
+report  = profile.report(report_options={"output_format": "pretty"})
+
+# Print the report
+print(json.dumps(report, indent=4))
+
+
+
+
+

Updating Profiles

+

Currently, the data profiler is equipped to update its profile in batches.

+
import json
+from dataprofiler import Data, Profiler
+
+# Load and profile a CSV file
+data = Data("your_file.csv")
+profile = Profiler(data)
+
+# Update the profile with new data:
+new_data = Data("new_data.csv")
+profile.update_profile(new_data)
+
+# Print the report using json to prettify.
+report  = profile.report(report_options={"output_format": "pretty"})
+print(json.dumps(report, indent=4))
+
+
+
+
+

Merging Profiles

+

If you have two files with the same schema (but different data), it is possible to merge the two profiles together via an addition operator.

+

This also enables profiles to be determined in a distributed manner.

+
import json
+from dataprofiler import Data, Profiler
+
+# Load a CSV file with a schema
+data1 = Data("file_a.csv")
+profile1 = Profiler(data)
+
+# Load another CSV file with the same schema
+data2 = Data("file_b.csv")
+profile2 = Profiler(data)
+
+profile3 = profile1 + profile2
+
+# Print the report using json to prettify.
+report  = profile3.report(report_options={"output_format": "pretty"})
+print(json.dumps(report, indent=4))
+
+
+
+
+

Profile Differences

+

Profile differences take two profiles and find the differences +between them. Create the difference report like this:

+
from dataprofiler import Data, Profiler
+
+# Load a CSV file
+data1 = Data("file_a.csv")
+profile1 = Profiler(data)
+
+# Load another CSV file
+data2 = Data("file_b.csv")
+profile2 = Profiler(data)
+
+diff_report = profile1.diff(profile2)
+print(diff_report)
+
+
+

The .diff() operation is available between two profiles, although there are different +outputs depending on the type of profile being differenced. For example, for numerical +column profiles (e.g. integers and floats), two valuable calculations that +.diff() returns are t-test, chi2-test, and psi (Popoulation Stability Index) +for understanding distributional changes.

+

The difference report contains a dictionary that mirrors the profile report. +Each data type has its own difference:

+
    +
  • Int/Float - One profile subtracts the value from the other.

  • +
  • String - The strings will be shown in a list:

    +
      +
    • [profile1 str, profile2 str]

    • +
    +
  • +
  • List - A list of 3 will be returned showing the unique values of +each profile and the shared values:

    +
      +
    • [profile 1 unique values, shared values, profile 2 unique values]

    • +
    +
  • +
  • Dict - Some dictionaries with varied keys will also return a list +of three in the format:

    +
      +
    • [profile 1 unique key-values, shared key differences, profile 2 unique key-values]

    • +
    +
  • +
+

Otherwise, when no differences occur:

+
    +
  • Any Type No Differences - A string will report: “unchanged”.

  • +
+

Below is the structured difference report:

+
{
+    'global_stats': {
+        'file_type': [str, str],
+        'encoding': [str, str],
+        'samples_used': int,
+        'column_count': int,
+        'row_count': int,
+        'row_has_null_ratio': float,
+        'row_is_null_ratio': float,
+        'unique_row_ratio': float,
+        'duplicate_row_count': int,
+        'correlation_matrix': list[list[float]],
+        'chi2_matrix': list[list[float]],
+        'profile_schema': list[dict[str, int]]
+    },
+    'data_stats': [{
+        'column_name': str,
+        'data_type': [str, str],
+        'data_label': [list[str], list[str], list[str]],
+        'categorical': [str, str],
+        'order': [str, str],
+        'statistics': {
+            'min': float,
+            'max': float,
+            'sum': float,
+            'mean': float,
+            'median': float,
+            'mode': [list[float], list[float], list[float]],
+            'median_absolute_deviation': float,
+            'variance': float,
+            'stddev': float,
+            't-test': {
+                't-statistic': float,
+                'conservative': {'df': int,
+                                 'p-value': float},
+                'welch': {'df': float,
+                          'p-value': float}},
+            'psi': float,
+            "chi2-test": {
+                "chi2-statistic": float,
+                "df": int,
+                "p-value": float
+            },
+            'unique_count': int,
+            'unique_ratio': float,
+            'categories': [list[str], list[str], list[str]],
+            'gini_impurity': float,
+            'unalikeability': float,
+            'categorical_count': [dict[str, int], dict[str, int], dict[str, int]],
+            'avg_predictions': [dict[str, float]],
+            'label_representation': [dict[str, float]],
+            'sample_size': int,
+            'null_count': int,
+            'null_types': [list[str], list[str], list[str]],
+            'null_types_index': [dict[str, int], dict[str, int], dict[str, int]],
+            'data_type_representation': [dict[str, float]]
+        },
+        "null_replication_metrics": {
+            "class_prior": list[int],
+            "class_sum": list[list[int]],
+            "class_mean": list[list[int]]
+        }
+    }
+
+
+

Below is the unstructured difference report:

+
{
+    'global_stats': {
+        'file_type': [str, str],
+        'encoding': [str, str],
+        'samples_used': int,
+        'empty_line_count': int,
+        'memory_size': float
+    },
+    'data_stats': {
+        'data_label': {
+            'entity_counts': {
+                'word_level': dict[str, int],
+                'true_char_level': dict[str, int],
+                'postprocess_char_level': dict[str, int]
+            },
+            'entity_percentages': {
+                'word_level': dict[str, float],
+                'true_char_level': dict[str, float],
+                'postprocess_char_level': dict[str, float]
+            }
+        },
+        'statistics': {
+            'vocab': [list[str], list[str], list[str]],
+            'vocab_count': [dict[str, int], dict[str, int], dict[str, int]],
+            'words': [list[str], list[str], list[str]],
+            'word_count': [dict[str, int], dict[str, int], dict[str, int]]
+        }
+    }
+}
+
+
+
+
+

Saving and Loading a Profile

+

The profiles can easily be saved and loaded as shown below:

+

NOTE: Json saving and loading only supports Structured Profiles currently.

+

There are two save/load methods:

+
    +
  • Pickle save/load

    +
      +
    • Save a profile as a .pkl file.

    • +
    • Load a .pkl file as a profile object.

    • +
    +
  • +
+
import json
+from dataprofiler import Data, Profiler
+
+# Load a CSV file, with "," as the delimiter
+data = Data("your_file.csv")
+
+# Read data into profile
+profile = Profiler(data)
+
+# save structured profile to pkl file
+profile.save(filepath="my_profile.pkl")
+
+# load pkl file to structured profile
+loaded_pkl_profile = dp.Profiler.load(filepath="my_profile.pkl")
+
+print(json.dumps(loaded_pkl_profile.report(report_options={"output_format": "compact"}),
+                                       indent=4))
+
+
+
    +
  • Json save/load

    +
      +
    • Save a profile as a human-readable .json file.

    • +
    • Load a .json file as a profile object.

    • +
    +
  • +
+
import json
+from dataprofiler import Data, Profiler
+
+# Load a CSV file, with "," as the delimiter
+data = Data("your_file.csv")
+
+# Read data into profile
+profile = Profiler(data)
+
+# save structured profile to json file
+profile.save(filepath="my_profile.json", save_method="json")
+
+# load json file to structured profile
+loaded_json_profile = dp.Profiler.load(filepath="my_profile.json", load_method="json")
+
+print(json.dumps(loaded_json_profile.report(report_options={"output_format": "compact"}),
+                                       indent=4))
+
+
+
+
+

Structured vs Unstructured Profiles

+

When using the profiler, the data profiler will automatically infer whether to +create the structured profile or the unstructured profile. However, you can be +explicit as shown below:

+
import json
+from dataprofiler import Data, Profiler
+
+# Creating a structured profile
+data1 = Data("normal_csv_file.csv")
+structured_profile = Profiler(data1, profiler_type="structured")
+
+structured_report = structured_profile.report(report_options={"output_format": "pretty"})
+print(json.dumps(structured_report, indent=4))
+
+# Creating an unstructured profile
+data2 = Data("normal_text_file.txt")
+unstructured_profile = Profiler(data2, profiler_type="unstructured")
+
+unstructured_report = unstructured_profile.report(report_options={"output_format": "pretty"})
+print(json.dumps(unstructured_report, indent=4))
+
+
+
+
+

Setting the Sample Size

+

There are two ways to set sample size in a profile: samples_per_update and +min_true_samples. Samples_per_update takes an integer as the exact amount that +will be sampled. Min_true_samples will set the minimum amount of samples that +are not null. For example:

+
from dataprofiler import Profiler
+
+sample_array = [1.0, NULL, 2.0]
+profile = dp.Profiler(sample_array, samples_per_update=2)
+
+
+

The first two samples (1.0 and NULL) are used for the statistical analysis.

+

In contrast, if we also set min_true_samples to 2 then the Data Reader will +continue to read until the minimum true samples were found for the given column. +For example:

+
from dataprofiler import Profiler
+
+sample_array = [1.0, NULL, 2.0]
+profile = dp.Profiler(sample_array, samples_per_update=2, min_true_samples=2)
+
+
+

This will use all samples in the statistical analysis until the number of “true” +(non-NULL) values are reached. Both min_true_samples and +samples_per_update conditions must be met. In this case, the profile will grab +the first two samples (1.0 and NULL) to satisfy the samples_per_update, and then +it will grab the first two VALID samples (1.0 and 2.0) to satisfy the +min_true_samples.

+
+
+

Profile a Pandas DataFrame

+
import pandas as pd
+import dataprofiler as dp
+import json
+
+my_dataframe = pd.DataFrame([[1, 2.0],[1, 2.2],[-1, 3]])
+profile = dp.Profiler(my_dataframe)
+
+# print the report using json to prettify.
+report = profile.report(report_options={"output_format": "pretty"})
+print(json.dumps(report, indent=4))
+
+# read a specified column, in this case it is labeled 0:
+print(json.dumps(report["data stats"][0], indent=4))
+
+
+
+
+

Specifying a Filetype or Delimiter

+

Example of specifying a CSV data type, with a , delimiter. +In addition, it utilizes only the first 10,000 rows.

+
import json
+from dataprofiler import Data, Profiler
+from dataprofiler.data_readers.csv_data import CSVData
+
+# Load a CSV file, with "," as the delimiter
+data = CSVData("your_file.csv", options={"delimiter": ","})
+
+# Split the data, such that only the first 10,000 rows are used
+data = data.data[0:10000]
+
+# Read in profile and print results
+profile = Profiler(data)
+print(json.dumps(profile.report(report_options={"output_format": "pretty"}), indent=4))
+
+
+
+
+

Setting Profiler Seed

+

Example of specifying a seed for reproducibility.

+
import dataprofiler as dp
+
+# Set seed to non-negative integer value or None
+dp.set_seed(0)
+
+
+
+
+
+

Profile Statistic Descriptions

+
+

Structured Profile

+

global_stats:

+
    +
  • samples_used - number of input data samples used to generate this profile

  • +
  • column_count - the number of columns contained in the input dataset

  • +
  • row_count - the number of rows contained in the input dataset

  • +
  • row_has_null_ratio - the proportion of rows that contain at least one null value to the total number of rows

  • +
  • row_is_null_ratio - the proportion of rows that are fully comprised of null values (null rows) to the total number of rows

  • +
  • unique_row_ratio - the proportion of distinct rows in the input dataset to the total number of rows

  • +
  • duplicate_row_count - the number of rows that occur more than once in the input dataset

  • +
  • file_type - the format of the file containing the input dataset (ex: .csv)

  • +
  • encoding - the encoding of the file containing the input dataset (ex: UTF-8)

  • +
  • correlation_matrix - matrix of shape column_count x column_count containing the correlation coefficients between each column in the dataset

  • +
  • chi2_matrix - matrix of shape column_count x column_count containing the chi-square statistics between each column in the dataset

  • +
  • +
    profile_schema - a description of the format of the input dataset labeling each column and its index in the dataset
      +
    • string - the label of the column in question and its index in the profile schema

    • +
    +
    +
    +
  • +
  • times - the duration of time it took to generate the global statistics for this dataset in milliseconds

  • +
+

data_stats:

+
    +
  • column_name - the label/title of this column in the input dataset

  • +
  • data_type - the primitive python data type that is contained within this column

  • +
  • data_label - the label/entity of the data in this column as determined by the Labeler component

  • +
  • categorical - ‘true’ if this column contains categorical data

  • +
  • order - the way in which the data in this column is ordered, if any, otherwise “random”

  • +
  • samples - a small subset of data entries from this column

  • +
  • +
    statistics - statistical information on the column
      +
    • sample_size - number of input data samples used to generate this profile

    • +
    • null_count - the number of null entries in the sample

    • +
    • null_types - a list of the different null types present within this sample

    • +
    • null_types_index - a dict containing each null type and a respective list of the indicies that it is present within this sample

    • +
    • data_type_representation - the percentage of samples used identifying as each data_type

    • +
    • min - minimum value in the sample

    • +
    • max - maximum value in the sample

    • +
    • mode - mode of the entries in the sample

    • +
    • median - median of the entries in the sample

    • +
    • median_absolute_deviation - the median absolute deviation of the entries in the sample

    • +
    • sum - the total of all sampled values from the column

    • +
    • mean - the average of all entries in the sample

    • +
    • variance - the variance of all entries in the sample

    • +
    • stddev - the standard deviation of all entries in the sample

    • +
    • skewness - the statistical skewness of all entries in the sample

    • +
    • kurtosis - the statistical kurtosis of all entries in the sample

    • +
    • num_zeros - the number of entries in this sample that have the value 0

    • +
    • num_negatives - the number of entries in this sample that have a value less than 0

    • +
    • +
      histogram - contains histogram relevant information
        +
      • bin_counts - the number of entries within each bin

      • +
      • bin_edges - the thresholds of each bin

      • +
      +
      +
      +
    • +
    • quantiles - the value at each percentile in the order they are listed based on the entries in the sample

    • +
    • vocab - a list of the characters used within the entries in this sample

    • +
    • avg_predictions - average of the data label prediction confidences across all data points sampled

    • +
    • categories - a list of each distinct category within the sample if categorial = ‘true’

    • +
    • unique_count - the number of distinct entries in the sample

    • +
    • unique_ratio - the proportion of the number of distinct entries in the sample to the total number of entries in the sample

    • +
    • categorical_count - number of entries sampled for each category if categorical = ‘true’

    • +
    • gini_impurity - measure of how often a randomly chosen element from the set would be incorrectly labeled if it was randomly labeled according to the distribution of labels in the subset

    • +
    • unalikeability - a value denoting how frequently entries differ from one another within the sample

    • +
    • precision - a dict of statistics with respect to the number of digits in a number for each sample

    • +
    • times - the duration of time it took to generate this sample’s statistics in milliseconds

    • +
    • format - list of possible datetime formats

    • +
    +
    +
    +
  • +
  • +
    null_replication_metrics - statistics of data partitioned based on whether column value is null (index 1 of lists referenced by dict keys) or not (index 0)
      +
    • class_prior - a list containing probability of a column value being null and not null

    • +
    • class_sum - a list containing sum of all other rows based on whether column value is null or not

    • +
    • class_mean - a list containing mean of all other rows based on whether column value is null or not

    • +
    +
    +
    +
  • +
+
+
+

Unstructured Profile

+

global_stats:

+
    +
  • samples_used - number of input data samples used to generate this profile

  • +
  • empty_line_count - the number of empty lines in the input data

  • +
  • file_type - the file type of the input data (ex: .txt)

  • +
  • encoding - file encoding of the input data file (ex: UTF-8)

  • +
  • memory_size - size of the input data in MB

  • +
  • times - duration of time it took to generate this profile in milliseconds

  • +
+

data_stats:

+
    +
  • +
    data_label - labels and statistics on the labels of the input data
      +
    • +
      entity_counts - the number of times a specific label or entity appears inside the input data
        +
      • word_level - the number of words counted within each label or entity

      • +
      • true_char_level - the number of characters counted within each label or entity as determined by the model

      • +
      • postprocess_char_level - the number of characters counted within each label or entity as determined by the postprocessor

      • +
      +
      +
      +
    • +
    • +
      entity_percentages - the percentages of each label or entity within the input data
        +
      • word_level - the percentage of words in the input data that are contained within each label or entity

      • +
      • true_char_level - the percentage of characters in the input data that are contained within each label or entity as determined by the model

      • +
      • postprocess_char_level - the percentage of characters in the input data that are contained within each label or entity as determined by the postprocessor

      • +
      +
      +
      +
    • +
    • times - the duration of time it took for the data labeler to predict on the data

    • +
    +
    +
    +
  • +
  • +
    statistics - statistics of the input data
      +
    • vocab - a list of each character in the input data

    • +
    • vocab_count - the number of occurrences of each distinct character in the input data

    • +
    • words - a list of each word in the input data

    • +
    • word_count - the number of occurrences of each distinct word in the input data

    • +
    • times - the duration of time it took to generate the vocab and words statistics in milliseconds

    • +
    +
    +
    +
  • +
+
+
+

Graph Profile

+
    +
  • num_nodes - number of nodes in the graph

  • +
  • num_edges - number of edges in the graph

  • +
  • categorical_attributes - list of categorical edge attributes

  • +
  • continuous_attributes - list of continuous edge attributes

  • +
  • avg_node_degree - average degree of nodes in the graph

  • +
  • global_max_component_size: size of the global max component

  • +
+

continuous_distribution:

+
    +
  • +
    <attribute_N>: name of N-th edge attribute in list of attributes
      +
    • name - name of distribution for attribute

    • +
    • scale - negative log likelihood used to scale and compare distributions

    • +
    • +
      properties - list of statistical properties describing the distribution
        +
      • [shape (optional), loc, scale, mean, variance, skew, kurtosis]

      • +
      +
      +
      +
    • +
    +
    +
    +
  • +
+

categorical_distribution:

+
    +
  • +
    <attribute_N>: name of N-th edge attribute in list of attributes
      +
    • bin_counts: counts in each bin of the distribution histogram

    • +
    • bin_edges: edges of each bin of the distribution histogram

    • +
    +
    +
    +
  • +
  • times - duration of time it took to generate this profile in milliseconds

  • +
+
+
+
+

Profile Options

+

The data profiler accepts several options to toggle on and off +features. The 8 columns (int options, float options, datetime options, +text options, order options, category options, data labeler options) can be +enabled or disabled. By default, all options are toggled on. Below is an example +of how to alter these options. Options shared by structured and unstructured options +must be specified as structured or unstructured when setting (ie. datalabeler options).

+
import json
+from dataprofiler import Data, Profiler, ProfilerOptions
+
+# Load and profile a CSV file
+data = Data("your_file.csv")
+profile_options = ProfilerOptions()
+
+#All of these are different examples of adjusting the profile options
+
+# Options can be toggled directly like this:
+profile_options.structured_options.text.is_enabled = False
+profile_options.structured_options.text.vocab.is_enabled = True
+profile_options.structured_options.int.variance.is_enabled = True
+profile_options.structured_options.data_labeler.data_labeler_dirpath = \
+    "Wheres/My/Datalabeler"
+profile_options.structured_options.data_labeler.is_enabled = False
+
+# A dictionary can be sent in to set the properties for all the options
+profile_options.set({"structured_options.data_labeler.is_enabled": False, "min.is_enabled": False})
+
+# Specific columns can be set/disabled/enabled in the same way
+profile_options.structured_options.text.set({"max.is_enabled":True,
+                                         "variance.is_enabled": True})
+
+# numeric stats can be turned off/on entirely
+profile_options.set({"is_numeric_stats_enabled": False})
+profile_options.set({"int.is_numeric_stats_enabled": False})
+
+profile = Profiler(data, options=profile_options)
+
+# Print the report using json to prettify.
+report  = profile.report(report_options={"output_format": "pretty"})
+print(json.dumps(report, indent=4))
+
+
+

Below is an breakdown of all the options.

+
    +
  • ProfilerOptions - The top-level options class that contains options for the Profiler class

    +
      +
    • presets - A pre-configured mapping of a string name to group of options:

      +
        +
      • default is None

      • +
      • “complete”

      • +
      +
      options = ProfilerOptions(presets="complete")
      +
      +
      +
        +
      • “data_types”

      • +
      +
      options = ProfilerOptions(presets="data_types")
      +
      +
      +
        +
      • “numeric_stats_disabled”

      • +
      +
      options = ProfilerOptions(presets="numeric_stats_disabled")
      +
      +
      +
        +
      • “lower_memory_sketching”

      • +
      +
      options = ProfilerOptions(presets="lower_memory_sketching")
      +
      +
      +
    • +
    • structured_options - Options responsible for all structured data

      +
        +
      • multiprocess - Option to enable multiprocessing. If on, multiprocessing is toggled on if the dataset contains more than 750,000 rows or more than 20 columns. +Automatically selects the optimal number of pooling processes to utilize based on system constraints when toggled on.

        +
          +
        • is_enabled - (Boolean) Enables or disables multiprocessing

        • +
        +
      • +
      • sampling_ratio - A percentage, as a decimal, ranging from greater than 0 to less than or equal to 1 indicating how much input data to sample. Default value set to 0.2.

      • +
      • int - Options for the integer columns

        +
          +
        • is_enabled - (Boolean) Enables or disables the integer operations

        • +
        • min - Finds minimum value in a column

        • +
        • is_enabled - (Boolean) Enables or disables min

        • +
        • max - Finds maximum value in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables max

          • +
          +
        • +
        • mode - Finds mode(s) in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables mode

          • +
          • top_k_modes - (Int) Sets the number of modes to return if multiple exist. Default returns max 5 modes.

          • +
          +
        • +
        • median - Finds median value in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables median

          • +
          +
        • +
        • sum - Finds sum of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables sum

          • +
          +
        • +
        • variance - Finds variance of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables variance

          • +
          +
        • +
        • skewness - Finds skewness of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables skewness

          • +
          +
        • +
        • kurtosis - Finds kurtosis of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables kurtosis

          • +
          +
        • +
        • median_abs_deviation - Finds median absolute deviation of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables median absolute deviation

          • +
          +
        • +
        • num_zeros - Finds the count of zeros in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables num_zeros

          • +
          +
        • +
        • num_negatives - Finds the count of negative numbers in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables num_negatives

          • +
          +
        • +
        • bias_correction - Applies bias correction to variance, skewness, and kurtosis calculations

          +
            +
          • is_enabled - (Boolean) Enables or disables bias correction

          • +
          +
        • +
        • histogram_and_quantiles - Generates a histogram and quantiles +from the column values

          +
            +
          • bin_count_or_method - (String/List[String]) Designates preferred method for calculating histogram bins or the number of bins to use. +If left unspecified (None) the optimal method will be chosen by attempting all methods. +If multiple specified (list) the optimal method will be chosen by attempting the provided ones. +methods: ‘auto’, ‘fd’, ‘doane’, ‘scott’, ‘rice’, ‘sturges’, ‘sqrt’ +Note: ‘auto’ is used to choose optimally between ‘fd’ and ‘sturges’

          • +
          • num_quantiles - (Int) Number of quantiles to bin the data. +Default value is set to 1,000 quantiles.

          • +
          • is_enabled - (Boolean) Enables or disables histogram and quantiles

          • +
          +
        • +
        +
      • +
      • float - Options for the float columns

        +
          +
        • is_enabled - (Boolean) Enables or disables the float operations

        • +
        • precision - Finds the precision (significant figures) within the column

          +
            +
          • is_enabled - (Boolean) Enables or disables precision

          • +
          +
        • +
        • sample_ratio - (Float) The ratio of 0 to 1 how much data (identified as floats) to utilize as samples in determining precision

        • +
        • min - Finds minimum value in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables min

          • +
          +
        • +
        • max - Finds maximum value in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables max

          • +
          +
        • +
        • mode - Finds mode(s) in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables mode

          • +
          • top_k_modes - (Int) Sets the number of modes to return if multiple exist. Default returns max 5 modes.

          • +
          +
        • +
        • median - Finds median value in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables median

          • +
          +
        • +
        • sum - Finds sum of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables sum

          • +
          +
        • +
        • variance - Finds variance of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables variance

          • +
          +
        • +
        • skewness - Finds skewness of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables skewness

          • +
          +
        • +
        • kurtosis - Finds kurtosis of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables kurtosis

          • +
          +
        • +
        • median_abs_deviation - Finds median absolute deviation of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables median absolute deviation

          • +
          +
        • +
        • is_numeric_stats_enabled - (Boolean) enable or disable all numeric stats

        • +
        • num_zeros - Finds the count of zeros in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables num_zeros

          • +
          +
        • +
        • num_negatives - Finds the count of negative numbers in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables num_negatives

          • +
          +
        • +
        • bias_correction - Applies bias correction to variance, skewness, and kurtosis calculations

          +
            +
          • is_enabled - (Boolean) Enables or disables bias correction

          • +
          +
        • +
        • histogram_and_quantiles - Generates a histogram and quantiles +from the column values

          +
            +
          • bin_count_or_method - (String/List[String]) Designates preferred method for calculating histogram bins or the number of bins to use. +If left unspecified (None) the optimal method will be chosen by attempting all methods. +If multiple specified (list) the optimal method will be chosen by attempting the provided ones. +methods: ‘auto’, ‘fd’, ‘doane’, ‘scott’, ‘rice’, ‘sturges’, ‘sqrt’ +Note: ‘auto’ is used to choose optimally between ‘fd’ and ‘sturges’

          • +
          • num_quantiles - (Int) Number of quantiles to bin the data. +Default value is set to 1,000 quantiles.

          • +
          • is_enabled - (Boolean) Enables or disables histogram and quantiles

          • +
          +
        • +
        +
      • +
      • text - Options for the text columns

        +
          +
        • is_enabled - (Boolean) Enables or disables the text operations

        • +
        • vocab - Finds all the unique characters used in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables vocab

          • +
          +
        • +
        • min - Finds minimum value in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables min

          • +
          +
        • +
        • max - Finds maximum value in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables max

          • +
          +
        • +
        • mode - Finds mode(s) in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables mode

          • +
          • top_k_modes - (Int) Sets the number of modes to return if multiple exist. Default returns max 5 modes.

          • +
          +
        • +
        • median - Finds median value in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables median

          • +
          +
        • +
        • sum - Finds sum of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables sum

          • +
          +
        • +
        • variance - Finds variance of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables variance

          • +
          +
        • +
        • skewness - Finds skewness of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables skewness

          • +
          +
        • +
        • kurtosis - Finds kurtosis of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables kurtosis

          • +
          +
        • +
        • median_abs_deviation - Finds median absolute deviation of all values in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables median absolute deviation

          • +
          +
        • +
        • bias_correction - Applies bias correction to variance, skewness, and kurtosis calculations

          +
            +
          • is_enabled - (Boolean) Enables or disables bias correction

          • +
          +
        • +
        • is_numeric_stats_enabled - (Boolean) enable or disable all numeric stats

        • +
        • num_zeros - Finds the count of zeros in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables num_zeros

          • +
          +
        • +
        • num_negatives - Finds the count of negative numbers in a column

          +
            +
          • is_enabled - (Boolean) Enables or disables num_negatives

          • +
          +
        • +
        • histogram_and_quantiles - Generates a histogram and quantiles +from the column values

          +
            +
          • bin_count_or_method - (String/List[String]) Designates preferred method for calculating histogram bins or the number of bins to use. +If left unspecified (None) the optimal method will be chosen by attempting all methods. +If multiple specified (list) the optimal method will be chosen by attempting the provided ones. +methods: ‘auto’, ‘fd’, ‘doane’, ‘scott’, ‘rice’, ‘sturges’, ‘sqrt’ +Note: ‘auto’ is used to choose optimally between ‘fd’ and ‘sturges’

          • +
          • num_quantiles - (Int) Number of quantiles to bin the data. +Default value is set to 1,000 quantiles.

          • +
          • is_enabled - (Boolean) Enables or disables histogram and quantiles

          • +
          +
        • +
        +
      • +
      • datetime - Options for the datetime columns

        +
          +
        • is_enabled - (Boolean) Enables or disables the datetime operations

        • +
        +
      • +
      • order - Options for the order columns

        +
          +
        • is_enabled - (Boolean) Enables or disables the order operations

        • +
        +
      • +
      • category - Options for the category columns

        +
          +
        • is_enabled - (Boolean) Enables or disables the category operations

        • +
        • top_k_categories - (int) Number of categories to be displayed when reporting

        • +
        • max_sample_size_to_check_stop_condition - (int) The maximum sample size before categorical stop conditions are checked

        • +
        • stop_condition_unique_value_ratio - (float) The highest ratio of unique values to dataset size that is to be considered a categorical type

        • +
        • cms - (Boolean) Enables or Disables the use of count min sketch / heavy hitters for approximate frequency counts

        • +
        • cms_confidence - (float) Defines the number of hashes used in CMS, default 0.95

        • +
        • cms_relative_error - (float) Defines the number of buckets used in CMS, default 0.01

        • +
        • cms_max_num_heavy_hitters - (int) The value used to define the threshold for minimum frequency required by a category to be counted

        • +
        +
      • +
      • data_labeler - Options for the data labeler columns

        +
          +
        • is_enabled - (Boolean) Enables or disables the data labeler operations

        • +
        • data_labeler_dirpath - (String) Directory path to data labeler

        • +
        • data_labeler_object - (BaseDataLabeler) Datalabeler to replace +the default labeler

        • +
        • max_sample_size - (Int) The max number of samples for the data +labeler

        • +
        +
      • +
      • correlation - Option set for correlation profiling +* is_enabled - (Boolean) Enables or disables performing correlation profiling +* columns - Columns considered to calculate correlation

      • +
      • row_statistics - (Boolean) Option to enable/disable row statistics calculations

        +
          +
        • unique_count - (UniqueCountOptions) Option to enable/disable unique row count calculations

          +
            +
          • is_enabled - (Bool) Enables or disables options for unique row count

          • +
          • hashing_method - (String) Property to specify row hashing method (“full” | “hll”)

          • +
          • hll - (HyperLogLogOptions) Options for alternative method of estimating unique row count (activated when hll is the selected hashing_method)

            +
              +
            • seed - (Int) Used to set HLL hashing function seed

            • +
            • register_count - (Int) Number of registers is equal to 2^register_count

            • +
            +
          • +
          +
        • +
        • null_count - (Boolean) Option to enable/disable functionalities for row_has_null_ratio and row_is_null_ratio

        • +
        +
      • +
      • chi2_homogeneity - Options for the chi-squared test matrix

        +
          +
        • is_enabled - (Boolean) Enables or disables performing chi-squared tests for homogeneity between the categorical columns of the dataset.

        • +
        +
      • +
      • null_replication_metrics - Options for calculating null replication metrics

        +
          +
        • is_enabled - (Boolean) Enables or disables calculation of null replication metrics

        • +
        +
      • +
      +
    • +
    • unstructured_options - Options responsible for all unstructured data

      +
        +
      • text - Options for the text profile

        +
          +
        • is_case_sensitive - (Boolean) Specify whether the profile is case sensitive

        • +
        • stop_words - (List of Strings) List of stop words to be removed when profiling

        • +
        • top_k_chars - (Int) Number of top characters to be retrieved when profiling

        • +
        • top_k_words - (Int) Number of top words to be retrieved when profiling

        • +
        • vocab - Options for vocab count

          +
            +
          • is_enabled - (Boolean) Enables or disables the vocab stats

          • +
          +
        • +
        • words - Options for word count

          +
            +
          • is_enabled - (Boolean) Enables or disables the word stats

          • +
          +
        • +
        +
      • +
      • data_labeler - Options for the data labeler

        +
          +
        • is_enabled - (Boolean) Enables or disables the data labeler operations

        • +
        • data_labeler_dirpath - (String) Directory path to data labeler

        • +
        • data_labeler_object - (BaseDataLabeler) Datalabeler to replace +the default labeler

        • +
        • max_sample_size - (Int) The max number of samples for the data +labeler

        • +
        +
      • +
      +
    • +
    +
  • +
+
+
+

Statistical Dependency on Order of Updates

+

Some profile features/statistics are dependent on the order in which the profiler +is updated with new data.

+
+

Order Profile

+

The order profiler utilizes the last value in the previous data batch to ensure +the subsequent dataset is above/below/equal to that value when predicting +non-random order.

+

For instance, a dataset to be predicted as ascending would require the following +batch data update to be ascending and its first value >= than that of the +previous batch of data.

+

Ex. of ascending:

+
batch_1 = [0, 1, 2]
+batch_2 = [3, 4, 5]
+
+
+

Ex. of random:

+
batch_1 = [0, 1, 2]
+batch_2 = [1, 2, 3] # notice how the first value is less than the last value in the previous batch
+
+
+
+
+
+

Reporting Structure

+

For every profile, we can provide a report and customize it with a couple optional parameters:

+
    +
  • output_format (string)

    +
      +
    • This will allow the user to decide the output format for report.

      +
        +
      • Options are one of [pretty, compact, serializable, flat]:

        +
          +
        • Pretty: floats are rounded to four decimal places, and lists are shortened.

        • +
        • Compact: Similar to pretty, but removes detailed statistics such as runtimes, label probabilities, index locations of null types, etc.

        • +
        • Serializable: Output is json serializable and not prettified

        • +
        • Flat: Nested output is returned as a flattened dictionary

        • +
        +
      • +
      +
    • +
    +
  • +
  • num_quantile_groups (int)

    +
      +
    • You can sample your data as you like! With a minimum of one and a maximum of 1000, you can decide the number of quantile groups!

    • +
    +
  • +
+
report  = profile.report(report_options={"output_format": "pretty"})
+report  = profile.report(report_options={"output_format": "compact"})
+report  = profile.report(report_options={"output_format": "serializable"})
+report  = profile.report(report_options={"output_format": "flat"})
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/profiler_example.html b/docs/0.10.5/html/profiler_example.html new file mode 100644 index 000000000..4c9c3e604 --- /dev/null +++ b/docs/0.10.5/html/profiler_example.html @@ -0,0 +1,949 @@ + + + + + + + + + Structured Profilers - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + + +

View this notebook on GitHub

+
+

Structured Profilers

+

Data profiling - is the process of examining a dataset and collecting statistical or informational summaries about said dataset.

+

The Profiler class inside the DataProfiler is designed to generate data profiles via the Profiler class, which ingests either a Data class or a Pandas DataFrame.

+

Currently, the Data class supports loading the following file formats:

+
    +
  • Any delimited (CSV, TSV, etc.)

  • +
  • JSON object

  • +
  • Avro

  • +
  • Parquet

  • +
  • Text files

  • +
  • Pandas Series/Dataframe

  • +
+

Once the data is loaded, the Profiler can calculate statistics and predict the entities (via the Labeler) of every column (csv) or key-value (JSON) store as well as dataset wide information, such as the number of nulls, duplicates, etc.

+

This example will look at specifically the structured data types for structured profiling.

+
+

Reporting

+

One of the primary purposes of the Profiler are to quickly identify what is in the dataset. This can be useful for analyzing a dataset prior to use or determining which columns could be useful for a given purpose.

+

In terms of reporting, there are multiple reporting options:

+
    +
  • Pretty: Floats are rounded to four decimal places, and lists are shortened.

  • +
  • Compact: Similar to pretty, but removes detailed statistics such as runtimes, label probabilities, index locations of null types, etc.

  • +
  • Serializable: Output is json serializable and not prettified

  • +
  • Flat: Nested Output is returned as a flattened dictionary

  • +
+

The Pretty and Compact reports are the two most commonly used reports and includes global_stats and data_stats for the given dataset. global_stats contains overall properties of the data such as number of rows/columns, null ratio, duplicate ratio. data_stats contains specific properties and statistics for each column file such as min, max, mean, variance, etc.

+

For structured profiles, the report looks like this:

+
"global_stats": {
+    "samples_used": int,
+    "column_count": int,
+    "row_count": int,
+    "row_has_null_ratio": float,
+    "row_is_null_ratio": float,
+    "unique_row_ratio": float,
+    "duplicate_row_count": int,
+    "file_type": string,
+    "encoding": string,
+},
+"data_stats": [
+    {
+        "column_name": string,
+        "data_type": string,
+        "data_label": string,
+        "categorical": bool,
+        "order": string,
+        "samples": list(str),
+        "statistics": {
+            "sample_size": int,
+            "null_count": int,
+            "null_types": list(string),
+            "null_types_index": {
+                string: list(int)
+            },
+            "data_type_representation": [string, list(string)],
+            "min": [null, float],
+            "max": [null, float],
+            "mean": float,
+            "variance": float,
+            "stddev": float,
+            "histogram": {
+                "bin_counts": list(int),
+                "bin_edges": list(float),
+            },
+            "quantiles": {
+                int: float
+            }
+            "vocab": list(char),
+            "avg_predictions": dict(float),
+            "data_label_representation": dict(float),
+            "categories": list(str),
+            "unique_count": int,
+            "unique_ratio": float,
+            "precision": {
+                'min': int,
+                'max': int,
+                'mean': float,
+                'var': float,
+                'std': float,
+                'sample_size': int,
+                'margin_of_error': float,
+                'confidence_level': float
+            },
+            "times": dict(float),
+            "format": string
+        }
+    }
+]
+
+
+

In the example, the compact format of the report is used to shorten the full list of the results.

+
+
[ ]:
+
+
+
+import os
+import sys
+import json
+
+try:
+    sys.path.insert(0, '..')
+    import dataprofiler as dp
+except ImportError:
+    import dataprofiler as dp
+
+data_path = "../dataprofiler/tests/data"
+
+# remove extra tf loggin
+import tensorflow as tf
+tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
+
+
+
+
+
[ ]:
+
+
+
+data = dp.Data(os.path.join(data_path, "csv/aws_honeypot_marx_geo.csv"))
+profile = dp.Profiler(data)
+
+# Compact - A high level view, good for quick reviews
+report  = profile.report(report_options={"output_format":"compact"})
+print(json.dumps(report, indent=4))
+
+
+
+

It should be noted, in addition to reading the input data from multiple file types, DataProfiler allows the input data as a dataframe. To get more results related to detailed predictions at the entity level from the DataLabeler component or histogram results, the format pretty should be used.

+
+
[ ]:
+
+
+
+# run data profiler and get the report
+import pandas as pd
+my_dataframe = pd.DataFrame([[1, 2.0],[1, 2.2],[-1, 3]], columns=["col_int", "col_float"])
+profile = dp.Profiler(my_dataframe)
+
+report  = profile.report(report_options={"output_format":"pretty"})
+print(json.dumps(report, indent=4))
+
+
+
+
+
+

Profiler Type

+

The profiler will infer what type of statistics to generate (structured or unstructured) based on the input. However, you can explicitly specify profile type as well. Here is an example of the the profiler explicitly calling the structured profile.

+
+
[ ]:
+
+
+
+data = dp.Data(os.path.join(data_path, "csv/aws_honeypot_marx_geo.csv"))
+profile = dp.Profiler(data, profiler_type='structured')
+
+# print the report using json to prettify.
+report = profile.report(report_options={"output_format": "pretty"})
+print(json.dumps(report, indent=4))
+
+
+
+
+
+

Profiler options

+

The DataProfiler has the ability to turn on and off components as needed. This is accomplished via the ProfilerOptions class.

+

For example, if a user doesn’t require histogram information they may desire to turn off the histogram functionality. Simialrly, if a user is looking for a more accurate labeling, they can increase the samples used to label.

+

Below, let’s remove the histogram and increase the number of samples to the labeler component (1,000 samples).

+

Full list of options in the Profiler section of the DataProfiler documentation.

+
+
[ ]:
+
+
+
+data = dp.Data(os.path.join(data_path, "csv/diamonds.csv"))
+
+profile_options = dp.ProfilerOptions()
+
+# Setting multiple options via set
+profile_options.set({ "histogram.is_enabled": False, "int.is_enabled": False})
+
+# Set options via directly setting them
+profile_options.structured_options.data_labeler.max_sample_size = 1000
+
+profile = dp.Profiler(data, options=profile_options)
+report  = profile.report(report_options={"output_format":"compact"})
+
+# Print the report
+print(json.dumps(report, indent=4))
+
+
+
+
+
+

Updating Profiles

+

Beyond just profiling, one of the unique aspects of the DataProfiler is the ability to update the profiles. To update appropriately, the schema (columns / keys) must match appropriately.

+
+
[ ]:
+
+
+
+# Load and profile a CSV file
+data = dp.Data(os.path.join(data_path, "csv/sparse-first-and-last-column-header-and-author.txt"))
+profile = dp.Profiler(data)
+
+# Update the profile with new data:
+new_data = dp.Data(os.path.join(data_path, "csv/sparse-first-and-last-column-skip-header.txt"))
+# new_data = dp.Data(os.path.join(data_path, "iris-utf-16.csv")) # will error due to schema mismatch
+profile.update_profile(new_data)
+
+# Take a peek at the data
+print(data.data)
+print(new_data.data)
+
+# Report the compact version of the profile
+report  = profile.report(report_options={"output_format":"compact"})
+print(json.dumps(report, indent=4))
+
+
+
+
+
+

Merging Profiles

+

Merging profiles are an alternative method for updating profiles. Particularly, multiple profiles can be generated seperately, then added together with a simple + command: profile3 = profile1 + profile2

+
+
[ ]:
+
+
+
+# Load a CSV file with a schema
+data1 = dp.Data(os.path.join(data_path, "csv/sparse-first-and-last-column-header-and-author.txt"))
+profile1 = dp.Profiler(data1)
+
+# Load another CSV file with the same schema
+data2 = dp.Data(os.path.join(data_path, "csv/sparse-first-and-last-column-skip-header.txt"))
+profile2 = dp.Profiler(data2)
+
+# Merge the profiles
+profile3 = profile1 + profile2
+
+# Report the compact version of the profile
+report  = profile3.report(report_options={"output_format":"compact"})
+print(json.dumps(report, indent=4))
+
+
+
+

As you can see, the update_profile function and the + operator function similarly. The reason the + operator is important is that it’s possible to save and load profiles, which we cover next.

+
+
+

Differences in Data

+

Can be applied to both structured and unstructured datasets.

+

Such reports can provide details on the differences between training and validation data like in this pseudo example:

+
profiler_training = dp.Profiler(training_data)
+profiler_testing = dp.Profiler(testing_data)
+
+validation_report = profiler_training.diff(profiler_testing)
+
+
+
+
[ ]:
+
+
+
+from pprint import pprint
+
+# structured differences example
+data_split_differences = profile1.diff(profile2)
+pprint(data_split_differences)
+
+
+
+
+
+

Graphing a Profile

+

We’ve also added the ability to generating visual reports from a profile.

+

The following plots are currently available to work directly with your profilers:

+
    +
  • missing values matrix

  • +
  • histogram (numeric columns only)

  • +
+
+
[ ]:
+
+
+
+import matplotlib.pyplot as plt
+
+
+# get the data
+data_folder = "../dataprofiler/tests/data"
+data = dp.Data(os.path.join(data_folder, "csv/aws_honeypot_marx_geo.csv"))
+
+# profile the data
+profile = dp.Profiler(data)
+
+
+
+
+
[ ]:
+
+
+
+# generate a missing values matrix
+fig = plt.figure(figsize=(8, 6), dpi=100)
+fig = dp.graphs.plot_missing_values_matrix(profile, ax=fig.gca(), title="Missing Values Matrix")
+
+
+
+
+
[ ]:
+
+
+
+# generate histogram of all int/float columns
+fig = dp.graphs.plot_histograms(profile)
+fig.set_size_inches(8, 6)
+fig.set_dpi(100)
+
+
+
+
+
+

Saving and Loading a Profile

+

Not only can the Profiler create and update profiles, it’s also possible to save, load then manipulate profiles.

+
+
[ ]:
+
+
+
+# Load data
+data = dp.Data(os.path.join(data_path, "csv/names-col.txt"))
+
+# Generate a profile
+profile = dp.Profiler(data)
+
+# Save a profile to disk for later (saves as pickle file)
+profile.save(filepath="my_profile.pkl")
+
+# Load a profile from disk
+loaded_profile = dp.Profiler.load("my_profile.pkl")
+
+# Report the compact version of the profile
+report = profile.report(report_options={"output_format":"compact"})
+print(json.dumps(report, indent=4))
+
+
+
+

With the ability to save and load profiles, profiles can be generated via multiple machines then merged. Further, profiles can be stored and later used in applications such as change point detection, synthetic data generation, and more.

+
+
[ ]:
+
+
+
+# Load a multiple files via the Data class
+filenames = ["csv/sparse-first-and-last-column-header-and-author.txt",
+             "csv/sparse-first-and-last-column-skip-header.txt"]
+data_objects = []
+for filename in filenames:
+    data_objects.append(dp.Data(os.path.join(data_path, filename)))
+
+
+# Generate and save profiles
+for i in range(len(data_objects)):
+    profile = dp.Profiler(data_objects[i])
+    profile.save(filepath="data-"+str(i)+".pkl")
+
+
+# Load profiles and add them together
+profile = None
+for i in range(len(data_objects)):
+    if profile is None:
+        profile = dp.Profiler.load("data-"+str(i)+".pkl")
+    else:
+        profile += dp.Profiler.load("data-"+str(i)+".pkl")
+
+
+# Report the compact version of the profile
+report = profile.report(report_options={"output_format":"compact"})
+print(json.dumps(report, indent=4))
+
+
+
+
+
[ ]:
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/profiler_example.ipynb b/docs/0.10.5/html/profiler_example.ipynb new file mode 100644 index 000000000..b6a4409c9 --- /dev/null +++ b/docs/0.10.5/html/profiler_example.ipynb @@ -0,0 +1,577 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f37ca393", + "metadata": {}, + "source": [ + "# Structured Profilers" + ] + }, + { + "cell_type": "markdown", + "id": "ff9bd095", + "metadata": {}, + "source": [ + "**Data profiling** - *is the process of examining a dataset and collecting statistical or informational summaries about said dataset.*\n", + "\n", + "The Profiler class inside the DataProfiler is designed to generate *data profiles* via the Profiler class, which ingests either a Data class or a Pandas DataFrame. \n", + "\n", + "Currently, the Data class supports loading the following file formats:\n", + "\n", + "* Any delimited (CSV, TSV, etc.)\n", + "* JSON object\n", + "* Avro\n", + "* Parquet\n", + "* Text files\n", + "* Pandas Series/Dataframe\n", + "\n", + "Once the data is loaded, the Profiler can calculate statistics and predict the entities (via the Labeler) of every column (csv) or key-value (JSON) store as well as dataset wide information, such as the number of nulls, duplicates, etc.\n", + "\n", + "This example will look at specifically the structured data types for structured profiling. " + ] + }, + { + "cell_type": "markdown", + "id": "de58b9c4", + "metadata": {}, + "source": [ + "## Reporting" + ] + }, + { + "cell_type": "markdown", + "id": "8001185a", + "metadata": {}, + "source": [ + "One of the primary purposes of the Profiler are to quickly identify what is in the dataset. This can be useful for analyzing a dataset prior to use or determining which columns could be useful for a given purpose.\n", + "\n", + "In terms of reporting, there are multiple reporting options:\n", + "\n", + "* **Pretty**: Floats are rounded to four decimal places, and lists are shortened.\n", + "* **Compact**: Similar to pretty, but removes detailed statistics such as runtimes, label probabilities, index locations of null types, etc.\n", + "* **Serializable**: Output is json serializable and not prettified\n", + "* **Flat**: Nested Output is returned as a flattened dictionary\n", + "\n", + "The **Pretty** and **Compact** reports are the two most commonly used reports and includes `global_stats` and `data_stats` for the given dataset. `global_stats` contains overall properties of the data such as number of rows/columns, null ratio, duplicate ratio. `data_stats` contains specific properties and statistics for each column file such as min, max, mean, variance, etc.\n", + "\n", + "For structured profiles, the report looks like this:\n", + "\n", + "```\n", + "\"global_stats\": {\n", + " \"samples_used\": int,\n", + " \"column_count\": int,\n", + " \"row_count\": int,\n", + " \"row_has_null_ratio\": float,\n", + " \"row_is_null_ratio\": float, \n", + " \"unique_row_ratio\": float,\n", + " \"duplicate_row_count\": int,\n", + " \"file_type\": string,\n", + " \"encoding\": string,\n", + "},\n", + "\"data_stats\": [\n", + " {\n", + " \"column_name\": string,\n", + " \"data_type\": string,\n", + " \"data_label\": string,\n", + " \"categorical\": bool,\n", + " \"order\": string,\n", + " \"samples\": list(str),\n", + " \"statistics\": {\n", + " \"sample_size\": int,\n", + " \"null_count\": int,\n", + " \"null_types\": list(string),\n", + " \"null_types_index\": {\n", + " string: list(int)\n", + " },\n", + " \"data_type_representation\": [string, list(string)],\n", + " \"min\": [null, float],\n", + " \"max\": [null, float],\n", + " \"mean\": float,\n", + " \"variance\": float,\n", + " \"stddev\": float,\n", + " \"histogram\": { \n", + " \"bin_counts\": list(int),\n", + " \"bin_edges\": list(float),\n", + " },\n", + " \"quantiles\": {\n", + " int: float\n", + " }\n", + " \"vocab\": list(char),\n", + " \"avg_predictions\": dict(float), \n", + " \"data_label_representation\": dict(float),\n", + " \"categories\": list(str),\n", + " \"unique_count\": int,\n", + " \"unique_ratio\": float,\n", + " \"precision\": {\n", + " 'min': int,\n", + " 'max': int,\n", + " 'mean': float,\n", + " 'var': float,\n", + " 'std': float,\n", + " 'sample_size': int,\n", + " 'margin_of_error': float,\n", + " 'confidence_level': float\t\t\n", + " },\n", + " \"times\": dict(float),\n", + " \"format\": string\n", + " }\n", + " }\n", + "]\n", + "```\n", + "\n", + "In the example, the `compact` format of the report is used to shorten the full list of the results. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5fcb5447", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " import dataprofiler as dp\n", + "\n", + "data_path = \"../dataprofiler/tests/data\"\n", + "\n", + "# remove extra tf loggin\n", + "import tensorflow as tf\n", + "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7fc2df6", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "data = dp.Data(os.path.join(data_path, \"csv/aws_honeypot_marx_geo.csv\"))\n", + "profile = dp.Profiler(data)\n", + "\n", + "# Compact - A high level view, good for quick reviews\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "d7ec39d2", + "metadata": {}, + "source": [ + "It should be noted, in addition to reading the input data from multiple file types, DataProfiler allows the input data as a dataframe. To get more results related to detailed predictions at the entity level from the DataLabeler component or histogram results, the format `pretty` should be used. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29737f25", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "# run data profiler and get the report\n", + "import pandas as pd\n", + "my_dataframe = pd.DataFrame([[1, 2.0],[1, 2.2],[-1, 3]], columns=[\"col_int\", \"col_float\"])\n", + "profile = dp.Profiler(my_dataframe)\n", + "\n", + "report = profile.report(report_options={\"output_format\":\"pretty\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "241f6e3e", + "metadata": {}, + "source": [ + "## Profiler Type" + ] + }, + { + "cell_type": "markdown", + "id": "5b20879b", + "metadata": {}, + "source": [ + "The profiler will infer what type of statistics to generate (structured or unstructured) based on the input. However, you can explicitly specify profile type as well. Here is an example of the the profiler explicitly calling the structured profile." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc44eb47", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "data = dp.Data(os.path.join(data_path, \"csv/aws_honeypot_marx_geo.csv\"))\n", + "profile = dp.Profiler(data, profiler_type='structured')\n", + "\n", + "# print the report using json to prettify.\n", + "report = profile.report(report_options={\"output_format\": \"pretty\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "fe02ad64", + "metadata": {}, + "source": [ + "## Profiler options" + ] + }, + { + "cell_type": "markdown", + "id": "40804cc9", + "metadata": {}, + "source": [ + "The DataProfiler has the ability to turn on and off components as needed. This is accomplished via the `ProfilerOptions` class.\n", + "\n", + "For example, if a user doesn't require histogram information they may desire to turn off the histogram functionality. Simialrly, if a user is looking for a more accurate labeling, they can increase the samples used to label.\n", + "\n", + "Below, let's remove the histogram and increase the number of samples to the labeler component (1,000 samples). \n", + "\n", + "Full list of options in the Profiler section of the [DataProfiler documentation](https://capitalone.github.io/DataProfiler/profile_options.html)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d25d899", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "data = dp.Data(os.path.join(data_path, \"csv/diamonds.csv\"))\n", + "\n", + "profile_options = dp.ProfilerOptions()\n", + "\n", + "# Setting multiple options via set\n", + "profile_options.set({ \"histogram.is_enabled\": False, \"int.is_enabled\": False})\n", + "\n", + "# Set options via directly setting them\n", + "profile_options.structured_options.data_labeler.max_sample_size = 1000\n", + "\n", + "profile = dp.Profiler(data, options=profile_options)\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "\n", + "# Print the report\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "2052415a", + "metadata": {}, + "source": [ + "## Updating Profiles" + ] + }, + { + "cell_type": "markdown", + "id": "7e02f746", + "metadata": {}, + "source": [ + "Beyond just profiling, one of the unique aspects of the DataProfiler is the ability to update the profiles. To update appropriately, the schema (columns / keys) must match appropriately." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ab8022f", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "# Load and profile a CSV file\n", + "data = dp.Data(os.path.join(data_path, \"csv/sparse-first-and-last-column-header-and-author.txt\"))\n", + "profile = dp.Profiler(data)\n", + "\n", + "# Update the profile with new data:\n", + "new_data = dp.Data(os.path.join(data_path, \"csv/sparse-first-and-last-column-skip-header.txt\"))\n", + "# new_data = dp.Data(os.path.join(data_path, \"iris-utf-16.csv\")) # will error due to schema mismatch\n", + "profile.update_profile(new_data)\n", + "\n", + "# Take a peek at the data\n", + "print(data.data)\n", + "print(new_data.data)\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "66ec6dc5", + "metadata": {}, + "source": [ + "## Merging Profiles" + ] + }, + { + "cell_type": "markdown", + "id": "e2265fe9", + "metadata": {}, + "source": [ + "Merging profiles are an alternative method for updating profiles. Particularly, multiple profiles can be generated seperately, then added together with a simple `+` command: `profile3 = profile1 + profile2`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc68ca07", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "# Load a CSV file with a schema\n", + "data1 = dp.Data(os.path.join(data_path, \"csv/sparse-first-and-last-column-header-and-author.txt\"))\n", + "profile1 = dp.Profiler(data1)\n", + "\n", + "# Load another CSV file with the same schema\n", + "data2 = dp.Data(os.path.join(data_path, \"csv/sparse-first-and-last-column-skip-header.txt\"))\n", + "profile2 = dp.Profiler(data2)\n", + "\n", + "# Merge the profiles\n", + "profile3 = profile1 + profile2\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile3.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "7ea07dc6", + "metadata": {}, + "source": [ + "As you can see, the `update_profile` function and the `+` operator function similarly. The reason the `+` operator is important is that it's possible to *save and load profiles*, which we cover next." + ] + }, + { + "cell_type": "markdown", + "id": "375ff25c-b189-436a-b07d-5e7f13cc6e03", + "metadata": {}, + "source": [ + "## Differences in Data\n", + "Can be applied to both structured and unstructured datasets. \n", + "\n", + "Such reports can provide details on the differences between training and validation data like in this pseudo example:\n", + "```python\n", + "profiler_training = dp.Profiler(training_data)\n", + "profiler_testing = dp.Profiler(testing_data)\n", + "\n", + "validation_report = profiler_training.diff(profiler_testing)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "65360a03-e3ff-4f3c-9963-412298fdb284", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "from pprint import pprint\n", + "\n", + "# structured differences example\n", + "data_split_differences = profile1.diff(profile2)\n", + "pprint(data_split_differences)" + ] + }, + { + "cell_type": "markdown", + "id": "2ae471ff-852f-400a-9bee-5c9fef96f10a", + "metadata": {}, + "source": [ + "## Graphing a Profile\n", + "\n", + "We've also added the ability to generating visual reports from a profile.\n", + "\n", + "The following plots are currently available to work directly with your profilers:\n", + "\n", + " * missing values matrix\n", + " * histogram (numeric columns only)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "734b588d-ac9a-409c-8eb5-b1a0aede8c63", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "\n", + "# get the data\n", + "data_folder = \"../dataprofiler/tests/data\"\n", + "data = dp.Data(os.path.join(data_folder, \"csv/aws_honeypot_marx_geo.csv\"))\n", + "\n", + "# profile the data\n", + "profile = dp.Profiler(data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e4e70204-fa30-43c2-9556-e84c19f82d32", + "metadata": {}, + "outputs": [], + "source": [ + "# generate a missing values matrix\n", + "fig = plt.figure(figsize=(8, 6), dpi=100)\n", + "fig = dp.graphs.plot_missing_values_matrix(profile, ax=fig.gca(), title=\"Missing Values Matrix\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d734d355-e542-4245-a1e9-66521e333c2d", + "metadata": {}, + "outputs": [], + "source": [ + "# generate histogram of all int/float columns\n", + "fig = dp.graphs.plot_histograms(profile)\n", + "fig.set_size_inches(8, 6)\n", + "fig.set_dpi(100)" + ] + }, + { + "cell_type": "markdown", + "id": "30868000", + "metadata": {}, + "source": [ + "## Saving and Loading a Profile" + ] + }, + { + "cell_type": "markdown", + "id": "f2858072", + "metadata": {}, + "source": [ + "Not only can the Profiler create and update profiles, it's also possible to save, load then manipulate profiles." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ad9ca57", + "metadata": {}, + "outputs": [], + "source": [ + "# Load data\n", + "data = dp.Data(os.path.join(data_path, \"csv/names-col.txt\"))\n", + "\n", + "# Generate a profile\n", + "profile = dp.Profiler(data)\n", + "\n", + "# Save a profile to disk for later (saves as pickle file)\n", + "profile.save(filepath=\"my_profile.pkl\")\n", + "\n", + "# Load a profile from disk\n", + "loaded_profile = dp.Profiler.load(\"my_profile.pkl\")\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "8f9859c2", + "metadata": {}, + "source": [ + "With the ability to save and load profiles, profiles can be generated via multiple machines then merged. Further, profiles can be stored and later used in applications such as change point detection, synthetic data generation, and more. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3571f2d0", + "metadata": {}, + "outputs": [], + "source": [ + "# Load a multiple files via the Data class\n", + "filenames = [\"csv/sparse-first-and-last-column-header-and-author.txt\",\n", + " \"csv/sparse-first-and-last-column-skip-header.txt\"]\n", + "data_objects = []\n", + "for filename in filenames:\n", + " data_objects.append(dp.Data(os.path.join(data_path, filename)))\n", + "\n", + "\n", + "# Generate and save profiles\n", + "for i in range(len(data_objects)):\n", + " profile = dp.Profiler(data_objects[i])\n", + " profile.save(filepath=\"data-\"+str(i)+\".pkl\")\n", + "\n", + "\n", + "# Load profiles and add them together\n", + "profile = None\n", + "for i in range(len(data_objects)):\n", + " if profile is None:\n", + " profile = dp.Profiler.load(\"data-\"+str(i)+\".pkl\")\n", + " else:\n", + " profile += dp.Profiler.load(\"data-\"+str(i)+\".pkl\")\n", + "\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4690068a-8fc3-4bd5-8649-63d0f34fa91d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/html/py-modindex.html b/docs/0.10.5/html/py-modindex.html new file mode 100644 index 000000000..bbb7198d7 --- /dev/null +++ b/docs/0.10.5/html/py-modindex.html @@ -0,0 +1,605 @@ + + + + + + + Python Module Index - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + +
+

Python Module Index

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
d
+ dataprofiler +
    + dataprofiler.data_readers +
    + dataprofiler.data_readers.avro_data +
    + dataprofiler.data_readers.base_data +
    + dataprofiler.data_readers.csv_data +
    + dataprofiler.data_readers.data +
    + dataprofiler.data_readers.data_utils +
    + dataprofiler.data_readers.filepath_or_buffer +
    + dataprofiler.data_readers.graph_data +
    + dataprofiler.data_readers.json_data +
    + dataprofiler.data_readers.parquet_data +
    + dataprofiler.data_readers.structured_mixins +
    + dataprofiler.data_readers.text_data +
    + dataprofiler.dp_logging +
    + dataprofiler.labelers +
    + dataprofiler.labelers.base_data_labeler +
    + dataprofiler.labelers.base_model +
    + dataprofiler.labelers.char_load_tf_model +
    + dataprofiler.labelers.character_level_cnn_model +
    + dataprofiler.labelers.classification_report_utils +
    + dataprofiler.labelers.column_name_model +
    + dataprofiler.labelers.data_labelers +
    + dataprofiler.labelers.data_processing +
    + dataprofiler.labelers.labeler_utils +
    + dataprofiler.labelers.regex_model +
    + dataprofiler.labelers.utils +
    + dataprofiler.profilers +
    + dataprofiler.profilers.base_column_profilers +
    + dataprofiler.profilers.categorical_column_profile +
    + dataprofiler.profilers.column_profile_compilers +
    + dataprofiler.profilers.data_labeler_column_profile +
    + dataprofiler.profilers.datetime_column_profile +
    + dataprofiler.profilers.float_column_profile +
    + dataprofiler.profilers.graph_profiler +
    + dataprofiler.profilers.helpers +
    + dataprofiler.profilers.helpers.report_helpers +
    + dataprofiler.profilers.histogram_utils +
    + dataprofiler.profilers.int_column_profile +
    + dataprofiler.profilers.json_decoder +
    + dataprofiler.profilers.json_encoder +
    + dataprofiler.profilers.numerical_column_stats +
    + dataprofiler.profilers.order_column_profile +
    + dataprofiler.profilers.profile_builder +
    + dataprofiler.profilers.profiler_options +
    + dataprofiler.profilers.profiler_utils +
    + dataprofiler.profilers.text_column_profile +
    + dataprofiler.profilers.unstructured_labeler_profile +
    + dataprofiler.profilers.unstructured_text_profile +
    + dataprofiler.reports +
    + dataprofiler.reports.graphs +
    + dataprofiler.reports.utils +
    + dataprofiler.rng_utils +
    + dataprofiler.settings +
    + dataprofiler.validators +
    + dataprofiler.validators.base_validators +
    + dataprofiler.version +
+ +
+
+ + + + + +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/regex_labeler_from_scratch.html b/docs/0.10.5/html/regex_labeler_from_scratch.html new file mode 100644 index 000000000..b49edeadf --- /dev/null +++ b/docs/0.10.5/html/regex_labeler_from_scratch.html @@ -0,0 +1,858 @@ + + + + + + + + + Building a Regex Data Labeler w/ your own Regex - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + + +

View this notebook on GitHub

+
+

Building a Regex Data Labeler w/ your own Regex

+

This notebook teaches how to use the existing / create your own regex labeler as well as utilize it for structured data profiling.

+
    +
  1. Loading and utilizing the pre-existing regex data labeler

  2. +
  3. Replacing the existing regex rules with your own.

  4. +
  5. Utilizng a regex data labeler inside of the structured profiler

  6. +
+

First, let’s import the libraries needed for this example.

+
+
[ ]:
+
+
+
+import os
+import sys
+import json
+from pprint import pprint
+
+import pandas as pd
+
+try:
+    import dataprofiler as dp
+except ImportError:
+    sys.path.insert(0, '../..')
+    import dataprofiler as dp
+
+
+
+
+

Loading and using the pre-existing regex data labeler

+

We can easily import the exsting regex labeler via the load_from_library command from the dp.DataLabeler. This allows us to import models other than the default structured / unstructured labelers which exist in the library.

+
+
[ ]:
+
+
+
+data_labeler = dp.DataLabeler.load_from_library('regex_model')
+data_labeler.model.help()
+
+
+
+
+
[ ]:
+
+
+
+pprint(data_labeler.label_mapping)
+
+
+
+
+
[ ]:
+
+
+
+pprint(data_labeler.model._parameters['regex_patterns'])
+
+
+
+
+

Predicting with the regex labeler

+

In the prediction below, the default settings will split the predictions by default as it’s aggregation function. In other words, if a string ‘123 Fake St.’ The first character would receive a vote for integer and for address giving both a 50% probability. This is because these regex functions are defined individually and a post prediction aggregation function must be used to get the results.

+
+
[ ]:
+
+
+
+# evaluate a prediction using the default parameters
+data_labeler.predict(['123 Fake St.'])
+
+
+
+
+
+
+

Replacing the regex rules in the existing labeler

+

We can achieve this by: 1. Setting the label mapping to the new labels 2. Setting the model parameters which include: regex_patterns, default_label, ignore_case, and encapsulators

+

where regex_patterns is a dict of lists or regex for each label, default_label is the expected default label for the regex, ignore_case tells the model to ignore case during its detection, and encapsulators are generic regex statements placed before (start) and after (end) each regex. Currently, this is used by the default model to capture labels that are within a cell rather than matching the entire cell. (e.g. ’ 123 ’ will still capture 123 as digits).

+

Below, we created 4 labels where other is the default_label. Additionally, we set enabled case sensitivity such that upper and lower case letters would be detected separately.

+
+
[ ]:
+
+
+
+data_labeler.set_labels({'other': 0, 'digits':1, 'lowercase_char': 2, 'uppercase_chars': 3})
+data_labeler.model.set_params(
+    regex_patterns={
+        'digits': [r'[+-]?[0-9]+'],
+        'lowercase_char': [r'[a-z]+'],
+        'uppercase_chars': [r'[A-Z]+'],
+    },
+    default_label='other',
+    ignore_case=False,
+)
+data_labeler.label_mapping
+
+
+
+
+

Predicting with the new regex labels

+

Here we notice the otuput of the predictions gives us a prediction per character for each regex. Note how by default it is matching subtext due to the encapsulators. Where 123 were found to be digits, FAKE was foudn to be upper case, and the whitespaces and St. were other due no single regex being correct.

+
+
[ ]:
+
+
+
+data_labeler.predict(['123 FAKE St.'])
+
+
+
+

Below we turn off case-sensitivity and we see how the aggregation funciton splits the votes for characters between the lowercase and uppercase chars.

+
+
[ ]:
+
+
+
+data_labeler.model.set_params(ignore_case=True)
+data_labeler.predict(['123 FAKE St.'])
+
+
+
+

For the rest of this notebook, we will just use a single regex serach which will capture both upper and lower case chars.

+
+
[ ]:
+
+
+
+data_labeler.set_labels({'other': 0, 'digits':1, 'chars': 2})
+data_labeler.model.set_params(
+    regex_patterns={
+        'digits': [r'[=-]?[0-9]+'],
+        'chars': [r'[a-zA-Z]+'],
+    },
+    default_label='other',
+    ignore_case=False,
+)
+data_labeler.label_mapping
+
+
+
+
+
[ ]:
+
+
+
+data_labeler.predict(['123 FAKE St.'])
+
+
+
+
+
+

Adjusting postprocessor properties

+

Below we can look at the possible postprocessor parameters to adjust the aggregation function to the desired output. The previous outputs by default used the split aggregation function, however, below we will show the random aggregation function which will randomly choose a label if multiple labels have a vote for a given character.

+

data_labeler.postprocessor.help()

+
+
[ ]:
+
+
+
+data_labeler.postprocessor.set_params(aggregation_func='random')
+data_labeler.predict(['123 FAKE St.'], predict_options=dict(show_confidences=True))
+
+
+
+
+
+
+

Integrating the new Regex labeler into Structured Profiling

+

While the labeler can be used alone, it is also possible to integrate the labeler into the StructuredProfiler with a slight change to its postprocessor. The StructuredProfiler requires a labeler which outputs othe confidence of each label for a given cell being processed. To convert the output of the RegexPostProcessor into said format, we will use the StructRegexPostProcessor. We can create the postprocessor and set the data_labeler’s postprocessor to this value.

+
+
[ ]:
+
+
+
+from dataprofiler.labelers.data_processing import StructRegexPostProcessor
+
+postprocesor = StructRegexPostProcessor()
+data_labeler.set_postprocessor(postprocesor)
+
+
+
+

Below we will see the output is now one vote per sample.

+
+
[ ]:
+
+
+
+data_labeler.predict(['123 FAKE St.', '123', 'FAKE'], predict_options=dict(show_confidences=True))
+
+
+
+
+

Setting the Structuredprofiler’s DataLabeler

+

We can create a ProfilerOption and set the structured options to have the new data_labeler as its value. We then run the StructuredProfiler with the specified options.

+
+
[ ]:
+
+
+
+# create and set the option for the regex data labeler to be used at profile time
+profile_options = dp.ProfilerOptions()
+profile_options.set({'structured_options.data_labeler.data_labeler_object': data_labeler})
+
+# profile the dataset using the suggested regex data labeler
+data = pd.DataFrame(
+    [['123 FAKE St.', 123, 'this'],
+     [123           ,  -9, 'IS'],
+     ['...'         , +80, 'A'],
+     ['123'         , 202, 'raNDom'],
+     ['test'        ,  -1, 'TEST']],
+    dtype=object)
+profiler = dp.Profiler(data, options=profile_options)
+
+
+
+

Below we see the first column is given 3 labels as it received multiple votes for said column. However, it was confident on the second and third column which is why it only specified digits and chars respectively.

+
+
[ ]:
+
+
+
+pprint(profiler.report(
+    dict(output_format='compact',
+         omit_keys=['data_stats.*.statistics',
+                    'data_stats.*.categorical',
+                    'data_stats.*.order',
+                    'global_stats'])))
+
+
+
+
+
+
+

Saving the Data Labeler for future use

+
+
[ ]:
+
+
+
+if not os.path.isdir('my_new_regex_labeler'):
+    os.mkdir('my_new_regex_labeler')
+data_labeler.save_to_disk('my_new_regex_labeler')
+
+
+
+
+
+

Loading the saved Data Labeler

+
+
[ ]:
+
+
+
+saved_labeler = dp.DataLabeler.load_from_disk('my_new_regex_labeler')
+
+
+
+
+
[ ]:
+
+
+
+# ensuring the parametesr are what we saved.
+print("label_mapping:")
+pprint(saved_labeler.label_mapping)
+print("\nmodel parameters:")
+pprint(saved_labeler.model._parameters)
+print()
+print("postprocessor: " + saved_labeler.postprocessor.__class__.__name__)
+
+
+
+
+
[ ]:
+
+
+
+# predicting with the loaded labeler.
+saved_labeler.predict(['test', '123'])
+
+
+
+
+
[ ]:
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/regex_labeler_from_scratch.ipynb b/docs/0.10.5/html/regex_labeler_from_scratch.ipynb new file mode 100644 index 000000000..96aee213a --- /dev/null +++ b/docs/0.10.5/html/regex_labeler_from_scratch.ipynb @@ -0,0 +1,444 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e04c382a-7c49-452b-b9bf-e448951c64fe", + "metadata": {}, + "source": [ + "# Building a Regex Data Labeler w/ your own Regex" + ] + }, + { + "cell_type": "markdown", + "id": "6fb3ecb9-bc51-4c18-93d5-7991bbee5165", + "metadata": {}, + "source": [ + "This notebook teaches how to use the existing / create your own regex labeler as well as utilize it for structured data profiling.\n", + "\n", + "1. Loading and utilizing the pre-existing regex data labeler\n", + "1. Replacing the existing regex rules with your own.\n", + "1. Utilizng a regex data labeler inside of the structured profiler\n", + "\n", + "First, let's import the libraries needed for this example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a67c197b-d3ee-4896-a96f-cc3d043601d3", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "from pprint import pprint\n", + "\n", + "import pandas as pd\n", + "\n", + "try:\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " sys.path.insert(0, '../..')\n", + " import dataprofiler as dp" + ] + }, + { + "cell_type": "markdown", + "id": "c71356f4-9020-4862-a1e1-816effbb5443", + "metadata": {}, + "source": [ + "## Loading and using the pre-existing regex data labeler\n", + "We can easily import the exsting regex labeler via the `load_from_library` command from the `dp.DataLabeler`. This allows us to import models other than the default structured / unstructured labelers which exist in the library." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "113d6655-4bca-4d8e-9e6f-b972e29d5684", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler = dp.DataLabeler.load_from_library('regex_model')\n", + "data_labeler.model.help()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b405887-2b92-44ca-b8d7-29c384f6dd9c", + "metadata": {}, + "outputs": [], + "source": [ + "pprint(data_labeler.label_mapping)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11916a48-098c-4056-ac6c-b9542d85fa86", + "metadata": {}, + "outputs": [], + "source": [ + "pprint(data_labeler.model._parameters['regex_patterns'])" + ] + }, + { + "cell_type": "markdown", + "id": "da0e97ee-8d6d-4631-9b55-78ed904d5f41", + "metadata": {}, + "source": [ + "### Predicting with the regex labeler\n", + "In the prediction below, the default settings will `split` the predictions by default as it's aggregation function. In other words, if a string '123 Fake St.' The first character would receive a vote for integer and for address giving both a 50% probability. This is because these regex functions are defined individually and a post prediction aggregation function must be used to get the results." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fe519e65-36a7-4f42-8314-5369de8635c7", + "metadata": {}, + "outputs": [], + "source": [ + "# evaluate a prediction using the default parameters\n", + "data_labeler.predict(['123 Fake St.'])" + ] + }, + { + "cell_type": "markdown", + "id": "b41d834d-e47b-45a6-8970-d2d2033e2ade", + "metadata": {}, + "source": [ + "## Replacing the regex rules in the existing labeler\n", + "\n", + "We can achieve this by:\n", + "1. Setting the label mapping to the new labels\n", + "2. Setting the model parameters which include: `regex_patterns`, `default_label`, `ignore_case`, and `encapsulators`\n", + "\n", + "where `regex_patterns` is a `dict` of lists or regex for each label, `default_label` is the expected default label for the regex, `ignore_case` tells the model to ignore case during its detection, and `encapsulators` are generic regex statements placed before (start) and after (end) each regex. Currently, this is used by the default model to capture labels that are within a cell rather than matching the entire cell. (e.g. ' 123 ' will still capture 123 as digits)." + ] + }, + { + "cell_type": "markdown", + "id": "c6bb010a-406f-4fd8-abd0-3355a5ad0ded", + "metadata": {}, + "source": [ + "Below, we created 4 labels where `other` is the `default_label`. Additionally, we set enabled case sensitivity such that upper and lower case letters would be detected separately." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f86584cf-a7af-4bae-bf44-d87caa68833a", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.set_labels({'other': 0, 'digits':1, 'lowercase_char': 2, 'uppercase_chars': 3})\n", + "data_labeler.model.set_params(\n", + " regex_patterns={\n", + " 'digits': [r'[+-]?[0-9]+'],\n", + " 'lowercase_char': [r'[a-z]+'],\n", + " 'uppercase_chars': [r'[A-Z]+'],\n", + " },\n", + " default_label='other',\n", + " ignore_case=False,\n", + ")\n", + "data_labeler.label_mapping" + ] + }, + { + "cell_type": "markdown", + "id": "1ece1c8c-18a5-46fc-b563-6458e6e71e53", + "metadata": {}, + "source": [ + "### Predicting with the new regex labels\n", + "\n", + "Here we notice the otuput of the predictions gives us a prediction per character for each regex. Note how by default it is matching subtext due to the encapsulators. Where `123` were found to be digits, `FAKE` was foudn to be upper case, and the whitespaces and `St.` were other due no single regex being correct." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92842e14-2ea6-4879-b58c-c52b607dc94c", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.predict(['123 FAKE St.'])" + ] + }, + { + "cell_type": "markdown", + "id": "2ce14e54-094f-41ff-9ce0-69acace6abc2", + "metadata": {}, + "source": [ + "Below we turn off case-sensitivity and we see how the aggregation funciton splits the votes for characters between the `lowercase` and `uppercase` chars." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f7b8ed9d-c912-4dc7-82c5-ba78a3affc1e", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.model.set_params(ignore_case=True)\n", + "data_labeler.predict(['123 FAKE St.'])" + ] + }, + { + "cell_type": "markdown", + "id": "dc66515f-24e4-40f0-8592-b1ee4fba7077", + "metadata": {}, + "source": [ + "For the rest of this notebook, we will just use a single regex serach which will capture both upper and lower case chars." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3e0c1b11-d111-4080-873f-40aff7cf7930", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.set_labels({'other': 0, 'digits':1, 'chars': 2})\n", + "data_labeler.model.set_params(\n", + " regex_patterns={\n", + " 'digits': [r'[=-]?[0-9]+'],\n", + " 'chars': [r'[a-zA-Z]+'],\n", + " },\n", + " default_label='other',\n", + " ignore_case=False,\n", + ")\n", + "data_labeler.label_mapping" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28e7b2ee-c661-4b31-b727-078f1393b5c4", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.predict(['123 FAKE St.'])" + ] + }, + { + "cell_type": "markdown", + "id": "f60c8fd1-76e1-469f-9e5a-62d7529301b3", + "metadata": {}, + "source": [ + "### Adjusting postprocessor properties\n", + "\n", + "Below we can look at the possible postprocessor parameters to adjust the aggregation function to the desired output. The previous outputs by default used the `split` aggregation function, however, below we will show the `random` aggregation function which will randomly choose a label if multiple labels have a vote for a given character." + ] + }, + { + "cell_type": "markdown", + "id": "36afa82b-1ca5-49ad-9aa9-84c6de621f59", + "metadata": {}, + "source": [ + "data_labeler.postprocessor.help()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "66840940-47bf-433a-8ee8-977f26926e0b", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.postprocessor.set_params(aggregation_func='random')\n", + "data_labeler.predict(['123 FAKE St.'], predict_options=dict(show_confidences=True))" + ] + }, + { + "cell_type": "markdown", + "id": "c32b74fc-5051-4d53-b02a-4d1e4a35958f", + "metadata": {}, + "source": [ + "## Integrating the new Regex labeler into Structured Profiling\n", + "\n", + "While the labeler can be used alone, it is also possible to integrate the labeler into the StructuredProfiler with a slight change to its postprocessor. The StructuredProfiler requires a labeler which outputs othe confidence of each label for a given cell being processed. To convert the output of the `RegexPostProcessor` into said format, we will use the `StructRegexPostProcessor`. We can create the postprocessor and set the `data_labeler`'s postprocessor to this value." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a2663f2d-29a2-41ed-88dd-8a213d303365", + "metadata": {}, + "outputs": [], + "source": [ + "from dataprofiler.labelers.data_processing import StructRegexPostProcessor\n", + "\n", + "postprocesor = StructRegexPostProcessor()\n", + "data_labeler.set_postprocessor(postprocesor)" + ] + }, + { + "cell_type": "markdown", + "id": "f7352769-d636-42c6-9706-7d9cff520a72", + "metadata": {}, + "source": [ + "Below we will see the output is now one vote per sample." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18814634-0fd0-4ce8-b0c3-9b9454701a43", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.predict(['123 FAKE St.', '123', 'FAKE'], predict_options=dict(show_confidences=True))" + ] + }, + { + "cell_type": "markdown", + "id": "b4aa4e36-7362-4966-b827-3f5a6f2dfa7c", + "metadata": {}, + "source": [ + "### Setting the Structuredprofiler's DataLabeler\n", + "\n", + "We can create a `ProfilerOption` and set the structured options to have the new data_labeler as its value. We then run the StructuredProfiler with the specified options." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f18cf7f-283e-4e54-b3f9-1312828c3029", + "metadata": {}, + "outputs": [], + "source": [ + "# create and set the option for the regex data labeler to be used at profile time\n", + "profile_options = dp.ProfilerOptions()\n", + "profile_options.set({'structured_options.data_labeler.data_labeler_object': data_labeler})\n", + "\n", + "# profile the dataset using the suggested regex data labeler\n", + "data = pd.DataFrame(\n", + " [['123 FAKE St.', 123, 'this'], \n", + " [123 , -9, 'IS'], \n", + " ['...' , +80, 'A'], \n", + " ['123' , 202, 'raNDom'], \n", + " ['test' , -1, 'TEST']], \n", + " dtype=object)\n", + "profiler = dp.Profiler(data, options=profile_options)" + ] + }, + { + "cell_type": "markdown", + "id": "663e49f7-358b-4b0f-99a4-1823908ef990", + "metadata": {}, + "source": [ + "Below we see the first column is given 3 labels as it received multiple votes for said column. However, it was confident on the second and third column which is why it only specified `digits` and `chars` respectively." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f796d7f5-7e8a-447b-9cbb-d5b8180660a3", + "metadata": {}, + "outputs": [], + "source": [ + "pprint(profiler.report(\n", + " dict(output_format='compact', \n", + " omit_keys=['data_stats.*.statistics', \n", + " 'data_stats.*.categorical', \n", + " 'data_stats.*.order', \n", + " 'global_stats'])))" + ] + }, + { + "cell_type": "markdown", + "id": "261b903f-8f4c-403f-839b-ab8813f850e9", + "metadata": {}, + "source": [ + "## Saving the Data Labeler for future use" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6ffbaf2-9400-486a-ba83-5fc9ba9334d7", + "metadata": {}, + "outputs": [], + "source": [ + "if not os.path.isdir('my_new_regex_labeler'):\n", + " os.mkdir('my_new_regex_labeler')\n", + "data_labeler.save_to_disk('my_new_regex_labeler')" + ] + }, + { + "cell_type": "markdown", + "id": "09e40cb6-9d89-41c4-ae28-3dca498f8c68", + "metadata": {}, + "source": [ + "## Loading the saved Data Labeler" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52615b25-70a6-4ebb-8a32-14aaf1e747d9", + "metadata": {}, + "outputs": [], + "source": [ + "saved_labeler = dp.DataLabeler.load_from_disk('my_new_regex_labeler')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d1ccc0b3-1dc2-4847-95c2-d6b8769b1590", + "metadata": {}, + "outputs": [], + "source": [ + "# ensuring the parametesr are what we saved.\n", + "print(\"label_mapping:\")\n", + "pprint(saved_labeler.label_mapping)\n", + "print(\"\\nmodel parameters:\")\n", + "pprint(saved_labeler.model._parameters)\n", + "print()\n", + "print(\"postprocessor: \" + saved_labeler.postprocessor.__class__.__name__)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c827f2ae-4af6-4f3f-9651-9ee9ebea9fa0", + "metadata": {}, + "outputs": [], + "source": [ + "# predicting with the loaded labeler.\n", + "saved_labeler.predict(['test', '123'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "606f9bbf-5955-4b7b-b0d1-390de5600f73", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/html/roadmap.html b/docs/0.10.5/html/roadmap.html new file mode 100644 index 000000000..a1963a365 --- /dev/null +++ b/docs/0.10.5/html/roadmap.html @@ -0,0 +1,388 @@ + + + + + + + + + Roadmap - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+

Roadmap

+

For more detailed tasks, checkout the repo’s github issues page here: +Github Issues.

+
+

Data Reader Updates

+
    +
  • +
    Read data from S3 bucket
      +
    • All in the current dp.Data() API paradigm, we want to enable passing an S3 bucket file path to read in data from AWS s3.

    • +
    +
    +
    +
  • +
  • Pass list of data file paths to data reader

  • +
  • Pass in linst of data frames to data reader

  • +
+
+
+

New Model

+
    +
  • Transformer model from sensitive data detection

  • +
+
+
+

Historical Profiles

+
    +
  • +
    Some questions about Historical Profiles / need to step back and rething design to start:
      +
    • Meta profile on top?

    • +
    • Stored windowed info inside? Etc…

    • +
    +
    +
    +
  • +
  • Branch with current state of Historical Profiles

  • +
  • +
    Two example notebooks of current state:
      +
    • Notebook example one.

    • +
    • Notebook example two.

    • +
    +
    +
    +
  • +
+
+
+

Conditional Report Metric

+
    +
  • Based on what is populated on other metrics in the report, have “secondary” / “derivatives” of that number (or that number in conjunction with another number) populate in thie report as well.

  • +
  • For example, if null_count is not None, then populate a null_percent key with a value of the dividence of (null_count / sample_count).

  • +
+
+
+

Space / Time Testing

+
    +
  • +
    Automatic comparison testing for space and time analysis on PR’s
      +
    • Standardize a report for space time analysis for future comparisons (create baseline numbers)

    • +
    • Include those in integration tests that will automatically run on code when it is changed in PRs

    • +
    +
    +
    +
  • +
  • Could be an optional test, if the user thinks there is concern around the change driving an issue in the library performance

  • +
+
+
+

Testing Suite Upgrades

+
    +
  • Add mocking to unit tests where mocking is not utilized

  • +
  • Integration testing separated out from the unit testing suite. Determine how to only run remotely during PRs

  • +
  • Backward compatibility testing along with informative warnings and errors when a user is utilizing incompatible versions of the library and saved profile object

  • +
+
+
+

Historical Versions

+
    +
  • Legacy version upgrades to enable patches to prior versions of the Data Profiler

  • +
+
+
+

Miscellaneous

+
    +
  • Refact/or Pandas to Polars DataFrames

  • +
  • Spearman correlation calculation

  • +
  • Workflow Profiles

  • +
+
+
+ +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/search.html b/docs/0.10.5/html/search.html new file mode 100644 index 000000000..359141982 --- /dev/null +++ b/docs/0.10.5/html/search.html @@ -0,0 +1,267 @@ + + + + + + + Search - <div class='hidden'>Data Profiler</div> <div class='version'> v0.10.5</div> + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + +
+

Error

+

+ Please activate JavaScript to enable the search functionality. +

+
+ + +
+ +
+
+ + + + + +
+
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/searchindex.js b/docs/0.10.5/html/searchindex.js new file mode 100644 index 000000000..0001769d9 --- /dev/null +++ b/docs/0.10.5/html/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["API","add_new_model_to_data_labeler","column_name_labeler_example","data_labeling","data_reader","data_readers","dataprofiler","dataprofiler.data_readers","dataprofiler.data_readers.avro_data","dataprofiler.data_readers.base_data","dataprofiler.data_readers.csv_data","dataprofiler.data_readers.data","dataprofiler.data_readers.data_utils","dataprofiler.data_readers.filepath_or_buffer","dataprofiler.data_readers.graph_data","dataprofiler.data_readers.json_data","dataprofiler.data_readers.parquet_data","dataprofiler.data_readers.structured_mixins","dataprofiler.data_readers.text_data","dataprofiler.dp_logging","dataprofiler.labelers","dataprofiler.labelers.base_data_labeler","dataprofiler.labelers.base_model","dataprofiler.labelers.char_load_tf_model","dataprofiler.labelers.character_level_cnn_model","dataprofiler.labelers.classification_report_utils","dataprofiler.labelers.column_name_model","dataprofiler.labelers.data_labelers","dataprofiler.labelers.data_processing","dataprofiler.labelers.labeler_utils","dataprofiler.labelers.regex_model","dataprofiler.labelers.utils","dataprofiler.profilers","dataprofiler.profilers.base_column_profilers","dataprofiler.profilers.categorical_column_profile","dataprofiler.profilers.column_profile_compilers","dataprofiler.profilers.data_labeler_column_profile","dataprofiler.profilers.datetime_column_profile","dataprofiler.profilers.float_column_profile","dataprofiler.profilers.graph_profiler","dataprofiler.profilers.helpers","dataprofiler.profilers.helpers.report_helpers","dataprofiler.profilers.histogram_utils","dataprofiler.profilers.int_column_profile","dataprofiler.profilers.json_decoder","dataprofiler.profilers.json_encoder","dataprofiler.profilers.numerical_column_stats","dataprofiler.profilers.order_column_profile","dataprofiler.profilers.profile_builder","dataprofiler.profilers.profiler_options","dataprofiler.profilers.profiler_utils","dataprofiler.profilers.text_column_profile","dataprofiler.profilers.unstructured_labeler_profile","dataprofiler.profilers.unstructured_text_profile","dataprofiler.profilers.utils","dataprofiler.reports","dataprofiler.reports.graphs","dataprofiler.reports.utils","dataprofiler.rng_utils","dataprofiler.settings","dataprofiler.validators","dataprofiler.validators.base_validators","dataprofiler.version","examples","graph_data_demo","graphs","index","install","labeler","merge_profile_list","modules","overview","popmon_dp_loader_example","profiler","profiler_example","regex_labeler_from_scratch","roadmap","unstructured_profiler_example"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.intersphinx":1,nbsphinx:3,sphinx:56},filenames:["API.rst","add_new_model_to_data_labeler.nblink","column_name_labeler_example.nblink","data_labeling.rst","data_reader.nblink","data_readers.rst","dataprofiler.rst","dataprofiler.data_readers.rst","dataprofiler.data_readers.avro_data.rst","dataprofiler.data_readers.base_data.rst","dataprofiler.data_readers.csv_data.rst","dataprofiler.data_readers.data.rst","dataprofiler.data_readers.data_utils.rst","dataprofiler.data_readers.filepath_or_buffer.rst","dataprofiler.data_readers.graph_data.rst","dataprofiler.data_readers.json_data.rst","dataprofiler.data_readers.parquet_data.rst","dataprofiler.data_readers.structured_mixins.rst","dataprofiler.data_readers.text_data.rst","dataprofiler.dp_logging.rst","dataprofiler.labelers.rst","dataprofiler.labelers.base_data_labeler.rst","dataprofiler.labelers.base_model.rst","dataprofiler.labelers.char_load_tf_model.rst","dataprofiler.labelers.character_level_cnn_model.rst","dataprofiler.labelers.classification_report_utils.rst","dataprofiler.labelers.column_name_model.rst","dataprofiler.labelers.data_labelers.rst","dataprofiler.labelers.data_processing.rst","dataprofiler.labelers.labeler_utils.rst","dataprofiler.labelers.regex_model.rst","dataprofiler.labelers.utils.rst","dataprofiler.profilers.rst","dataprofiler.profilers.base_column_profilers.rst","dataprofiler.profilers.categorical_column_profile.rst","dataprofiler.profilers.column_profile_compilers.rst","dataprofiler.profilers.data_labeler_column_profile.rst","dataprofiler.profilers.datetime_column_profile.rst","dataprofiler.profilers.float_column_profile.rst","dataprofiler.profilers.graph_profiler.rst","dataprofiler.profilers.helpers.rst","dataprofiler.profilers.helpers.report_helpers.rst","dataprofiler.profilers.histogram_utils.rst","dataprofiler.profilers.int_column_profile.rst","dataprofiler.profilers.json_decoder.rst","dataprofiler.profilers.json_encoder.rst","dataprofiler.profilers.numerical_column_stats.rst","dataprofiler.profilers.order_column_profile.rst","dataprofiler.profilers.profile_builder.rst","dataprofiler.profilers.profiler_options.rst","dataprofiler.profilers.profiler_utils.rst","dataprofiler.profilers.text_column_profile.rst","dataprofiler.profilers.unstructured_labeler_profile.rst","dataprofiler.profilers.unstructured_text_profile.rst","dataprofiler.profilers.utils.rst","dataprofiler.reports.rst","dataprofiler.reports.graphs.rst","dataprofiler.reports.utils.rst","dataprofiler.rng_utils.rst","dataprofiler.settings.rst","dataprofiler.validators.rst","dataprofiler.validators.base_validators.rst","dataprofiler.version.rst","examples.rst","graph_data_demo.nblink","graphs.rst","index.rst","install.rst","labeler.nblink","merge_profile_list.nblink","modules.rst","overview.nblink","popmon_dp_loader_example.nblink","profiler.rst","profiler_example.nblink","regex_labeler_from_scratch.nblink","roadmap.rst","unstructured_profiler_example.nblink"],objects:{"":{dataprofiler:[6,0,0,"-"]},"dataprofiler.data_readers":{avro_data:[8,0,0,"-"],base_data:[9,0,0,"-"],csv_data:[10,0,0,"-"],data:[11,0,0,"-"],data_utils:[12,0,0,"-"],filepath_or_buffer:[13,0,0,"-"],graph_data:[14,0,0,"-"],json_data:[15,0,0,"-"],parquet_data:[16,0,0,"-"],structured_mixins:[17,0,0,"-"],text_data:[18,0,0,"-"]},"dataprofiler.data_readers.avro_data":{AVROData:[8,1,1,""]},"dataprofiler.data_readers.avro_data.AVROData":{data:[8,2,1,""],data_and_metadata:[8,2,1,""],data_format:[8,2,1,""],data_type:[8,3,1,""],file_encoding:[8,2,1,""],get_batch_generator:[8,4,1,""],info:[8,3,1,""],is_match:[8,4,1,""],is_structured:[8,2,1,""],length:[8,2,1,""],metadata:[8,2,1,""],reload:[8,4,1,""],selected_keys:[8,2,1,""]},"dataprofiler.data_readers.base_data":{BaseData:[9,1,1,""]},"dataprofiler.data_readers.base_data.BaseData":{data:[9,2,1,""],data_format:[9,2,1,""],data_type:[9,3,1,""],file_encoding:[9,2,1,""],get_batch_generator:[9,4,1,""],info:[9,3,1,""],is_match:[9,4,1,""],is_structured:[9,2,1,""],length:[9,2,1,""],reload:[9,4,1,""]},"dataprofiler.data_readers.csv_data":{CSVData:[10,1,1,""]},"dataprofiler.data_readers.csv_data.CSVData":{data:[10,2,1,""],data_format:[10,2,1,""],data_type:[10,3,1,""],delimiter:[10,2,1,""],file_encoding:[10,2,1,""],get_batch_generator:[10,4,1,""],header:[10,2,1,""],info:[10,3,1,""],is_match:[10,4,1,""],is_structured:[10,2,1,""],length:[10,2,1,""],options:[10,3,1,""],quotechar:[10,2,1,""],reload:[10,4,1,""],sample_nrows:[10,2,1,""],selected_columns:[10,2,1,""]},"dataprofiler.data_readers.data":{Data:[11,1,1,""]},"dataprofiler.data_readers.data.Data":{data_classes:[11,3,1,""]},"dataprofiler.data_readers.data_utils":{convert_int_to_string:[12,5,1,""],data_generator:[12,5,1,""],detect_cell_type:[12,5,1,""],detect_file_encoding:[12,5,1,""],find_nth_loc:[12,5,1,""],generator_on_file:[12,5,1,""],get_delimiter_regex:[12,5,1,""],is_valid_url:[12,5,1,""],json_to_dataframe:[12,5,1,""],load_as_str_from_file:[12,5,1,""],read_csv_df:[12,5,1,""],read_json:[12,5,1,""],read_json_df:[12,5,1,""],read_parquet_df:[12,5,1,""],read_text_as_list_of_strs:[12,5,1,""],reservoir:[12,5,1,""],rsample:[12,5,1,""],unicode_to_str:[12,5,1,""],url_to_bytes:[12,5,1,""]},"dataprofiler.data_readers.filepath_or_buffer":{FileOrBufferHandler:[13,1,1,""],is_stream_buffer:[13,5,1,""]},"dataprofiler.data_readers.graph_data":{GraphData:[14,1,1,""]},"dataprofiler.data_readers.graph_data.GraphData":{check_integer:[14,4,1,""],csv_column_names:[14,4,1,""],data:[14,2,1,""],data_format:[14,2,1,""],data_type:[14,3,1,""],file_encoding:[14,2,1,""],get_batch_generator:[14,4,1,""],info:[14,3,1,""],is_match:[14,4,1,""],is_structured:[14,2,1,""],length:[14,2,1,""],options:[14,3,1,""],reload:[14,4,1,""]},"dataprofiler.data_readers.json_data":{JSONData:[15,1,1,""]},"dataprofiler.data_readers.json_data.JSONData":{data:[15,2,1,""],data_and_metadata:[15,2,1,""],data_format:[15,2,1,""],data_type:[15,3,1,""],file_encoding:[15,2,1,""],get_batch_generator:[15,4,1,""],info:[15,3,1,""],is_match:[15,4,1,""],is_structured:[15,2,1,""],length:[15,2,1,""],metadata:[15,2,1,""],options:[15,3,1,""],reload:[15,4,1,""],selected_keys:[15,2,1,""]},"dataprofiler.data_readers.parquet_data":{ParquetData:[16,1,1,""]},"dataprofiler.data_readers.parquet_data.ParquetData":{data:[16,2,1,""],data_format:[16,2,1,""],data_type:[16,3,1,""],file_encoding:[16,2,1,""],get_batch_generator:[16,4,1,""],info:[16,3,1,""],is_match:[16,4,1,""],is_structured:[16,2,1,""],length:[16,2,1,""],options:[16,3,1,""],reload:[16,4,1,""],selected_columns:[16,2,1,""]},"dataprofiler.data_readers.structured_mixins":{SpreadSheetDataMixin:[17,1,1,""]},"dataprofiler.data_readers.text_data":{TextData:[18,1,1,""]},"dataprofiler.data_readers.text_data.TextData":{data:[18,2,1,""],data_format:[18,2,1,""],data_type:[18,3,1,""],file_encoding:[18,2,1,""],get_batch_generator:[18,4,1,""],info:[18,3,1,""],is_match:[18,4,1,""],is_structured:[18,2,1,""],length:[18,2,1,""],options:[18,3,1,""],reload:[18,4,1,""],samples_per_line:[18,2,1,""],tokenize:[18,4,1,""]},"dataprofiler.dp_logging":{get_child_logger:[19,5,1,""],get_logger:[19,5,1,""],set_verbosity:[19,5,1,""]},"dataprofiler.labelers":{base_data_labeler:[21,0,0,"-"],base_model:[22,0,0,"-"],char_load_tf_model:[23,0,0,"-"],character_level_cnn_model:[24,0,0,"-"],classification_report_utils:[25,0,0,"-"],column_name_model:[26,0,0,"-"],data_labelers:[27,0,0,"-"],data_processing:[28,0,0,"-"],labeler_utils:[29,0,0,"-"],regex_model:[30,0,0,"-"],utils:[31,0,0,"-"]},"dataprofiler.labelers.base_data_labeler":{BaseDataLabeler:[21,1,1,""],TrainableDataLabeler:[21,1,1,""]},"dataprofiler.labelers.base_data_labeler.BaseDataLabeler":{add_label:[21,4,1,""],check_pipeline:[21,4,1,""],help:[21,4,1,""],label_mapping:[21,2,1,""],labels:[21,2,1,""],load_from_disk:[21,4,1,""],load_from_library:[21,4,1,""],load_with_components:[21,4,1,""],model:[21,2,1,""],postprocessor:[21,2,1,""],predict:[21,4,1,""],preprocessor:[21,2,1,""],reverse_label_mapping:[21,2,1,""],save_to_disk:[21,4,1,""],set_labels:[21,4,1,""],set_model:[21,4,1,""],set_params:[21,4,1,""],set_postprocessor:[21,4,1,""],set_preprocessor:[21,4,1,""]},"dataprofiler.labelers.base_data_labeler.TrainableDataLabeler":{add_label:[21,4,1,""],check_pipeline:[21,4,1,""],fit:[21,4,1,""],help:[21,4,1,""],label_mapping:[21,2,1,""],labels:[21,2,1,""],load_from_disk:[21,4,1,""],load_from_library:[21,4,1,""],load_with_components:[21,4,1,""],model:[21,2,1,""],postprocessor:[21,2,1,""],predict:[21,4,1,""],preprocessor:[21,2,1,""],reverse_label_mapping:[21,2,1,""],save_to_disk:[21,4,1,""],set_labels:[21,4,1,""],set_model:[21,4,1,""],set_params:[21,4,1,""],set_postprocessor:[21,4,1,""],set_preprocessor:[21,4,1,""]},"dataprofiler.labelers.base_model":{AutoSubRegistrationMeta:[22,1,1,""],BaseModel:[22,1,1,""],BaseTrainableModel:[22,1,1,""]},"dataprofiler.labelers.base_model.AutoSubRegistrationMeta":{mro:[22,4,1,""],register:[22,4,1,""]},"dataprofiler.labelers.base_model.BaseModel":{add_label:[22,4,1,""],get_class:[22,4,1,""],get_parameters:[22,4,1,""],help:[22,4,1,""],label_mapping:[22,2,1,""],labels:[22,2,1,""],load_from_disk:[22,4,1,""],num_labels:[22,2,1,""],predict:[22,4,1,""],requires_zero_mapping:[22,3,1,""],reset_weights:[22,4,1,""],reverse_label_mapping:[22,2,1,""],save_to_disk:[22,4,1,""],set_label_mapping:[22,4,1,""],set_params:[22,4,1,""]},"dataprofiler.labelers.base_model.BaseTrainableModel":{add_label:[22,4,1,""],fit:[22,4,1,""],get_class:[22,4,1,""],get_parameters:[22,4,1,""],help:[22,4,1,""],label_mapping:[22,2,1,""],labels:[22,2,1,""],load_from_disk:[22,4,1,""],num_labels:[22,2,1,""],predict:[22,4,1,""],requires_zero_mapping:[22,3,1,""],reset_weights:[22,4,1,""],reverse_label_mapping:[22,2,1,""],save_to_disk:[22,4,1,""],set_label_mapping:[22,4,1,""],set_params:[22,4,1,""]},"dataprofiler.labelers.char_load_tf_model":{CharLoadTFModel:[23,1,1,""]},"dataprofiler.labelers.char_load_tf_model.CharLoadTFModel":{add_label:[23,4,1,""],details:[23,4,1,""],fit:[23,4,1,""],get_class:[23,4,1,""],get_parameters:[23,4,1,""],help:[23,4,1,""],label_mapping:[23,2,1,""],labels:[23,2,1,""],load_from_disk:[23,4,1,""],num_labels:[23,2,1,""],predict:[23,4,1,""],requires_zero_mapping:[23,3,1,""],reset_weights:[23,4,1,""],reverse_label_mapping:[23,2,1,""],save_to_disk:[23,4,1,""],set_label_mapping:[23,4,1,""],set_params:[23,4,1,""]},"dataprofiler.labelers.character_level_cnn_model":{CharacterLevelCnnModel:[24,1,1,""],build_embd_dictionary:[24,5,1,""],create_glove_char:[24,5,1,""]},"dataprofiler.labelers.character_level_cnn_model.CharacterLevelCnnModel":{add_label:[24,4,1,""],details:[24,4,1,""],fit:[24,4,1,""],get_class:[24,4,1,""],get_parameters:[24,4,1,""],help:[24,4,1,""],label_mapping:[24,2,1,""],labels:[24,2,1,""],load_from_disk:[24,4,1,""],num_labels:[24,2,1,""],predict:[24,4,1,""],requires_zero_mapping:[24,3,1,""],reset_weights:[24,4,1,""],reverse_label_mapping:[24,2,1,""],save_to_disk:[24,4,1,""],set_label_mapping:[24,4,1,""],set_params:[24,4,1,""]},"dataprofiler.labelers.classification_report_utils":{classification_report:[25,5,1,""],convert_confusion_matrix_to_MCM:[25,5,1,""],precision_recall_fscore_support:[25,5,1,""]},"dataprofiler.labelers.column_name_model":{ColumnNameModel:[26,1,1,""]},"dataprofiler.labelers.column_name_model.ColumnNameModel":{add_label:[26,4,1,""],get_class:[26,4,1,""],get_parameters:[26,4,1,""],help:[26,4,1,""],label_mapping:[26,2,1,""],labels:[26,2,1,""],load_from_disk:[26,4,1,""],num_labels:[26,2,1,""],predict:[26,4,1,""],requires_zero_mapping:[26,3,1,""],reset_weights:[26,4,1,""],reverse_label_mapping:[26,2,1,""],save_to_disk:[26,4,1,""],set_label_mapping:[26,4,1,""],set_params:[26,4,1,""]},"dataprofiler.labelers.data_labelers":{DataLabeler:[27,1,1,""],StructuredDataLabeler:[27,1,1,""],UnstructuredDataLabeler:[27,1,1,""],train_structured_labeler:[27,5,1,""]},"dataprofiler.labelers.data_labelers.DataLabeler":{labeler_classes:[27,3,1,""],load_from_disk:[27,4,1,""],load_from_library:[27,4,1,""],load_with_components:[27,4,1,""]},"dataprofiler.labelers.data_labelers.StructuredDataLabeler":{add_label:[27,4,1,""],check_pipeline:[27,4,1,""],help:[27,4,1,""],label_mapping:[27,2,1,""],labels:[27,2,1,""],load_from_disk:[27,4,1,""],load_from_library:[27,4,1,""],load_with_components:[27,4,1,""],model:[27,2,1,""],postprocessor:[27,2,1,""],predict:[27,4,1,""],preprocessor:[27,2,1,""],reverse_label_mapping:[27,2,1,""],save_to_disk:[27,4,1,""],set_labels:[27,4,1,""],set_model:[27,4,1,""],set_params:[27,4,1,""],set_postprocessor:[27,4,1,""],set_preprocessor:[27,4,1,""]},"dataprofiler.labelers.data_labelers.UnstructuredDataLabeler":{add_label:[27,4,1,""],check_pipeline:[27,4,1,""],help:[27,4,1,""],label_mapping:[27,2,1,""],labels:[27,2,1,""],load_from_disk:[27,4,1,""],load_from_library:[27,4,1,""],load_with_components:[27,4,1,""],model:[27,2,1,""],postprocessor:[27,2,1,""],predict:[27,4,1,""],preprocessor:[27,2,1,""],reverse_label_mapping:[27,2,1,""],save_to_disk:[27,4,1,""],set_labels:[27,4,1,""],set_model:[27,4,1,""],set_params:[27,4,1,""],set_postprocessor:[27,4,1,""],set_preprocessor:[27,4,1,""]},"dataprofiler.labelers.data_processing":{AutoSubRegistrationMeta:[28,1,1,""],BaseDataPostprocessor:[28,1,1,""],BaseDataPreprocessor:[28,1,1,""],BaseDataProcessor:[28,1,1,""],CharEncodedPreprocessor:[28,1,1,""],CharPostprocessor:[28,1,1,""],CharPreprocessor:[28,1,1,""],ColumnNameModelPostprocessor:[28,1,1,""],DirectPassPreprocessor:[28,1,1,""],RegexPostProcessor:[28,1,1,""],StructCharPostprocessor:[28,1,1,""],StructCharPreprocessor:[28,1,1,""],StructRegexPostProcessor:[28,1,1,""]},"dataprofiler.labelers.data_processing.AutoSubRegistrationMeta":{mro:[28,4,1,""],register:[28,4,1,""]},"dataprofiler.labelers.data_processing.BaseDataPostprocessor":{get_class:[28,4,1,""],get_parameters:[28,4,1,""],help:[28,4,1,""],load_from_disk:[28,4,1,""],load_from_library:[28,4,1,""],process:[28,4,1,""],processor_type:[28,3,1,""],save_to_disk:[28,4,1,""],set_params:[28,4,1,""]},"dataprofiler.labelers.data_processing.BaseDataPreprocessor":{get_class:[28,4,1,""],get_parameters:[28,4,1,""],help:[28,4,1,""],load_from_disk:[28,4,1,""],load_from_library:[28,4,1,""],process:[28,4,1,""],processor_type:[28,3,1,""],save_to_disk:[28,4,1,""],set_params:[28,4,1,""]},"dataprofiler.labelers.data_processing.BaseDataProcessor":{get_class:[28,4,1,""],get_parameters:[28,4,1,""],help:[28,4,1,""],load_from_disk:[28,4,1,""],load_from_library:[28,4,1,""],process:[28,4,1,""],processor_type:[28,3,1,""],save_to_disk:[28,4,1,""],set_params:[28,4,1,""]},"dataprofiler.labelers.data_processing.CharEncodedPreprocessor":{get_class:[28,4,1,""],get_parameters:[28,4,1,""],help:[28,4,1,""],load_from_disk:[28,4,1,""],load_from_library:[28,4,1,""],process:[28,4,1,""],processor_type:[28,3,1,""],save_to_disk:[28,4,1,""],set_params:[28,4,1,""]},"dataprofiler.labelers.data_processing.CharPostprocessor":{convert_to_NER_format:[28,4,1,""],get_class:[28,4,1,""],get_parameters:[28,4,1,""],help:[28,4,1,""],load_from_disk:[28,4,1,""],load_from_library:[28,4,1,""],match_sentence_lengths:[28,4,1,""],process:[28,4,1,""],processor_type:[28,3,1,""],save_to_disk:[28,4,1,""],set_params:[28,4,1,""]},"dataprofiler.labelers.data_processing.CharPreprocessor":{get_class:[28,4,1,""],get_parameters:[28,4,1,""],help:[28,4,1,""],load_from_disk:[28,4,1,""],load_from_library:[28,4,1,""],process:[28,4,1,""],processor_type:[28,3,1,""],save_to_disk:[28,4,1,""],set_params:[28,4,1,""]},"dataprofiler.labelers.data_processing.ColumnNameModelPostprocessor":{get_class:[28,4,1,""],get_parameters:[28,4,1,""],help:[28,4,1,""],load_from_disk:[28,4,1,""],load_from_library:[28,4,1,""],process:[28,4,1,""],processor_type:[28,3,1,""],save_to_disk:[28,4,1,""],set_params:[28,4,1,""]},"dataprofiler.labelers.data_processing.DirectPassPreprocessor":{get_class:[28,4,1,""],get_parameters:[28,4,1,""],help:[28,4,1,""],load_from_disk:[28,4,1,""],load_from_library:[28,4,1,""],process:[28,4,1,""],processor_type:[28,3,1,""],save_to_disk:[28,4,1,""],set_params:[28,4,1,""]},"dataprofiler.labelers.data_processing.RegexPostProcessor":{get_class:[28,4,1,""],get_parameters:[28,4,1,""],help:[28,4,1,""],load_from_disk:[28,4,1,""],load_from_library:[28,4,1,""],priority_prediction:[28,4,1,""],process:[28,4,1,""],processor_type:[28,3,1,""],save_to_disk:[28,4,1,""],set_params:[28,4,1,""],split_prediction:[28,4,1,""]},"dataprofiler.labelers.data_processing.StructCharPostprocessor":{convert_to_structured_analysis:[28,4,1,""],get_class:[28,4,1,""],get_parameters:[28,4,1,""],help:[28,4,1,""],load_from_disk:[28,4,1,""],load_from_library:[28,4,1,""],match_sentence_lengths:[28,4,1,""],process:[28,4,1,""],processor_type:[28,3,1,""],save_to_disk:[28,4,1,""],set_params:[28,4,1,""]},"dataprofiler.labelers.data_processing.StructCharPreprocessor":{convert_to_unstructured_format:[28,4,1,""],get_class:[28,4,1,""],get_parameters:[28,4,1,""],help:[28,4,1,""],load_from_disk:[28,4,1,""],load_from_library:[28,4,1,""],process:[28,4,1,""],processor_type:[28,3,1,""],save_to_disk:[28,4,1,""],set_params:[28,4,1,""]},"dataprofiler.labelers.data_processing.StructRegexPostProcessor":{get_class:[28,4,1,""],get_parameters:[28,4,1,""],help:[28,4,1,""],load_from_disk:[28,4,1,""],load_from_library:[28,4,1,""],process:[28,4,1,""],processor_type:[28,3,1,""],save_to_disk:[28,4,1,""],set_params:[28,4,1,""]},"dataprofiler.labelers.labeler_utils":{F1Score:[29,1,1,""],FBetaScore:[29,1,1,""],evaluate_accuracy:[29,5,1,""],f1_report_dict_to_str:[29,5,1,""],get_tf_layer_index_from_name:[29,5,1,""],hide_tf_logger_warnings:[29,5,1,""],protected_register_keras_serializable:[29,5,1,""]},"dataprofiler.labelers.labeler_utils.F1Score":{activity_regularizer:[29,2,1,""],add_loss:[29,4,1,""],add_metric:[29,4,1,""],add_update:[29,4,1,""],add_variable:[29,4,1,""],add_weight:[29,4,1,""],build:[29,4,1,""],build_from_config:[29,4,1,""],call:[29,4,1,""],compute_dtype:[29,2,1,""],compute_mask:[29,4,1,""],compute_output_shape:[29,4,1,""],compute_output_signature:[29,4,1,""],count_params:[29,4,1,""],dtype:[29,2,1,""],dtype_policy:[29,2,1,""],dynamic:[29,2,1,""],finalize_state:[29,4,1,""],from_config:[29,4,1,""],get_build_config:[29,4,1,""],get_config:[29,4,1,""],get_input_at:[29,4,1,""],get_input_mask_at:[29,4,1,""],get_input_shape_at:[29,4,1,""],get_output_at:[29,4,1,""],get_output_mask_at:[29,4,1,""],get_output_shape_at:[29,4,1,""],get_weights:[29,4,1,""],inbound_nodes:[29,2,1,""],input:[29,2,1,""],input_mask:[29,2,1,""],input_shape:[29,2,1,""],input_spec:[29,2,1,""],load_own_variables:[29,4,1,""],losses:[29,2,1,""],merge_state:[29,4,1,""],metrics:[29,2,1,""],name:[29,2,1,""],name_scope:[29,2,1,""],non_trainable_variables:[29,2,1,""],non_trainable_weights:[29,2,1,""],outbound_nodes:[29,2,1,""],output:[29,2,1,""],output_mask:[29,2,1,""],output_shape:[29,2,1,""],reset_state:[29,4,1,""],reset_states:[29,4,1,""],result:[29,4,1,""],save_own_variables:[29,4,1,""],set_weights:[29,4,1,""],stateful:[29,2,1,""],submodules:[29,2,1,""],supports_masking:[29,2,1,""],trainable:[29,2,1,""],trainable_variables:[29,2,1,""],trainable_weights:[29,2,1,""],update_state:[29,4,1,""],updates:[29,2,1,""],variable_dtype:[29,2,1,""],variables:[29,2,1,""],weights:[29,2,1,""],with_name_scope:[29,4,1,""]},"dataprofiler.labelers.labeler_utils.FBetaScore":{activity_regularizer:[29,2,1,""],add_loss:[29,4,1,""],add_metric:[29,4,1,""],add_update:[29,4,1,""],add_variable:[29,4,1,""],add_weight:[29,4,1,""],build:[29,4,1,""],build_from_config:[29,4,1,""],call:[29,4,1,""],compute_dtype:[29,2,1,""],compute_mask:[29,4,1,""],compute_output_shape:[29,4,1,""],compute_output_signature:[29,4,1,""],count_params:[29,4,1,""],dtype:[29,2,1,""],dtype_policy:[29,2,1,""],dynamic:[29,2,1,""],finalize_state:[29,4,1,""],from_config:[29,4,1,""],get_build_config:[29,4,1,""],get_config:[29,4,1,""],get_input_at:[29,4,1,""],get_input_mask_at:[29,4,1,""],get_input_shape_at:[29,4,1,""],get_output_at:[29,4,1,""],get_output_mask_at:[29,4,1,""],get_output_shape_at:[29,4,1,""],get_weights:[29,4,1,""],inbound_nodes:[29,2,1,""],input:[29,2,1,""],input_mask:[29,2,1,""],input_shape:[29,2,1,""],input_spec:[29,2,1,""],load_own_variables:[29,4,1,""],losses:[29,2,1,""],merge_state:[29,4,1,""],metrics:[29,2,1,""],name:[29,2,1,""],name_scope:[29,2,1,""],non_trainable_variables:[29,2,1,""],non_trainable_weights:[29,2,1,""],outbound_nodes:[29,2,1,""],output:[29,2,1,""],output_mask:[29,2,1,""],output_shape:[29,2,1,""],reset_state:[29,4,1,""],reset_states:[29,4,1,""],result:[29,4,1,""],save_own_variables:[29,4,1,""],set_weights:[29,4,1,""],stateful:[29,2,1,""],submodules:[29,2,1,""],supports_masking:[29,2,1,""],trainable:[29,2,1,""],trainable_variables:[29,2,1,""],trainable_weights:[29,2,1,""],update_state:[29,4,1,""],updates:[29,2,1,""],variable_dtype:[29,2,1,""],variables:[29,2,1,""],weights:[29,2,1,""],with_name_scope:[29,4,1,""]},"dataprofiler.labelers.regex_model":{RegexModel:[30,1,1,""]},"dataprofiler.labelers.regex_model.RegexModel":{add_label:[30,4,1,""],get_class:[30,4,1,""],get_parameters:[30,4,1,""],help:[30,4,1,""],label_mapping:[30,2,1,""],labels:[30,2,1,""],load_from_disk:[30,4,1,""],num_labels:[30,2,1,""],predict:[30,4,1,""],requires_zero_mapping:[30,3,1,""],reset_weights:[30,4,1,""],reverse_label_mapping:[30,2,1,""],save_to_disk:[30,4,1,""],set_label_mapping:[30,4,1,""],set_params:[30,4,1,""]},"dataprofiler.labelers.utils":{require_module:[31,5,1,""],warn_missing_module:[31,5,1,""]},"dataprofiler.profilers":{base_column_profilers:[33,0,0,"-"],categorical_column_profile:[34,0,0,"-"],column_profile_compilers:[35,0,0,"-"],data_labeler_column_profile:[36,0,0,"-"],datetime_column_profile:[37,0,0,"-"],float_column_profile:[38,0,0,"-"],graph_profiler:[39,0,0,"-"],helpers:[40,0,0,"-"],histogram_utils:[42,0,0,"-"],int_column_profile:[43,0,0,"-"],json_decoder:[44,0,0,"-"],json_encoder:[45,0,0,"-"],numerical_column_stats:[46,0,0,"-"],order_column_profile:[47,0,0,"-"],profile_builder:[48,0,0,"-"],profiler_options:[49,0,0,"-"],profiler_utils:[50,0,0,"-"],text_column_profile:[51,0,0,"-"],unstructured_labeler_profile:[52,0,0,"-"],unstructured_text_profile:[53,0,0,"-"]},"dataprofiler.profilers.base_column_profilers":{BaseColumnPrimitiveTypeProfiler:[33,1,1,""],BaseColumnProfiler:[33,1,1,""]},"dataprofiler.profilers.base_column_profilers.BaseColumnPrimitiveTypeProfiler":{col_type:[33,3,1,""],diff:[33,4,1,""],load_from_dict:[33,4,1,""],metadata:[33,3,1,""],name:[33,3,1,""],profile:[33,2,1,""],report:[33,4,1,""],sample_size:[33,3,1,""],thread_safe:[33,3,1,""],times:[33,3,1,""],update:[33,4,1,""]},"dataprofiler.profilers.base_column_profilers.BaseColumnProfiler":{col_type:[33,3,1,""],diff:[33,4,1,""],load_from_dict:[33,4,1,""],profile:[33,2,1,""],report:[33,4,1,""],update:[33,4,1,""]},"dataprofiler.profilers.categorical_column_profile":{CategoricalColumn:[34,1,1,""]},"dataprofiler.profilers.categorical_column_profile.CategoricalColumn":{categorical_counts:[34,2,1,""],categories:[34,2,1,""],col_type:[34,3,1,""],diff:[34,4,1,""],gini_impurity:[34,2,1,""],is_match:[34,2,1,""],load_from_dict:[34,4,1,""],metadata:[34,3,1,""],name:[34,3,1,""],profile:[34,2,1,""],report:[34,4,1,""],sample_size:[34,3,1,""],thread_safe:[34,3,1,""],times:[34,3,1,""],type:[34,3,1,""],unalikeability:[34,2,1,""],unique_count:[34,2,1,""],unique_ratio:[34,2,1,""],update:[34,4,1,""]},"dataprofiler.profilers.column_profile_compilers":{BaseCompiler:[35,1,1,""],ColumnDataLabelerCompiler:[35,1,1,""],ColumnPrimitiveTypeProfileCompiler:[35,1,1,""],ColumnStatsProfileCompiler:[35,1,1,""],UnstructuredCompiler:[35,1,1,""]},"dataprofiler.profilers.column_profile_compilers.BaseCompiler":{diff:[35,4,1,""],load_from_dict:[35,4,1,""],profile:[35,2,1,""],report:[35,4,1,""],update_profile:[35,4,1,""]},"dataprofiler.profilers.column_profile_compilers.ColumnDataLabelerCompiler":{diff:[35,4,1,""],load_from_dict:[35,4,1,""],profile:[35,2,1,""],report:[35,4,1,""],update_profile:[35,4,1,""]},"dataprofiler.profilers.column_profile_compilers.ColumnPrimitiveTypeProfileCompiler":{diff:[35,4,1,""],load_from_dict:[35,4,1,""],profile:[35,2,1,""],report:[35,4,1,""],selected_data_type:[35,2,1,""],update_profile:[35,4,1,""]},"dataprofiler.profilers.column_profile_compilers.ColumnStatsProfileCompiler":{diff:[35,4,1,""],load_from_dict:[35,4,1,""],profile:[35,2,1,""],report:[35,4,1,""],update_profile:[35,4,1,""]},"dataprofiler.profilers.column_profile_compilers.UnstructuredCompiler":{diff:[35,4,1,""],load_from_dict:[35,4,1,""],profile:[35,2,1,""],report:[35,4,1,""],update_profile:[35,4,1,""]},"dataprofiler.profilers.data_labeler_column_profile":{DataLabelerColumn:[36,1,1,""]},"dataprofiler.profilers.data_labeler_column_profile.DataLabelerColumn":{assert_equal_conditions:[36,4,1,""],avg_predictions:[36,2,1,""],col_type:[36,3,1,""],data_label:[36,2,1,""],diff:[36,4,1,""],label_representation:[36,2,1,""],load_from_dict:[36,4,1,""],metadata:[36,3,1,""],name:[36,3,1,""],possible_data_labels:[36,2,1,""],profile:[36,2,1,""],rank_distribution:[36,2,1,""],report:[36,4,1,""],reverse_label_mapping:[36,2,1,""],sample_size:[36,3,1,""],sum_predictions:[36,2,1,""],thread_safe:[36,3,1,""],times:[36,3,1,""],type:[36,3,1,""],update:[36,4,1,""]},"dataprofiler.profilers.datetime_column_profile":{DateTimeColumn:[37,1,1,""]},"dataprofiler.profilers.datetime_column_profile.DateTimeColumn":{col_type:[37,3,1,""],data_type_ratio:[37,2,1,""],diff:[37,4,1,""],load_from_dict:[37,4,1,""],match_count:[37,3,1,""],metadata:[37,3,1,""],name:[37,3,1,""],profile:[37,2,1,""],report:[37,4,1,""],sample_size:[37,3,1,""],thread_safe:[37,3,1,""],times:[37,3,1,""],type:[37,3,1,""],update:[37,4,1,""]},"dataprofiler.profilers.float_column_profile":{FloatColumn:[38,1,1,""]},"dataprofiler.profilers.float_column_profile.FloatColumn":{col_type:[38,3,1,""],data_type_ratio:[38,2,1,""],diff:[38,4,1,""],is_float:[38,4,1,""],is_int:[38,4,1,""],kurtosis:[38,2,1,""],load_from_dict:[38,4,1,""],match_count:[38,3,1,""],mean:[38,2,1,""],median:[38,2,1,""],median_abs_deviation:[38,2,1,""],metadata:[38,3,1,""],mode:[38,2,1,""],name:[38,3,1,""],np_type_to_type:[38,4,1,""],precision:[38,2,1,""],profile:[38,2,1,""],report:[38,4,1,""],sample_size:[38,3,1,""],skewness:[38,2,1,""],stddev:[38,2,1,""],thread_safe:[38,3,1,""],times:[38,3,1,""],type:[38,3,1,""],update:[38,4,1,""],variance:[38,2,1,""]},"dataprofiler.profilers.graph_profiler":{GraphProfiler:[39,1,1,""]},"dataprofiler.profilers.graph_profiler.GraphProfiler":{diff:[39,4,1,""],load:[39,4,1,""],profile:[39,2,1,""],report:[39,4,1,""],save:[39,4,1,""],times:[39,3,1,""],update:[39,4,1,""]},"dataprofiler.profilers.helpers":{calculate_quantiles:[40,5,1,""],report_helpers:[41,0,0,"-"]},"dataprofiler.profilers.helpers.report_helpers":{calculate_quantiles:[41,5,1,""],flat_dict:[41,5,1,""]},"dataprofiler.profilers.int_column_profile":{IntColumn:[43,1,1,""]},"dataprofiler.profilers.int_column_profile.IntColumn":{col_type:[43,3,1,""],data_type_ratio:[43,2,1,""],diff:[43,4,1,""],is_float:[43,4,1,""],is_int:[43,4,1,""],kurtosis:[43,2,1,""],load_from_dict:[43,4,1,""],match_count:[43,3,1,""],mean:[43,2,1,""],median:[43,2,1,""],median_abs_deviation:[43,2,1,""],metadata:[43,3,1,""],mode:[43,2,1,""],name:[43,3,1,""],np_type_to_type:[43,4,1,""],profile:[43,2,1,""],report:[43,4,1,""],sample_size:[43,3,1,""],skewness:[43,2,1,""],stddev:[43,2,1,""],thread_safe:[43,3,1,""],times:[43,3,1,""],type:[43,3,1,""],update:[43,4,1,""],variance:[43,2,1,""]},"dataprofiler.profilers.json_decoder":{get_column_profiler_class:[44,5,1,""],get_compiler_class:[44,5,1,""],get_option_class:[44,5,1,""],get_profiler_class:[44,5,1,""],get_structured_col_profiler_class:[44,5,1,""],load_column_profile:[44,5,1,""],load_compiler:[44,5,1,""],load_option:[44,5,1,""],load_profiler:[44,5,1,""],load_structured_col_profiler:[44,5,1,""]},"dataprofiler.profilers.json_encoder":{ProfileEncoder:[45,1,1,""]},"dataprofiler.profilers.json_encoder.ProfileEncoder":{"default":[45,4,1,""],encode:[45,4,1,""],item_separator:[45,3,1,""],iterencode:[45,4,1,""],key_separator:[45,3,1,""]},"dataprofiler.profilers.numerical_column_stats":{NumericStatsMixin:[46,1,1,""],abstractstaticmethod:[46,1,1,""]},"dataprofiler.profilers.numerical_column_stats.NumericStatsMixin":{col_type:[46,3,1,""],diff:[46,4,1,""],is_float:[46,4,1,""],is_int:[46,4,1,""],kurtosis:[46,2,1,""],load_from_dict:[46,4,1,""],mean:[46,2,1,""],median:[46,2,1,""],median_abs_deviation:[46,2,1,""],metadata:[46,3,1,""],mode:[46,2,1,""],name:[46,3,1,""],np_type_to_type:[46,4,1,""],profile:[46,4,1,""],report:[46,4,1,""],sample_size:[46,3,1,""],skewness:[46,2,1,""],stddev:[46,2,1,""],thread_safe:[46,3,1,""],times:[46,3,1,""],type:[46,3,1,""],update:[46,4,1,""],variance:[46,2,1,""]},"dataprofiler.profilers.order_column_profile":{Comparable:[47,1,1,""],OrderColumn:[47,1,1,""]},"dataprofiler.profilers.order_column_profile.OrderColumn":{col_type:[47,3,1,""],diff:[47,4,1,""],load_from_dict:[47,4,1,""],metadata:[47,3,1,""],name:[47,3,1,""],profile:[47,2,1,""],report:[47,4,1,""],sample_size:[47,3,1,""],thread_safe:[47,3,1,""],times:[47,3,1,""],type:[47,3,1,""],update:[47,4,1,""]},"dataprofiler.profilers.profile_builder":{BaseProfiler:[48,1,1,""],Profiler:[48,1,1,""],StructuredColProfiler:[48,1,1,""],StructuredProfiler:[48,1,1,""],UnstructuredProfiler:[48,1,1,""]},"dataprofiler.profilers.profile_builder.BaseProfiler":{diff:[48,4,1,""],load:[48,4,1,""],load_from_dict:[48,4,1,""],profile:[48,2,1,""],report:[48,4,1,""],save:[48,4,1,""],update_profile:[48,4,1,""]},"dataprofiler.profilers.profile_builder.Profiler":{load:[48,4,1,""]},"dataprofiler.profilers.profile_builder.StructuredColProfiler":{clean_data_and_get_base_stats:[48,4,1,""],diff:[48,4,1,""],load_from_dict:[48,4,1,""],profile:[48,2,1,""],report:[48,4,1,""],update_column_profilers:[48,4,1,""],update_profile:[48,4,1,""]},"dataprofiler.profilers.profile_builder.StructuredProfiler":{diff:[48,4,1,""],load:[48,4,1,""],load_from_dict:[48,4,1,""],profile:[48,2,1,""],report:[48,4,1,""],save:[48,4,1,""],update_profile:[48,4,1,""]},"dataprofiler.profilers.profile_builder.UnstructuredProfiler":{diff:[48,4,1,""],load:[48,4,1,""],load_from_dict:[48,4,1,""],profile:[48,2,1,""],report:[48,4,1,""],save:[48,4,1,""],update_profile:[48,4,1,""]},"dataprofiler.profilers.profiler_options":{BaseInspectorOptions:[49,1,1,""],BaseOption:[49,1,1,""],BooleanOption:[49,1,1,""],CategoricalOptions:[49,1,1,""],CorrelationOptions:[49,1,1,""],DataLabelerOptions:[49,1,1,""],DateTimeOptions:[49,1,1,""],FloatOptions:[49,1,1,""],HistogramAndQuantilesOption:[49,1,1,""],HyperLogLogOptions:[49,1,1,""],IntOptions:[49,1,1,""],ModeOption:[49,1,1,""],NumericalOptions:[49,1,1,""],OrderOptions:[49,1,1,""],PrecisionOptions:[49,1,1,""],ProfilerOptions:[49,1,1,""],RowStatisticsOptions:[49,1,1,""],StructuredOptions:[49,1,1,""],TextOptions:[49,1,1,""],TextProfilerOptions:[49,1,1,""],UniqueCountOptions:[49,1,1,""],UnstructuredOptions:[49,1,1,""]},"dataprofiler.profilers.profiler_options.BaseInspectorOptions":{is_prop_enabled:[49,4,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.BaseOption":{load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.BooleanOption":{load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.CategoricalOptions":{is_prop_enabled:[49,4,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.CorrelationOptions":{is_prop_enabled:[49,4,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.DataLabelerOptions":{is_prop_enabled:[49,4,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.DateTimeOptions":{is_prop_enabled:[49,4,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.FloatOptions":{is_numeric_stats_enabled:[49,2,1,""],is_prop_enabled:[49,4,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.HistogramAndQuantilesOption":{load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.HyperLogLogOptions":{load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.IntOptions":{is_numeric_stats_enabled:[49,2,1,""],is_prop_enabled:[49,4,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.ModeOption":{load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.NumericalOptions":{is_numeric_stats_enabled:[49,2,1,""],is_prop_enabled:[49,4,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.OrderOptions":{is_prop_enabled:[49,4,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.PrecisionOptions":{load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.ProfilerOptions":{load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.RowStatisticsOptions":{load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.StructuredOptions":{enabled_profiles:[49,2,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.TextOptions":{is_numeric_stats_enabled:[49,2,1,""],is_prop_enabled:[49,4,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.TextProfilerOptions":{is_prop_enabled:[49,4,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.UniqueCountOptions":{load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_options.UnstructuredOptions":{enabled_profiles:[49,2,1,""],load_from_dict:[49,4,1,""],properties:[49,2,1,""],set:[49,4,1,""],validate:[49,4,1,""]},"dataprofiler.profilers.profiler_utils":{KeyDict:[50,1,1,""],Subtractable:[50,1,1,""],add_nested_dictionaries:[50,5,1,""],auto_multiprocess_toggle:[50,5,1,""],biased_kurt:[50,5,1,""],biased_skew:[50,5,1,""],chunk:[50,5,1,""],find_diff_of_dates:[50,5,1,""],find_diff_of_dicts:[50,5,1,""],find_diff_of_dicts_with_diff_keys:[50,5,1,""],find_diff_of_lists_and_sets:[50,5,1,""],find_diff_of_matrices:[50,5,1,""],find_diff_of_numbers:[50,5,1,""],find_diff_of_strings_and_bools:[50,5,1,""],generate_pool:[50,5,1,""],get_memory_size:[50,5,1,""],merge:[50,5,1,""],merge_profile_list:[50,5,1,""],method_timeit:[50,5,1,""],overlap:[50,5,1,""],partition:[50,5,1,""],perform_chi_squared_test_for_homogeneity:[50,5,1,""],recursive_dict_update:[50,5,1,""],reload_labeler_from_options_or_get_new:[50,5,1,""],shuffle_in_chunks:[50,5,1,""],suggest_pool_size:[50,5,1,""],warn_on_profile:[50,5,1,""]},"dataprofiler.profilers.profiler_utils.KeyDict":{clear:[50,4,1,""],copy:[50,4,1,""],default_factory:[50,3,1,""],fromkeys:[50,4,1,""],get:[50,4,1,""],items:[50,4,1,""],keys:[50,4,1,""],pop:[50,4,1,""],popitem:[50,4,1,""],setdefault:[50,4,1,""],update:[50,4,1,""],values:[50,4,1,""]},"dataprofiler.profilers.text_column_profile":{TextColumn:[51,1,1,""]},"dataprofiler.profilers.text_column_profile.TextColumn":{bias_correction:[51,3,1,""],col_type:[51,3,1,""],data_type_ratio:[51,2,1,""],diff:[51,4,1,""],histogram_bin_method_names:[51,3,1,""],histogram_methods:[51,3,1,""],histogram_selection:[51,3,1,""],is_float:[51,4,1,""],is_int:[51,4,1,""],kurtosis:[51,2,1,""],load_from_dict:[51,4,1,""],match_count:[51,3,1,""],max:[51,3,1,""],max_histogram_bin:[51,3,1,""],mean:[51,2,1,""],median:[51,2,1,""],median_abs_deviation:[51,2,1,""],metadata:[51,3,1,""],min:[51,3,1,""],min_histogram_bin:[51,3,1,""],mode:[51,2,1,""],name:[51,3,1,""],np_type_to_type:[51,4,1,""],num_negatives:[51,3,1,""],num_zeros:[51,3,1,""],profile:[51,2,1,""],quantiles:[51,3,1,""],report:[51,4,1,""],sample_size:[51,3,1,""],skewness:[51,2,1,""],stddev:[51,2,1,""],sum:[51,3,1,""],thread_safe:[51,3,1,""],times:[51,3,1,""],type:[51,3,1,""],update:[51,4,1,""],user_set_histogram_bin:[51,3,1,""],variance:[51,2,1,""]},"dataprofiler.profilers.unstructured_labeler_profile":{UnstructuredLabelerProfile:[52,1,1,""]},"dataprofiler.profilers.unstructured_labeler_profile.UnstructuredLabelerProfile":{diff:[52,4,1,""],label_encoding:[52,2,1,""],profile:[52,2,1,""],report:[52,4,1,""],type:[52,3,1,""],update:[52,4,1,""]},"dataprofiler.profilers.unstructured_text_profile":{TextProfiler:[53,1,1,""]},"dataprofiler.profilers.unstructured_text_profile.TextProfiler":{diff:[53,4,1,""],profile:[53,2,1,""],report:[53,4,1,""],type:[53,3,1,""],update:[53,4,1,""]},"dataprofiler.reports":{graphs:[56,0,0,"-"],utils:[57,0,0,"-"]},"dataprofiler.reports.utils":{require_module:[57,5,1,""],warn_missing_module:[57,5,1,""]},"dataprofiler.rng_utils":{get_random_number_generator:[58,5,1,""]},"dataprofiler.validators":{base_validators:[61,0,0,"-"]},"dataprofiler.validators.base_validators":{Validator:[61,1,1,""],is_in_list:[61,5,1,""],is_in_range:[61,5,1,""]},"dataprofiler.validators.base_validators.Validator":{get:[61,4,1,""],validate:[61,4,1,""]},dataprofiler:{data_readers:[7,0,0,"-"],dp_logging:[19,0,0,"-"],labelers:[20,0,0,"-"],profilers:[32,0,0,"-"],reports:[55,0,0,"-"],rng_utils:[58,0,0,"-"],set_seed:[6,5,1,""],settings:[59,0,0,"-"],validators:[60,0,0,"-"],version:[62,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","property","Python property"],"3":["py","attribute","Python attribute"],"4":["py","method","Python method"],"5":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:class","2":"py:property","3":"py:attribute","4":"py:method","5":"py:function"},terms:{"0":[1,2,3,4,5,12,13,14,21,25,28,29,34,38,43,45,46,48,49,51,64,65,66,67,68,69,71,72,73,74,75,77],"00":[12,29,38,43,46,51],"000":[66,73,74],"000043219499392912":3,"01":[49,50,73],"02":72,"05":4,"07":[4,68,72],"0700":68,"0f":68,"0m":4,"0s":1,"1":[1,2,4,5,12,14,21,25,28,29,34,36,38,43,46,49,51,61,65,66,68,69,71,73,74,75],"10":[3,4,12,29,65,66,68,72,73],"100":[2,68,74],"1000":[10,15,49,71,73,74],"10000":[66,73],"1024":12,"108":4,"11":[4,66,68],"11111111":68,"1111111111111":68,"116":4,"12":29,"123":[68,75],"1234":3,"127":1,"13":[4,68],"15":[4,49,71],"16":[68,74],"177":4,"18":[3,66],"180":4,"1w":72,"2":[1,2,3,4,21,25,27,29,34,35,48,49,50,61,65,66,68,69,71,73,74,75],"20":[12,29,50,73],"200":5,"2004":25,"2005":[34,68],"2014":4,"2015":72,"2018":50,"2019":29,"202":75,"2020":65,"2021":65,"21":4,"22":25,"225":4,"23":4,"27":34,"289":4,"29":4,"2x2":25,"3":[2,3,4,25,29,61,65,66,68,69,71,72,73,74,75],"30":[25,29],"301":3,"31":[4,68],"31m":4,"32":[1,21,23,24,27,28],"326":4,"327":4,"33":29,"334":4,"335":4,"34":4,"3400":[1,28],"35":4,"37":68,"3f":68,"3x":77,"4":[0,2,4,29,65,66,68,69,71,73,74,75,77],"40":29,"429":4,"43":4,"4448069":4,"454":4,"456":68,"458":4,"5":[4,25,49,50,65,66,73],"50":[2,29,75],"5000":[28,48,49],"55":4,"56":4,"57":29,"58":[4,34],"59":4,"6":[64,66,74],"60":[15,29,34],"61":4,"62":4,"63":4,"63359209":4,"64":1,"65":4,"65064207":4,"65536":12,"67":[25,29],"7":[4,64,66,68,72],"75":[4,28,29],"750":73,"750000":50,"76715529":4,"7890":68,"79":4,"79556889":4,"7bit":68,"8":[4,12,14,66,73,74],"80":[4,29,38,43,46,51,75],"81":4,"83":4,"84":4,"85":[2,71],"89":4,"9":[4,66,72,75],"92m":4,"95":[4,49,73],"97":3,"98":4,"9959787":4,"\u03c3":34,"abstract":[3,9,21,22,28,33,34,35,36,37,46,47,48],"boolean":[1,2,5,12,13,29,33,34,35,36,37,43,47,49,52,73],"break":1,"byte":12,"case":[1,4,25,28,29,47,49,50,51,66,72,73,75],"char":[6,12,20,22,24,26,28,30,66,74,75,77],"class":[1,3,4,5,8,9,10,11,13,14,15,16,17,18,20,21,22,23,24,25,26,27,28,29,30,33,34,35,36,37,38,39,43,44,45,46,47,48,49,50,51,52,53,61,63,64,66,68,73,74,77],"default":[1,2,3,4,5,10,25,26,28,29,44,45,48,49,50,64,66,67,68,72,73,75],"do":[29,31,49,57,65,72],"final":[1,2,24,29,72],"float":[1,3,6,12,21,22,23,24,25,28,29,32,34,36,37,43,45,46,47,48,49,50,51,61,64,65,66,68,73,74,77],"function":[1,3,4,12,13,17,21,25,26,28,29,31,38,39,40,41,42,43,45,46,49,50,51,56,57,64,65,68,69,71,72,73,74,75,77],"import":[1,2,3,4,5,45,63,64,66,68,71,72,73,74,75,77],"int":[1,5,6,8,9,10,12,13,14,15,16,18,19,21,22,23,24,25,26,27,28,29,30,32,33,34,36,37,38,40,41,45,46,47,48,49,50,51,61,65,66,68,71,73,74,77],"long":1,"new":[8,9,10,14,15,16,18,21,22,23,24,26,27,30,34,50,63,64,66,68,69,73,74,77],"null":[46,48,49,66,71,72,73,74,77],"return":[1,2,4,5,8,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,26,27,28,29,30,31,33,34,35,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,57,61,66,68,72,73,74,77],"short":1,"static":[28,36,38,43,46,48,51],"super":[29,72],"switch":[68,72],"true":[1,2,3,4,5,9,12,13,18,21,22,23,24,25,26,27,28,29,30,34,38,43,45,46,49,50,51,64,66,68,72,73,75,77],"try":[2,4,29,64,68,69,71,72,74,75,77],"var":[66,74],"while":[1,3,4,25,71,75],A:[5,25,26,28,29,30,42,49,63,66,71,73,74,75],AS:29,And:69,As:[2,4,29,42,68,71,74,77],At:15,By:[3,4,25,29,68,73],For:[2,3,4,5,22,23,25,28,29,34,35,38,43,45,46,48,49,50,51,53,61,64,67,68,71,73,74,75,76,77],IS:[29,75],If:[12,25,29,31,36,45,49,50,57,64,65,66,67,72,73],In:[1,2,3,4,12,25,28,29,50,66,68,71,73,74,75,77],Is:4,It:[3,5,29,45,64,66,68,74,77],NOT:29,No:[34,61,73],Not:[74,77],OF:29,OR:[12,29],One:[71,73,74,77],Or:[6,7],Such:[74,77],The:[0,1,2,3,4,5,12,20,25,29,45,48,49,50,61,64,65,66,67,68,71,72,73,74,75,77],There:[4,66,68,73],These:[4,29,63,65,77],To:[3,45,66,67,68,71,72,74,75,77],Will:[3,49],With:[65,73,74,77],_:[29,41],__calcul:[39,46],__call__:29,__class__:[2,75],__init__:[1,3,29],__missing__:50,__name__:[2,44,75],_argmax_threshold_lay:1,_char_encoding_lay:1,_construct_model:[1,3],_epoch_id:1,_gener:58,_io:[8,11,12,13,15,16],_model:1,_model_default_ind:1,_model_num_label:1,_need_to_reconstruct_model:3,_one_shot:45,_paramet:[1,2,75],_postprocessor:1,_preprocessor:1,_pull:72,_reconstruct_model:3,_save_processor:3,_validate_paramet:[1,3],a_natural_but_biased_estim:50,a_out:29,ab:29,abc:[4,22,28,68],abcmeta:[22,28],abil:[4,66,71,74,77],abl:[3,21,29,64,68],about:[3,4,66,68,74,76,77],abov:[1,5,29,64,66,67,68,73],absolut:[38,43,46,51,73],abstractstaticmethod:46,acc:1,accept:[1,3,14,29,73],access:[5,19,29,63,66,73],accomplish:[74,77],accord:73,account:[3,25,50,66],accur:74,accuraci:[25,29,68],achiev:[2,75],across:[28,29,61,73],activ:[1,4,29,67,73],activity_regular:29,actual:72,ad:[12,21,22,23,24,26,27,29,30,48,63,74,77],adam:1,adapt:[1,29],add:[1,3,17,21,22,23,24,26,27,29,30,50,66,68,74,76,77],add_label:[3,21,22,23,24,26,27,30,68],add_loss:29,add_metr:29,add_nested_dictionari:50,add_true_false_color:4,add_upd:29,add_vari:29,add_weight:29,addit:[1,4,12,29,66,68,71,73,74,77],addition:[4,5,48,65,71,75],addon:29,address:[2,3,66,68,75],adjust:[63,73],advanc:25,aforement:71,after:[29,63,64,71,75],again:[2,29,64,68],against:29,aggreg:[28,29,75],aggregation_func:[28,75],agre:29,ahead:72,algorithm:4,alia:29,all:[1,4,8,9,10,12,14,15,16,18,22,23,24,25,26,28,29,30,36,45,48,49,50,51,65,67,68,69,71,72,73,74,76],all_fil:[4,71],alloc:50,allow:[3,4,19,21,22,27,28,29,48,50,68,71,72,73,74,75,77],allow_nan:45,alon:75,along:[46,48,61,66,73,76],alreadi:[1,29,67],also:[1,3,4,5,8,10,14,15,16,18,25,29,49,61,64,65,66,68,71,73,74,75,77],alter:[19,21,22,23,24,25,26,27,28,30,63,73],altern:[49,73,74,77],although:[29,49,73],alwai:[13,51],amount:73,an:[1,4,8,9,10,12,14,15,16,17,18,22,25,28,29,30,34,38,43,45,46,47,50,51,61,64,66,68,69,71,72,73,74,76,77],analysi:[28,38,43,47,51,52,66,73,76],analyz:[74,77],ani:[2,3,4,5,8,9,10,11,12,13,14,16,17,22,23,24,26,28,29,30,33,34,35,36,37,38,43,46,47,48,49,50,51,65,66,67,68,71,72,73,74,77],annot:50,anoth:[29,34,64,66,68,73,74,76,77],anyth:28,apach:29,api:[29,66,76],appear:73,append:[1,68,74,77],appl:67,appli:[26,28,29,30,48,52,73,74,77],applic:[25,29,49,66,71,74,77],approach:72,appropri:[22,23,24,26,30,36,37,47,49,68,74,77],approxim:[28,73],apt:67,ar:[1,2,3,4,5,10,12,18,22,23,24,25,26,28,29,30,34,45,48,49,50,65,66,67,68,71,72,73,74,75,77],architectur:[1,3],aren:29,arg:[12,28,29,47,50],argmax:[1,28,29],argmax_lay:1,argmax_output:1,argument:[13,21,27,29,50],around:[38,43,46,51,76],arrai:[3,25,29,45,50,66],ascend:73,ascii:[45,68],ascii_num:1,aspect:[74,77],assert_equal_condit:36,assign:50,assist:3,associ:[21,27,29,30],assum:[28,29,35,50,69,71],astyp:[1,68],attempt:[29,45,73],attr1:44,attr2:44,attr:[22,28,35,49],attribut:[2,14,29,33,34,35,36,37,38,39,43,46,47,48,49,50,51,53,63,64,73],attribute_1:66,attribute_2:66,attribute_n:73,attributeerror:[4,29],attributt:[66,73],aug:68,august:68,author:[4,29,71,74],auto:[4,5,11,22,49,66,73],auto_multiprocess_toggl:50,autom:50,automat:[29,63,64,66,73,76],automaticali:4,autosubregistr:28,autosubregistrationmeta:[22,28],avail:[2,5,42,45,65,73,74],averag:[1,25,29,36,64,73],avg:29,avg_node_degre:[64,66,73],avg_predict:[36,66,73,74],avro:[4,5,6,7,16,66,67,71,73,74,77],avro_data:[8,11,71],avro_fil:[4,71],avrodata:[4,8,11,71],aw:[1,68,76],aws_honeypot_marx_geo:[1,4,71,72,74],ax:[65,74],b:[29,30,50,65],b_out:29,back:[29,76],backend:1,background:[2,28,30],backward:[29,76],ban:[3,66],bank:[3,66],bar:45,barchart:65,bargraph:65,base:[3,5,6,7,8,10,11,13,14,15,16,17,18,20,23,24,26,27,28,29,30,32,34,35,36,37,38,39,43,45,46,47,48,49,50,51,52,53,60,71,73,74,76],base_column_profil:[33,34,36,37,38,43,46,47,51],base_data:[8,9,10,14,15,16,18,48],base_data_label:[21,27],base_metr:29,base_model:[1,3,21,22,23,24,26,27,30],base_valid:61,basecolumnprimitivetypeprofil:[33,37,38,43,51],basecolumnprimitivetypeprofilert:33,basecolumnprofil:[33,34,36,37,44,45,46,47,51],basecolumnprofilert:[33,46],basecompil:[35,44,48],basecompilert:35,basedata:[8,9,10,14,15,16,18,48],basedatalabel:[20,21,27,49,50,73],basedatapostprocessor:[3,21,27,28],basedatapreprocessor:[3,21,27,28],basedataprocessor:28,baseinspectoropt:49,baseinspectoroptionst:49,baselin:76,basemodel:[1,3,21,22,23,24,26,27,30,68],baseopt:[33,44,48,49],baseoptiont:49,baseprocessor:68,baseprofil:[44,48,50],baseprofilert:48,basetrainablemodel:[22,23,24],basi:[29,45],basic:[3,68,69],batch:[8,9,10,14,15,16,18,21,22,23,24,27,28,66,71,73],batch_1:73,batch_2:73,batch_data:28,batch_siz:[8,9,10,14,15,16,18,21,22,23,24,26,27,28,30],batchnorm:29,baz:45,bc:4,bcc:68,bdist:67,bdist_wheel:67,becaus:[4,25,29,49,50,75],becom:[28,29,50],been:[4,29,44],befor:[3,29,49,73,75],behavior:[29,45],behind:2,being:[2,4,5,8,9,10,12,13,14,15,16,17,18,21,22,23,24,25,26,27,28,30,36,39,48,49,73,75],belong:3,below:[2,4,5,25,28,29,42,49,64,65,66,68,71,72,73,74,75,77],besid:[68,71],best:[4,5,36,66],beta:[25,29],better:68,between:[2,3,4,25,27,28,29,35,36,37,39,47,48,49,50,52,53,64,68,72,73,74,75,77],beyond:[74,77],bfloat16:29,bia:[29,49,73],bias:50,bias_correct:[49,51,73],biased_kurt:50,biased_skew:50,big:68,bigobject:45,bin:[38,43,46,49,51,64,67,71,73],bin_count:[64,66,73,74],bin_count_or_method:[49,71,73],bin_edg:[64,66,73,74],binari:25,bit:2,blob:[29,42],block:72,blog:4,blogpost:4,bool:[8,9,10,12,14,15,16,18,21,22,23,24,25,26,27,28,29,30,33,34,35,36,37,38,39,43,46,47,48,49,50,51,52,53,61,66,73,74],booleanopt:49,booleanoptiont:49,both:[4,12,29,47,49,63,68,73,74,75,77],bound:50,branch:76,brand:2,breadth:29,breakdown:73,breviti:68,brew:67,broken:71,bucket:[49,73,76],buffer:[6,7,12],buffer_s:12,bufferediobas:13,bug:66,build:[1,12,25,29,46,48,61,63],build_embd_dictionari:[1,24],build_from_config:29,builder:[6,32],built:[1,20,28,29],builtin:3,byte_s:12,bytesio:[8,11,12,13,16],c:[29,65],cach:29,calcul:[3,25,29,34,37,38,39,40,41,43,46,48,49,50,51,66,73,74,76,77],calculate_quantil:[40,41],call:[3,5,12,25,29,44,45,46,49,50,71,74],callabl:[29,31,46,50,57],came:29,can:[1,2,3,4,5,8,9,10,15,16,17,18,21,25,29,45,48,50,51,64,65,66,67,68,71,72,73,74,75,77],candid:29,cannot:[3,12,29,65],capabl:[4,29],capitalon:[4,67],captur:75,carat:4,cast:29,categor:[6,32,49,64,66,73,74,75],categori:[1,34,49,50,66,68,71,73,74],categorical_attribut:[64,66,73],categorical_column_profil:34,categorical_count:[34,66,73],categorical_crossentropi:1,categorical_distribut:[64,66,73],categorical_statu:4,categoricalcolumn:[34,35,47],categoricalopt:[34,49],categories1:50,categories2:50,caus:[29,45,49],cc:68,cdist:26,cdot:29,cell:[3,12,64,66,68,75],certain:29,chang:[3,4,29,35,38,43,46,48,51,72,73,74,75,76,77],char_in_vector:1,char_load_tf_model:23,charact:[3,4,6,10,12,14,20,28,30,41,45,48,49,63,66,68,71,73,75],character_argmax:28,character_level_cnn_model:[1,3,24,68],characterlevelcnnmodel:[1,3,20,24,28,68],characterlevellstmmodel:1,charencodedpreprocessor:28,charloadtfmodel:23,charpostprocessor:28,charpreprocessor:[20,28],charset:68,check:[1,2,3,8,10,12,14,16,21,27,29,31,34,38,43,45,46,49,51,57,61,63,68,69,71,73],check_circular:45,check_integ:14,check_pipelin:[3,21,27,68],checkout:76,chi2:73,chi2_homogen:[49,68,73],chi2_matrix:[66,73],chi:[50,73],child:19,chip:67,choic:[4,5,8,10,15,16,18],choos:[4,27,28,72,73,75],chose:28,chosen:[73,77],chr:1,chunk:[5,12,18,45,50],chunk_siz:50,chunk_size_byt:12,cij:34,circular:45,clariti:4,class_mean:[66,73],class_nam:[22,23,24,26,28,30,44],class_prior:[66,73],class_sum:[66,73],classif:[6,20,29,34],classifi:3,classification_report:[25,29],classification_report_util:25,classmethod:[8,9,10,14,15,16,18,21,22,23,24,26,27,28,29,30,33,34,35,36,37,38,39,43,46,47,48,49,51],clean_data_and_get_base_stat:48,clean_sampled_df:48,clear:50,clear_sess:1,close:2,clsname:[22,28],cm:[49,73],cms_confid:[49,73],cms_max_num_heavy_hitt:[49,73],cms_relative_error:[49,73],cn:68,cnn:[1,6,20],code:[4,25,29,42,46,50,66,68,71,72,76],coeffici:73,col1:69,col2:69,col:[14,33,36,37,38,43,46,47,48,50,51,60,61,68,72,74],col_float:[71,74],col_int:[71,74],col_pro_compil:44,col_profil:50,col_report:1,col_typ:[33,34,36,37,38,43,46,47,51],collaps:41,collect:[29,48,50,71,74,77],color:4,column:[1,3,5,6,10,12,14,16,20,25,28,32,44,48,49,50,52,53,61,63,65,66,68,71,72,73,74,75,77],column_count:[66,71,73,74],column_ind:65,column_index:48,column_nam:[1,14,61,65,66,68,73,74],column_name_label:2,column_name_model:[2,26],column_null_valu:49,column_profile_compil:[35,48],columnar:1,columndatalabelercompil:35,columnnam:63,columnnamemodel:[2,26],columnnamemodelpostprocessor:[2,28],columnprimitivetypeprofilecompil:35,columns_nam:65,columnstatsprofilecompil:35,com:[4,5,29,42,50,67,68],combin:[1,4,10,29,50,71],come:[29,66,71],command:[2,5,66,72,74,75,77],comment:1,common:[4,49],commonli:[4,74,77],compact:[45,48,64,66,71,73,74,75,77],compani:68,compar:[29,45,47,64,72,73],compare_neg:2,compare_posit:2,comparison:[63,76],compat:[3,8,9,10,14,15,16,18,29,66,68,69,74,76,77],compen:68,compil:[1,6,32,44],complet:[49,73],complex:3,complex_nest:[4,71],complianc:29,compliant:[29,45],compon:[0,1,21,24,25,27,44,64,68,71,72,73,74,77],compos:29,compris:[68,73],comput:[25,29,71],compute_dtyp:29,compute_mask:29,compute_output_shap:29,compute_output_signatur:29,concaten:41,concern:76,conclus:63,condit:[29,49,73],conduct:[4,28],conf:[3,28,68],conf_matrix:25,confid:[1,2,3,22,23,24,26,28,30,49,68,73,75],confidence_level:[66,74],config:[29,33,34,35,36,37,38,43,44,46,47,48,49,50,51,61],configur:[29,49,59,61,73],conflict:49,confus:[25,29],confusion_matrix:25,confusion_matrix_fil:29,conjunct:76,connect:[1,21,27,29],consecut:12,conserv:73,consid:[1,12,29,30,49,51,73],consist:45,constant_initi:29,constraint:73,construct:[1,3,29,44,49],constructor:[1,29,45],contain:[1,3,4,5,8,9,10,11,12,13,14,15,16,17,18,21,22,23,24,25,26,27,28,29,30,31,33,34,36,37,41,42,44,45,47,49,50,56,57,62,65,66,68,71,73,74,77],content:[45,68],context:13,continu:[3,64,73],continuous_attribut:[64,66,73],continuous_distribut:[64,66,73],continuous_weight:4,contract_numb:2,contrast:73,control:29,conv2d:29,convent:4,convert:[3,4,12,22,25,26,28,29,30,38,43,46,51,68,72,75],convert_confusion_matrix_to_mcm:25,convert_int_to_str:12,convert_to_ner_format:28,convert_to_structured_analysi:28,convert_to_tensor:29,convert_to_unstructured_format:28,convolut:1,copi:[25,29,42,49,50],copyfileobj:72,copyright:29,core:[8,9,10,12,14,15,16,18,21,22,23,24,26,27,30,33,34,35,36,37,38,43,46,47,48,50,51,52,53],correct:[73,75],correctli:4,correl:[49,66,73,76],correlation_matrix:[66,73],correlationopt:49,correspond:[25,28,29,50,71],cost:[50,68],could:[28,29,36,64,74,76,77],count:[25,29,34,38,43,46,49,50,51,52,64,73,77],count_param:29,coupl:73,cover:[71,72,74,77],cppflag:67,cpu:50,cpu_count:50,creat:[1,2,3,11,22,27,28,29,30,39,44,50,58,63,64,68,72,73,74,75,76,77],create_glove_char:[1,24],creation:29,credit_card:[3,66],critic:19,cross:21,csv:[1,3,4,5,6,7,12,14,64,66,68,71,72,73,74,77],csv_column_nam:14,csv_data:[4,5,10,11,66,71,73],csv_file:[4,71],csvdata:[10,11,63,66,71,73],current:[3,5,14,22,23,24,26,28,29,30,64,65,66,73,74,75,76,77],custom:[29,44,45,66,71,73],cut:[4,66],d:[1,29,46,50,65,69],dai:[45,50],daili:4,dask:61,data1:[66,73,74,77],data2:[66,73,74,77],data:[0,1,6,17,20,22,23,24,25,26,29,30,32,33,34,35,37,38,39,43,44,45,46,47,48,49,50,51,52,53,56,61,63,67,70],data_and_metadata:[5,8,15],data_class:11,data_fold:[4,74],data_format:[5,8,9,10,14,15,16,18,63,77],data_gener:12,data_label:[1,2,3,27,36,49,52,66,68,71,73,74,75,77],data_label_represent:[66,74],data_labeler2:36,data_labeler_column_profil:36,data_labeler_dirpath:[49,52,68,73],data_labeler_load_attr:50,data_labeler_object:[1,49,68,73,75],data_labeler_sav:[1,68],data_length:50,data_list:12,data_object:[74,77],data_path:[64,71,74,77],data_process:[2,3,21,27,28,68,75],data_processor:[21,27],data_read:[4,5,8,9,10,11,12,13,14,15,16,17,18,39,48,66,67,71,73],data_s:50,data_split_differ:[74,77],data_stat:[1,66,68,71,73,74,75,77],data_test:[1,68],data_train:[1,68],data_typ:[4,8,9,10,11,14,15,16,18,35,49,64,66,71,72,73,74],data_type_ratio:[37,38,43,51],data_type_represent:[66,73,74],data_util:12,dataarrai:[21,22,23,24],datafram:[1,5,8,9,10,12,14,15,16,18,21,22,23,24,26,27,28,30,33,48,50,61,63,65,68,69,71,72,74,75,76,77],datalabel:[2,3,21,27,36,49,63,68,73,74],datalabelercolumn:[35,36],datalabeleropt:[36,49,50,52],datalaod:72,dataload:63,dataprofil:[1,2,3,4,5,8,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,26,27,28,29,30,31,33,34,35,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,57,58,59,61,63,64,65,66,67,68,69,71,73,74,75,77],dataprofiler_loader_report:72,dataprofiler_se:[58,67],dataproil:4,dataset:[3,4,5,8,9,10,14,15,16,17,18,21,29,32,33,34,36,37,38,39,43,46,47,48,49,50,51,52,61,63,64,66,67,68,71,72,73,74,75,77],datatim:72,datatyp:45,date:[3,4,50,66,68,72],datetim:[1,3,4,6,32,49,50,64,65,66,68,72,73],datetime_column_profil:37,datetimecolumn:37,datetimeopt:[37,49],dd:61,deal:68,debug:[19,29],decid:[49,73],decim:[48,73,74,77],deciph:[4,10,14],decod:[6,32,45],decor:[22,28,29],deep:66,deeper:63,def:[1,4,29,68,72],default_factori:50,default_ind:1,default_label:[1,2,23,24,27,28,30,68,75],defaultdict:50,defin:[1,5,29,46,49,65,73,75],definit:50,degre:[64,73],delet:67,delimit:[5,10,12,14,63,71,74,77],delimti:4,demo:[68,72],demonstr:[4,65,71],denot:73,dens:[1,29],depart:68,depend:[29,31,48,50,57,64,67,68],deprec:29,depth:[4,63],deriv:[1,76],descend:34,descent:29,describ:[13,21,22,23,24,25,26,27,28,29,30,39,73],descript:[4,5,64,71],deseri:44,design:[7,12,66,68,71,73,74,76,77],desir:[1,4,48,66,71,74,75,77],destin:14,destination_nod:14,detail:[2,3,4,23,24,25,48,63,71,73,74,76,77],detect:[5,8,11,12,16,63,64,66,67,71,73,74,75,76,77],detect_cell_typ:12,detect_file_encod:12,determin:[2,3,4,8,9,10,12,13,14,15,16,18,21,22,23,24,25,26,27,28,29,30,33,34,35,36,37,43,47,49,52,66,73,74,76,77],dev:67,deviat:[38,43,46,51,73],devid:71,df1:71,df2:71,df:[4,36,37,38,43,46,47,51,53,68,69,71,73],df_data:[1,68],df_result:[1,68],df_seri:[33,34,35,36,37,38,43,46,47,48,50,51,52],diamond:[4,74],dict1:50,dict2:50,dict:[2,3,4,5,8,9,10,11,12,14,15,16,17,18,21,22,23,24,25,26,27,28,29,30,33,34,35,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,61,66,71,73,74,75,77],dictat:27,dictionari:[4,5,12,15,21,24,25,27,29,33,34,35,36,37,38,41,43,45,46,47,48,49,50,51,64,66,73,74,77],did:29,diff:[33,34,35,36,37,38,39,43,46,47,48,51,52,53,64,73,74,77],diff_report:73,differ:[1,4,29,33,34,35,36,37,38,39,43,46,47,48,50,51,52,53,61,63,66,68,71,72],differenc:73,differenti:[36,64],digest:3,digit:[3,25,66,73,75],dim:24,dim_emb:[1,23,24,26,30],dimens:29,dir:29,directli:[4,29,65,66,68,71,73,74,77],directori:[22,23,24,26,30,52,68,72,73],directpasspreprocessor:[2,20,28],dirpath:[3,21,22,23,24,26,27,28,30,68],disabl:[1,26,29,33,34,35,36,37,43,46,47,49,52,66,67,68,71,72,73],discov:67,discoveri:25,discret:29,discrimin:25,discuss:4,discussion_reddit:[4,71,77],disk:[3,20,21,22,23,24,26,27,28,30,39,48,74,77],displai:[4,25,34,49,68,73],dist:67,distinct:73,distribut:[29,36,64,66,67,69,71,73],dive:[63,68],divid:76,doan:73,doc:[4,64],document:[68,74,77],doe:[25,26,29,30,44,50,64,66],doesn:[29,31,57,74,77],domin:28,don:[29,66,67],done:[21,27,29],doubl:67,down:24,download:[12,72],downstream:[29,66],dp:[1,2,3,4,5,6,64,65,66,68,69,70,71,72,73,74,75,76,77],dp_data:72,dp_datafram:72,dp_dataload:72,dp_log:19,dpi:74,drive:76,drivers_licens:[3,66],drmaciv:50,drop:[1,48,68],dropout:[1,23,24],dtype:[1,12,29,65,75],dtype_polici:29,due:[50,74,75],dummi:69,dump:[66,71,73,74,77],duplic:[50,71,74,77],duplicate_row_count:[66,71,73,74],durat:73,dure:[2,3,29,45,75,76],dynam:[29,72],e:[3,4,21,27,29,50,68,73,75],each:[3,4,12,21,22,23,24,25,27,28,29,30,34,36,38,41,45,50,64,66,68,71,72,73,74,75,77],eager:29,earlier:68,easi:[5,66,68,73],easiest:2,easili:[68,71,73,75],ecosystem:29,edg:[4,14,38,43,46,51,64,66,73],educ:68,effici:66,effort:4,eg:49,egg:67,either:[12,21,27,29,50,64,67,74,77],element:[29,38,45,73],elif:1,elimin:45,els:[1,50,71,72,74,77],email:68,email_address:[3,66],emb:24,embed:[1,24,28],embed_fil:1,embedding_dict:1,embedding_matrix:1,empti:[1,4,50,71,73],empty_line_count:[66,73,77],en:50,enabl:[29,49,66,71,73,75,76],enabled_profil:49,encapsul:[30,75],encod:[1,3,4,6,8,9,10,12,13,14,15,16,18,21,22,23,24,26,27,28,29,30,32,44,66,68,73,74,77],encoding_funct:1,encoding_map:28,end:[3,28,30,61,68,75],enron:68,ensur:[2,4,12,29,36,45,47,64,68,72,73,75],ensure_ascii:45,enter:29,entir:[4,5,8,10,15,16,73,75],entiti:[28,29,30,52,66,67,68,71,73,74,77],entity_count:[66,73,77],entity_percentag:[66,73],entity_priority_ord:28,entity_rev_dict:29,entri:[25,29,66,73],enumer:72,env:67,environ:71,epoch:[1,3,21,22,23,24,27,68],epoch_id:[3,24],equal:[2,28,49,71,73],equip:[66,73],equival:29,eras:[8,9,10,14,15,16,18],error:[1,4,19,21,27,29,36,49,50,67,68,69,71,74,76,77],error_on_mismatch:[21,27],escap:45,estim:[38,43,46,49,50,51,73],etc:[3,4,12,28,29,48,50,66,71,73,74,76,77],evalu:[1,2,3,29,75],evaluate_accuraci:29,evan:68,even:72,ever:68,everi:[12,73,74,77],ex:73,exact:[72,73],exactli:[4,29,71],examin:[8,10,15,16,18,74,77],exampl:[1,2,3,4,5,25,29,30,45,61,64,66,68,69,71,73,74,75,76,77],except:[1,2,3,4,28,29,50,64,68,69,72,74,75,77],exclud:[25,33,34,35,36,37,43,47,52],execut:[3,29,50,72],exist:[8,9,10,14,15,16,18,21,22,23,24,26,27,28,29,30,31,44,49,50,57,63,66,68,72,73],expect:[3,12,29,44,68,71,75],explicit:73,explicitli:[29,71,74,77],explor:[1,66],expon:64,express:29,exst:[2,75],extend:68,extended_report:72,extens:[4,71],extra:[1,4,10,64,68,69,74,77],extract:[22,23,24,26,30],extran:3,f1:[1,22,23,24,25,29,68],f1_report:[22,23,24,29],f1_report_dict_to_str:29,f1_score_train:1,f1score:[1,29],f:[25,29,50,57],f_1:29,f_:29,f_in:72,f_out:72,f_score:29,factor:24,factori:[11,48,50],fail:4,failur:[4,49],fake:75,faliur:4,fall:29,fals:[1,2,4,5,9,12,13,21,22,23,24,25,26,27,28,29,30,33,34,35,36,37,38,39,43,45,46,47,48,49,51,52,53,64,66,68,71,72,73,74,75,77],false_positive_dict:2,fashion:61,fbeta_scor:25,fbetascor:29,fd:73,featur:[71,73],fed:48,feed:68,fetch:14,few:[66,68],field:4,fig:[65,74],figsiz:74,figur:[38,65,73,74],file:[1,5,8,9,10,11,12,13,14,15,16,17,18,19,20,21,24,27,29,39,42,48,62,63,64,67,68,71,72,74,76,77],file_a:[66,73],file_b:[66,73],file_encod:[4,8,9,10,12,14,15,16,18],file_object:12,file_path:[8,10,12,14,15,16,18],file_typ:[66,71,73,74,77],filenam:[24,68,74,77],fileorbufferhandl:13,filepath:[4,6,7,19,39,48,64,73,74,77],filepath_or_buff:13,fill:1,filter:[2,29],final_confid:3,final_predicted_lay:1,final_result:3,finalize_st:29,find:[12,14,25,29,33,34,35,38,39,43,46,48,50,51,52,53,66,73],find_diff_of_d:50,find_diff_of_dict:50,find_diff_of_dicts_with_diff_kei:50,find_diff_of_lists_and_set:50,find_diff_of_matric:50,find_diff_of_numb:50,find_diff_of_strings_and_bool:50,find_nth_loc:12,finetun:4,first:[1,2,4,10,15,29,36,50,64,65,66,68,71,72,73,74,75],first_dict:50,fisher:50,fit:[1,3,21,22,23,24,29,36,68],fix:[26,30],flag:[1,2,3,21,22,23,24,26,27,28,30,33,34,35,36,37,43,47,48,49,52],flat:[48,73,74,77],flat_dict:41,flatten:[28,41,48,73,74,77],flatten_separ:28,flatten_split:28,flattened_datafram:[5,15],flight_delai:72,flight_delays_ful:72,flight_delays_mini:72,float16:29,float32:29,float64:[38,43,46,50,51],float_column_profil:38,floatcolumn:38,floatopt:[38,49],flow:2,fly:29,focu:4,fold:[38,43,46,51],folder:[1,2,67,68],follow:[1,3,4,5,19,20,21,25,27,28,29,50,64,65,68,71,72,73,74,77],foo:45,form:[12,29,67],formal:50,format:[1,3,4,5,8,9,10,14,15,16,18,21,24,25,27,28,29,36,37,44,47,48,49,68,71,72,73,74,75,77],former:71,foudn:75,found:[5,29,36,50,68,73,75],four:[48,73,74,77],fp:4,frac:[1,29,68],frame:[8,9,10,12,14,15,16,18,21,22,23,24,26,27,30,33,35,50,76],framework:29,free:29,frequenc:[49,73],frequent:[34,73],fri:68,fridai:68,from:[1,2,3,4,5,8,10,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27,28,29,30,33,34,35,36,37,38,39,42,43,44,45,46,47,48,49,50,51,53,63,66,69,71,72,73,74,75,76,77],from_config:29,fromkei:50,fscore:25,full:[29,49,66,67,71,73,74,77],fulli:[1,73],func:[19,25],funciton:75,funky_on:2,funky_thre:2,funky_two:2,further:[5,74,77],futur:[63,76],g:[4,29,34,50,68,73,75],g_1:50,g_2:50,game:4,gamma:64,gather:[49,71],gaussian:4,gca:74,gener:[1,8,9,10,12,14,15,16,18,28,29,33,35,36,37,40,41,47,48,49,50,55,56,58,64,66,71,72,73,74,75,77],generate_pool:50,generator_on_fil:12,get:[1,3,8,9,10,14,15,16,18,22,23,24,26,28,29,30,38,43,45,46,50,51,61,65,67,68,71,72,74,75,77],get_batch_gener:[8,9,10,14,15,16,18],get_build_config:29,get_child_logg:19,get_class:[22,23,24,26,28,30],get_column_profiler_class:44,get_compiler_class:44,get_config:29,get_delimiter_regex:12,get_figur:65,get_input_at:29,get_input_mask_at:29,get_input_shape_at:29,get_logg:19,get_memory_s:50,get_option_class:44,get_output_at:29,get_output_mask_at:29,get_output_shape_at:29,get_paramet:[22,23,24,26,28,30],get_profiler_class:44,get_random_number_gener:58,get_structured_col_profiler_class:44,get_structured_result:[1,68],get_tf_layer_index_from_nam:29,get_unstructured_result:68,get_weight:29,gini:34,gini_impur:[34,66,73],git:67,github:[1,2,4,29,42,64,67,68,69,71,72,74,75,76,77],githubusercont:4,give:[4,28,31,57,71,75],given:[1,3,4,8,10,11,12,13,16,19,21,22,23,24,26,27,28,29,30,31,32,35,44,45,48,50,57,61,66,67,68,71,73,74,75,77],global:[25,64,66,73],global_max_component_s:[64,66,73],global_stat:[66,71,73,74,75,77],glove:[1,24],go:68,godbol:25,good:[4,72,74],govern:29,grab:73,gradient:29,gradienttap:29,graph:[3,4,5,6,7,31,32,48,55,57,63],graph_data:[4,11,14,39],graph_data_csv_identifi:[4,64],graph_fil:[4,66],graph_func:57,graph_keyword:14,graph_profil:39,graphdata:[11,14,39,63,64],graphopt:39,graphprofil:[4,39,48,64],greater:[1,2,29,73],green:4,ground:63,group:[12,40,41,49,50,73],guarante:45,guess:68,guid:25,gz:72,gzip:72,ha:[3,4,8,10,14,15,16,25,28,29,30,36,44,46,50,68,71,73,74,77],half:71,hall:4,halv:71,handl:[3,12,13,29,71],happen:[4,29],harmon:29,hasattr:29,hash:[3,49,66,73],hash_or_kei:[3,66],hashing_method:[49,73],have:[3,4,12,15,21,22,23,24,26,27,28,29,30,36,50,61,64,66,67,68,71,72,73,75,76],head:[1,4,66,68,71,73],header:[5,10,12,14,16,63,71,74],heard:68,heavi:73,help:[2,3,21,22,23,24,26,27,28,30,68,75],helper:[6,32,50,68],henc:29,here:[2,4,22,29,42,50,68,71,72,74,75,76],hide_tf_logger_warn:29,high:74,higher:[28,29],highest:[49,73],histogram:[6,32,38,43,46,49,51,64,66,71,73,74],histogram_and_quantil:[49,71,73],histogram_bin_method_nam:51,histogram_method:51,histogram_select:51,histogramandquantilesopt:49,histori:[22,23,24],hitter:73,hll:[49,73],homebrew:67,homogen:[50,73],honeypot:[1,68],honeypot_intentially_mislabeled_fil:[4,71],host:4,how:[2,3,4,5,10,22,29,34,45,61,63,64,65,68,73,75,76],howev:[3,4,71,73,74,75],html:[4,64,72],http:[4,5,29,42,50,64,67],human:[68,73],hyperloglog:49,hyperloglogopt:[49,73],i:[3,4,21,27,29,34,67,68,74,77],id:68,id_count:12,idea:[2,50],ideal:4,ident:3,identif:[12,30],identifi:[5,14,30,46,48,60,61,66,68,73,74,77],ideolog:25,idx:12,ie:73,iff:50,ignor:[12,25,29,75],ignore_cas:75,ignore_consecut:12,ignore_dict:12,illustr:[3,4],iloc:71,imbal:25,impact:[26,30,35,48],implement:[4,12,14,29,63,64],impli:29,importerror:[2,4,64,68,69,72,74,75,77],impos:[38,43,46,51],improp:49,improv:[68,72],impur:34,inbound:29,inbound_nod:29,includ:[1,2,21,23,24,25,27,29,49,67,71,74,75,76,77],include_label:2,incom:[29,45],incompat:[29,76],incorrect:[4,34],incorrectli:[4,71,73],increas:74,ind:72,indent:[45,66,71,73,74,77],independ:29,index:[1,3,5,12,14,21,22,23,24,26,27,28,29,30,47,48,50,65,73,74],indic:[1,22,23,24,25,26,29,30,48,50,73],indici:73,individu:[4,12,38,43,47,51,67,68,71,75],infer:[29,71,73,74],infin:45,infinit:45,info:[8,9,10,14,15,16,18,19,29,68,76],inform:[3,4,29,64,68,71,73,74,76,77],ingest:[3,74,77],inherit:[1,21,68],init_scop:29,initi:[1,3,8,9,10,12,13,14,15,16,17,18,21,22,23,24,26,27,28,29,30,33,34,35,36,37,38,39,43,46,47,49,50,51,52,53,61],inplac:[28,66,73],input:[1,3,4,8,9,10,11,12,13,14,15,16,17,18,21,22,23,24,25,26,27,28,29,49,50,64,68,71,73,74,77],input_file_path:[4,5,8,9,10,11,14,15,16,17,18],input_length:1,input_mask:29,input_shap:[1,29],input_signatur:29,input_spec:29,input_str:[1,30],inputspec:29,insert:[1,2,4,29,45,50,64,66,68,69,71,72,74,75,77],insid:[29,66,73,74,75,76,77],instal:[31,57,63,65,66],instanc:[19,21,25,27,29,34,44,73],instanti:[29,48,61,69],instead:[8,9,10,14,15,16,17,18,21,25,27,29,68],insturl:68,int64:[50,51],int_column_profil:43,intcolumn:43,integ:[1,2,3,14,23,24,28,29,30,38,43,45,46,51,65,66,68,73,75],integr:[29,63,76],intel:67,intend:72,intent:4,intention:4,intentionally_mislabled_fil:[4,71],interchang:68,interept:4,interest:[1,71],intern:[25,27,29,50],interpol:[38,43,46,51],interpret:[3,4],intopt:[43,49],intro:[63,73],introductori:71,invalid:1,investig:68,invoc:29,invok:29,involv:68,io:4,ipv4:[3,66],ipv6:[3,66],iri:[4,74],is_case_sensit:[49,73,77],is_en:[1,49,50,66,68,71,72,73,74,77],is_float:[38,43,46,51],is_in_list:61,is_in_rang:61,is_int:[38,43,46,51],is_match:[8,9,10,14,15,16,18,34,63],is_numeric_stats_en:[49,73],is_pred_label:28,is_prop_en:49,is_separate_at_max_len:28,is_stream_buff:13,is_structur:[8,9,10,14,15,16,18],is_valid_url:12,isdir:[2,75],isinst:1,isn:29,issu:[66,76],item:[1,12,45,50,61,68],item_separ:45,iter:[3,12,21,22,26,29,30,50],iterencod:45,its:[1,3,4,21,25,27,29,46,48,61,66,73,75],itself:[5,34,38,43,46,51],ivar:49,j:[4,34],javamail:68,javascript:45,john:68,join:[1,4,8,15,28,41,64,71,72,74,77],js:29,jsmith:68,json:[1,2,3,4,5,6,7,12,16,32,33,34,35,36,37,38,43,46,47,48,49,51,66,68,69,71,72,73,74,75,77],json_data:[8,11,15,71],json_decod:44,json_encod:[44,45],json_fil:[4,71],json_lin:12,json_to_datafram:12,jsondata:[4,8,11,15,71],jsonencod:45,jsonifi:45,jsontyp:12,jupyt:71,just:[5,71,73,74,75,77],k:[34,50],kader:34,keep:[29,68],kei:[4,5,8,12,15,21,27,28,39,41,45,48,50,66,73,74,76,77],kera:[1,29],kernel:29,kernel_initi:29,key_separ:45,keydict:50,keyerror:50,keyword:[14,29],kind:[11,29],know:72,knowledg:25,known:[25,72],kurtosi:[38,43,46,49,50,51,64,66,73],kwarg:[11,22,23,24,26,28,29,30,47,50],l211:29,l283:29,l:[29,67],label1:3,label2:3,label:[0,1,6,22,23,24,25,26,28,30,31,32,48,49,50,63,67,70,71,72,73,74,77],label_1:30,label_1_pattern_1:30,label_1_pattern_2:30,label_2:30,label_2_pattern_1:30,label_2_pattern_2:30,label_df:68,label_encod:52,label_map:[1,2,21,22,23,24,26,27,28,30,68,75],label_nam:[3,29],label_represent:[36,73],labeled_data:68,labeler_class:27,labeler_from_librari:2,labeler_funct:31,labeler_typ:[1,3,27,68],labeler_util:[1,29],labler:[66,67],lack:50,lambda:[1,29],languag:29,larg:71,largest:64,last:[4,12,50,65,68,71,73,74],later:[4,29,66,74,77],latter:71,law:29,layer:[1,29],layer_a:29,layer_b:29,layer_nam:29,lazi:50,learn:[63,66],least:[15,73],left:73,leftov:28,legaci:76,len:[1,4,29,68,71,74,77],length:[4,8,9,10,12,14,15,16,18,28,50,64],less:[12,50,72,73],let:[1,2,64,68,69,71,74,75,77],letter:75,level:[3,6,19,20,22,23,26,28,30,41,45,49,63,65,66,68,71,73,74],lib:[19,67],libarari:72,librari:[1,2,3,21,27,28,63,64,66,68,71,75,76],libsnappi:67,licens:[29,42],lifo:50,like:[1,3,24,25,29,41,50,64,71,73,74,77],likelihood:[34,64,73],limit:29,line:[4,10,12,15,18,66,68,71,73],linst:76,linux:67,list:[1,2,3,4,5,8,9,10,11,12,14,15,16,18,20,21,22,23,24,25,26,27,28,29,30,31,34,36,38,43,45,46,48,49,50,51,52,57,61,63,64,65,66,68,71,73,74,75,76,77],list_of_necessary_param:1,list_of_profil:[50,69],live:29,ll:[68,72],load:[1,5,6,8,9,10,12,13,14,15,16,17,18,20,21,22,24,26,27,28,29,30,33,34,35,36,37,38,39,43,44,46,47,48,49,50,51,63,72],load_as_str_from_fil:12,load_attr:50,load_column_profil:44,load_compil:44,load_from_dict:[33,34,35,36,37,38,43,46,47,48,49,51],load_from_disk:[2,3,21,22,23,24,26,27,28,30,75],load_from_librari:[20,21,27,28,63,75],load_method:[48,73],load_model:29,load_opt:[21,27,44],load_own_vari:29,load_profil:44,load_structured_col_profil:44,load_with_compon:[21,27,63],loadabl:23,loaded_json_profil:73,loaded_pkl_profil:73,loaded_profil:[74,77],loader:72,loc:[12,64,73],local:67,locat:[4,10,14,21,24,27,48,71,73,74],log:[6,64,68,69,70,73,74,77],logger:[19,29],loggin:[68,69,74,77],logic:[12,29],logist:64,lognorm:64,look:[63,64,68,69,74,75,77],lookup:29,loop:[27,29],loss:[1,29],low:65,lower:75,lower_memory_sketch:[49,73],lowercas:75,lowercase_char:75,lowest:28,lst:50,lstm:63,m1:29,m2:29,m:[3,5,12,29,34,50,67],mac_address:[3,66],machin:[71,74,77],macklemor:3,maco:67,macro:[25,29],made:25,mai:[4,5,8,10,15,16,18,29,49,71,74,77],mail:68,main:[0,1,3,4,25,42,65],maintain:3,major:[25,68],make:[1,3,29,46,66,68,71],makedir:[1,68,72],manag:13,mani:[4,5,10,22],manipul:[74,77],manner:[4,66,73],manual:[4,29,58],map:[1,2,3,22,23,24,26,28,30,36,48,49,68,73,75],margin_of_error:[66,74],mari:68,mask:29,match:[9,12,21,25,27,29,30,37,38,43,51,64,74,75,77],match_count:[37,38,43,51],match_sentence_length:28,math:72,math_op:29,mathemat:[4,12],matmul:29,matplotlib:[65,71,74],matric:50,matrix1:50,matrix2:50,matrix:[1,25,29,49,50,66,73,74],max:[22,23,24,26,29,30,37,49,50,51,64,66,71,73,74],max_byt:12,max_char_encoding_id:[1,23,24],max_histogram_bin:51,max_k_mod:49,max_length:[1,23,24,26,28,30,68],max_lin:12,max_num_char:[26,30],max_pool_s:50,max_sample_s:[49,73,74],max_sample_size_to_check_stop_condit:[49,73],maximum:[12,28,49,73],mayb:9,mb:[66,73],mcm:25,mcm_:25,md5:[3,66],mean:[25,29,38,43,46,51,64,65,66,67,68,71,73,74,77],meant:29,measur:[50,73],mechan:[3,4],median:[38,43,46,49,51,66,71,73],median_abs_devi:[38,43,46,51,71,73],median_absolute_devi:[66,73],meet:4,melt:[1,68],member:45,memori:[1,5,8,10,15,16,18,50],memory_s:[66,73],mention:[4,68],merg:[29,50,63],merge_profile_list:[50,69],merge_st:29,messag:[50,68],met:73,meta:76,metadata:[5,8,15,29,33,34,36,37,38,43,46,47,51],method:[2,3,4,22,25,28,29,34,36,37,44,46,47,48,49,50,71,73,74,77],method_timeit:50,metric:[1,25,29,49,73],metric_1:29,metric_2:29,micro:[1,25,29],might:[64,68],millisecond:73,mime:68,min:[29,37,48,49,51,66,71,73,74],min_histogram_bin:51,min_sample_s:48,min_true_sampl:[48,73],mind:68,mine:25,mini:72,minimum:[36,48,49,73],mirror:73,mismatch:[21,27,74],miss:[31,46,50,57,74],mix:29,mixed_precis:29,mixin:[6,7,38,43,49],mkdir:[2,75],ml:[66,67,68],mock:76,mod:29,mode:[13,28,29,38,43,46,49,51,66,71,73],model:[6,20,21,27,28,29,46,48,61,63,66,68,73,75],model_path:23,model_predict:3,model_result:[3,68],modeopt:49,modif:1,modifi:[28,29,42,71],modul:[19,25,27,29,31,57,70],module_nam:[31,57],monitor:66,monti:4,more:[2,4,9,25,28,29,36,63,64,66,68,71,72,73,74,76,77],most:[34,45,74,77],move:29,mro:[22,28],much:73,multi:[21,22,23,24,25,26,27,29,30],multiclass:25,multilabel:25,multilabel_confusion_matrix:25,multipl:[3,8,9,10,14,15,16,17,18,29,61,65,67,68,71,73,74,75,77],multiprocess:[35,48,50,73],multiproess:50,must:[1,3,5,19,21,22,23,24,27,28,29,36,48,73,74,75,77],my:[3,4,73],my_datafram:[66,71,73,74],my_graph:66,my_home_address:2,my_label:68,my_metric_lay:29,my_modul:29,my_new_regex_label:75,my_profil:[73,74,77],my_text:66,mydata:4,mylay:29,mymetriclay:29,mymodul:29,mysocket:45,n:[1,3,4,5,12,14,26,28,30,34,68,71,73],n_dim:24,n_label:25,n_output:25,n_sampl:25,n_unique_label:25,na:68,name:[1,4,6,14,19,20,21,25,27,28,29,31,33,34,35,36,37,38,43,44,46,47,49,50,51,53,57,63,64,65,66,67,68,71,73,74],name_scop:29,nan:[12,45,49],nation:[4,71],ndarrai:[21,22,23,24,25,26,27,28,30,36,48,50],ndim:29,nearest:28,nearli:3,necessari:[1,64,69],need:[1,2,3,12,19,21,22,23,24,26,29,30,49,50,64,66,68,71,72,74,75,76,77],neg:[25,38,43,45,46,50,51,64,73],negative_threshold_config:2,ner:[3,28,68],nest:[5,29,41,48,50,73,74,77],network:[1,29],networkx:[4,5,14,39,64],neural:1,new_column_name_label:2,new_data:[66,73,74,77],new_label:[3,68],new_profil:64,new_report:64,newlin:45,next:[1,4,68,72,74,77],nice:29,nmodel:[2,75],node:[14,29,64,73],node_id_dst:4,node_id_src:4,node_index:29,non:[1,28,29,45,48,68,73],non_csv_fil:4,non_trainable_vari:29,non_trainable_weight:29,none:[1,5,6,8,9,10,11,12,13,14,15,16,17,18,21,22,23,24,25,26,27,28,29,30,31,33,34,35,36,37,38,39,43,44,45,46,47,48,49,50,51,52,53,57,61,65,66,67,68,72,73,74,76,77],noqa:72,nor:29,norm:64,normal:29,normal_csv_fil:73,normal_text_fil:73,not_my_address:2,note:[1,3,12,25,29,42,51,67,73,74,75,77],notebook:[1,2,4,64,68,69,71,72,74,75,76,77],noth:36,notic:[4,64,73,75],notimplementederror:[45,48],notset:19,now:[29,64,68,69,75],np:[1,12,21,22,23,24,25,27,28,29,38,43,46,48,50,51,66],np_type_to_typ:[38,43,46,51],npt:28,nth:12,null_count:[49,66,73,74,76],null_perc:76,null_replication_metr:[49,66,73],null_typ:[66,73,74],null_types_index:[66,73,74],null_valu:[48,49],num_class:[1,29],num_cols_threshold:50,num_edg:[64,66,73],num_fil:[23,24],num_label:[1,22,23,24,26,29,30],num_lin:4,num_neg:[49,51,66,73],num_nod:[64,66,73],num_quantil:[49,73],num_quantile_group:[40,41,73],num_rows_threshold:50,num_sampl:28,num_zero:[49,51,66,73],number:[1,3,12,21,22,23,24,25,27,28,29,40,41,48,49,50,58,61,62,64,66,68,71,73,74,76,77],numer:[6,29,32,38,43,49,65,73,74],numeric_stats_dis:[49,73],numerical_column_stat:[38,43,46,51],numericalopt:[46,49],numericaloptionst:49,numerican:49,numericstatsmixin:[38,43,46,51],numericstatsmixint:[43,46],numpi:[1,12,21,22,23,24,26,27,28,29,30,36,38,42,43,46,48,50,51,58,66],nx:39,o:[14,45,68],object:[1,4,5,9,11,12,13,17,21,22,27,28,29,35,39,41,44,45,46,48,49,50,52,53,61,65,66,68,69,71,73,74,75,76,77],observ:[34,64],obtain:[29,71],occur:[12,34,61,68,73],occurr:[12,25,73],od:41,off:[4,49,66,71,73,74,75,77],offic:68,offset:13,often:[29,34,73],older:67,omit:29,omit_kei:75,omitted_label:29,on_read:29,onc:[1,4,73,74,77],one:[1,3,5,12,19,25,29,34,35,48,66,67,68,71,72,73,74,75,76,77],ones:[29,68,73],onli:[2,4,5,8,10,14,15,16,18,22,25,29,45,50,61,65,66,68,71,72,73,74,75,76,77],op:29,opeid6:68,open:[4,12,13,66,68,72],open_method:13,oper:[66,73,74,77],opportun:28,opt:67,optim:[1,23,24,73],option:[1,2,3,5,6,8,9,10,11,12,13,14,15,16,17,18,21,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,43,44,46,47,48,50,51,52,53,61,63,64,65,66,68,72,75,76],order:[1,3,6,22,23,24,25,26,28,29,30,32,34,35,36,49,50,66,68,74,75],order_column_profil:47,ordercolumn:[35,47],ordereddict:48,orderopt:[47,49],ordin:[3,66],org:[29,50,64],origin:[4,12,24,28,29,40,41,68,71,72],os:[1,2,4,64,66,68,69,71,72,74,75,77],oth:75,other:[1,2,23,24,29,35,66,68,71,73,75,76],other_profil:[33,34,36,37,38,39,43,46,47,48,50,51,52,53],otherwis:[9,25,28,36,45,49,50,73],otuput:75,ou:68,our:[64,65],out:[1,2,3,5,12,29,50,68,69,73,76],outbound_nod:29,output:[1,2,3,5,12,14,21,25,27,28,29,36,37,39,45,47,48,50,52,53,64,68,72,73,74,75,77],output_dict:25,output_format:[3,28,48,66,68,71,73,74,75,77],output_mask:29,output_shap:[1,29],over:[4,21,61],overal:[29,71,74,77],overlap:50,overrid:[3,29,44,48,49],overridden:29,overview:63,overwrit:[49,68],own:[1,29,68,73],p:[34,67,73],packag:[6,7,29,32,40,55,60,62,66,67,69],pad:[1,28,29,68],pad_label:[1,28],page:[73,76],pair:[21,27,50],panda:[1,2,5,8,9,10,12,14,15,16,18,21,22,23,24,26,27,28,30,33,34,35,36,37,38,43,46,47,48,50,51,52,53,61,63,65,68,69,71,72,74,75,76,77],paradigm:76,param1:3,param2:3,param3:3,param:[1,8,10,16,21,22,27,29,33,34,35,36,37,38,43,44,46,47,48,49,51,61],param_list:[22,23,24,26,28,30],paramet:[1,3,4,5,8,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,26,27,28,29,30,31,33,34,35,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,57,61,63,64,68,73,75],parameter:29,parametesr:[2,75],parent:[21,33],parq:4,parquet:[4,5,6,7,12,66,67,71,73,74,77],parquet_data:[11,16,66,71,73],parquet_fil:[4,71],parquetdata:[4,11,16,66,71,73],pars:[33,34,35,36,37,38,43,46,47,48,49,51],parse_d:72,part:[29,38,43,46,51,66],partial:[29,61],particular:[1,2,12,71],particularli:[74,77],partit:[50,73],pass:[2,3,5,8,10,12,14,15,16,18,29,69,76],patch:76,path:[1,2,3,4,5,8,9,10,12,13,14,15,16,17,18,21,22,23,24,26,27,28,30,39,48,52,64,68,69,71,72,73,74,75,76,77],pattern:[12,30],pattern_dict:30,payload:[5,15],payload_kei:[5,15],pb:1,pd:[1,2,4,12,21,22,27,28,48,61,65,66,68,69,71,72,73,74,75,77],pdt:68,peek:[74,77],per:[3,18,25,29,66,68,75],percent:15,percentag:[52,73],percentil:73,percis:49,perform:[1,25,29,50,68,73,76],perform_chi_squared_test_for_homogen:50,permiss:29,perri:34,person:[3,66,68],pertain:[5,8,9,10,14,15,16,17,18],phone:68,phone_numb:[3,66],pickl:[48,73,74,77],piec:68,pii:66,pip3:[67,72],pip:[65,66,67],pipelin:[3,21,27,63,66,68],pkl:[64,73,74,77],place:[28,45,48,72,73,74,75,77],plain:[4,68,71],pleas:[3,66],plethora:71,plot:74,plot_col_histogram:65,plot_col_missing_valu:65,plot_histogram:[65,74],plot_missing_values_matrix:[65,74],plt:[71,74],plug:1,pm:[68,72],pm_data:72,pm_stability_report:72,point:[5,25,66,73,74,77],polar:76,polici:29,pool:[35,48,50,73],pool_count:50,pop:[35,38,39,46,50,51,53],popitem:50,popmon:63,popmon_dataload:72,popmon_loader_report:72,popmon_output:72,popmon_tutorial_data:72,popoul:73,popul:[33,34,35,36,37,38,43,46,47,48,49,50,51,76],pos_label:25,posit:[2,3,25,29,38,43,46,51,64,68],positive_threshold_config:2,possibl:[2,3,5,8,10,14,15,16,18,23,24,26,30,36,50,66,73,74,75,77],possible_data_label:36,post:[2,4,75],postprocesor:75,postprocess:28,postprocess_char_level:[66,73,77],postprocessor:[1,2,20,21,27,28,63,68,73],potenti:[29,35,38,50,51,53],pp:[25,34,64],pprint:[2,64,66,74,75,77],pr:76,pre:[1,28,49,63,66,73],precis:[25,29,38,49,50,66,68,73,74],precision_recall_fscore_support:25,precisionopt:49,pred:[3,25,28,68],predict:[1,3,21,22,23,24,26,27,28,29,30,32,36,63,66,71,73,74,77],predict_opt:[2,3,21,27,68,75],predicted_entities_in_index:29,prefer:73,preivous:4,premium:4,prep:68,prepar:[4,68],preprocess:28,preprocessor:[1,2,20,21,27,28,68],present:[1,25,46,50,73],preset:[49,73],pretti:[12,45,48,66,71,73,74,77],prettifi:[48,66,73,74,77],prettyprint:[64,66],prevent:45,previou:[29,64,73,75],previous:4,price:4,prim:33,primari:[74,77],primit:[35,73],princip:24,print:[1,2,3,4,12,21,22,23,24,26,27,29,30,45,66,68,71,72,73,74,75,77],printer:66,printout:[29,72],prior:[12,31,57,74,76,77],prioriti:28,priority_ord:28,priority_predict:28,privat:[34,36,37,47],privileg:68,probabl:[34,36,48,49,73,74,75],process:[1,3,6,12,20,22,26,50,61,71,73,74,75,77],processor:[2,3,20,21,27,28,68],processor_param:1,processor_typ:28,produc:[29,50],profil:[0,1,2,3,4,6,7,40,41,44,45,46,63,65,67,68,70,72],profile1:[66,71,73,74,77],profile2:[66,71,73,74,77],profile3:[66,73,74,77],profile_build:[48,50,65],profile_ful:71,profile_merg:71,profile_opt:[1,68,71,73,74,75,77],profile_schema:[66,73],profileencod:45,profiler_opt:[35,46,48,49,52,72],profiler_test:[74,77],profiler_train:[74,77],profiler_typ:[48,66,71,73,74,77],profiler_util:[50,69],profilerencod:45,profileropt:[1,39,48,49,68,71,72,73,74,75,77],prop:[49,64],propag:29,proper:[11,72],properli:[12,49,72],properti:[4,5,8,9,10,14,15,16,18,21,22,23,24,26,27,29,30,33,34,35,36,37,38,39,43,46,47,48,49,51,52,53,63,64,66,71,73,74,77],proport:73,protect:29,protected_register_keras_serializ:29,proto:4,protocol:[47,50],provid:[1,2,4,27,29,32,40,48,50,63,64,65,66,68,69,71,73,74,77],pseudo:[74,77],psi:73,pst:68,pull_rul:72,purpos:[2,74,77],put:28,py3:67,py:[29,67],pypi:[66,67],pyplot:[71,74],pytest:67,python3:67,python:[29,38,43,45,46,51,66,67,73],quadratur:4,quantil:[40,41,49,51,66,73,74],quantiti:[3,66],queri:12,question:[73,76],quick:[68,74],quickli:[2,74,77],quot:[4,10,14],quotechar:[10,12,14,63],r:[13,30,67,75],rag:28,rais:[1,4,12,25,29,36,44,45,48,49,50,71],raise_error:49,random:[3,4,28,29,34,48,58,66,68,72,73,75],random_st:[28,68],randomli:[28,73,75],rang:[1,14,29,61,73,74,77],rank:[29,36],rank_distribut:36,rare:[66,73],rather:[29,75],ratio:[1,34,37,38,43,49,51,71,73,74],raw:[4,68],rb:72,re:[29,48,49,68],reach:[4,73],read:[1,5,8,10,11,12,13,14,15,16,18,25,63,66,71,72,73,74,76,77],read_csv:72,read_csv_df:12,read_in_str:12,read_json:12,read_json_df:12,read_parquet_df:12,read_text_as_list_of_str:12,readabl:[13,25,50,68,73],readable_report:[66,73],reader:[0,1,6,12,63,66,68,70,72,73],readlin:4,real:68,reason:[29,74,77],rec_dropout:1,recal:[25,29,68],receiv:[25,29,75],recipi:68,recision_recall_fscore_support:25,recognit:[3,66,67,68,73],recommend:[29,50],reconstruct:[1,3,68],record:[4,5,8,10,15,16,50,77],record_samples_per_lin:[4,10],recurr:1,recurrent_activ:1,recurrent_dropout:1,recurs:[29,45,50],recursionerror:45,recursive_dict_upd:50,red:4,reduc:[1,50],reduce_max:29,reduce_mean:29,reduce_min:29,reduce_sum:29,redund:49,refact:76,refer:[3,25,29,34,45],referenc:[25,73],refit:21,reflect:29,regard:68,regardless:71,regex:[6,12,20,28,48,63],regex_model:[20,30,75],regex_pattern:[30,75],regexflag:[48,49],regexmodel:[20,30],regexpostprocessor:[20,28,75],regist:[22,28,29,49,73],register_count:[49,73],registr:22,regress:45,regular:29,reinstanti:61,reject:50,rel:12,relat:[42,71,74],relev:[23,24,73],reload:[8,9,10,14,15,16,18,63],reload_labeler_from_options_or_get_new:50,relu:1,remain:28,remot:76,remov:[2,46,48,50,67,68,69,71,73,74,77],remove_disabled_flag:[33,34,35,36,37,38,39,43,46,47,48,51,52,53],replac:[1,8,9,10,14,15,16,18,30,63,73],replic:[49,73],replica:29,repo:[67,76],report:[1,6,20,29,32,33,34,35,36,37,38,39,40,43,46,47,48,51,52,53,56,57,63,64,65,66,68,69,70,71,75],report_dp_load:72,report_ful:71,report_help:41,report_merg:71,report_opt:[48,66,71,73,74,77],report_output_dir:72,report_pm_load:72,repres:[12,29,34,36,37,38,43,44,46,47,48,51,64],represent:[12,44,45],reproduc:73,request:4,requir:[1,3,4,26,28,29,30,48,49,50,65,66,67,68,73,74,75,77],require_modul:[31,57],requires_zero_map:[1,22,23,24,26,30],rerun:67,reserv:[1,29],reservoir:[5,12],reset:[1,21,22,23,24,26,29,30,66],reset_index:[1,68],reset_st:29,reset_weight:[21,22,23,24,26,30,68],resolut:[22,28],resolv:67,resourc:[2,29,50,72],respect:[46,48,50,61,65,68,73,75],respons:[5,73],rest:[29,64,75],restor:29,result:[1,2,3,25,28,29,35,48,50,61,66,68,71,73,74,75],reth:76,retrain:[3,68],retriev:[21,22,23,24,26,27,28,29,30,44,73],return_sequ:1,reus:[3,29,50],revers:[22,23,24,26,29,30,36],reverse_label_map:[21,22,23,24,26,27,30,36],review:[3,74],rice:[71,73],right:29,rng:[6,70],rng_util:58,role:2,round:[25,48,73,74,77],row:[3,4,5,10,12,49,50,66,68,71,73,74],row_count:[66,71,73,74],row_has_null_ratio:[66,73,74],row_is_null_ratio:[66,71,73,74],row_statist:[49,73],rowstatisticsopt:49,rsampl:12,rtype:[12,28,29,36,37,38,43,46,47,49,50,51],rule:[29,63],run:[2,3,22,23,24,29,31,49,57,61,63,64,67,68,71,72,74,75,76,77],runtim:[48,73,74],runtimeerror:29,s3:76,s:[1,2,3,5,12,22,28,29,38,41,43,46,49,50,51,63,64,65,68,69,73,74,76,77],safe:29,sai:[36,66,67],said:[28,74,75,77],sake:[1,68],sale:68,same:[1,3,4,12,21,22,23,24,25,26,27,28,29,30,36,49,50,64,66,71,72,73,74,77],same_a:[3,21,22,23,24,26,27,30],sampl:[1,3,5,12,18,21,22,23,24,25,28,36,37,38,43,48,49,50,51,66,68,71,74,75,77],sample1:71,sample2:71,sample3:71,sample_arrai:73,sample_count:76,sample_id:48,sample_in_chunk:50,sample_nrow:[5,10,12],sample_ratio:[49,73],sample_s:[33,34,36,37,38,43,46,47,48,51,66,71,73,74],sample_size1:50,sample_size2:50,sample_skew:50,sample_weight:[25,29],samples_per_lin:[5,18],samples_per_upd:[48,73],samples_us:[66,73,74,77],sampling_ratio:[48,49,73],sarawagi:25,satisfi:73,save:[3,8,9,10,15,16,18,21,22,23,24,26,27,28,29,30,39,48,63,72,76],save_dirpath:[1,3,27,68],save_method:[48,73],save_own_vari:29,save_to_disk:[1,2,3,21,22,23,24,26,27,28,30,68,75],saved_label:[2,75],savedmodel:29,saw:68,scalar:29,scale:[64,66,73],scan:68,schema:[66,73,74,77],schooldatasmal:[68,77],scipi:64,scope:29,score:[1,25,26,29,68],scott:73,scratch:63,sdist:67,seaborn:65,search:[12,29],search_queri:12,search_str:68,second:[1,36,50,66,71,75],second_dict:50,secondari:76,section:[1,4,66,68,69,71,73,74,77],see:[2,25,29,44,49,61,64,66,67,71,72,73,74,75,77],seed:[6,49,58],seek_offset:13,seek_whenc:13,seem:49,seemlessli:72,seen:36,select:[5,8,10,15,16,18,28,35,63,73,77],selected_column:[4,5,10,12,16],selected_data_typ:35,selected_kei:[5,8,15],self:[1,29,33,34,35,36,37,38,39,43,46,47,48,49,51,53],send:[21,49,68,73],send_address:2,sensibl:45,sensit:[25,49,66,67,71,73,75,76],sent:[1,21,68,73],sentenc:[4,28,29,77],separ:[12,28,41,45,69,71,75,76],seper:[41,74,77],sequenc:29,sequenti:[1,71],serach:75,seri:[12,21,22,23,24,26,27,30,34,35,36,37,38,43,46,47,48,50,51,52,53,65,66,74,77],serial:[29,44,45],serializ:[3,29,48,73,74,77],serializbl:45,serialized_json:44,serv:1,set:[1,2,3,4,5,6,8,12,16,19,21,22,23,24,25,26,27,28,29,30,31,49,50,57,61,63,66,68,70,71,72,74,77],set_dpi:74,set_label:[2,21,27,75],set_label_map:[22,23,24,26,30],set_model:[1,3,21,27,68],set_opt:68,set_param:[1,2,3,21,22,23,24,26,27,28,30,68,75],set_postprocessor:[3,21,27,68,75],set_preprocessor:[3,21,27,68],set_se:[6,73],set_size_inch:74,set_verbos:[19,68,69,74,77],set_weight:29,setdefault:[1,50],setter:49,setup:[63,67],sever:[43,46,71,73],sha1:[3,66],sha256:[3,66],shallow:50,shantanu:25,shape:[1,25,28,29,64,73],share:[50,73],sheet:4,shorten:[48,71,73,74,77],should:[2,4,26,29,30,33,34,35,36,37,43,45,47,52,61,66,71,73,74,77],show:[1,2,25,65,68,69,71,73,75],show_confid:[2,3,21,22,23,24,26,27,30,68,75],shown:[4,25,29,64,71,73],shuffl:50,shuffle_in_chunk:50,shutil:72,si1:4,si2:4,sigmoid:1,sign:50,signatur:29,signific:[38,73],simialrli:74,similar:[2,3,26,48,73,74,77],similarli:[29,64,74,77],simpl:[68,74,77],simpli:[36,45,72],simultan:3,sinc:[3,8,16,29,68],singl:[4,10,21,22,23,24,26,27,28,29,30,50,66,69,75,77],single_profil:69,singlequot:4,size:[1,12,21,27,28,48,49,50,64,71],size_conv:[1,23,24],size_fc:[1,23,24],size_lstm:1,skeleton:64,sketch:[49,73],skew:[38,43,46,49,50,51,64,66,73],skip:[4,21,27,45,71,74],skip_postprocessor:[21,27],skipkei:45,sklearn:[25,29],slight:75,slightli:29,slimmer:[66,67],small:[68,73],smith:68,snappy_compressed_intentionally_mislabeled_fil:4,so:[29,49,51,65],softmax:1,softmax_output_layer_nam:1,softwar:29,some:[1,29,65,68,71,72,73,76],someth:[4,68],sort:[25,29,45,66,73],sort_dict:[64,66],sort_kei:45,sort_valu:[66,73],sourc:[12,14,24,67,68],source_fil:24,source_keyword:14,source_nod:14,space:1,spaci:[3,68],spam:68,spars:[4,71,74],spearman:76,special:[17,29],specif:[3,4,5,9,12,19,25,29,45,65,66,68,71,72,73,74,77],specifi:[1,2,3,5,8,9,10,11,14,15,16,17,18,21,25,27,28,29,41,45,48,49,50,61,63,64,65,71,72,74,75],split:[0,1,21,28,64,66,68,73,75],split_predict:28,split_ratio:[1,68],spreadsheet:[8,10,15,17],spreadsheetdata:[10,15,16],spreadsheetdatamixin:[10,15,16,17],sqrt:73,squar:[25,50,73],src:[4,29],ssmith:68,ssn:[2,3,5,66],st:75,stabil:[29,73],stage:2,standard:[68,72,73,76],standardli:72,start:[2,3,13,28,30,61,68,69,75,76],stat1:50,stat2:50,stat:[6,32,33,38,43,49,50,64,66,73],state:[28,29,49,76],statement:75,staticmethod:46,statist:[4,32,34,38,39,48,49,50,64,66,71,74,75,77],statu:[21,22,23,24,26,27,30],std:[66,74],stddev:[38,43,46,51,66,73,74],step:[1,2,29,67,76],still:[29,66,75],stop:[49,73,77],stop_condition_unique_value_ratio:[49,73],stop_word:[49,73,77],store:[22,29,48,50,74,76,77],str:[1,4,8,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,26,27,28,29,30,31,33,34,35,36,37,38,39,41,43,44,45,46,47,48,49,50,51,52,53,57,61,65,66,68,73,74,77],str_:28,stream:[5,12,13,71],strength:25,strict:[66,67],string:[1,2,3,4,5,12,13,14,17,25,26,28,29,30,33,34,35,36,37,38,39,43,45,46,47,48,49,50,51,52,53,61,66,68,71,72,73,74,75,77],stringio:[8,12,13,15,16],struct:28,structcharpostprocessor:[3,20,28,68],structcharpreprocessor:[3,20,28,68],structregexpostprocessor:[28,75],structur:[1,4,5,6,7,12,13,25,27,28,29,36,38,43,45,47,48,49,51,63,66,77],structured_mixin:[10,15,16,17],structured_model:20,structured_opt:[1,49,68,71,73,74,75],structured_profil:73,structured_report:73,structuredcol:48,structuredcolprofil:[44,48,65],structureddatalabel:[20,27],structuredopt:[35,48,49],structuredprofil:[8,9,10,14,15,16,18,48,63],sturg:73,sub:29,subclass:[9,13,21,22,23,24,26,27,28,29,30,33,34,37,44,45,46,47,51],subject:[4,29,68],sublass:36,submodul:29,subsequ:[28,73],subset:[25,49,68,73],subtext:75,subtract:[38,43,46,50,51,73],success:41,successfulli:71,sudo:67,suffix:2,suggest:[50,66,75],suggest_pool_s:50,suggested_pool_s:50,suit:68,sum:[29,36,49,51,66,73],sum_predict:36,summari:[1,3,23,24,25,68,74,77],sunita:25,superimpos:[38,43,46,51],supplement:4,suppli:29,support:[5,25,29,68,73,74,77],supports_mask:29,sure:[1,29],swap:[1,3],sy:[1,2,4,31,57,64,68,69,71,72,74,75,77],symbol:29,synchron:29,synthet:[74,77],system:[29,73],t334:3,t555:3,t:[28,29,31,45,50,57,66,67,73,74,77],tabl:[4,29],tabular:[1,3,64,68],take:[3,5,12,25,28,29,45,65,66,68,69,73,74,77],taken:29,tanh:1,target:[14,25],target_keyword:14,target_nam:25,target_nod:14,task:76,tcall:3,teach:[2,34,75],techniqu:4,tell:[46,75],tensor:29,tensorflow:[1,29,50,66,67,68,69,74,77],tensorflow_addon:29,tensorshap:29,tensorspec:29,term:[1,3,74,77],terminolog:66,test:[1,2,4,8,12,15,16,38,43,45,46,50,51,64,68,71,72,73,74,75,77],test_csv_data:67,test_label:68,test_profile_build:67,test_train_diff:64,testing_data:[64,74,77],testing_profil:64,testprofil:67,text:[1,3,4,5,6,7,10,20,23,24,25,28,29,32,46,49,66,68,71,73,74,77],text_column_profil:51,text_data:[11,18,66,71],text_fil:[4,66,71],text_sampl:71,textcolumn:51,textdata:[4,11,18,66,71],textiobas:13,textiowrapp:12,textopt:[49,51],textprofil:[35,53],textprofileropt:[49,53],textrm:29,tf:[1,6,20,29,68,69,74,77],tflite:29,tfmot:29,tfood:3,th:73,than:[1,2,12,28,29,36,73,75],thei:[4,22,23,24,26,28,29,30,31,57,68,71,73,74,77],them:[48,64,65,66,68,71,72,73,74,77],themselv:29,theori:4,therefor:12,thereof:29,thi:[1,2,3,4,7,8,9,10,12,14,15,16,18,25,26,28,29,30,34,35,36,37,38,40,42,43,45,46,47,48,49,50,51,61,64,65,66,67,68,69,71,72,73,74,75,77],thie:76,thing:50,think:[68,76],third:75,those:[2,68,76],thread_saf:[33,34,36,37,38,43,46,47,51],three:[68,73],threshold:[1,28,29,49,50,73],through:[5,12,34,68,71],throught:2,thrown:1,thu:29,thyme:68,ti:3,tie:28,time:[3,12,25,29,33,34,36,37,38,39,43,46,47,50,51,61,64,66,72,73,74,75,77],time_axi:72,time_index:72,time_offset:72,time_width:72,timedelta:50,titan:4,titl:[65,73,74],tjohn:3,tneed:3,tnot:3,to_datetim:72,to_fil:72,to_seri:45,togeth:[21,27,28,50,66,69,73,74,77],toggl:[50,66,71,73],token:18,tolist:[1,68],too:[2,50,66,67],took:73,top:[34,36,49,73,76],top_k:36,top_k_categori:[49,73],top_k_char:[49,73],top_k_mod:73,top_k_word:[49,73],top_profil:50,topolog:29,total:[5,12,25,29,73],tpleas:3,trace:29,track:29,train:[1,21,22,23,24,27,29,63,64,66,74,77],train_data:[22,23,24],train_structured_label:[3,27,68],trainabl:[1,3,21,27,29,68],trainable_vari:29,trainable_weight:29,trainabledatalabel:[3,21,27],training_data:[74,77],training_profil:64,transfer:63,transform:[29,76],travers:34,treat:29,tree:42,true_char_level:[66,73,77],true_entities_in_index:29,true_positive_dict:2,tssn:3,tsv:[4,66,74,77],tupl:[1,12,22,23,24,25,28,29,45,48,50],turn:[29,49,68,71,73,74,75,77],tutori:[4,64],two:[3,4,28,29,36,37,38,39,43,46,47,48,50,51,52,53,64,66,69,71,72,73,74,76,77],txt:[1,4,42,66,67,71,73,74,77],tye:17,type:[1,3,5,8,9,10,11,12,13,14,15,16,17,18,21,22,23,24,25,26,27,28,29,30,33,34,35,36,37,38,39,40,41,43,44,46,47,48,49,50,51,52,53,61,63,66,68,71,72,73],typeerror:[29,45],typeguard:[12,13],typic:[5,29,50,68],typing_extens:[12,13],u:34,unalik:[34,66,73],unchang:[50,73],unclean:46,undefin:25,undefinedmetricwarn:25,under:29,underli:66,understand:73,unicod:12,unicode_to_str:12,uniform:64,unik:34,union:[8,9,10,11,12,13,14,15,16,18,21,22,23,24,25,26,27,28,30,39,48,49,50],uniqu:[1,4,29,34,49,50,68,73,74,77],unique_count:[34,49,66,73,74],unique_ratio:[34,66,73,74],unique_row_ratio:[66,73,74],uniquecountopt:[49,73],unit:[1,50,67,76],unittest:67,unknown:[1,3,28,29,66,68],unless:[29,72],unlik:[29,34],unnest:41,unspecifi:73,unstructur:[4,6,27,28,32,48,49,63,74,75],unstructured_labeler_profil:52,unstructured_model:20,unstructured_opt:[49,73,77],unstructured_profil:73,unstructured_report:73,unstructured_text_profil:53,unstructuredcompil:35,unstructureddatalabel:[20,27],unstructuredlabelerprofil:[35,52],unstructuredopt:49,unstructuredprofil:48,unstuctur:48,until:[28,73],unusu:29,unweight:25,up:[12,63],updat:[1,3,25,29,33,34,35,36,37,38,39,43,46,47,48,49,50,51,52,53,63,65],update_column_profil:48,update_d:50,update_profil:[35,48,66,71,73,74,77],update_st:29,upon:[21,26,27,28,29,30],upper:75,uppercas:75,uppercase_char:75,upstream:29,url:[3,4,12,66,68],url_as_str:12,url_to_byt:12,us:[1,3,4,8,10,12,13,14,15,16,18,20,21,22,23,24,25,26,27,28,29,30,36,44,45,48,49,50,58,63,64,65,66,67,68,71,73,74,77],us_stat:[3,66],usag:[22,28,63],use_word_level_argmax:[3,28,68],user:[1,2,3,4,5,8,10,15,16,18,21,22,23,24,25,27,30,31,48,57,64,66,68,69,71,73,74,76,77],user_set_histogram_bin:51,userdata1:[4,71],userdata1_intentionally_mislabled_fil:[4,71],usr:67,utf:[4,12,14,73,74],util:[2,3,4,6,7,19,20,32,35,48,55,66,68,69,70,73,75,76],utilizng:75,uuid:[3,66],v0:29,v1:[68,69,74,77],v:[50,67],val:[35,38,43,46,49,51,53],val_data:[22,23,24],valid:[0,1,3,5,6,8,10,12,15,16,21,22,23,24,27,49,66,70,71,72,73,74,77],validation_report:[74,77],validation_split:[3,21,68],valu:[1,2,4,10,12,13,19,21,22,23,24,25,26,27,28,29,30,33,34,35,36,37,38,39,43,46,47,48,49,50,51,66,68,72,73,74,75,76,77],valuabl:73,value1:[3,44],value2:[3,44],value3:3,value_label_df:1,valueerror:[1,12,29,44,45],vari:73,variabl:[27,29,34,38,43,46,48,49,51,65],variable_dtyp:29,variableaggregationv2:29,variablesynchron:29,varianc:[29,38,43,46,49,51,64,66,71,73,74],variat:34,variou:[5,11,29],vartyp:49,vast:73,ve:74,vector:29,venv3:67,verbos:[19,21,22,23,24,26,27,29,30],verifi:71,verify_ssl:5,version:[6,29,42,44,45,67,68,70,72,74,77],versu:25,via:[2,4,5,8,10,12,15,16,18,22,23,24,26,29,30,66,67,73,74,75,77],view:[1,2,4,50,64,68,69,71,72,74,75,77],virtual:[22,28,67],virtualenv:67,visit:66,visual:74,vocab:[49,66,73,74,77],vocab_count:[66,73],vocabulari:1,vol:34,vote:[28,36,75],vs1:4,vs2:4,vs:[28,63],w:[3,29,30,68],wa:[4,28,29,31,44,57,64,68,73,75],wai:[29,34,68,73],walk:71,want:[4,12,22,23,24,26,27,30,49,64,65,66,67,71,76],warn:[19,21,25,27,29,31,49,50,57,76],warn_for:25,warn_missing_modul:[31,57],warn_on_profil:50,warranti:29,wb:72,we:[1,2,4,12,29,34,49,64,68,71,72,73,74,75,76,77],weight:[1,3,21,22,23,24,25,26,29,30],welch:73,well:[3,12,29,71,73,74,75,76,77],went:4,were:[4,28,29,73,75],what:[2,3,4,12,49,50,63,74,75,76,77],when:[1,3,4,22,23,24,25,26,28,29,30,36,44,48,49,64,66,72,73,76,77],where:[1,2,3,12,21,22,23,24,26,27,28,29,30,34,48,73,75,76],whether:[4,12,13,14,15,21,22,23,24,26,27,28,29,30,49,71,73],which:[1,2,3,4,5,8,9,10,12,14,15,16,18,21,25,28,29,34,36,37,38,43,45,46,47,49,50,51,66,68,71,72,73,74,75,77],whitespac:[45,75],whl:67,whole:[22,23,24,26,30],whose:29,why:75,wide:[74,77],width:68,wiki:50,wikipedia:[25,50],window:76,wise:61,wish:29,with_name_scop:29,within:[4,12,19,21,27,28,29,30,36,38,43,47,49,51,52,65,73,75],without:[21,27,29,61],word:[28,49,66,68,73,75,77],word_count:[66,73,77],word_level:[28,66,73,77],word_level_min_perc:28,work:[1,14,29,49,64,65,66,71,72,73,74,77],workflow:76,would:[1,3,29,45,68,73,75],wrap:[7,29],wrapper:[12,27],write:[29,45],wrong:4,www:[29,50],x01:28,x1:50,x1b:4,x2:[50,67],x:[1,3,4,12,21,29,38,43,46,51,61,67,68,73],y1:50,y2:[50,67],y:[1,3,4,21,67,68],y_:25,y_pred:[25,29],y_true:[25,29],yate:50,yet:29,yield:45,you:[3,4,12,22,23,24,26,27,29,30,45,49,61,64,65,66,67,68,71,72,73,74,77],you_websit:5,your:[4,29,68,72,74],your_data:3,your_fil:[3,5,66,73],z2:67,z:[4,67,75],za:75,zero:[1,29,38,43,46,51,73],zoo:[21,27]},titles:["API","Adding new model to the existing DataLabeler pipeline","ColumnName Labeler Tutorial","Labeler (Sensitive Data)","Intro to Data Readers","Data Readers","Dataprofiler","Data Readers","Avro Data","Base Data","CSV Data","Data","Data Utils","Filepath Or Buffer","Graph Data","JSON Data","Parquet Data","Structured Mixins","Text Data","Dp Logging","Labelers","Base Data Labeler","Base Model","Char Load Tf Model","Character Level Cnn Model","Classification Report Utils","Column Name Model","Data Labelers","Data Processing","Labeler Utils","Regex Model","Utils","Profilers","Base Column Profilers","Categorical Column Profile","Column Profile Compilers","Data Labeler Column Profile","Datetime Column Profile","Float Column Profile","Graph Profiler","Helpers","Report Helpers","Histogram Utils","Int Column Profile","JSON Decoder","JSON Encoder","Numerical Column Stats","Order Column Profile","Profile Builder","Profiler Options","Profiler Utils","Text Column Profile","Unstructured Labeler Profile","Unstructured Text Profile","Utils","Reports","Graphs","Utils","Rng Utils","Settings","Validators","Base Validators","Version","Examples","Graph Pipeline Demo","Graphs","Data Profiler | What\u2019s in your data?","Install","Sensitive Data Detection with the Labeler","Merge List of Profiles","dataprofiler","Data Profiler - What\u2019s in your data?","Dataloader with Popmon Reports","Profiler","Structured Profilers","Building a Regex Data Labeler w/ your own Regex","Roadmap","Unstructured Profilers"],titleterms:{"char":23,"class":[65,71],"float":38,"import":[65,69],"int":43,"new":[1,2,3,75,76],A:4,Or:13,access:4,ad:1,adjust:75,after:4,alter:4,an:[3,65],api:0,attribut:4,automat:4,avro:8,avrodata:5,base:[9,21,22,33,61],basic:[63,71],both:72,buffer:13,build:[3,67,68,75],builder:48,categor:34,charact:[1,24],check:4,classif:25,cnn:24,column:[2,4,26,33,34,35,36,37,38,43,46,47,51],columnnam:2,comparison:72,compil:35,compon:3,conclus:[64,71],condit:76,content:0,csv:10,csvdata:[4,5],data:[2,3,4,5,7,8,9,10,11,12,14,15,16,18,21,27,28,36,64,65,66,68,69,71,72,73,74,75,76,77],data_format:4,datafram:[4,66,73],datalabel:[1,75],dataload:72,dataprofil:[6,70,72],dataset:1,datetim:37,decod:44,deeper:4,delimit:[4,66,73],demo:64,depend:73,descript:73,detect:[4,68],differ:[64,73,74,77],dive:4,dp:19,encod:45,entiti:3,exampl:[63,65,72],exist:[1,2,3,75],extend:3,file:[4,66,73],filepath:13,filetyp:[66,73],floatcolumn:65,format:66,from:[65,67,68],futur:[2,75],get:66,graph:[14,39,56,64,65,66,73,74],graphdata:[4,5],ground:68,header:4,helper:[40,41],histogram:[42,65],histor:76,how:72,identifi:3,implement:1,individu:65,instal:[67,72],intcolumn:65,integr:[1,75],intro:4,is_match:4,json:[15,44,45],jsondata:5,label:[2,3,20,21,27,29,36,52,66,68,75],learn:[3,68],level:[1,24],list:69,load:[2,3,4,23,64,66,68,73,74,75,77],load_from_librari:2,load_with_compon:2,log:19,lstm:1,matrix:65,merg:[66,69,71,73,74,77],metric:76,miscellan:76,miss:65,mixin:17,model:[1,2,3,22,23,24,26,30,76],modul:[6,7,20,32,40,55,60],name:[2,26],need:65,numer:46,option:[4,49,71,73,74,77],order:[47,73],own:[3,75],panda:[4,66,73],paramet:2,parquet:16,parquetdata:5,pipelin:[1,64],plot:65,popmon:72,postprocessor:[3,75],pre:[2,75],predict:[2,68,75],preprocessor:3,process:28,profil:[32,33,34,35,36,37,38,39,43,47,48,49,50,51,52,53,64,66,69,71,73,74,75,76,77],properti:75,purpos:66,quotechar:4,read:4,reader:[4,5,7,71,76],regex:[30,75],reload:4,replac:[2,75],report:[25,41,55,72,73,74,76,77],rng:58,roadmap:76,rule:75,run:69,s:[66,71,72,75],sampl:73,save:[2,64,68,73,74,75,77],scratch:[67,68],seed:73,select:4,sensit:[3,68],set:[59,73,75],setup:69,size:73,snappi:67,space:76,specifi:[4,66,73],start:66,stat:46,statist:73,structur:[3,17,68,71,73,74,75],structuredprofil:[65,75],suit:76,support:66,test:[67,76],text:[18,51,53],textdata:5,tf:23,time:76,train:[3,68],transfer:[3,68],tutori:2,type:[4,74,77],unstructur:[3,52,53,66,68,71,73,77],up:68,updat:[66,71,73,74,76,77],upgrad:76,url:5,us:[2,5,72,75],usag:[71,72],util:[12,25,29,31,42,50,54,57,58],valid:[60,61],valu:65,version:[62,66,76],vs:[71,73],w:75,we:65,what:[65,66,68,71],your:[3,65,66,71,73,75]}}) \ No newline at end of file diff --git a/docs/0.10.5/html/unstructured_profiler_example.html b/docs/0.10.5/html/unstructured_profiler_example.html new file mode 100644 index 000000000..78c694147 --- /dev/null +++ b/docs/0.10.5/html/unstructured_profiler_example.html @@ -0,0 +1,836 @@ + + + + + + + + + Unstructured Profilers - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + + +

View this notebook on GitHub

+
+

Unstructured Profilers

+

Data profiling - is the process of examining a dataset and collecting statistical or informational summaries about said dataset.

+

The Profiler class inside the DataProfiler is designed to generate data profiles via the Profiler class, which ingests either a Data class or a Pandas DataFrame.

+

Currently, the Data class supports loading the following file formats:

+
    +
  • Any delimited (CSV, TSV, etc.)

  • +
  • JSON object

  • +
  • Avro

  • +
  • Parquet

  • +
  • Text files

  • +
  • Pandas Series/Dataframe

  • +
+

Once the data is loaded, the Profiler can calculate statistics and predict the entities (via the Labeler) of every column (csv) or key-value (JSON) store as well as dataset wide information, such as the number of nulls, duplicates, etc.

+

This example will look at specifically the unstructured data types for unstructured profiling. This means that only text files, lists of strings, single column pandas dataframes/series, or DataProfile Data objects in string format will work with the unstructured profiler.

+
+

Reporting

+

One of the primary purposes of the Profiler are to quickly identify what is in the dataset. This can be useful for analyzing a dataset prior to use or determining which columns could be useful for a given purpose.

+

In terms of reporting, there are multiple reporting options:

+
    +
  • Pretty: Floats are rounded to four decimal places, and lists are shortened.

  • +
  • Compact: Similar to pretty, but removes detailed statistics

  • +
  • Serializable: Output is json serializable and not prettified

  • +
  • Flat: Nested Output is returned as a flattened dictionary

  • +
+

The Pretty and Compact reports are the two most commonly used reports and includes global_stats and data_stats for the given dataset. global_stats contains overall properties of the data such as samples used and file encoding. data_stats contains specific properties and statistics for each text sample.

+

For unstructured profiles, the report looks like this:

+
"global_stats": {
+    "samples_used": int,
+    "empty_line_count": int,
+    "file_type": string,
+    "encoding": string
+},
+"data_stats": {
+    "data_label": {
+        "entity_counts": {
+            "word_level": dict(int),
+            "true_char_level": dict(int),
+            "postprocess_char_level": dict(int)
+        },
+        "times": dict(float)
+    },
+    "statistics": {
+        "vocab": list(char),
+        "words": list(string),
+        "word_count": dict(int),
+        "times": dict(float)
+    }
+}
+
+
+
+
[ ]:
+
+
+
+import os
+import sys
+import json
+
+try:
+    sys.path.insert(0, '..')
+    import dataprofiler as dp
+except ImportError:
+    import dataprofiler as dp
+
+data_path = "../dataprofiler/tests/data"
+
+# remove extra tf loggin
+import tensorflow as tf
+tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
+
+
+
+
+
[ ]:
+
+
+
+data = dp.Data(os.path.join(data_path, "txt/discussion_reddit.txt"))
+profile = dp.Profiler(data)
+
+report  = profile.report(report_options={"output_format": "pretty"})
+print(json.dumps(report, indent=4))
+
+
+
+
+
+

Profiler Type

+

It should be noted, in addition to reading the input data from text files, DataProfiler allows the input data as a pandas dataframe, a pandas series, a list, and Data objects (when an unstructured format is selected) if the Profiler is explicitly chosen as unstructured.

+
+
[ ]:
+
+
+
+# run data profiler and get the report
+import pandas as pd
+data = dp.Data(os.path.join(data_path, "csv/SchoolDataSmall.csv"), options={"data_format": "records"})
+profile = dp.Profiler(data, profiler_type='unstructured')
+
+report  = profile.report(report_options={"output_format":"pretty"})
+print(json.dumps(report, indent=4))
+
+
+
+
+
+

Profiler options

+

The DataProfiler has the ability to turn on and off components as needed. This is accomplished via the ProfilerOptions class.

+

For example, if a user doesn’t require vocab count information they may desire to turn off the word count functionality.

+

Below, let’s remove the vocab count and set the stop words.

+

Full list of options in the Profiler section of the DataProfiler documentation.

+
+
[ ]:
+
+
+
+data = dp.Data(os.path.join(data_path, "txt/discussion_reddit.txt"))
+
+profile_options = dp.ProfilerOptions()
+
+# Setting multiple options via set
+profile_options.set({ "*.vocab.is_enabled": False, "*.is_case_sensitive": True })
+
+# Set options via directly setting them
+profile_options.unstructured_options.text.stop_words = ["These", "are", "stop", "words"]
+
+profile = dp.Profiler(data, options=profile_options)
+report  = profile.report(report_options={"output_format": "compact"})
+
+# Print the report
+print(json.dumps(report, indent=4))
+
+
+
+
+
+

Updating Profiles

+

Beyond just profiling, one of the unique aspects of the DataProfiler is the ability to update the profiles. To update appropriately, the schema (columns / keys) must match appropriately.

+
+
[ ]:
+
+
+
+# Load and profile a CSV file
+data = dp.Data(os.path.join(data_path, "txt/sentence-3x.txt"))
+profile = dp.Profiler(data)
+
+# Update the profile with new data:
+new_data = dp.Data(os.path.join(data_path, "txt/sentence-3x.txt"))
+profile.update_profile(new_data)
+
+# Take a peek at the data
+print(data.data)
+print(new_data.data)
+
+# Report the compact version of the profile
+report  = profile.report(report_options={"output_format": "compact"})
+print(json.dumps(report, indent=4))
+
+
+
+
+
+

Merging Profiles

+

Merging profiles are an alternative method for updating profiles. Particularly, multiple profiles can be generated seperately, then added together with a simple + command: profile3 = profile1 + profile2

+
+
[ ]:
+
+
+
+# Load a CSV file with a schema
+data1 = dp.Data(os.path.join(data_path, "txt/sentence-3x.txt"))
+profile1 = dp.Profiler(data1)
+
+# Load another CSV file with the same schema
+data2 = dp.Data(os.path.join(data_path, "txt/sentence-3x.txt"))
+profile2 = dp.Profiler(data2)
+
+# Merge the profiles
+profile3 = profile1 + profile2
+
+# Report the compact version of the profile
+report  = profile3.report(report_options={"output_format":"compact"})
+print(json.dumps(report, indent=4))
+
+
+
+

As you can see, the update_profile function and the + operator function similarly. The reason the + operator is important is that it’s possible to save and load profiles, which we cover next.

+
+
+

Differences in Data

+

Can be applied to both structured and unstructured datasets.

+

Such reports can provide details on the differences between training and validation data like in this pseudo example:

+
profiler_training = dp.Profiler(training_data)
+profiler_testing = dp.Profiler(testing_data)
+
+validation_report = profiler_training.diff(profiler_testing)
+
+
+
+
[ ]:
+
+
+
+from pprint import pprint
+
+# unstructured differences example
+data_split_differences = profile1.diff(profile2)
+pprint(data_split_differences)
+
+
+
+
+
+

Saving and Loading a Profile

+

Not only can the Profiler create and update profiles, it’s also possible to save, load then manipulate profiles.

+
+
[ ]:
+
+
+
+# Load data
+data = dp.Data(os.path.join(data_path, "txt/sentence-3x.txt"))
+
+# Generate a profile
+profile = dp.Profiler(data)
+
+# Save a profile to disk for later (saves as pickle file)
+profile.save(filepath="my_profile.pkl")
+
+# Load a profile from disk
+loaded_profile = dp.Profiler.load("my_profile.pkl")
+
+# Report the compact version of the profile
+report = profile.report(report_options={"output_format":"compact"})
+print(json.dumps(report, indent=4))
+
+
+
+

With the ability to save and load profiles, profiles can be generated via multiple machines then merged. Further, profiles can be stored and later used in applications such as change point detection, synthetic data generation, and more.

+
+
[ ]:
+
+
+
+# Load a multiple files via the Data class
+filenames = ["txt/sentence-3x.txt",
+             "txt/sentence.txt"]
+data_objects = []
+for filename in filenames:
+    data_objects.append(dp.Data(os.path.join(data_path, filename)))
+
+print(data_objects)
+# Generate and save profiles
+for i in range(len(data_objects)):
+    profile = dp.Profiler(data_objects[i])
+    report = profile.report(report_options={"output_format":"compact"})
+    print(json.dumps(report, indent=4))
+    profile.save(filepath="data-"+str(i)+".pkl")
+
+
+# Load profiles and add them together
+profile = None
+for i in range(len(data_objects)):
+    if profile is None:
+        profile = dp.Profiler.load("data-"+str(i)+".pkl")
+    else:
+        profile += dp.Profiler.load("data-"+str(i)+".pkl")
+
+
+# Report the compact version of the profile
+report = profile.report(report_options={"output_format":"compact"})
+print(json.dumps(report, indent=4))
+
+
+
+
+
+ +
+ +
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/0.10.5/html/unstructured_profiler_example.ipynb b/docs/0.10.5/html/unstructured_profiler_example.ipynb new file mode 100644 index 000000000..9ab754cc7 --- /dev/null +++ b/docs/0.10.5/html/unstructured_profiler_example.ipynb @@ -0,0 +1,436 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f37ca393", + "metadata": {}, + "source": [ + "# Unstructured Profilers" + ] + }, + { + "cell_type": "markdown", + "id": "ff9bd095", + "metadata": {}, + "source": [ + "**Data profiling** - *is the process of examining a dataset and collecting statistical or informational summaries about said dataset.*\n", + "\n", + "The Profiler class inside the DataProfiler is designed to generate *data profiles* via the Profiler class, which ingests either a Data class or a Pandas DataFrame. \n", + "\n", + "Currently, the Data class supports loading the following file formats:\n", + "\n", + "* Any delimited (CSV, TSV, etc.)\n", + "* JSON object\n", + "* Avro\n", + "* Parquet\n", + "* Text files\n", + "* Pandas Series/Dataframe\n", + "\n", + "Once the data is loaded, the Profiler can calculate statistics and predict the entities (via the Labeler) of every column (csv) or key-value (JSON) store as well as dataset wide information, such as the number of nulls, duplicates, etc.\n", + "\n", + "This example will look at specifically the unstructured data types for unstructured profiling. This means that only text files, lists of strings, single column pandas dataframes/series, or DataProfile Data objects in string format will work with the unstructured profiler. " + ] + }, + { + "cell_type": "markdown", + "id": "de58b9c4", + "metadata": {}, + "source": [ + "## Reporting" + ] + }, + { + "cell_type": "markdown", + "id": "8001185a", + "metadata": {}, + "source": [ + "One of the primary purposes of the Profiler are to quickly identify what is in the dataset. This can be useful for analyzing a dataset prior to use or determining which columns could be useful for a given purpose.\n", + "\n", + "In terms of reporting, there are multiple reporting options:\n", + "\n", + "* **Pretty**: Floats are rounded to four decimal places, and lists are shortened.\n", + "* **Compact**: Similar to pretty, but removes detailed statistics\n", + "* **Serializable**: Output is json serializable and not prettified\n", + "* **Flat**: Nested Output is returned as a flattened dictionary\n", + "\n", + "The **Pretty** and **Compact** reports are the two most commonly used reports and includes `global_stats` and `data_stats` for the given dataset. `global_stats` contains overall properties of the data such as samples used and file encoding. `data_stats` contains specific properties and statistics for each text sample.\n", + "\n", + "For unstructured profiles, the report looks like this:\n", + "\n", + "```\n", + "\"global_stats\": {\n", + " \"samples_used\": int,\n", + " \"empty_line_count\": int,\n", + " \"file_type\": string,\n", + " \"encoding\": string\n", + "},\n", + "\"data_stats\": {\n", + " \"data_label\": {\n", + " \"entity_counts\": {\n", + " \"word_level\": dict(int),\n", + " \"true_char_level\": dict(int),\n", + " \"postprocess_char_level\": dict(int)\n", + " },\n", + " \"times\": dict(float)\n", + " },\n", + " \"statistics\": {\n", + " \"vocab\": list(char),\n", + " \"words\": list(string),\n", + " \"word_count\": dict(int),\n", + " \"times\": dict(float)\n", + " }\n", + "}\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5fcb5447", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " import dataprofiler as dp\n", + "\n", + "data_path = \"../dataprofiler/tests/data\"\n", + "\n", + "# remove extra tf loggin\n", + "import tensorflow as tf\n", + "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7fc2df6", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "data = dp.Data(os.path.join(data_path, \"txt/discussion_reddit.txt\"))\n", + "profile = dp.Profiler(data)\n", + "\n", + "report = profile.report(report_options={\"output_format\": \"pretty\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "4d183992", + "metadata": {}, + "source": [ + "## Profiler Type" + ] + }, + { + "cell_type": "markdown", + "id": "d7ec39d2", + "metadata": {}, + "source": [ + "It should be noted, in addition to reading the input data from text files, DataProfiler allows the input data as a pandas dataframe, a pandas series, a list, and Data objects (when an unstructured format is selected) if the Profiler is explicitly chosen as unstructured." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29737f25", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "# run data profiler and get the report\n", + "import pandas as pd\n", + "data = dp.Data(os.path.join(data_path, \"csv/SchoolDataSmall.csv\"), options={\"data_format\": \"records\"})\n", + "profile = dp.Profiler(data, profiler_type='unstructured')\n", + "\n", + "report = profile.report(report_options={\"output_format\":\"pretty\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "fe02ad64", + "metadata": {}, + "source": [ + "## Profiler options" + ] + }, + { + "cell_type": "markdown", + "id": "40804cc9", + "metadata": {}, + "source": [ + "The DataProfiler has the ability to turn on and off components as needed. This is accomplished via the `ProfilerOptions` class.\n", + "\n", + "For example, if a user doesn't require vocab count information they may desire to turn off the word count functionality.\n", + "\n", + "Below, let's remove the vocab count and set the stop words. \n", + "\n", + "Full list of options in the Profiler section of the [DataProfiler documentation](https://capitalone.github.io/DataProfiler/profile_options.html)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d25d899", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "data = dp.Data(os.path.join(data_path, \"txt/discussion_reddit.txt\"))\n", + "\n", + "profile_options = dp.ProfilerOptions()\n", + "\n", + "# Setting multiple options via set\n", + "profile_options.set({ \"*.vocab.is_enabled\": False, \"*.is_case_sensitive\": True })\n", + "\n", + "# Set options via directly setting them\n", + "profile_options.unstructured_options.text.stop_words = [\"These\", \"are\", \"stop\", \"words\"]\n", + "\n", + "profile = dp.Profiler(data, options=profile_options)\n", + "report = profile.report(report_options={\"output_format\": \"compact\"})\n", + "\n", + "# Print the report\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "2052415a", + "metadata": {}, + "source": [ + "## Updating Profiles" + ] + }, + { + "cell_type": "markdown", + "id": "7e02f746", + "metadata": {}, + "source": [ + "Beyond just profiling, one of the unique aspects of the DataProfiler is the ability to update the profiles. To update appropriately, the schema (columns / keys) must match appropriately." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ab8022f", + "metadata": {}, + "outputs": [], + "source": [ + "# Load and profile a CSV file\n", + "data = dp.Data(os.path.join(data_path, \"txt/sentence-3x.txt\"))\n", + "profile = dp.Profiler(data)\n", + "\n", + "# Update the profile with new data:\n", + "new_data = dp.Data(os.path.join(data_path, \"txt/sentence-3x.txt\"))\n", + "profile.update_profile(new_data)\n", + "\n", + "# Take a peek at the data\n", + "print(data.data)\n", + "print(new_data.data)\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile.report(report_options={\"output_format\": \"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "66ec6dc5", + "metadata": {}, + "source": [ + "## Merging Profiles" + ] + }, + { + "cell_type": "markdown", + "id": "e2265fe9", + "metadata": {}, + "source": [ + "Merging profiles are an alternative method for updating profiles. Particularly, multiple profiles can be generated seperately, then added together with a simple `+` command: `profile3 = profile1 + profile2`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc68ca07", + "metadata": {}, + "outputs": [], + "source": [ + "# Load a CSV file with a schema\n", + "data1 = dp.Data(os.path.join(data_path, \"txt/sentence-3x.txt\"))\n", + "profile1 = dp.Profiler(data1)\n", + "\n", + "# Load another CSV file with the same schema\n", + "data2 = dp.Data(os.path.join(data_path, \"txt/sentence-3x.txt\"))\n", + "profile2 = dp.Profiler(data2)\n", + "\n", + "# Merge the profiles\n", + "profile3 = profile1 + profile2\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile3.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "7ea07dc6", + "metadata": {}, + "source": [ + "As you can see, the `update_profile` function and the `+` operator function similarly. The reason the `+` operator is important is that it's possible to *save and load profiles*, which we cover next." + ] + }, + { + "cell_type": "markdown", + "id": "4704961a", + "metadata": {}, + "source": [ + "## Differences in Data\n", + "Can be applied to both structured and unstructured datasets. \n", + "\n", + "Such reports can provide details on the differences between training and validation data like in this pseudo example:\n", + "```python\n", + "profiler_training = dp.Profiler(training_data)\n", + "profiler_testing = dp.Profiler(testing_data)\n", + "\n", + "validation_report = profiler_training.diff(profiler_testing)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "58f92c1b", + "metadata": {}, + "outputs": [], + "source": [ + "from pprint import pprint\n", + "\n", + "# unstructured differences example\n", + "data_split_differences = profile1.diff(profile2)\n", + "pprint(data_split_differences)" + ] + }, + { + "cell_type": "markdown", + "id": "30868000", + "metadata": {}, + "source": [ + "## Saving and Loading a Profile" + ] + }, + { + "cell_type": "markdown", + "id": "f2858072", + "metadata": {}, + "source": [ + "Not only can the Profiler create and update profiles, it's also possible to save, load then manipulate profiles." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ad9ca57", + "metadata": {}, + "outputs": [], + "source": [ + "# Load data\n", + "data = dp.Data(os.path.join(data_path, \"txt/sentence-3x.txt\"))\n", + "\n", + "# Generate a profile\n", + "profile = dp.Profiler(data)\n", + "\n", + "# Save a profile to disk for later (saves as pickle file)\n", + "profile.save(filepath=\"my_profile.pkl\")\n", + "\n", + "# Load a profile from disk\n", + "loaded_profile = dp.Profiler.load(\"my_profile.pkl\")\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "8f9859c2", + "metadata": {}, + "source": [ + "With the ability to save and load profiles, profiles can be generated via multiple machines then merged. Further, profiles can be stored and later used in applications such as change point detection, synthetic data generation, and more. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3571f2d0", + "metadata": {}, + "outputs": [], + "source": [ + "# Load a multiple files via the Data class\n", + "filenames = [\"txt/sentence-3x.txt\",\n", + " \"txt/sentence.txt\"]\n", + "data_objects = []\n", + "for filename in filenames:\n", + " data_objects.append(dp.Data(os.path.join(data_path, filename)))\n", + "\n", + "print(data_objects)\n", + "# Generate and save profiles\n", + "for i in range(len(data_objects)):\n", + " profile = dp.Profiler(data_objects[i])\n", + " report = profile.report(report_options={\"output_format\":\"compact\"})\n", + " print(json.dumps(report, indent=4))\n", + " profile.save(filepath=\"data-\"+str(i)+\".pkl\")\n", + "\n", + "\n", + "# Load profiles and add them together\n", + "profile = None\n", + "for i in range(len(data_objects)):\n", + " if profile is None:\n", + " profile = dp.Profiler.load(\"data-\"+str(i)+\".pkl\")\n", + " else:\n", + " profile += dp.Profiler.load(\"data-\"+str(i)+\".pkl\")\n", + "\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/index.rst b/docs/source/index.rst index 7961de1cd..5e97ab064 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -476,6 +476,7 @@ In addition, it utilizes only the first 10,000 rows. Versions ======== +* `0.10.5`_ * `0.10.4`_ * `0.10.3`_ * `0.10.2`_ @@ -582,3 +583,5 @@ Versions .. _0.10.4: ../../0.10.4/html/index.html +.. _0.10.5: ../../0.10.5/html/index.html + diff --git a/index.html b/index.html index e61dd1fe2..11f8ba6e8 100644 --- a/index.html +++ b/index.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/profiler_options.html b/profiler_options.html index b7c436e11..1c6c42076 100644 --- a/profiler_options.html +++ b/profiler_options.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file

bgrK&!qU8R?ePu=h|vk{TuFkI)a)wH3d!&F zBV<$|`BD*zl#qN5wRa1NAn;8Ul2qKqI~-u5UXxOrnhz)Pi!@Y1M|jduF;AvI zvOwmSRWf&^ew5|H^H=#z>D4Ya2kEGe%mO39OMT(FWv(Xq`%3aH-I>LdogOP3S=@l( z&N+{HnR{v3ECH%)?)N{TN{e`;aq?&%Q5)5X%mc_!nNv>WI}opcMpd+S5jvHkJ&oGC6-|)+ zW-8j_Ge~o*5r|Vu4R8Ugd=)~kew>z0Lab4cogcjBL2C*F);#8LsjRZ&Ul7xshEi7Lr;V8wM;;OF9 zhAJae;-_?%W#iG1=X638n@?w3k9=~)*|dB}1?e!#Ma=hxl~sFlI@e?Khhl8LtT;Ww zQpe*rA;+{Dq{)oUtyzgq3zU}RIh=i$k~e4zk4sESKSc87RhfKwl_y`;U~k9`J0;59 ztsy+cb+R&poXQ&fu1wZ4vAXq0e51@3h2e+s+CBCmbZ$Ej|dMqd2&dK277pbvLl|uwjUmj ziEb)@y@AKMuEz^JHm)G+ zzDMi7y?8bXo2x&v8rb-~n0;A6o>0%PSXfs^8g%fPP_2i(_=HFvl!7wFq4eT&xi>iw z?Ss>BB?|(s#zD4T%)ZDqj!zN|0T_iO=v{}WD4&<9cENEZ!i^8%^9S(_KC63v11T-& zq#wG$U1kg@W5DJz|%jv zNcjjbCwK|C>jpIZx~LnlsNq$RN*%RM((%B6LGp2sFlou9q#jl_ZA?+Ph@PN}_LQ^_ zgd|u_OND>}9S1SAfWWOMfX*k?DzxXwzcg@`exVb}+Y6V3u_0&;4EZs9Cqg|!L{E`c zL2~G1B($JohrP!R{PTZJ#S2~5#inEOQ3fLCIF;0px4c5?5gYR8#@5zWS!ALWr*+uo z8fpe>z4#2Z;HaQQC1f!B&^^i}&$_Gcx$}p>*#*B@&vip3x|>DWP3U>}fQ8M%ChvyM z{-BFlWG{pkHA1U*WhOocne0@QdMflQB8mNr@yTEZUT3?a67nOpGQM5`aX%h(Or-Jr zXav26HHvTG&*HIy^QX8j#94c;Zs8y(@-g~C-@s+gLbTq9x=7AXAKT!m?h`xkBBaNw z(^)8O7*3O^2%=iH-bsdB84c*_4*Ief3jys+9h(dr6^0LLAhAmWpY-5goVXqzX6`0^ zo+3`NAwef0UN#Q1Lf|o5<==GR7@tB%5Eq=CB2mDmHhsk+KAkD0ixRvT(3{y+pf3J7wxzN&7aMnkCy!d|N8nZo;-yGO_8k zKSR(`K^cW?JSc0wLT}PeE{bOf7fN-;KgVHRxXzJT=l!np?$$ZLb>4VAvX_d#eRj?zKLArAqPnurdSS<4h3Q^j2Pj!AcpW6ShO Rl(`03-o!{zu#0cT{13NlXvqKo literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/graphs.doctree b/docs/0.10.5/doctrees/graphs.doctree new file mode 100644 index 0000000000000000000000000000000000000000..c784de8ecddb1bec80489e3c0dc461f6a2e57493 GIT binary patch literal 25584 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/index.doctree b/docs/0.10.5/doctrees/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..3e88752111de14c7d6ceb074ba86c2bd4d308feb GIT binary patch literal 64408 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 bvvrm4p%`}d48>q5&oP@nyy1)l{LlVh$^61= literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/install.doctree b/docs/0.10.5/doctrees/install.doctree new file mode 100644 index 0000000000000000000000000000000000000000..985f360b6ad1077186908168c5d96485e56fb55f GIT binary patch literal 12450 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 OHqLU7A@!y0=Dz{_4szQ7 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/labeler.doctree b/docs/0.10.5/doctrees/labeler.doctree new file mode 100644 index 0000000000000000000000000000000000000000..62347eb2670e507ae6d160c51e740ce5acdb4908 GIT binary patch literal 46397 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/merge_profile_list.doctree b/docs/0.10.5/doctrees/merge_profile_list.doctree new file mode 100644 index 0000000000000000000000000000000000000000..943bd89b1b46313838d64524d3d3cec848a64089 GIT binary patch literal 11848 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 1\n", + " ):\n", + " errors.append(\n", + " param + \" must be a valid integer or float \" \"from 0 to 1.\"\n", + " )\n", + " elif (\n", + " param == \"size_fc\" or param == \"size_lstm\"\n", + " ): # additional check for size_lstm\n", + " if (\n", + " not isinstance(parameters[param], list)\n", + " or len(parameters[param]) == 0\n", + " ):\n", + " errors.append(param + \" must be a non-empty list of \" \"integers.\")\n", + " else:\n", + " for item in parameters[param]:\n", + " if not isinstance(item, int):\n", + " errors.append(\n", + " param + \" must be a non-empty \" \"list of integers.\"\n", + " )\n", + " break\n", + " elif param in [\n", + " \"default_label\",\n", + " \"activation\",\n", + " \"recurrent_activation\",\n", + " ]: # additional check for activation and recurrent_activation\n", + " if not isinstance(parameters[param], str):\n", + " error = str(param) + \" must be a string.\"\n", + " errors.append(error)\n", + "\n", + " # Error if there are extra parameters thrown in\n", + " for param in parameters:\n", + " if param not in list_of_necessary_params:\n", + " errors.append(param + \" is not an accepted parameter.\")\n", + " if errors:\n", + " raise ValueError(\"\\n\".join(errors))\n", + "\n", + " def _construct_model(self):\n", + " \"\"\"\n", + " Model constructor for the data labeler. This also serves as a weight\n", + " reset.\n", + "\n", + " :return: None\n", + " \"\"\"\n", + " num_labels = self.num_labels\n", + " default_ind = self.label_mapping[self._parameters[\"default_label\"]]\n", + "\n", + " # Reset model\n", + " tf.keras.backend.clear_session()\n", + "\n", + " # generate glove embedding\n", + " create_glove_char(self._parameters[\"dim_embed\"])\n", + "\n", + " # generate model\n", + " self._model = tf.keras.models.Sequential()\n", + "\n", + " # default parameters\n", + " max_length = self._parameters[\"max_length\"]\n", + " max_char_encoding_id = self._parameters[\"max_char_encoding_id\"]\n", + "\n", + " # Encoding layer\n", + " def encoding_function(input_str):\n", + " char_in_vector = CharacterLevelLstmModel._char_encoding_layer(\n", + " input_str, max_char_encoding_id, max_length\n", + " )\n", + " return char_in_vector\n", + "\n", + " self._model.add(tf.keras.layers.Input(shape=(None,), dtype=tf.string))\n", + "\n", + " self._model.add(\n", + " tf.keras.layers.Lambda(encoding_function, output_shape=tuple([max_length]))\n", + " )\n", + "\n", + " # Create a pre-trained weight matrix\n", + " # character encoding indices range from 0 to max_char_encoding_id,\n", + " # we add one extra index for out-of-vocabulary character\n", + " embed_file = os.path.join(\n", + " \"../dataprofiler/labelers\",\n", + " \"embeddings/glove-reduced-{}D.txt\".format(self._parameters[\"dim_embed\"]),\n", + " )\n", + " embedding_matrix = np.zeros(\n", + " (max_char_encoding_id + 2, self._parameters[\"dim_embed\"])\n", + " )\n", + " embedding_dict = build_embd_dictionary(embed_file)\n", + "\n", + " input_shape = tuple([max_length])\n", + " # Fill in the weight matrix: let pad and space be 0s\n", + " for ascii_num in range(max_char_encoding_id):\n", + " if chr(ascii_num) in embedding_dict:\n", + " embedding_matrix[ascii_num + 1] = embedding_dict[chr(ascii_num)]\n", + "\n", + " self._model.add(\n", + " tf.keras.layers.Embedding(\n", + " max_char_encoding_id + 2,\n", + " self._parameters[\"dim_embed\"],\n", + " weights=[embedding_matrix],\n", + " input_length=input_shape[0],\n", + " trainable=True,\n", + " )\n", + " )\n", + "\n", + " # Add the lstm layers\n", + " #########################################################\n", + " #########################################################\n", + " for size in self._parameters[\"size_lstm\"]:\n", + " self._model.add(\n", + " tf.keras.layers.LSTM(\n", + " units=size,\n", + " recurrent_dropout=self._parameters[\"rec_dropout\"],\n", + " activation=self._parameters[\"activation\"],\n", + " recurrent_activation=self._parameters[\"recurrent_activation\"],\n", + " return_sequences=True,\n", + " )\n", + " )\n", + " if self._parameters[\"dropout\"]:\n", + " self._model.add(tf.keras.layers.Dropout(self._parameters[\"dropout\"]))\n", + " #########################################################\n", + " #########################################################\n", + "\n", + " # Add the fully connected layers\n", + " for size in self._parameters[\"size_fc\"]:\n", + " self._model.add(tf.keras.layers.Dense(units=size, activation=\"relu\"))\n", + " if self._parameters[\"dropout\"]:\n", + " self._model.add(tf.keras.layers.Dropout(self._parameters[\"dropout\"]))\n", + "\n", + " # Add the final Softmax layer\n", + " self._model.add(tf.keras.layers.Dense(num_labels, activation=\"softmax\"))\n", + "\n", + " # Output the model into a .pb file for TensorFlow\n", + " argmax_layer = tf.keras.backend.argmax(self._model.output)\n", + "\n", + " # Create confidence layers\n", + " final_predicted_layer = CharacterLevelLstmModel._argmax_threshold_layer(\n", + " num_labels, threshold=0.0, default_ind=default_ind\n", + " )\n", + "\n", + " argmax_outputs = self._model.outputs + [\n", + " argmax_layer,\n", + " final_predicted_layer(argmax_layer, self._model.output),\n", + " ]\n", + " self._model = tf.keras.Model(self._model.inputs, argmax_outputs)\n", + "\n", + " # Compile the model\n", + " softmax_output_layer_name = self._model.outputs[0].name.split(\"/\")[0]\n", + " losses = {softmax_output_layer_name: \"categorical_crossentropy\"}\n", + "\n", + " # use f1 score metric\n", + " f1_score_training = F1Score(num_classes=num_labels, average=\"micro\")\n", + " metrics = {softmax_output_layer_name: [\"acc\", f1_score_training]}\n", + "\n", + " self._model.compile(loss=losses, optimizer=\"adam\", metrics=metrics)\n", + "\n", + " self._epoch_id = 0\n", + " self._model_num_labels = num_labels\n", + " self._model_default_ind = default_ind" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "d66bd25c", + "metadata": {}, + "source": [ + "## Integrate the new LSTM model to the DataLabeler" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "479f407a", + "metadata": {}, + "source": [ + "Once the LSTM model is built, it replaces the existing model in the DataLabeler pipeline, which is then trained on the given dataset. Note that, as the DataLabeler is trained on the above tabular dataset, its label mapping is updated by the list of column names in that dataset while training." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb482ffe", + "metadata": {}, + "outputs": [], + "source": [ + "# get labels from the given dataset\n", + "value_label_df = data_train.reset_index(drop=True).melt()\n", + "value_label_df.columns = [1, 0] # labels=1, values=0 in that order\n", + "value_label_df = value_label_df.astype(str)\n", + "labels = value_label_df[1].unique().tolist()\n", + "\n", + "# create a new LSTM model\n", + "# set default label (one of the column names) to the model\n", + "model = CharacterLevelLstmModel(label_mapping=labels, parameters={'default_label': 'comment'})\n", + "\n", + "# add the new LSTM model to the data labeler\n", + "data_labeler = dp.DataLabeler(labeler_type='structured', trainable=True)\n", + "data_labeler.set_model(model)\n", + "\n", + "# set default label (one of the column names) to the preprocessor and postprocessor\n", + "processor_params = {'default_label': 'comment'}\n", + "data_labeler._preprocessor.set_params(**processor_params)\n", + "data_labeler._postprocessor.set_params(**processor_params)\n", + "\n", + "# train the data labeler\n", + "save_dirpath=\"data_labeler_saved\"\n", + "if not os.path.exists(save_dirpath):\n", + " os.makedirs(save_dirpath)\n", + "\n", + "epochs=2\n", + "data_labeler.fit(\n", + " x=value_label_df[0], y=value_label_df[1], labels=labels, epochs=epochs)\n", + "if save_dirpath:\n", + " data_labeler.save_to_disk(save_dirpath)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "14b78c69", + "metadata": {}, + "source": [ + "The trained Data Labeler is then used by the Data Profiler to provide the prediction on the new dataset. In this example, all options except data labeler are disabled for the sake of presenting data labeler functionality. The results are given in the columnar format where true column types are given in the first column, and the predicted column labels are given in the second column." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bdfcf1d2", + "metadata": {}, + "outputs": [], + "source": [ + "# predict with the data labeler object\n", + "profile_options = dp.ProfilerOptions()\n", + "profile_options.set({\"structured_options.text.is_enabled\": False, \n", + " \"int.is_enabled\": False, \n", + " \"float.is_enabled\": False, \n", + " \"order.is_enabled\": False, \n", + " \"category.is_enabled\": False, \n", + " \"datetime.is_enabled\": False,})\n", + "profile_options.set({'structured_options.data_labeler.data_labeler_object': data_labeler})\n", + "profile = dp.Profiler(data_test, options=profile_options)\n", + "\n", + "# get the prediction from the data profiler\n", + "def get_structured_results(results):\n", + " columns = []\n", + " predictions = []\n", + " for col_report in results['data_stats']:\n", + " columns.append(col_report['column_name'])\n", + " predictions.append(col_report['data_label'])\n", + "\n", + " df_results = pd.DataFrame({'Column': columns, 'Prediction': predictions})\n", + " return df_results\n", + "\n", + "results = profile.report()\n", + "print(get_structured_results(results))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "cc60ff8a", + "metadata": {}, + "source": [ + "In summary, users can define their own model, plug it in the DataLabeler pipeline, and train the labeler with the new dataset. Above, we show one example of adding the LSTM model to the pipeline. Interested users can implement other neural network models as desired with the same process." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/doctrees/nbsphinx/column_name_labeler_example.ipynb b/docs/0.10.5/doctrees/nbsphinx/column_name_labeler_example.ipynb new file mode 100644 index 000000000..6d3369698 --- /dev/null +++ b/docs/0.10.5/doctrees/nbsphinx/column_name_labeler_example.ipynb @@ -0,0 +1,364 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e04c382a-7c49-452b-b9bf-e448951c64fe", + "metadata": {}, + "source": [ + "# ColumnName Labeler Tutorial" + ] + }, + { + "cell_type": "markdown", + "id": "6fb3ecb9-bc51-4c18-93d5-7991bbee5165", + "metadata": {}, + "source": [ + "This notebook teaches how to use the existing `ColumnNameModel`:\n", + "\n", + "1. Loading and utilizing the pre-existing `ColumnNameModel`\n", + "2. Run the labeler\n", + "\n", + "First, let's import the libraries needed for this example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a67c197b-d3ee-4896-a96f-cc3d043601d3", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "from pprint import pprint\n", + "\n", + "import pandas as pd\n", + "\n", + "try:\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " sys.path.insert(0, '../..')\n", + " import dataprofiler as dp" + ] + }, + { + "cell_type": "markdown", + "id": "35841215", + "metadata": {}, + "source": [ + "## Loading and predicting using a pre-existing model using `load_from_library`\n", + "\n", + "The easiest option for users is to `load_from_library` by specifying the name for the labeler in the `resources/` folder. Quickly import and start predicting with any model from the Data Profiler's library of models available." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "46e36dd6", + "metadata": {}, + "outputs": [], + "source": [ + "labeler_from_library = dp.DataLabeler.load_from_library('column_name_labeler')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dfa94868", + "metadata": {}, + "outputs": [], + "source": [ + "labeler_from_library.predict(data=[\"ssn\"])" + ] + }, + { + "cell_type": "markdown", + "id": "c71356f4-9020-4862-a1e1-816effbb5443", + "metadata": {}, + "source": [ + "## Loading and using the pre-existing column name labeler using `load_with_components`\n", + "\n", + "For example purposes here, we will import the exsting `ColumnName` labeler via the `load_with_components` command from the `dp.DataLabeler`. This shows a bit more of the details of the data labeler's flow." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "818c5b88", + "metadata": {}, + "outputs": [], + "source": [ + "parameters = {\n", + " \"true_positive_dict\": [\n", + " {\"attribute\": \"ssn\", \"label\": \"ssn\"},\n", + " {\"attribute\": \"suffix\", \"label\": \"name\"},\n", + " {\"attribute\": \"my_home_address\", \"label\": \"address\"},\n", + " ],\n", + " \"false_positive_dict\": [\n", + " {\n", + " \"attribute\": \"contract_number\",\n", + " \"label\": \"ssn\",\n", + " },\n", + " {\n", + " \"attribute\": \"role\",\n", + " \"label\": \"name\",\n", + " },\n", + " {\n", + " \"attribute\": \"send_address\",\n", + " \"label\": \"address\",\n", + " },\n", + " ],\n", + " \"negative_threshold_config\": 50,\n", + " \"positive_threshold_config\": 85,\n", + " \"include_label\": True,\n", + " }\n", + "\n", + "label_mapping = {\"ssn\": 1, \"name\": 2, \"address\": 3}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9098329e", + "metadata": {}, + "outputs": [], + "source": [ + "# pre processor \n", + "preprocessor = dp.labelers.data_processing.DirectPassPreprocessor()\n", + "\n", + "# model\n", + "from dataprofiler.labelers.column_name_model import ColumnNameModel\n", + "model = ColumnNameModel(\n", + " parameters=parameters,\n", + " label_mapping=label_mapping,\n", + ")\n", + "\n", + "\n", + "# post processor\n", + "postprocessor = dp.labelers.data_processing.ColumnNameModelPostprocessor()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "113d6655-4bca-4d8e-9e6f-b972e29d5684", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler = dp.DataLabeler.load_with_components(\n", + " preprocessor=preprocessor,\n", + " model=model,\n", + " postprocessor=postprocessor,\n", + ")\n", + "data_labeler.model.help()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b405887-2b92-44ca-b8d7-29c384f6dd9c", + "metadata": {}, + "outputs": [], + "source": [ + "pprint(data_labeler.label_mapping)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11916a48-098c-4056-ac6c-b9542d85fa86", + "metadata": {}, + "outputs": [], + "source": [ + "pprint(data_labeler.model._parameters)" + ] + }, + { + "cell_type": "markdown", + "id": "da0e97ee-8d6d-4631-9b55-78ed904d5f41", + "metadata": {}, + "source": [ + "### Predicting with the ColumnName labeler\n", + "\n", + "In the prediction below, the data will be passed into to stages in the background\n", + "- 1) `compare_negative`: The idea behind the `compare_negative` is to first filter out any possibility of flagging a false positive in the model prediction. In this step, the confidence value is checked and if the similarity is too close to being a false positive, that particular string in the `data` is removed and not returned to the `compare_positive`.\n", + "- 2) `compare_positive`: Finally the `data` is passed to the `compare_positive` step and checked for similarity with the the `true_positive_dict` values. Again, during this stage the `positive_threshold_config` is used to filter the results to only those `data` values that are greater than or equal to the `positive_threshold_config` provided by the user." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fe519e65-36a7-4f42-8314-5369de8635c7", + "metadata": {}, + "outputs": [], + "source": [ + "# evaluate a prediction using the default parameters\n", + "data_labeler.predict(data=[\"ssn\", \"name\", \"address\"])" + ] + }, + { + "cell_type": "markdown", + "id": "b41d834d-e47b-45a6-8970-d2d2033e2ade", + "metadata": {}, + "source": [ + "## Replacing the parameters in the existing labeler\n", + "\n", + "We can achieve this by:\n", + "1. Setting the label mapping to the new labels\n", + "2. Setting the model parameters which include: `true_positive_dict`, `false_positive_dict`, `negative_threshold_config`, `positive_threshold_config`, and `include_label`\n", + "\n", + "where `true_positive_dict` and `false_positive_dict` are `lists` of `dicts`, `negative_threshold_config` and `positive_threshold_config` are integer values between `0` and `100`, and `include_label` is a `boolean` value that determines if the output should include the prediction labels or only the confidence values." + ] + }, + { + "cell_type": "markdown", + "id": "c6bb010a-406f-4fd8-abd0-3355a5ad0ded", + "metadata": {}, + "source": [ + "Below, we created 4 labels where `other` is the `default_label`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f86584cf-a7af-4bae-bf44-d87caa68833a", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.set_labels({'other': 0, \"funky_one\": 1, \"funky_two\": 2, \"funky_three\": 3})\n", + "data_labeler.model.set_params(\n", + " true_positive_dict= [\n", + " {\"attribute\": \"ssn\", \"label\": \"funky_one\"},\n", + " {\"attribute\": \"suffix\", \"label\": \"funky_two\"},\n", + " {\"attribute\": \"my_home_address\", \"label\": \"funky_three\"},\n", + " ],\n", + " false_positive_dict=[\n", + " {\n", + " \"attribute\": \"contract_number\",\n", + " \"label\": \"ssn\",\n", + " },\n", + " {\n", + " \"attribute\": \"role\",\n", + " \"label\": \"name\",\n", + " },\n", + " {\n", + " \"attribute\": \"not_my_address\",\n", + " \"label\": \"address\",\n", + " },\n", + " ],\n", + " negative_threshold_config=50,\n", + " positive_threshold_config=85,\n", + " include_label=True,\n", + ")\n", + "data_labeler.label_mapping" + ] + }, + { + "cell_type": "markdown", + "id": "1ece1c8c-18a5-46fc-b563-6458e6e71e53", + "metadata": {}, + "source": [ + "### Predicting with the new labels\n", + "\n", + "Here we are testing the `predict()` method with brand new labels for label_mapping. As we can see the new labels flow throught to the output of the data labeler." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92842e14-2ea6-4879-b58c-c52b607dc94c", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.predict(data=[\"ssn\", \"suffix\"], predict_options=dict(show_confidences=True))" + ] + }, + { + "cell_type": "markdown", + "id": "261b903f-8f4c-403f-839b-ab8813f850e9", + "metadata": {}, + "source": [ + "## Saving the Data Labeler for future use" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6ffbaf2-9400-486a-ba83-5fc9ba9334d7", + "metadata": {}, + "outputs": [], + "source": [ + "if not os.path.isdir('new_column_name_labeler'):\n", + " os.mkdir('new_column_name_labeler')\n", + "data_labeler.save_to_disk('new_column_name_labeler')" + ] + }, + { + "cell_type": "markdown", + "id": "09e40cb6-9d89-41c4-ae28-3dca498f8c68", + "metadata": {}, + "source": [ + "## Loading the saved Data Labeler" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52615b25-70a6-4ebb-8a32-14aaf1e747d9", + "metadata": {}, + "outputs": [], + "source": [ + "saved_labeler = dp.DataLabeler.load_from_disk('new_column_name_labeler')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d1ccc0b3-1dc2-4847-95c2-d6b8769b1590", + "metadata": {}, + "outputs": [], + "source": [ + "# ensuring the parametesr are what we saved.\n", + "print(\"label_mapping:\")\n", + "pprint(saved_labeler.label_mapping)\n", + "print(\"\\nmodel parameters:\")\n", + "pprint(saved_labeler.model._parameters)\n", + "print()\n", + "print(\"postprocessor: \" + saved_labeler.postprocessor.__class__.__name__)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c827f2ae-4af6-4f3f-9651-9ee9ebea9fa0", + "metadata": {}, + "outputs": [], + "source": [ + "# predicting with the loaded labeler.\n", + "saved_labeler.predict([\"ssn\", \"name\", \"address\"])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.7.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/doctrees/nbsphinx/data_reader.ipynb b/docs/0.10.5/doctrees/nbsphinx/data_reader.ipynb new file mode 100644 index 000000000..d2ce887e6 --- /dev/null +++ b/docs/0.10.5/doctrees/nbsphinx/data_reader.ipynb @@ -0,0 +1,689 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "d4d79832-59ab-410a-ad6d-fbba01a3f0d3", + "metadata": {}, + "source": [ + "# Intro to Data Readers\n", + "Within the Data Profiler, there are 5 data reader classes:\n", + "\n", + " * CSVData (delimited data: CSV, TSV, etc.)\n", + " * JSONData\n", + " * ParquetData\n", + " * AVROData\n", + " * GraphData\n", + " * TextData\n", + " \n", + "Each of these classes can be used to read data individually, however the Data Profiler provides the unique capability of auto detecting what data you have and reading it automatically by using the `Data` class.\n", + "```python\n", + "import dataprofiler as dp\n", + "data = dp.Data('/path/to/mydata.abc') # auto detects and reads your data\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "f2315666-20be-4937-9f9a-26d42dc135e2", + "metadata": { + "tags": [] + }, + "source": [ + "## Automatically reading and detecting data\n", + "\n", + "Below is a demonstration of utilizing the `Data` class which automatically detects the type of data for a given file and reads it automatically." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "99e61c6c-43b8-4700-b627-759b5ef8bdda", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " import dataprofiler as dp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8821ad8d-b2c0-489c-ae6a-54c11b7f0a08", + "metadata": {}, + "outputs": [], + "source": [ + "# use data reader to read input data with different file types\n", + "data_folder = \"../dataprofiler/tests/data\"\n", + "csv_files = [\n", + " \"csv/aws_honeypot_marx_geo.csv\",\n", + " \"csv/all-strings-skip-header-author.csv\", # csv files with the author/description on the first line\n", + " \"csv/sparse-first-and-last-column-empty-first-row.txt\", # csv file with the .txt extension\n", + "]\n", + "json_files = [\n", + " \"json/complex_nested.json\",\n", + " \"json/honeypot_intentially_mislabeled_file.csv\", # json file with the .csv extension\n", + "]\n", + "parquet_files = [\n", + " \"parquet/nation.dict.parquet\",\n", + " \"parquet/nation.plain.intentionally_mislabled_file.csv\", # parquet file with the .csv extension\n", + "]\n", + "avro_files = [\n", + " \"avro/userdata1.avro\",\n", + " \"avro/userdata1_intentionally_mislabled_file.json\", # avro file with the .json extension\n", + "]\n", + "graph_files = [\n", + " \"csv/graph_data_csv_identify.csv\", # csv file with graph column names\n", + "]\n", + "text_files = [\n", + " \"txt/discussion_reddit.txt\",\n", + "]\n", + "all_files = csv_files + json_files + parquet_files + avro_files + graph_files + text_files\n", + "print('filepath' + ' ' * 58 + 'data type')\n", + "print('='*80)\n", + "for file in all_files:\n", + " filepath = os.path.join(data_folder, file)\n", + " data = dp.Data(filepath)\n", + " print(\"{:<65} {:<15}\".format(file, data.data_type))\n", + "print(\"\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "49dfc981-59fd-48a5-ad7b-e01f0a52d0b2", + "metadata": {}, + "outputs": [], + "source": [ + "# importing from a url\n", + "data = dp.Data('https://raw.githubusercontent.com/capitalone/DataProfiler/main/dataprofiler/tests/data/csv/diamonds.csv')\n", + "data.head()" + ] + }, + { + "cell_type": "markdown", + "id": "77f8ef2d-5aaf-44d6-b6d1-bf14f7eb7aa6", + "metadata": {}, + "source": [ + "## Specifying detection options of `Data` and loading `pandas.DataFrame`\n", + "\n", + "The `Data` class also gives the ability to set options or if the user wants to load their data with specific requirements.\n", + "Options for each data reader are specified in the docs: https://capitalone.github.io/DataProfiler/docs/0.4.4/html/dataprofiler.data_readers.html\n", + "\n", + "```python\n", + "import dataprofiler as dp\n", + "\n", + "options = {...} # allowed options are specified for each data reader.\n", + "data = dp.Data(data, options=options)\n", + "```\n", + "Later in this tutorial, the options for the CSVData class will be discussed.\n", + "\n", + "Additionally, a user can directly load a `pandas.DataFrame` as any data reader they choose." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b925d4e-ca94-4913-9acf-26a883585e85", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "from dataprofiler.data_readers.csv_data import CSVData\n", + "\n", + "\n", + "df = pd.DataFrame(['my', 'random', 'data'])\n", + "\n", + "# specify via the `Data` class\n", + "data = dp.Data(data=df, data_type='csv')\n", + "print('Data Type: ', data.data_type)\n", + "\n", + "# specifically use the CSVData class\n", + "data = CSVData(data=df)\n", + "print('Data Type: ', data.data_type)" + ] + }, + { + "cell_type": "markdown", + "id": "52c3c3ac-c241-4d91-8ac7-b3d28ffd19c3", + "metadata": {}, + "source": [ + "## Accessing data and attributes\n", + "\n", + "Once loaded, the data can be accessed via the `data` property of the object. Additional information about the data loaded may differ between data readers.\n", + "\n", + "For this example we will focus on `CSVData`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "09fa5929-e710-4107-9313-1370ab639c9c", + "metadata": {}, + "outputs": [], + "source": [ + "filepath = \"../dataprofiler/tests/data/csv/aws_honeypot_marx_geo.csv\"\n", + "data = dp.Data(filepath)\n", + "print('Data Type: ', data.data_type)\n", + "print('Data Filepath: ', data.input_file_path)\n", + "print('File Encoding: ', data.file_encoding)\n", + "print('Data Length (two techniques): ', len(data), data.length)\n", + "print(\"Data Access:\")\n", + "data.data" + ] + }, + { + "cell_type": "markdown", + "id": "b98be971-4768-479d-9e54-00f05a6fb790", + "metadata": {}, + "source": [ + "## Checking data file types with `is_match`\n", + "\n", + "Each data reader has a class method `is_match` which determines whether or not a dataset is of a given data type.\n", + "```python\n", + "CSVData.is_match\n", + "JSONData.is_match\n", + "ParquetData.is_match\n", + "AVROData.is_match\n", + "GraphData.is_match\n", + "TextData.is_match\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "104a32c1-1d50-4aa5-94ce-b2e72de38476", + "metadata": {}, + "outputs": [], + "source": [ + "# supplemental function\n", + "def add_true_false_color(value):\n", + " \"\"\"Converts True to green and False to red in printed text.\"\"\"\n", + " if value:\n", + " return \"\\x1b[92m \" + str(is_match) + \"\\x1b[0m\"\n", + " return \"\\x1b[31m \" + str(is_match) + \"\\x1b[0m\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06868d90-2726-4096-a6da-3866174e6671", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from dataprofiler.data_readers.csv_data import CSVData\n", + "\n", + "\n", + "non_csv_files = [\n", + " 'json/iris-utf-8.json',\n", + " 'json/honeypot_intentially_mislabeled_file.csv',\n", + " 'parquet/titanic.parq',\n", + " 'parquet/nation.plain.intentionally_mislabled_file.csv',\n", + " 'txt/code.txt',\n", + " 'txt/sentence.txt',\n", + " 'avro/users.avro',\n", + " 'avro/snappy_compressed_intentionally_mislabeled_file.csv',\n", + "]\n", + "\n", + "print(\"Is the file a CSV?\")\n", + "print('=' * 80)\n", + "for file in csv_files:\n", + " filepath = os.path.join(data_folder, file)\n", + " is_match = CSVData.is_match(filepath)\n", + " print(add_true_false_color(is_match), ':', file)\n", + " print('=' * 80)\n", + " \n", + "for file in non_csv_files:\n", + " filepath = os.path.join(data_folder, file)\n", + " is_match = CSVData.is_match(filepath)\n", + " print(add_true_false_color(is_match), ':', file)\n", + " print('=' * 80)" + ] + }, + { + "cell_type": "markdown", + "id": "38889990-8e19-4114-a4f3-dc2af938e29d", + "metadata": {}, + "source": [ + "## Reloading data after altering options with `reload`\n", + "\n", + "There are two cases for using the reload function, both of which require the data type to have been interpreted correctly:\n", + "\n", + " 1. The options were not correctly determined\n", + " 2. The options were loaded correctly but a change is desired.\n", + " \n", + "In the example below, the `data_format` for reading the data is changed and the data is then reloaded." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "01870e8d-45ee-4f33-a088-4453c7ffc7c2", + "metadata": {}, + "outputs": [], + "source": [ + "filepath = \"../dataprofiler/tests/data/csv/diamonds.csv\"\n", + "\n", + "data = dp.Data(filepath)\n", + "print('original data:')\n", + "print('=' * 80)\n", + "print(data.data[:5])\n", + "\n", + "print()\n", + "data.reload(options={'data_format': 'records', 'record_samples_per_line': 1})\n", + "print('reloaded data:')\n", + "print('=' * 80)\n", + "data.data[:5]" + ] + }, + { + "cell_type": "markdown", + "id": "e2285f19-9b34-4484-beaa-79df890b2825", + "metadata": {}, + "source": [ + "## A deeper dive into `CSVData`\n", + "\n", + "This next section will focus on how to use the data reader class: `CSVData`. The `CSVData` class is used for reading delimited data. Delimited data are datasets which have their columns specified by a specific character, commonly the `,`. E.g. from the `diamonds.csv` dataset:\n", + "```\n", + "carat,cut,color,clarity,depth,table,price,x,y,z\n", + "0.23,Ideal,E,SI2,61.5,55,326,3.95,3.98,2.43\n", + "0.21,Premium,E,SI1,59.8,61,326,3.89,3.84,2.31\n", + "0.23,Good,E,VS1,56.9,65,327,4.05,4.07,2.31\n", + "0.29,Premium,I,VS2,62.4,58,334,4.2,4.23,2.63\n", + "0.31,Good,J,SI2,63.3,58,335,4.34,4.35,2.75\n", + "```\n", + "\n", + "However, the delimiter can be any character. Additionally, a `quotechar`, commonly `\"`, can be specified which allows a delimiter to be contained within a column value.\n", + "E.g. from the `blogposts.csv` dataset:\n", + "```\n", + "Blog Post,Date,Subject,Field\n", + "\"Monty Hall, meet Game Theory\",4/13/2014,Statistics,Mathematics\n", + "Gaussian Quadrature,4/13/2014,Algorithms,Mathematics\n", + "```\n", + "Notice how `\"Monty Hall, meet Game Theory\"` is contained by the quotechar because it contains the delimiter value `,`.\n", + "\n", + "These delimiter dataset parameters (and more) can be automatically determined by the `CSVData` data reader, however they can also be set via the options as demonstrated later in this tutorial." + ] + }, + { + "cell_type": "markdown", + "id": "cccb6bf9-7fb8-46b8-992e-9caacb7ab3a8", + "metadata": {}, + "source": [ + "## Intro to the `CSVData` data reader\n", + "\n", + "Previously, it was shown that `CSVData` may automatically be detected using `Data` or can be manually specified by the user:\n", + "\n", + "```python\n", + "import dataprofiler as dp\n", + "from dataprofiler.data_readers.csv_data import CSVData\n", + "\n", + "data = dp.Data(filepath)\n", + "data = CSVData(filepath)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e25f5130-4f19-40c5-9d13-549a04f1aef5", + "metadata": {}, + "outputs": [], + "source": [ + "# use data reader to read delimited data \n", + "data_folder = \"../dataprofiler/tests/data\"\n", + "csv_files = [\n", + " \"csv/diamonds.csv\",\n", + " \"csv/all-strings-skip-header-author.csv\", # csv files with the author/description on the first line\n", + " \"csv/sparse-first-and-last-column-empty-first-row.txt\", # csv file with the .txt extension\n", + "]\n", + "\n", + "for file in csv_files:\n", + " data = CSVData(os.path.join(data_folder, file))\n", + " print(data.data.head())\n", + " print('=' * 80)" + ] + }, + { + "cell_type": "markdown", + "id": "8940de56-1417-4bf6-af87-9d4d00b9a631", + "metadata": {}, + "source": [ + "## CSVData Options\n", + "\n", + "As mentioned preivously, `CSVData` has options that can be set to finetune its detection or to ensure the data is being read in a specific manner.\n", + "The options for `CSVData` are detailed below:\n", + "\n", + " * delimiter - delimiter used to decipher the csv input file\n", + " * quotechar - quote character used in the delimited file\n", + " * header - location of the header in the file.\n", + " * data_format - user selected format in which to return data can only be of specified types\n", + " * selected_columns - columns being selected from the entire dataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3d74f2e8-0ec3-4e93-8778-0a5f013e0cdb", + "metadata": {}, + "outputs": [], + "source": [ + "# options are set via a dictionary object in which the parameters are specified.\n", + "# these are the default values for each option\n", + "options = {\n", + " \"delimiter\": \",\",\n", + " \"quotechar\": '\"',\n", + " \"header\": 'auto',\n", + " \"data_format\": \"dataframe\", # type: str, choices: \"dataframe\", \"records\"\n", + " \"selected_columns\": list(),\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "9af108a1-ffe6-4c3a-82cc-833b1a3b57a1", + "metadata": {}, + "source": [ + "## Options: delimiter and quotechar\n", + "\n", + "Below, both the auto detection and use of options will be illustrated for `delimiter` and `quotechar`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "570e20c3-198e-4356-98d3-92eb9655ef4e", + "metadata": {}, + "outputs": [], + "source": [ + "# display the data we are reading\n", + "filepath = \"../dataprofiler/tests/data/csv/daily-activity-sheet-@-singlequote.csv\"\n", + "num_lines = 10\n", + "with open(filepath) as fp:\n", + " print(''.join(fp.readlines()[:num_lines]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "98385148-861e-4eb1-ba8d-e93120515401", + "metadata": {}, + "outputs": [], + "source": [ + "data = dp.Data(filepath) # or use CSVData\n", + "print('Auto detected')\n", + "print('=' * 80)\n", + "print('delimiter: ', data.delimiter)\n", + "print('quotechar: ', data.quotechar)\n", + "data.data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7f5d9306-d90a-4fc6-85a7-a0d535fe2d80", + "metadata": {}, + "outputs": [], + "source": [ + "options = {'delimiter': '@', 'quotechar': \"'\"}\n", + "data = dp.Data(filepath, options=options) # or use CSVData\n", + "print('manually set')\n", + "print('=' * 80)\n", + "print('delimiter: ', data.delimiter)\n", + "print('quotechar: ', data.quotechar)\n", + "data.data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7bfa60f-b5b9-48a5-adc5-3937aed145da", + "metadata": {}, + "outputs": [], + "source": [ + "# intentional failure with incorrect options\n", + "options = {'delimiter': ',', 'quotechar': '\"'}\n", + "\n", + "# will be interepted as TextData because the delimtier and quotechar were incorrect\n", + "data = dp.Data(filepath, options=options)\n", + "print('intentional faliure set')\n", + "print('=' * 80)\n", + "try:\n", + " print('delimiter: ', data.delimiter) # attribute error raised here, bc TextData, not CSVData\n", + " print('quotechar: ', data.quotechar)\n", + " \n", + " # should not reach this or something went wrong\n", + " raise Exception('Should have failed because this is detected as TextData.')\n", + "except AttributeError:\n", + " print('When data_type is not set or the CSVData is not set, it will fail over to the\\n'\n", + " 'next best reader. In this case it is \"TextData\"\\n')\n", + "data.data" + ] + }, + { + "cell_type": "markdown", + "id": "eeb41c7c-8319-40a3-9d87-88edbb3c5290", + "metadata": {}, + "source": [ + "## Options: header\n", + "\n", + "Below, both the auto detection and use of options will be illustrated for `header`.\n", + "\n", + "Notice how in the manually set mechanism, we are intentionally setting the header incorrectly to illustrate what happens." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16a927ef-1ba8-4bf2-ae40-2a9909030609", + "metadata": {}, + "outputs": [], + "source": [ + "# display the data we are reading\n", + "filepath = \"../dataprofiler/tests/data/csv/sparse-first-and-last-column-header-and-author-description.txt\"\n", + "num_lines = 10\n", + "with open(filepath) as fp:\n", + " print(''.join(fp.readlines()[:num_lines]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0701d7bf-2de0-4dce-8f09-7f0cddd1132c", + "metadata": {}, + "outputs": [], + "source": [ + "options = {'header': 'auto'} # auto detected (default value)\n", + "data = dp.Data(filepath, options=options) # or use CSVData\n", + "print('Data Header:', data.header)\n", + "print('=' * 80)\n", + "data.data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b8642a0a-367a-44c6-b611-b89d97b29f85", + "metadata": {}, + "outputs": [], + "source": [ + "options = {'header': 2} # intentionally set incorrectly at value 2\n", + "data = dp.Data(filepath, options=options) # or use CSVData\n", + "print('Data Header:', data.header)\n", + "print('=' * 80)\n", + "data.data.head()" + ] + }, + { + "cell_type": "markdown", + "id": "d6e3f640-c809-4eb6-9571-30065821615e", + "metadata": {}, + "source": [ + "## Options: data_format\n", + "\n", + "For CSVData, the `data_format` option can have the following values:\n", + "\n", + " * dataframe - (default) loads the dataset as a pandas.DataFrame\n", + " * records - loads the data as rows of text values, the extra parameter `record_samples_per_line` how many rows are combined into a single line\n", + " \n", + "`dataframe` is used for conducting **structured profiling** of the dataset while `records` is for **unstructured profiling**.\n", + "\n", + "Below, both the auto detection and use of options will be illustrated for `data_format`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "146109ea-a554-4766-bb19-78c116d2a8dd", + "metadata": {}, + "outputs": [], + "source": [ + "# display the data we are reading\n", + "filepath = \"../dataprofiler/tests/data/csv/diamonds.csv\"\n", + "num_lines = 10\n", + "with open(filepath) as fp:\n", + " print(''.join(fp.readlines()[:num_lines]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dceac967-d326-4064-ba1c-87a1146c9d72", + "metadata": {}, + "outputs": [], + "source": [ + "options = {'data_format': 'dataframe'} # default\n", + "data = dp.Data(filepath, options=options) # or use CSVData\n", + "data.data[:5]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c25524f-ef23-4e06-9023-842c64c2640e", + "metadata": {}, + "outputs": [], + "source": [ + "options = {'data_format': 'records', 'record_samples_per_line': 1}\n", + "data = dp.Data(filepath, options=options)\n", + "data.data[:5]" + ] + }, + { + "cell_type": "markdown", + "id": "d45f3ed6-ddcd-4bf3-95bc-09f23eb94c97", + "metadata": {}, + "source": [ + "## Options: selected columns\n", + "\n", + "By default, all columns of a dataset will be read and loaded into the data reader. However, `selected_columns` can be set to only load columns which the user requests." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c9b45e18-93c6-42e6-b978-af51574307eb", + "metadata": {}, + "outputs": [], + "source": [ + "# display the data we are reading\n", + "filepath = \"../dataprofiler/tests/data/csv/aws_honeypot_marx_geo.csv\"\n", + "num_lines = 10\n", + "with open(filepath) as fp:\n", + " print(''.join(fp.readlines()[:num_lines]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "018f3f4d-32ac-411a-9918-bae78aff0b0e", + "metadata": {}, + "outputs": [], + "source": [ + "options = {'selected_columns': ['datetime', 'host', 'src', 'proto']}\n", + "data = dp.Data(filepath, options=options)\n", + "data.data.head()" + ] + }, + { + "cell_type": "markdown", + "id": "b50679ea", + "metadata": {}, + "source": [ + "## Intro to `GraphData` data reader\n", + "\n", + "This tutorial will focus on how to use the data reader class: `GraphData`. The `GraphData` class is used for reading the delimited data from a CSV file into a `NetworkX` Graph object. This is all in an effort to prepare the data automaticaly for `GraphProfiler` class to then profile graph data. \n", + "\n", + "The DataProiler keys off of common graph naming conventions in the column header row. E.G. from `dataprofiler/tests/csv/graph_data_csv_identify.csv`\n", + "```\n", + "node_id_dst, node_id_src, continuous_weight, categorical_status\n", + "108,289,7.4448069,9\n", + "81,180,3.65064207,0\n", + "458,83,5.9959787,10\n", + "55,116,4.63359209,79\n", + "454,177,5.76715529,11\n", + "429,225,4.79556889,3\n", + "```\n", + "\n", + "Options for the `GraphData` are exactly the same as `CSVData`.\n", + "\n", + "\n", + "Example implementation of `GraphData`:\n", + "```python\n", + "import dataprofiler as dp\n", + "from dataprofiler.data_readers.graph_data import GraphData\n", + "\n", + "data = dp.Data(graph_file)\n", + "data = GraphData(graph_file)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "838db976", + "metadata": {}, + "outputs": [], + "source": [ + "from dataprofiler.data_readers.graph_data import GraphData\n", + "\n", + "# use data reader to read delimited data \n", + "data_folder = \"../dataprofiler/tests/data\"\n", + "graph_file = \"csv/graph_data_csv_identify.csv\"\n", + "\n", + "data = GraphData(os.path.join(data_folder, graph_file))\n", + "print(data.data.edges)\n", + "print('=' * 80)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/doctrees/nbsphinx/graph_data_demo.ipynb b/docs/0.10.5/doctrees/nbsphinx/graph_data_demo.ipynb new file mode 100644 index 000000000..088612872 --- /dev/null +++ b/docs/0.10.5/doctrees/nbsphinx/graph_data_demo.ipynb @@ -0,0 +1,271 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Graph Pipeline Demo" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "DataProfiler can also load and profile graph datasets. Similarly to the rest of DataProfiler profilers, this is split into two components:\n", + "- GraphData\n", + "- GraphProfiler\n", + "\n", + "We will demo the use of this graph pipeline.\n", + "\n", + "First, let's import the libraries needed for this example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import pprint\n", + "\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " import dataprofiler as dp\n", + "\n", + "data_path = \"../dataprofiler/tests/data\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now input our dataset into the generic DataProfiler pipeline:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data = dp.Data(os.path.join(data_path, \"csv/graph_data_csv_identify.csv\"))\n", + "profile = dp.Profiler(data)\n", + "\n", + "report = profile.report()\n", + "\n", + "pp = pprint.PrettyPrinter(sort_dicts=False, compact=True)\n", + "pp.pprint(report)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We notice that the `Data` class automatically detected the input file as graph data. The `GraphData` class is able to differentiate between tabular and graph csv data. After `Data` matches the input file as graph data, `GraphData` does the necessary work to load the csv data into a NetworkX Graph. \n", + "\n", + "`Profiler` runs `GraphProfiler` when graph data is input (or when `data_type=\"graph\"` is specified). The `report()` function outputs the profile for the user." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Profile" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The profile skeleton looks like this:\n", + "```\n", + "profile = {\n", + " \"num_nodes\": ...,\n", + " \"num_edges\": ...,\n", + " \"categorical_attributes\": ...,\n", + " \"continuous_attributes\": ...,\n", + " \"avg_node_degree\": ...,\n", + " \"global_max_component_size\": ...,\n", + " \"continuous_distribution\": ...,\n", + " \"categorical_distribution\": ...,\n", + " \"times\": ...,\n", + "}\n", + "```\n", + "\n", + "Description of properties in profile:\n", + "- `num_nodes`: number of nodes in the graph\n", + "- `num_edges`: number of edges in the graph\n", + "- `categorical_attributes`: list of categorical edge attributes\n", + "- `continuous_attributes`: list of continuous edge attributes\n", + "- `avg_node_degree`: average degree of nodes in the graph\n", + "- `global_max_component_size`: size of largest global max component in the graph\n", + "- `continuous_distribution`: dictionary of statistical properties for each continuous attribute\n", + "- `categorical_distribution`: dictionary of statistical properties for each categorical attribute\n", + "\n", + "The `continuous_distribution` and `categorical_distribution` dictionaries list statistical properties for each edge attribute in the graph:\n", + "```\n", + "continuous_distribution = {\n", + " \"name\": ...,\n", + " \"scale\": ...,\n", + " \"properties\": ...,\n", + "}\n", + "```\n", + "```\n", + "categorical_distribution = {\n", + " \"bin_counts\": ...,\n", + " \"bin_edges\": ...,\n", + "}\n", + "```\n", + "Description of each attribute:\n", + "- Continuous distribution:\n", + " - `name`: name of the distribution\n", + " - `scale`: negative log likelihood used to scale distributions and compare them in `GraphProfiler`\n", + " - `properties`: list of distribution props\n", + "- Categorical distribution:\n", + " - `bin_counts`: histogram bin counts\n", + " - `bin_edges`: histogram bin edges\n", + "\n", + "`properties` lists the following distribution properties: [optional: shape, loc, scale, mean, variance, skew, kurtosis]. The list can be either 6 length or 7 length depending on the distribution (extra shape parameter):\n", + "- 6 length: norm, uniform, expon, logistic\n", + "- 7 length: gamma, lognorm\n", + " - gamma: shape=`a` (float)\n", + " - lognorm: shape=`s` (float)\n", + " \n", + "For more information on shape parameters `a` and `s`: https://docs.scipy.org/doc/scipy/tutorial/stats.html#shape-parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Saving and Loading a Profile\n", + "Below you will see an example of how a Graph Profile can be saved and loaded again." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# The default save filepath is profile-.pkl\n", + "profile.save(filepath=\"profile.pkl\")\n", + "\n", + "new_profile = dp.GraphProfiler.load(\"profile.pkl\")\n", + "new_report = new_profile.report()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pp.pprint(report)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Difference in Data\n", + "If we wanted to ensure that this new profile was the same as the previous profile that we loaded, we could compare them using the diff functionality." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "diff = profile.diff(new_profile)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pp.pprint(diff)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another use for diff might be to provide differences between training and testing profiles as shown in the cell below.\n", + "We will use the profile above as the training profile and create a new profile to represent the testing profile" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "training_profile = profile\n", + "\n", + "testing_data = dp.Data(os.path.join(data_path, \"csv/graph-differentiator-input-positive.csv\"))\n", + "testing_profile = dp.Profiler(testing_data)\n", + "\n", + "test_train_diff = training_profile.diff(testing_profile)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Below you can observe the difference between the two profiles." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pp.pprint(test_train_diff)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Conclusion" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have shown the graph pipeline in the DataProfiler. It works similarly to the current DataProfiler implementation." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/0.10.5/doctrees/nbsphinx/labeler.ipynb b/docs/0.10.5/doctrees/nbsphinx/labeler.ipynb new file mode 100644 index 000000000..af31b68c5 --- /dev/null +++ b/docs/0.10.5/doctrees/nbsphinx/labeler.ipynb @@ -0,0 +1,650 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "spoken-reunion", + "metadata": {}, + "source": [ + "# Sensitive Data Detection with the Labeler" + ] + }, + { + "cell_type": "markdown", + "id": "interesting-bidder", + "metadata": {}, + "source": [ + "In this example, we utilize the Labeler component of the Data Profiler to detect the sensitive information for both structured and unstructured data. In addition, we show how to train the Labeler on some specific dataset with different list of entities.\n", + "\n", + "First, let's dive into what the Labeler is." + ] + }, + { + "cell_type": "markdown", + "id": "1965b83b", + "metadata": {}, + "source": [ + "## What is the Labeler" + ] + }, + { + "cell_type": "markdown", + "id": "388c643f", + "metadata": {}, + "source": [ + "The Labeler is a pipeline designed to make building, training, and predictions with ML models quick and easy. There are 3 major components to the Labeler: the preprocessor, the model, and the postprocessor." + ] + }, + { + "cell_type": "markdown", + "id": "e5d0aeb4", + "metadata": {}, + "source": [ + "![alt text](DL-Flowchart.png \"Title\")" + ] + }, + { + "cell_type": "markdown", + "id": "550323c7", + "metadata": {}, + "source": [ + "Each component can be switched out individually to suit your needs. As you might expect, the preprocessor takes in raw data and prepares it for the model, the model performs the prediction or training, and the postprocessor takes prediction results and turns them into human-readable results. \n", + "\n", + "Now let's run some examples. Start by importing all the requirements." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "scientific-stevens", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "import pandas as pd\n", + "\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " import dataprofiler as dp\n", + "\n", + "# remove extra tf loggin\n", + "import tensorflow as tf\n", + "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)" + ] + }, + { + "cell_type": "markdown", + "id": "5125b215", + "metadata": {}, + "source": [ + "## Structured Data Prediction" + ] + }, + { + "cell_type": "markdown", + "id": "wicked-devon", + "metadata": {}, + "source": [ + "We'll use the aws honeypot dataset in the test folder for this example. First, look at the data using the Data Reader class of the Data Profiler. This dataset is from the US department of educations, [found here!](https://data.ed.gov/dataset/college-scorecard-all-data-files-through-6-2020/resources?resource=823ac095-bdfc-41b0-b508-4e8fc3110082)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "adjusted-native", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "data = dp.Data(\"../dataprofiler/tests/data/csv/SchoolDataSmall.csv\")\n", + "df_data = data.data\n", + "df_data.head()" + ] + }, + { + "cell_type": "markdown", + "id": "ab6ccf8a", + "metadata": {}, + "source": [ + "We can directly predict the labels of a structured dataset on the cell level." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19529af4", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "labeler = dp.DataLabeler(labeler_type='structured')\n", + "\n", + "# print out the labels and label mapping\n", + "print(\"Labels: {}\".format(labeler.labels)) \n", + "print(\"\\n\")\n", + "print(\"Label Mapping: {}\".format(labeler.label_mapping))\n", + "print(\"\\n\")\n", + "\n", + "# make predictions and get labels for each cell going row by row\n", + "# predict options are model dependent and the default model can show prediction confidences\n", + "predictions = labeler.predict(data, predict_options={\"show_confidences\": True})\n", + "\n", + "# display prediction results\n", + "print(\"Predictions: {}\".format(predictions['pred']))\n", + "print(\"\\n\")\n", + "\n", + "# display confidence results\n", + "print(\"Confidences: {}\".format(predictions['conf']))" + ] + }, + { + "cell_type": "markdown", + "id": "2af72e2c", + "metadata": {}, + "source": [ + "The profiler uses the Labeler to perform column by column predictions. The data contains 11 columns, each of which has data label. Next, we will use the Labeler of the Data Profiler to predict the label for each column in this tabular dataset. Since we are only going to demo the labeling functionality, other options of the Data Profiler are disabled to keep this quick." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d6cb9d7e-149a-4cfe-86f8-76c47c57aeea", + "metadata": {}, + "outputs": [], + "source": [ + "# helper functions for printing results\n", + "\n", + "def get_structured_results(results):\n", + " \"\"\"Helper function to get data labels for each column.\"\"\"\n", + " columns = []\n", + " predictions = []\n", + " samples = []\n", + " for col in results['data_stats']:\n", + " columns.append(col['column_name'])\n", + " predictions.append(col['data_label'])\n", + " samples.append(col['samples'])\n", + "\n", + " df_results = pd.DataFrame({'Column': columns, 'Prediction': predictions, 'Sample': samples})\n", + " return df_results\n", + "\n", + "def get_unstructured_results(data, results):\n", + " \"\"\"Helper function to get data labels for each labeled piece of text.\"\"\"\n", + " labeled_data = []\n", + " for pred in results['pred'][0]:\n", + " labeled_data.append([data[0][pred[0]:pred[1]], pred[2]])\n", + " label_df = pd.DataFrame(labeled_data, columns=['Text', 'Labels'])\n", + " return label_df\n", + " \n", + "\n", + "pd.set_option('display.width', 100)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "secret-million", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# set options to only run the labeler\n", + "profile_options = dp.ProfilerOptions()\n", + "profile_options.set({\"structured_options.text.is_enabled\": False, \n", + " \"int.is_enabled\": False, \n", + " \"float.is_enabled\": False, \n", + " \"order.is_enabled\": False, \n", + " \"category.is_enabled\": False, \n", + " \"chi2_homogeneity.is_enabled\": False,\n", + " \"datetime.is_enabled\": False,})\n", + "\n", + "profile = dp.Profiler(data, options=profile_options)\n", + "\n", + "results = profile.report() \n", + "print(get_structured_results(results))" + ] + }, + { + "cell_type": "markdown", + "id": "fatty-louisville", + "metadata": {}, + "source": [ + "In this example, the results show that the Data Profiler is able to detect integers, URLs, address, and floats appropriately. Unknown is typically strings of text, which is appropriate for those columns." + ] + }, + { + "cell_type": "markdown", + "id": "unavailable-diploma", + "metadata": {}, + "source": [ + "## Unstructured Data Prediction" + ] + }, + { + "cell_type": "markdown", + "id": "metallic-coaching", + "metadata": {}, + "source": [ + "Besides structured data, the Labeler detects the sensitive information on the unstructured text. We use a sample of spam email in Enron email dataset for this demo. As above, we start investigating the content of the given email sample." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "unauthorized-lounge", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# load data\n", + "data = \"Message-ID: <11111111.1111111111111.JavaMail.evans@thyme>\\n\" + \\\n", + " \"Date: Fri, 10 Aug 2005 11:31:37 -0700 (PDT)\\n\" + \\\n", + " \"From: w..smith@company.com\\n\" + \\\n", + " \"To: john.smith@company.com\\n\" + \\\n", + " \"Subject: RE: ABC\\n\" + \\\n", + " \"Mime-Version: 1.0\\n\" + \\\n", + " \"Content-Type: text/plain; charset=us-ascii\\n\" + \\\n", + " \"Content-Transfer-Encoding: 7bit\\n\" + \\\n", + " \"X-From: Smith, Mary W. \\n\" + \\\n", + " \"X-To: Smith, John \\n\" + \\\n", + " \"X-cc: \\n\" + \\\n", + " \"X-bcc: \\n\" + \\\n", + " \"X-Folder: \\SSMITH (Non-Privileged)\\Sent Items\\n\" + \\\n", + " \"X-Origin: Smith-S\\n\" + \\\n", + " \"X-FileName: SSMITH (Non-Privileged).pst\\n\\n\" + \\\n", + " \"All I ever saw was the e-mail from the office.\\n\\n\" + \\\n", + " \"Mary\\n\\n\" + \\\n", + " \"-----Original Message-----\\n\" + \\\n", + " \"From: Smith, John \\n\" + \\\n", + " \"Sent: Friday, August 10, 2005 13:07 PM\\n\" + \\\n", + " \"To: Smith, Mary W.\\n\" + \\\n", + " \"Subject: ABC\\n\\n\" + \\\n", + " \"Have you heard any more regarding the ABC sale? I guess that means that \" + \\\n", + " \"it's no big deal here, but you think they would have send something.\\n\\n\\n\" + \\\n", + " \"John Smith\\n\" + \\\n", + " \"123-456-7890\\n\"\n", + "\n", + "# convert string data to list to feed into the labeler\n", + "data = [data]" + ] + }, + { + "cell_type": "markdown", + "id": "concerned-segment", + "metadata": {}, + "source": [ + "By default, the Labeler predicts the results at the character level for unstructured text." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "junior-acrobat", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "labeler = dp.DataLabeler(labeler_type='unstructured')\n", + "\n", + "# make predictions and get labels per character\n", + "predictions = labeler.predict(data)\n", + "\n", + "# display results\n", + "print(predictions['pred'])" + ] + }, + { + "cell_type": "markdown", + "id": "individual-diabetes", + "metadata": {}, + "source": [ + "In addition to the character-level result, the Labeler provides the results at the word level following the standard NER (Named Entity Recognition), e.g., utilized by spaCy. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "optical-universe", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# convert prediction to word format and ner format\n", + "# Set the output to the NER format (start position, end position, label)\n", + "labeler.set_params(\n", + " { 'postprocessor': { 'output_format':'ner', 'use_word_level_argmax':True } } \n", + ")\n", + "\n", + "# make predictions and get labels per character\n", + "predictions = labeler.predict(data)\n", + "\n", + "# display results\n", + "print('\\n')\n", + "print('=======================Prediction======================\\n')\n", + "for pred in predictions['pred'][0]:\n", + " print('{}: {}'.format(data[0][pred[0]: pred[1]], pred[2]))\n", + " print('--------------------------------------------------------')" + ] + }, + { + "cell_type": "markdown", + "id": "behavioral-tourism", + "metadata": {}, + "source": [ + "Here, the Labeler is able to identify sensitive information such as datetime, email address, person names, and phone number in an email sample. " + ] + }, + { + "cell_type": "markdown", + "id": "nasty-disney", + "metadata": {}, + "source": [ + "## Train the Labeler from Scratch" + ] + }, + { + "cell_type": "markdown", + "id": "destroyed-twist", + "metadata": {}, + "source": [ + "The Labeler can be trained from scratch with a new list of labels. Below, we show an example of training the Labeler on a dataset with labels given as the columns of that dataset. For brevity's sake, let's only train a few epochs with a subset of a dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "utility-evaluation", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "data = dp.Data(\"../dataprofiler/tests/data/csv/SchoolDataSmall.csv\")\n", + "df = data.data[[\"OPEID6\", \"INSTURL\", \"SEARCH_STRING\"]]\n", + "df.head()\n", + "\n", + "# split data to training and test set\n", + "split_ratio = 0.2\n", + "df = df.sample(frac=1).reset_index(drop=True)\n", + "data_train = df[:int((1 - split_ratio) * len(df))]\n", + "data_test = df[int((1 - split_ratio) * len(df)):]\n", + "\n", + "# train a new labeler with column names as labels\n", + "if not os.path.exists('data_labeler_saved'):\n", + " os.makedirs('data_labeler_saved')\n", + "\n", + "labeler = dp.train_structured_labeler(\n", + " data=data_train,\n", + " save_dirpath=\"data_labeler_saved\",\n", + " epochs=10,\n", + " default_label=\"OPEID6\"\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "utility-torture", + "metadata": {}, + "source": [ + "The trained Labeler is then used by the Data Profiler to provide the prediction on the new dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "answering-panel", + "metadata": {}, + "outputs": [], + "source": [ + "# predict with the labeler object\n", + "profile_options.set({'structured_options.data_labeler.data_labeler_object': labeler})\n", + "profile = dp.Profiler(data_test, options=profile_options)\n", + "\n", + "# get the prediction from the data profiler\n", + "results = profile.report()\n", + "print(get_structured_results(results))" + ] + }, + { + "cell_type": "markdown", + "id": "polish-stand", + "metadata": {}, + "source": [ + "Another way to use the trained Labeler is through the directory path of the saved labeler." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "industrial-characterization", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# predict with the labeler loaded from path\n", + "profile_options.set({'structured_options.data_labeler.data_labeler_dirpath': 'data_labeler_saved'})\n", + "profile = dp.Profiler(data_test, options=profile_options)\n", + "\n", + "# get the prediction from the data profiler\n", + "results = profile.report()\n", + "print(get_structured_results(results))" + ] + }, + { + "cell_type": "markdown", + "id": "2acedba0", + "metadata": {}, + "source": [ + "## Transfer Learning a Labeler" + ] + }, + { + "cell_type": "markdown", + "id": "2f15fb1f", + "metadata": {}, + "source": [ + "Instead of training a model from scratch, we can also transfer learn to improve the model and/or extend the labels. Again for brevity's sake, let's only train a few epochs with a small dataset at the cost of accuracy." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0104c374", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "data = dp.Data(\"../dataprofiler/tests/data/csv/SchoolDataSmall.csv\")\n", + "df_data = data.data[[\"OPEID6\", \"INSTURL\", \"SEARCH_STRING\"]]\n", + "\n", + "\n", + "# prep data\n", + "df_data = df_data.reset_index(drop=True).melt()\n", + "df_data.columns = [1, 0] # labels=1, values=0 in that order\n", + "df_data = df_data.astype(str)\n", + "new_labels = df_data[1].unique().tolist()\n", + "\n", + "# load structured Labeler w/ trainable set to True\n", + "labeler = dp.DataLabeler(labeler_type='structured', trainable=True)\n", + "\n", + "# Reconstruct the model to add each new label\n", + "for label in new_labels:\n", + " labeler.add_label(label)\n", + "\n", + "# this will use transfer learning to retrain the labeler on your new\n", + "# dataset and labels.\n", + "# Setting labels with a list of labels or label mapping will overwrite the existing labels with new ones\n", + "# Setting the reset_weights parameter to false allows transfer learning to occur\n", + "model_results = labeler.fit(x=df_data[0], y=df_data[1], validation_split=0.2, \n", + " epochs=10, labels=None, reset_weights=False)" + ] + }, + { + "cell_type": "markdown", + "id": "ae78745f", + "metadata": {}, + "source": [ + "Let's display the training results of the last epoch:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b764aa8c", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "print(\"{:16s} Precision Recall F1-score Support\".format(\"\"))\n", + "for item in model_results[-1][2]:\n", + " print(\"{:16s} {:4.3f} {:4.3f} {:4.3f} {:7.0f}\".format(item,\n", + " model_results[-1][2][item][\"precision\"],\n", + " model_results[-1][2][item][\"recall\"],\n", + " model_results[-1][2][item][\"f1-score\"],\n", + " model_results[-1][2][item][\"support\"]))" + ] + }, + { + "cell_type": "markdown", + "id": "44009522", + "metadata": {}, + "source": [ + "It is now trained to detect additional labels! The model results here show all the labels training accuracy. Since only new labels existed in the dataset, only the new labels are given accuracy scores. Keep in mind this is a small dataset for brevity's sake and that real training would involve more samples and better results." + ] + }, + { + "cell_type": "markdown", + "id": "e110ee1c", + "metadata": {}, + "source": [ + "## Saving and Loading a Labeler" + ] + }, + { + "cell_type": "markdown", + "id": "c484d193", + "metadata": {}, + "source": [ + "The Labeler can easily be saved or loaded with one simple line." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4d8684fa", + "metadata": {}, + "outputs": [], + "source": [ + "# Ensure save directory exists\n", + "if not os.path.exists('my_labeler'):\n", + " os.makedirs('my_labeler')\n", + "\n", + "# Saving the labeler\n", + "labeler.save_to_disk(\"my_labeler\")\n", + "\n", + "# Loading the labeler\n", + "labeler = dp.DataLabeler(labeler_type='structured', dirpath=\"my_labeler\")" + ] + }, + { + "cell_type": "markdown", + "id": "8d36dec8", + "metadata": {}, + "source": [ + "## Building a Labeler from the Ground Up" + ] + }, + { + "cell_type": "markdown", + "id": "59346d2b", + "metadata": {}, + "source": [ + "As mentioned earlier, the labeler is comprised of three components, and each of the compenents can be created and interchanged in the the labeler pipeline." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6506ef97", + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "from dataprofiler.labelers.character_level_cnn_model import \\\n", + " CharacterLevelCnnModel\n", + "from dataprofiler.labelers.data_processing import \\\n", + " StructCharPreprocessor, StructCharPostprocessor\n", + "\n", + "model = CharacterLevelCnnModel({\"PAD\":0, \"UNKNOWN\":1, \"Test_Label\":2})\n", + "preprocessor = StructCharPreprocessor()\n", + "postprocessor = StructCharPostprocessor()\n", + "\n", + "labeler = dp.DataLabeler(labeler_type='structured')\n", + "labeler.set_preprocessor(preprocessor)\n", + "labeler.set_model(model)\n", + "labeler.set_postprocessor(postprocessor)\n", + "\n", + "# check for basic compatibility between the processors and the model\n", + "labeler.check_pipeline()\n", + "\n", + "# Optionally set the parameters\n", + "parameters={\n", + " 'preprocessor':{\n", + " 'max_length': 100,\n", + " },\n", + " 'model':{\n", + " 'max_length': 100,\n", + " },\n", + " 'postprocessor':{\n", + " 'random_state': random.Random(1)\n", + " }\n", + "} \n", + "labeler.set_params(parameters)\n", + "\n", + "labeler.help()" + ] + }, + { + "cell_type": "markdown", + "id": "5f020d7f", + "metadata": {}, + "source": [ + "The components can each be created if you inherit the BaseModel and BaseProcessor for the model and processors, respectively. More info can be found about coding your own components in the Labeler section of the [documentation]( https://capitalone.github.io/dataprofiler). In summary, the Data Profiler open source library can be used to scan sensitive information in both structured and unstructured data with different file types. It supports multiple input formats and output formats at word and character levels. Users can also train the labeler on their own datasets." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/doctrees/nbsphinx/merge_profile_list.ipynb b/docs/0.10.5/doctrees/nbsphinx/merge_profile_list.ipynb new file mode 100644 index 000000000..7a6d8005a --- /dev/null +++ b/docs/0.10.5/doctrees/nbsphinx/merge_profile_list.ipynb @@ -0,0 +1,159 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "60af5256", + "metadata": {}, + "source": [ + "# Merge List of Profiles\n", + "\n", + "This is an example of a new utils in the dataprofiler for distributed merging of profile objects. This assumes the user is providing a list of profile objects to the utils function for merging all the profiles together." + ] + }, + { + "cell_type": "markdown", + "id": "7eee37ff", + "metadata": {}, + "source": [ + "## Imports\n", + "\n", + "Let's start by importing the necessary packages..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f0d27009", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "\n", + "import pandas as pd\n", + "import tensorflow as tf\n", + "\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + " from dataprofiler.profilers.profiler_utils import merge_profile_list\n", + "except ImportError:\n", + " import dataprofiler as dp\n", + " from dataprofiler.profilers.profiler_utils import merge_profile_list\n", + "\n", + "# remove extra tf loggin\n", + "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)" + ] + }, + { + "cell_type": "markdown", + "id": "b4369e64", + "metadata": {}, + "source": [ + "## Setup the Data and Profiler" + ] + }, + { + "cell_type": "markdown", + "id": "410c3c4d", + "metadata": {}, + "source": [ + "This section shows the basic example of the Data Profiler. \n", + "\n", + "1. Instantiate a Pandas dataframe with dummy data\n", + "2. Pass the dataframe to the `Profiler` and instantiate two separate profilers in a list" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3567c82", + "metadata": {}, + "outputs": [], + "source": [ + "d = {'col1': [1, 2], 'col2': [3, 4]}\n", + "df = pd.DataFrame(data=d)\n", + "\n", + "list_of_profiles = [dp.Profiler(df), dp.Profiler(df)]" + ] + }, + { + "cell_type": "markdown", + "id": "350502eb", + "metadata": {}, + "source": [ + "Take a look at the list of profiles... " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b649db32", + "metadata": {}, + "outputs": [], + "source": [ + "list_of_profiles" + ] + }, + { + "cell_type": "markdown", + "id": "4ed4fc12", + "metadata": {}, + "source": [ + "## Run Merge on List of Profiles\n", + "\n", + "Now let's merge the list of profiles into a `single_profile`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4a636047", + "metadata": {}, + "outputs": [], + "source": [ + "single_profile = merge_profile_list(list_of_profiles=list_of_profiles)" + ] + }, + { + "cell_type": "markdown", + "id": "0aa88720", + "metadata": {}, + "source": [ + "And check out the `.report` on the single profile:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34059c21", + "metadata": {}, + "outputs": [], + "source": [ + "single_profile.report()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "dataprofiler", + "language": "python", + "name": "dataprofiler" + }, + "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.7.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/doctrees/nbsphinx/overview.ipynb b/docs/0.10.5/doctrees/nbsphinx/overview.ipynb new file mode 100644 index 000000000..d5e77abe4 --- /dev/null +++ b/docs/0.10.5/doctrees/nbsphinx/overview.ipynb @@ -0,0 +1,470 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fc2826d9", + "metadata": {}, + "source": [ + "# Data Profiler - What's in your data?" + ] + }, + { + "cell_type": "markdown", + "id": "b997522b", + "metadata": {}, + "source": [ + "This introductory jupyter notebook demonstrates the basic usages of the Data Profiler. The library is designed to easily detect sensitive data and gather statistics on your datasets with just several lines of code. The Data Profiler can handle several different data types including: CSV (or any delimited file), JSON, Parquet, AVRO, and text. Additionally, there are a plethora of options to customize your profile. This library also has the ability to update profiles from multiple batches of large datasets, or merge multiple profiles. In particular, this example covers the followings:\n", + "\n", + "- Basic usage of the Data Profiler\n", + "- The data reader class\n", + "- Profiler options\n", + "- Updating profiles and merging profiles\n", + "\n", + "First, let's import the libraries needed for this example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ef404c84", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "sys.path.insert(0, '..')\n", + "import dataprofiler as dp\n", + "\n", + "data_path = \"../dataprofiler/tests/data\"" + ] + }, + { + "cell_type": "markdown", + "id": "f51971e3", + "metadata": {}, + "source": [ + "## Basic Usage of the Data Profiler" + ] + }, + { + "cell_type": "markdown", + "id": "639e66d3", + "metadata": {}, + "source": [ + "This section shows the basic example of the Data Profiler. A CSV dataset is read using the data reader, then the Data object is given to the Data Profiler to detect sensitive data and obtain the statistics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5379c45c", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "# use data reader to read input data\n", + "data = dp.Data(os.path.join(data_path, \"csv/aws_honeypot_marx_geo.csv\"))\n", + "print(data.data.head())\n", + "\n", + "# run data profiler and get the report\n", + "profile = dp.Profiler(data)\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "\n", + "# print the report\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "57fe2827", + "metadata": {}, + "source": [ + "The report includes `global_stats` and `data_stats` for the given dataset. The former contains overall properties of the data such as number of rows/columns, null ratio, duplicate ratio, while the latter contains specific properties and statistics for each column such as detected data label, min, max, mean, variance, etc. In this example, the `compact` format of the report is used to shorten the full list of the results. To get more results related to detailed predictions at the entity level from the Data Labeler component or histogram results, the format `pretty` should be used." + ] + }, + { + "cell_type": "markdown", + "id": "74027cfd", + "metadata": {}, + "source": [ + "## Data reader class" + ] + }, + { + "cell_type": "markdown", + "id": "41364888", + "metadata": {}, + "source": [ + "DataProfiler can detect multiple file types including CSV (or any delimited file), JSON, Parquet, AVRO, and text. The example below shows that it successfully detects data types from multiple categories regardless of the file extensions." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "823829f4", + "metadata": {}, + "outputs": [], + "source": [ + "# use data reader to read input data with different file types\n", + "csv_files = [\n", + " \"csv/aws_honeypot_marx_geo.csv\",\n", + " \"csv/all-strings-skip-header-author.csv\", # csv files with the author/description on the first line\n", + " \"csv/sparse-first-and-last-column-empty-first-row.txt\", # csv file with the .txt extension\n", + "]\n", + "json_files = [\n", + " \"json/complex_nested.json\",\n", + " \"json/honeypot_intentially_mislabeled_file.csv\", # json file with the .csv extension\n", + "]\n", + "parquet_files = [\n", + " \"parquet/nation.dict.parquet\",\n", + " \"parquet/nation.plain.intentionally_mislabled_file.csv\", # parquet file with the .csv extension\n", + "]\n", + "avro_files = [\n", + " \"avro/userdata1.avro\",\n", + " \"avro/userdata1_intentionally_mislabled_file.json\", # avro file with the .json extension\n", + "]\n", + "text_files = [\n", + " \"txt/discussion_reddit.txt\",\n", + "]\n", + "\n", + "all_files = {\n", + " \"csv\": csv_files,\n", + " \"json\": json_files,\n", + " \"parquet\": parquet_files,\n", + " \"avro\": avro_files,\n", + " \"text\": text_files\n", + "}\n", + "\n", + "for file_type in all_files:\n", + " print(file_type)\n", + " for file in all_files[file_type]:\n", + " data = dp.Data(os.path.join(data_path, file))\n", + " print(\"{:<85} {:<15}\".format(file, data.data_type))\n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "3f9d7e02", + "metadata": {}, + "source": [ + "The `Data` class detects the file type and uses one of the following classes: `CSVData`, `JSONData`, `ParquetData`, `AVROData`, `TextData`. Users can call these specific classes directly if desired. For example, below we provide a collection of data with different types, each of them is processed by the corresponding data class." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "831e68a3", + "metadata": {}, + "outputs": [], + "source": [ + "# use individual data reader classes\n", + "from dataprofiler.data_readers.csv_data import CSVData\n", + "from dataprofiler.data_readers.json_data import JSONData\n", + "from dataprofiler.data_readers.parquet_data import ParquetData\n", + "from dataprofiler.data_readers.avro_data import AVROData\n", + "from dataprofiler.data_readers.text_data import TextData\n", + "\n", + "csv_files = \"csv/aws_honeypot_marx_geo.csv\"\n", + "json_files = \"json/complex_nested.json\"\n", + "parquet_files = \"parquet/nation.dict.parquet\"\n", + "avro_files = \"avro/userdata1.avro\"\n", + "text_files = \"txt/discussion_reddit.txt\"\n", + "\n", + "all_files = {\n", + " \"csv\": [csv_files, CSVData],\n", + " \"json\": [json_files, JSONData],\n", + " \"parquet\": [parquet_files, ParquetData],\n", + " \"avro\": [avro_files, AVROData],\n", + " \"text\": [text_files, TextData],\n", + "}\n", + "\n", + "for file_type in all_files:\n", + " file, data_reader = all_files[file_type]\n", + " data = data_reader(os.path.join(data_path, file))\n", + " print(\"File name {}\\n\".format(file))\n", + " if file_type == \"text\":\n", + " print(data.data[0][:1000]) # print the first 1000 characters\n", + " else:\n", + " print(data.data)\n", + " print('===============================================================================')" + ] + }, + { + "cell_type": "markdown", + "id": "572df0a8", + "metadata": {}, + "source": [ + "In addition to reading the input data from multiple file types, the Data Profiler allows the input data as a dataframe." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df87ab83", + "metadata": {}, + "outputs": [], + "source": [ + "# run data profiler and get the report\n", + "my_dataframe = pd.DataFrame([[1, 2.0],[1, 2.2],[-1, 3]], columns=[\"col_int\", \"col_float\"])\n", + "profile = dp.Profiler(my_dataframe)\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "\n", + "# Print the report\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "84a06312", + "metadata": {}, + "source": [ + "## Structured Profiler vs. Unstructured Profiler" + ] + }, + { + "cell_type": "markdown", + "id": "4c0ea925", + "metadata": {}, + "source": [ + "The profiler will infer what type of statistics to generate (structured or unstructured) based on the input. However, you can explicitly specify profile type as well. Here is an example of the the profiler explicitly calling the structured profile and the unstructured profile." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5f4565d8", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "# Using the structured profiler\n", + "data = dp.Data(os.path.join(data_path, \"csv/aws_honeypot_marx_geo.csv\"))\n", + "profile = dp.Profiler(data, profiler_type='structured')\n", + "\n", + "report = profile.report(report_options={\"output_format\": \"pretty\"})\n", + "print(json.dumps(report, indent=4))\n", + "\n", + "# Using the unstructured profiler\n", + "my_dataframe = pd.DataFrame([[\"Sample1\"],[\"Sample2\"],[\"Sample3\"]], columns=[\"Text_Samples\"])\n", + "profile = dp.Profiler(my_dataframe, profiler_type='unstructured')\n", + "\n", + "report = profile.report(report_options={\"output_format\":\"pretty\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "b16648ba", + "metadata": {}, + "source": [ + "## Profiler options" + ] + }, + { + "cell_type": "markdown", + "id": "8b0cc8ad", + "metadata": {}, + "source": [ + "The Data Profiler can enable/disable statistics and modify features through profiler options. For example, if the users only want the statistics information, they may turn off the Data Labeler functionality. Below, let's remove the histogram and data labeler component while running Data Profiler." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bbac3a2c", + "metadata": {}, + "outputs": [], + "source": [ + "profile_options = dp.ProfilerOptions()\n", + "profile_options.set({\"histogram_and_quantiles.is_enabled\": False,\n", + " \"median_abs_deviation.is_enabled\": False,\n", + " \"median.is_enabled\": False,\n", + " \"mode.is_enabled\": False,\n", + " \"data_labeler.is_enabled\": False,})\n", + "\n", + "profile = dp.Profiler(my_dataframe, options=profile_options)\n", + "report = profile.report(report_options={\"output_format\":\"pretty\"})\n", + "\n", + "# Print the report\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "590ca50b", + "metadata": {}, + "source": [ + "Besides toggling on and off features, other options like the data labeler sample size or histogram bin method can be directly set and validated as shown here:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ed21bc1", + "metadata": {}, + "outputs": [], + "source": [ + "profile_options = dp.ProfilerOptions()\n", + "profile_options.structured_options.data_labeler.sample_size = 1\n", + "profile_options.structured_options.int.histogram_and_quantiles.bin_count_or_method = \"rice\"\n", + "# An error will raise if the options are set incorrectly.\n", + "profile_options.validate()\n", + "\n", + "profile = dp.Profiler(my_dataframe, options=profile_options)\n", + "report = profile.report(report_options={\"output_format\":\"pretty\"})\n", + "\n", + "# Print the report\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "9f690616", + "metadata": {}, + "source": [ + "## Update profiles" + ] + }, + { + "cell_type": "markdown", + "id": "965f8c85", + "metadata": {}, + "source": [ + "One of the interesting features of the Data Profiler is the ability to update profiles from batches of data, which allows for data streaming usage. In this section, the original dataset is separated into two batches with equal size. Each batch is then updated with Data Profiler sequentially. \n", + "\n", + "After the update, we expect the resulted profiles give the same statistics as the profiles updated from the full dataset. We will verify that through some properties in `global_stats` of the profiles including `column_count`, `row_count`, `row_is_null_ratio`, `duplicate_row_count`. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34ac4346", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# read the input data and devide it into two equal halves\n", + "data = dp.Data(os.path.join(data_path, \"csv/aws_honeypot_marx_geo.csv\"))\n", + "df = data.data\n", + "df1 = df.iloc[:int(len(df)/2)]\n", + "df2 = df.iloc[int(len(df)/2):]\n", + "\n", + "# Update the profile with the first half\n", + "profile = dp.Profiler(df1)\n", + "\n", + "# Update the profile with the second half\n", + "profile.update_profile(df2)\n", + "\n", + "# Update profile with the full dataset\n", + "profile_full = dp.Profiler(df)\n", + "\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "report_full = profile_full.report(report_options={\"output_format\":\"compact\"})\n", + "\n", + "# print the report\n", + "print(json.dumps(report, indent=4))\n", + "print(json.dumps(report_full, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "b41ee2bf", + "metadata": {}, + "source": [ + "You can see that the profiles are exactly the same whether they are broken into several updates or not." + ] + }, + { + "cell_type": "markdown", + "id": "c547f051", + "metadata": {}, + "source": [ + "## Merge profiles" + ] + }, + { + "cell_type": "markdown", + "id": "a5292962", + "metadata": {}, + "source": [ + "In addition to the profile update, Data Profiler provides the merging functionality which allows users to combine the profiles updated from multiple locations. This enables Data Profiler to be used in a distributed computing environment. Below, we assume that the two aforementioned halves of the original dataset come from two different machines. Each of them is then updated with the Data Profiler on the same machine, then the resulted profiles are merged.\n", + "\n", + "As with the profile update, we expect the merged profiles give the same statistics as the profiles updated from the full dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a565b8d1", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Update the profile with the first half\n", + "profile1 = dp.Profiler(df1)\n", + "\n", + "# Update the profile with the second half\n", + "profile2 = dp.Profiler(df2)\n", + "\n", + "# merge profiles\n", + "profile_merge = profile1 + profile2\n", + "\n", + "# check results of the merged profile\n", + "report_merge = profile.report(report_options={\"output_format\":\"compact\"})\n", + "\n", + "# print the report\n", + "print(json.dumps(report_merge, indent=4))\n", + "print(json.dumps(report_full, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "b77fac3f", + "metadata": {}, + "source": [ + "You can see that the profiles are exactly the same!" + ] + }, + { + "cell_type": "markdown", + "id": "c644ee42", + "metadata": {}, + "source": [ + "## Conclusion\n", + "\n", + "We have walked through some basic examples of Data Profiler usage, with different input data types and profiling options. We also work with update and merging functionality of the Data Profiler, which make it applicable for data streaming and distributed environment. Interested users can try with different datasets and functionalities as desired." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/doctrees/nbsphinx/popmon_dp_loader_example.ipynb b/docs/0.10.5/doctrees/nbsphinx/popmon_dp_loader_example.ipynb new file mode 100644 index 000000000..3ddb267da --- /dev/null +++ b/docs/0.10.5/doctrees/nbsphinx/popmon_dp_loader_example.ipynb @@ -0,0 +1,416 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7f0cceea", + "metadata": {}, + "source": [ + "# Dataloader with Popmon Reports" + ] + }, + { + "cell_type": "markdown", + "id": "9e79d9c5", + "metadata": {}, + "source": [ + "This demo is to cover the usage of popmon with the dataloader from the dataprofiler\n", + "\n", + "This demo covers the followings:\n", + "\n", + " - How to install popmon\n", + " - Comparison of the dynamic dataloader from dataprofiler to the \n", + " standard dataloader used in pandas\n", + " - Popmon's usage example using both dataloaders\n", + " - Dataprofiler's examples using both dataloaders\n", + " - Usage of the pm_stability_report function (popmon reports)\n" + ] + }, + { + "cell_type": "markdown", + "id": "aec2198a", + "metadata": {}, + "source": [ + "## How to Install Popmon\n", + "To install popmon you can use the command below:" + ] + }, + { + "cell_type": "markdown", + "id": "4383ed2a", + "metadata": {}, + "source": [ + "`pip3 install popmon`\n" + ] + }, + { + "cell_type": "markdown", + "id": "91dedc34", + "metadata": {}, + "source": [ + "From here, we can import the libararies needed for this demo." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2adec556", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " import dataprofiler as dp\n", + "import pandas as pd\n", + "import popmon # noqa" + ] + }, + { + "cell_type": "markdown", + "id": "2ed532ec", + "metadata": {}, + "source": [ + "## Comparison of Dataloaders" + ] + }, + { + "cell_type": "markdown", + "id": "cccbf4cd", + "metadata": {}, + "source": [ + "First, we have the original pandas dataloading which works for specific file types. \n", + "This is good for if the data format is known ahead of time but is less useful for more dynamic cases." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "96e9ff89", + "metadata": {}, + "outputs": [], + "source": [ + "def popmon_dataloader(path, time_index):\n", + " # Load pm dataframe (Can only read csvs unless reader option is changed)\n", + " if not time_index is None:\n", + " pm_data = pd.read_csv(path, parse_dates=[time_index])\n", + " else:\n", + " time_index = True\n", + " pm_data = pd.read_csv(path)\n", + " return pm_data" + ] + }, + { + "cell_type": "markdown", + "id": "16dfbe10", + "metadata": {}, + "source": [ + "Next, we have the dataprofiler's dataloader. This allows for the dynamic loading of different data formats which is super useful when the data format is not know ahead of time.\n", + "This is intended to be an improvement on the dataloader standardly used in pandas." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "07481259", + "metadata": {}, + "outputs": [], + "source": [ + "def dp_dataloader(path):\n", + " # Datalaoder from dataprofiler used\n", + " dp_data = dp.Data(path)\n", + " \n", + " # Profiler used to ensure proper label for datetime even \n", + " # when null values exist\n", + " profiler_options = dp.ProfilerOptions()\n", + " profiler_options.set({'*.is_enabled': False, # Runs first disabling all options in profiler\n", + " '*.datetime.is_enabled': True})\n", + " profile = dp.Profiler(dp_data, options=profiler_options)\n", + "\n", + " # convert any time/datetime types from strings to actual datatime type\n", + " for ind, col in enumerate(dp_data.data.columns):\n", + " if profile.profile[ind].profile.get('data_type') == 'datetime':\n", + " dp_data.data[col] = pd.to_datetime(dp_data.data[col])\n", + "\n", + " return dp_data.data" + ] + }, + { + "cell_type": "markdown", + "id": "69a8ea9b", + "metadata": {}, + "source": [ + "## Popmon's usage example using both dataloaders" + ] + }, + { + "cell_type": "markdown", + "id": "ff914ca7", + "metadata": {}, + "source": [ + "Next, we'll download a dataset from the resources component" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bff33da8", + "metadata": {}, + "outputs": [], + "source": [ + "import gzip\n", + "import shutil\n", + "popmon_tutorial_data = popmon.resources.data(\"flight_delays.csv.gz\")\n", + "with gzip.open(popmon_tutorial_data, 'rb') as f_in:\n", + " with open('./flight_delays.csv', 'wb') as f_out:\n", + " shutil.copyfileobj(f_in, f_out)" + ] + }, + { + "cell_type": "markdown", + "id": "19222c4a", + "metadata": {}, + "source": [ + "Finally we read in the data with popmon and print the report to a file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0090a2f3", + "metadata": {}, + "outputs": [], + "source": [ + "# Default csv from popmon example\n", + "path = \"./flight_delays.csv\"\n", + "time_index = \"DATE\"\n", + "report_output_dir = \"./popmon_output/flight_delays_full\"\n", + "if not os.path.exists(report_output_dir):\n", + " os.makedirs(report_output_dir)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0abcd9b", + "metadata": {}, + "outputs": [], + "source": [ + "pm_data = popmon_dataloader(path, time_index)\n", + "\n", + "report_pm_loader = pm_data.pm_stability_report(\n", + " time_axis=time_index,\n", + " time_width=\"1w\",\n", + " time_offset=\"2015-07-02\",\n", + " extended_report=False,\n", + " pull_rules={\"*_pull\": [10, 7, -7, -10]},\n", + ")\n", + "\n", + "# Save popmon reports\n", + "report_pm_loader.to_file(os.path.join(report_output_dir, \"popmon_loader_report.html\"))\n", + "print(\"Report printed at:\", os.path.join(report_output_dir, \"popmon_loader_report.html\"))" + ] + }, + { + "cell_type": "markdown", + "id": "2303b5cf", + "metadata": {}, + "source": [ + "We then do the same for the dataprofiler loader" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f2854383", + "metadata": {}, + "outputs": [], + "source": [ + "dp_dataframe = dp_dataloader(path)\n", + "# Generate pm report using dp dataloader\n", + "report_dp_loader = dp_dataframe.pm_stability_report(\n", + " time_axis=time_index,\n", + " time_width=\"1w\",\n", + " time_offset=\"2015-07-02\",\n", + " extended_report=False,\n", + " pull_rules={\"*_pull\": [10, 7, -7, -10]},\n", + ")\n", + "\n", + "# Save popmon reports\n", + "report_dp_loader.to_file(os.path.join(report_output_dir, \"dataprofiler_loader_report.html\"))\n", + "print(\"Report printed at:\", os.path.join(report_output_dir, \"dataprofiler_loader_report.html\"))" + ] + }, + { + "cell_type": "markdown", + "id": "8cc4e5f3", + "metadata": {}, + "source": [ + "## Examples of data\n", + "Next, We'll use some data from the test files of the data profiler to compare the dynamic loading of the dataprofiler's data loader to that of the standard pandas approach. \n" + ] + }, + { + "cell_type": "markdown", + "id": "352eaeea", + "metadata": {}, + "source": [ + "## Dataprofiler's examples using both dataloaders" + ] + }, + { + "cell_type": "markdown", + "id": "e99af913", + "metadata": {}, + "source": [ + "To execute this properly, simply choose one of the 3 examples below and then run the report generation below." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "80eb601d", + "metadata": {}, + "outputs": [], + "source": [ + "# Default csv from popmon example (mini version)\n", + "path = \"../dataprofiler/tests/data/csv/flight_delays.csv\"\n", + "time_index = \"DATE\"\n", + "report_output_dir = \"./popmon_output/flight_delays_mini\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c127288", + "metadata": {}, + "outputs": [], + "source": [ + "# Random csv from dataprofiler tests\n", + "path = \"../dataprofiler/tests/data/csv/aws_honeypot_marx_geo.csv\"\n", + "time_index = \"datetime\"\n", + "report_output_dir = \"./popmon_output/aws_honeypot_marx_geo\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6cd5c385", + "metadata": {}, + "outputs": [], + "source": [ + "# Random json file from dataprofiler tests\n", + "path = \"../dataprofiler/tests/data/json/math.json\"\n", + "\n", + "time_index = \"data.9\"\n", + "report_output_dir = \"./popmon_output/math\"" + ] + }, + { + "cell_type": "markdown", + "id": "ec860cb7", + "metadata": {}, + "source": [ + "Run the block below to create an output directory for your popmon reports." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cf21835c", + "metadata": {}, + "outputs": [], + "source": [ + "if not os.path.exists(report_output_dir):\n", + " os.makedirs(report_output_dir)\n", + "dp_dataframe = dp_dataloader(path)" + ] + }, + { + "cell_type": "markdown", + "id": "479975a5", + "metadata": {}, + "source": [ + "## Report comparison" + ] + }, + { + "cell_type": "markdown", + "id": "02a355e7", + "metadata": {}, + "source": [ + "We generate reports using different sets of data from the dataprofiler and pandas below using dataprofiler's dataloader and popmons report generator\n" + ] + }, + { + "cell_type": "markdown", + "id": "6ce69145", + "metadata": {}, + "source": [ + "The dataprofiler's dataloader can seemlessly switch between data formats and generate reports with the exact same code in place." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a0dcb405", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Generate pm report using dp dataloader\n", + "report_dp_loader = dp_dataframe.pm_stability_report(\n", + " time_axis=time_index,\n", + " time_width=\"1w\",\n", + " time_offset=\"2015-07-02\",\n", + " extended_report=False,\n", + " pull_rules={\"*_pull\": [10, 7, -7, -10]},\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "9eb0035c", + "metadata": {}, + "source": [ + "If the dataloaders are valid, you can see the reports and compare them at the output directory specified in the printout below each report generation block (the two code blocks below)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "efe7d8d6", + "metadata": {}, + "outputs": [], + "source": [ + "# Save dp reports\n", + "report_dp_loader.to_file(os.path.join(report_output_dir, \"dataprofiler_loader_report.html\"))\n", + "print(\"Report printed at:\", os.path.join(report_output_dir, \"dataprofiler_loader_report.html\"))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/doctrees/nbsphinx/profiler_example.ipynb b/docs/0.10.5/doctrees/nbsphinx/profiler_example.ipynb new file mode 100644 index 000000000..b6a4409c9 --- /dev/null +++ b/docs/0.10.5/doctrees/nbsphinx/profiler_example.ipynb @@ -0,0 +1,577 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f37ca393", + "metadata": {}, + "source": [ + "# Structured Profilers" + ] + }, + { + "cell_type": "markdown", + "id": "ff9bd095", + "metadata": {}, + "source": [ + "**Data profiling** - *is the process of examining a dataset and collecting statistical or informational summaries about said dataset.*\n", + "\n", + "The Profiler class inside the DataProfiler is designed to generate *data profiles* via the Profiler class, which ingests either a Data class or a Pandas DataFrame. \n", + "\n", + "Currently, the Data class supports loading the following file formats:\n", + "\n", + "* Any delimited (CSV, TSV, etc.)\n", + "* JSON object\n", + "* Avro\n", + "* Parquet\n", + "* Text files\n", + "* Pandas Series/Dataframe\n", + "\n", + "Once the data is loaded, the Profiler can calculate statistics and predict the entities (via the Labeler) of every column (csv) or key-value (JSON) store as well as dataset wide information, such as the number of nulls, duplicates, etc.\n", + "\n", + "This example will look at specifically the structured data types for structured profiling. " + ] + }, + { + "cell_type": "markdown", + "id": "de58b9c4", + "metadata": {}, + "source": [ + "## Reporting" + ] + }, + { + "cell_type": "markdown", + "id": "8001185a", + "metadata": {}, + "source": [ + "One of the primary purposes of the Profiler are to quickly identify what is in the dataset. This can be useful for analyzing a dataset prior to use or determining which columns could be useful for a given purpose.\n", + "\n", + "In terms of reporting, there are multiple reporting options:\n", + "\n", + "* **Pretty**: Floats are rounded to four decimal places, and lists are shortened.\n", + "* **Compact**: Similar to pretty, but removes detailed statistics such as runtimes, label probabilities, index locations of null types, etc.\n", + "* **Serializable**: Output is json serializable and not prettified\n", + "* **Flat**: Nested Output is returned as a flattened dictionary\n", + "\n", + "The **Pretty** and **Compact** reports are the two most commonly used reports and includes `global_stats` and `data_stats` for the given dataset. `global_stats` contains overall properties of the data such as number of rows/columns, null ratio, duplicate ratio. `data_stats` contains specific properties and statistics for each column file such as min, max, mean, variance, etc.\n", + "\n", + "For structured profiles, the report looks like this:\n", + "\n", + "```\n", + "\"global_stats\": {\n", + " \"samples_used\": int,\n", + " \"column_count\": int,\n", + " \"row_count\": int,\n", + " \"row_has_null_ratio\": float,\n", + " \"row_is_null_ratio\": float, \n", + " \"unique_row_ratio\": float,\n", + " \"duplicate_row_count\": int,\n", + " \"file_type\": string,\n", + " \"encoding\": string,\n", + "},\n", + "\"data_stats\": [\n", + " {\n", + " \"column_name\": string,\n", + " \"data_type\": string,\n", + " \"data_label\": string,\n", + " \"categorical\": bool,\n", + " \"order\": string,\n", + " \"samples\": list(str),\n", + " \"statistics\": {\n", + " \"sample_size\": int,\n", + " \"null_count\": int,\n", + " \"null_types\": list(string),\n", + " \"null_types_index\": {\n", + " string: list(int)\n", + " },\n", + " \"data_type_representation\": [string, list(string)],\n", + " \"min\": [null, float],\n", + " \"max\": [null, float],\n", + " \"mean\": float,\n", + " \"variance\": float,\n", + " \"stddev\": float,\n", + " \"histogram\": { \n", + " \"bin_counts\": list(int),\n", + " \"bin_edges\": list(float),\n", + " },\n", + " \"quantiles\": {\n", + " int: float\n", + " }\n", + " \"vocab\": list(char),\n", + " \"avg_predictions\": dict(float), \n", + " \"data_label_representation\": dict(float),\n", + " \"categories\": list(str),\n", + " \"unique_count\": int,\n", + " \"unique_ratio\": float,\n", + " \"precision\": {\n", + " 'min': int,\n", + " 'max': int,\n", + " 'mean': float,\n", + " 'var': float,\n", + " 'std': float,\n", + " 'sample_size': int,\n", + " 'margin_of_error': float,\n", + " 'confidence_level': float\t\t\n", + " },\n", + " \"times\": dict(float),\n", + " \"format\": string\n", + " }\n", + " }\n", + "]\n", + "```\n", + "\n", + "In the example, the `compact` format of the report is used to shorten the full list of the results. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5fcb5447", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " import dataprofiler as dp\n", + "\n", + "data_path = \"../dataprofiler/tests/data\"\n", + "\n", + "# remove extra tf loggin\n", + "import tensorflow as tf\n", + "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7fc2df6", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "data = dp.Data(os.path.join(data_path, \"csv/aws_honeypot_marx_geo.csv\"))\n", + "profile = dp.Profiler(data)\n", + "\n", + "# Compact - A high level view, good for quick reviews\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "d7ec39d2", + "metadata": {}, + "source": [ + "It should be noted, in addition to reading the input data from multiple file types, DataProfiler allows the input data as a dataframe. To get more results related to detailed predictions at the entity level from the DataLabeler component or histogram results, the format `pretty` should be used. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29737f25", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "# run data profiler and get the report\n", + "import pandas as pd\n", + "my_dataframe = pd.DataFrame([[1, 2.0],[1, 2.2],[-1, 3]], columns=[\"col_int\", \"col_float\"])\n", + "profile = dp.Profiler(my_dataframe)\n", + "\n", + "report = profile.report(report_options={\"output_format\":\"pretty\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "241f6e3e", + "metadata": {}, + "source": [ + "## Profiler Type" + ] + }, + { + "cell_type": "markdown", + "id": "5b20879b", + "metadata": {}, + "source": [ + "The profiler will infer what type of statistics to generate (structured or unstructured) based on the input. However, you can explicitly specify profile type as well. Here is an example of the the profiler explicitly calling the structured profile." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc44eb47", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "data = dp.Data(os.path.join(data_path, \"csv/aws_honeypot_marx_geo.csv\"))\n", + "profile = dp.Profiler(data, profiler_type='structured')\n", + "\n", + "# print the report using json to prettify.\n", + "report = profile.report(report_options={\"output_format\": \"pretty\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "fe02ad64", + "metadata": {}, + "source": [ + "## Profiler options" + ] + }, + { + "cell_type": "markdown", + "id": "40804cc9", + "metadata": {}, + "source": [ + "The DataProfiler has the ability to turn on and off components as needed. This is accomplished via the `ProfilerOptions` class.\n", + "\n", + "For example, if a user doesn't require histogram information they may desire to turn off the histogram functionality. Simialrly, if a user is looking for a more accurate labeling, they can increase the samples used to label.\n", + "\n", + "Below, let's remove the histogram and increase the number of samples to the labeler component (1,000 samples). \n", + "\n", + "Full list of options in the Profiler section of the [DataProfiler documentation](https://capitalone.github.io/DataProfiler/profile_options.html)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d25d899", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "data = dp.Data(os.path.join(data_path, \"csv/diamonds.csv\"))\n", + "\n", + "profile_options = dp.ProfilerOptions()\n", + "\n", + "# Setting multiple options via set\n", + "profile_options.set({ \"histogram.is_enabled\": False, \"int.is_enabled\": False})\n", + "\n", + "# Set options via directly setting them\n", + "profile_options.structured_options.data_labeler.max_sample_size = 1000\n", + "\n", + "profile = dp.Profiler(data, options=profile_options)\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "\n", + "# Print the report\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "2052415a", + "metadata": {}, + "source": [ + "## Updating Profiles" + ] + }, + { + "cell_type": "markdown", + "id": "7e02f746", + "metadata": {}, + "source": [ + "Beyond just profiling, one of the unique aspects of the DataProfiler is the ability to update the profiles. To update appropriately, the schema (columns / keys) must match appropriately." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ab8022f", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "# Load and profile a CSV file\n", + "data = dp.Data(os.path.join(data_path, \"csv/sparse-first-and-last-column-header-and-author.txt\"))\n", + "profile = dp.Profiler(data)\n", + "\n", + "# Update the profile with new data:\n", + "new_data = dp.Data(os.path.join(data_path, \"csv/sparse-first-and-last-column-skip-header.txt\"))\n", + "# new_data = dp.Data(os.path.join(data_path, \"iris-utf-16.csv\")) # will error due to schema mismatch\n", + "profile.update_profile(new_data)\n", + "\n", + "# Take a peek at the data\n", + "print(data.data)\n", + "print(new_data.data)\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "66ec6dc5", + "metadata": {}, + "source": [ + "## Merging Profiles" + ] + }, + { + "cell_type": "markdown", + "id": "e2265fe9", + "metadata": {}, + "source": [ + "Merging profiles are an alternative method for updating profiles. Particularly, multiple profiles can be generated seperately, then added together with a simple `+` command: `profile3 = profile1 + profile2`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc68ca07", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "# Load a CSV file with a schema\n", + "data1 = dp.Data(os.path.join(data_path, \"csv/sparse-first-and-last-column-header-and-author.txt\"))\n", + "profile1 = dp.Profiler(data1)\n", + "\n", + "# Load another CSV file with the same schema\n", + "data2 = dp.Data(os.path.join(data_path, \"csv/sparse-first-and-last-column-skip-header.txt\"))\n", + "profile2 = dp.Profiler(data2)\n", + "\n", + "# Merge the profiles\n", + "profile3 = profile1 + profile2\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile3.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "7ea07dc6", + "metadata": {}, + "source": [ + "As you can see, the `update_profile` function and the `+` operator function similarly. The reason the `+` operator is important is that it's possible to *save and load profiles*, which we cover next." + ] + }, + { + "cell_type": "markdown", + "id": "375ff25c-b189-436a-b07d-5e7f13cc6e03", + "metadata": {}, + "source": [ + "## Differences in Data\n", + "Can be applied to both structured and unstructured datasets. \n", + "\n", + "Such reports can provide details on the differences between training and validation data like in this pseudo example:\n", + "```python\n", + "profiler_training = dp.Profiler(training_data)\n", + "profiler_testing = dp.Profiler(testing_data)\n", + "\n", + "validation_report = profiler_training.diff(profiler_testing)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "65360a03-e3ff-4f3c-9963-412298fdb284", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "from pprint import pprint\n", + "\n", + "# structured differences example\n", + "data_split_differences = profile1.diff(profile2)\n", + "pprint(data_split_differences)" + ] + }, + { + "cell_type": "markdown", + "id": "2ae471ff-852f-400a-9bee-5c9fef96f10a", + "metadata": {}, + "source": [ + "## Graphing a Profile\n", + "\n", + "We've also added the ability to generating visual reports from a profile.\n", + "\n", + "The following plots are currently available to work directly with your profilers:\n", + "\n", + " * missing values matrix\n", + " * histogram (numeric columns only)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "734b588d-ac9a-409c-8eb5-b1a0aede8c63", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "\n", + "# get the data\n", + "data_folder = \"../dataprofiler/tests/data\"\n", + "data = dp.Data(os.path.join(data_folder, \"csv/aws_honeypot_marx_geo.csv\"))\n", + "\n", + "# profile the data\n", + "profile = dp.Profiler(data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e4e70204-fa30-43c2-9556-e84c19f82d32", + "metadata": {}, + "outputs": [], + "source": [ + "# generate a missing values matrix\n", + "fig = plt.figure(figsize=(8, 6), dpi=100)\n", + "fig = dp.graphs.plot_missing_values_matrix(profile, ax=fig.gca(), title=\"Missing Values Matrix\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d734d355-e542-4245-a1e9-66521e333c2d", + "metadata": {}, + "outputs": [], + "source": [ + "# generate histogram of all int/float columns\n", + "fig = dp.graphs.plot_histograms(profile)\n", + "fig.set_size_inches(8, 6)\n", + "fig.set_dpi(100)" + ] + }, + { + "cell_type": "markdown", + "id": "30868000", + "metadata": {}, + "source": [ + "## Saving and Loading a Profile" + ] + }, + { + "cell_type": "markdown", + "id": "f2858072", + "metadata": {}, + "source": [ + "Not only can the Profiler create and update profiles, it's also possible to save, load then manipulate profiles." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ad9ca57", + "metadata": {}, + "outputs": [], + "source": [ + "# Load data\n", + "data = dp.Data(os.path.join(data_path, \"csv/names-col.txt\"))\n", + "\n", + "# Generate a profile\n", + "profile = dp.Profiler(data)\n", + "\n", + "# Save a profile to disk for later (saves as pickle file)\n", + "profile.save(filepath=\"my_profile.pkl\")\n", + "\n", + "# Load a profile from disk\n", + "loaded_profile = dp.Profiler.load(\"my_profile.pkl\")\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "8f9859c2", + "metadata": {}, + "source": [ + "With the ability to save and load profiles, profiles can be generated via multiple machines then merged. Further, profiles can be stored and later used in applications such as change point detection, synthetic data generation, and more. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3571f2d0", + "metadata": {}, + "outputs": [], + "source": [ + "# Load a multiple files via the Data class\n", + "filenames = [\"csv/sparse-first-and-last-column-header-and-author.txt\",\n", + " \"csv/sparse-first-and-last-column-skip-header.txt\"]\n", + "data_objects = []\n", + "for filename in filenames:\n", + " data_objects.append(dp.Data(os.path.join(data_path, filename)))\n", + "\n", + "\n", + "# Generate and save profiles\n", + "for i in range(len(data_objects)):\n", + " profile = dp.Profiler(data_objects[i])\n", + " profile.save(filepath=\"data-\"+str(i)+\".pkl\")\n", + "\n", + "\n", + "# Load profiles and add them together\n", + "profile = None\n", + "for i in range(len(data_objects)):\n", + " if profile is None:\n", + " profile = dp.Profiler.load(\"data-\"+str(i)+\".pkl\")\n", + " else:\n", + " profile += dp.Profiler.load(\"data-\"+str(i)+\".pkl\")\n", + "\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4690068a-8fc3-4bd5-8649-63d0f34fa91d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/doctrees/nbsphinx/regex_labeler_from_scratch.ipynb b/docs/0.10.5/doctrees/nbsphinx/regex_labeler_from_scratch.ipynb new file mode 100644 index 000000000..96aee213a --- /dev/null +++ b/docs/0.10.5/doctrees/nbsphinx/regex_labeler_from_scratch.ipynb @@ -0,0 +1,444 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e04c382a-7c49-452b-b9bf-e448951c64fe", + "metadata": {}, + "source": [ + "# Building a Regex Data Labeler w/ your own Regex" + ] + }, + { + "cell_type": "markdown", + "id": "6fb3ecb9-bc51-4c18-93d5-7991bbee5165", + "metadata": {}, + "source": [ + "This notebook teaches how to use the existing / create your own regex labeler as well as utilize it for structured data profiling.\n", + "\n", + "1. Loading and utilizing the pre-existing regex data labeler\n", + "1. Replacing the existing regex rules with your own.\n", + "1. Utilizng a regex data labeler inside of the structured profiler\n", + "\n", + "First, let's import the libraries needed for this example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a67c197b-d3ee-4896-a96f-cc3d043601d3", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "from pprint import pprint\n", + "\n", + "import pandas as pd\n", + "\n", + "try:\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " sys.path.insert(0, '../..')\n", + " import dataprofiler as dp" + ] + }, + { + "cell_type": "markdown", + "id": "c71356f4-9020-4862-a1e1-816effbb5443", + "metadata": {}, + "source": [ + "## Loading and using the pre-existing regex data labeler\n", + "We can easily import the exsting regex labeler via the `load_from_library` command from the `dp.DataLabeler`. This allows us to import models other than the default structured / unstructured labelers which exist in the library." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "113d6655-4bca-4d8e-9e6f-b972e29d5684", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler = dp.DataLabeler.load_from_library('regex_model')\n", + "data_labeler.model.help()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b405887-2b92-44ca-b8d7-29c384f6dd9c", + "metadata": {}, + "outputs": [], + "source": [ + "pprint(data_labeler.label_mapping)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11916a48-098c-4056-ac6c-b9542d85fa86", + "metadata": {}, + "outputs": [], + "source": [ + "pprint(data_labeler.model._parameters['regex_patterns'])" + ] + }, + { + "cell_type": "markdown", + "id": "da0e97ee-8d6d-4631-9b55-78ed904d5f41", + "metadata": {}, + "source": [ + "### Predicting with the regex labeler\n", + "In the prediction below, the default settings will `split` the predictions by default as it's aggregation function. In other words, if a string '123 Fake St.' The first character would receive a vote for integer and for address giving both a 50% probability. This is because these regex functions are defined individually and a post prediction aggregation function must be used to get the results." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fe519e65-36a7-4f42-8314-5369de8635c7", + "metadata": {}, + "outputs": [], + "source": [ + "# evaluate a prediction using the default parameters\n", + "data_labeler.predict(['123 Fake St.'])" + ] + }, + { + "cell_type": "markdown", + "id": "b41d834d-e47b-45a6-8970-d2d2033e2ade", + "metadata": {}, + "source": [ + "## Replacing the regex rules in the existing labeler\n", + "\n", + "We can achieve this by:\n", + "1. Setting the label mapping to the new labels\n", + "2. Setting the model parameters which include: `regex_patterns`, `default_label`, `ignore_case`, and `encapsulators`\n", + "\n", + "where `regex_patterns` is a `dict` of lists or regex for each label, `default_label` is the expected default label for the regex, `ignore_case` tells the model to ignore case during its detection, and `encapsulators` are generic regex statements placed before (start) and after (end) each regex. Currently, this is used by the default model to capture labels that are within a cell rather than matching the entire cell. (e.g. ' 123 ' will still capture 123 as digits)." + ] + }, + { + "cell_type": "markdown", + "id": "c6bb010a-406f-4fd8-abd0-3355a5ad0ded", + "metadata": {}, + "source": [ + "Below, we created 4 labels where `other` is the `default_label`. Additionally, we set enabled case sensitivity such that upper and lower case letters would be detected separately." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f86584cf-a7af-4bae-bf44-d87caa68833a", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.set_labels({'other': 0, 'digits':1, 'lowercase_char': 2, 'uppercase_chars': 3})\n", + "data_labeler.model.set_params(\n", + " regex_patterns={\n", + " 'digits': [r'[+-]?[0-9]+'],\n", + " 'lowercase_char': [r'[a-z]+'],\n", + " 'uppercase_chars': [r'[A-Z]+'],\n", + " },\n", + " default_label='other',\n", + " ignore_case=False,\n", + ")\n", + "data_labeler.label_mapping" + ] + }, + { + "cell_type": "markdown", + "id": "1ece1c8c-18a5-46fc-b563-6458e6e71e53", + "metadata": {}, + "source": [ + "### Predicting with the new regex labels\n", + "\n", + "Here we notice the otuput of the predictions gives us a prediction per character for each regex. Note how by default it is matching subtext due to the encapsulators. Where `123` were found to be digits, `FAKE` was foudn to be upper case, and the whitespaces and `St.` were other due no single regex being correct." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92842e14-2ea6-4879-b58c-c52b607dc94c", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.predict(['123 FAKE St.'])" + ] + }, + { + "cell_type": "markdown", + "id": "2ce14e54-094f-41ff-9ce0-69acace6abc2", + "metadata": {}, + "source": [ + "Below we turn off case-sensitivity and we see how the aggregation funciton splits the votes for characters between the `lowercase` and `uppercase` chars." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f7b8ed9d-c912-4dc7-82c5-ba78a3affc1e", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.model.set_params(ignore_case=True)\n", + "data_labeler.predict(['123 FAKE St.'])" + ] + }, + { + "cell_type": "markdown", + "id": "dc66515f-24e4-40f0-8592-b1ee4fba7077", + "metadata": {}, + "source": [ + "For the rest of this notebook, we will just use a single regex serach which will capture both upper and lower case chars." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3e0c1b11-d111-4080-873f-40aff7cf7930", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.set_labels({'other': 0, 'digits':1, 'chars': 2})\n", + "data_labeler.model.set_params(\n", + " regex_patterns={\n", + " 'digits': [r'[=-]?[0-9]+'],\n", + " 'chars': [r'[a-zA-Z]+'],\n", + " },\n", + " default_label='other',\n", + " ignore_case=False,\n", + ")\n", + "data_labeler.label_mapping" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28e7b2ee-c661-4b31-b727-078f1393b5c4", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.predict(['123 FAKE St.'])" + ] + }, + { + "cell_type": "markdown", + "id": "f60c8fd1-76e1-469f-9e5a-62d7529301b3", + "metadata": {}, + "source": [ + "### Adjusting postprocessor properties\n", + "\n", + "Below we can look at the possible postprocessor parameters to adjust the aggregation function to the desired output. The previous outputs by default used the `split` aggregation function, however, below we will show the `random` aggregation function which will randomly choose a label if multiple labels have a vote for a given character." + ] + }, + { + "cell_type": "markdown", + "id": "36afa82b-1ca5-49ad-9aa9-84c6de621f59", + "metadata": {}, + "source": [ + "data_labeler.postprocessor.help()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "66840940-47bf-433a-8ee8-977f26926e0b", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.postprocessor.set_params(aggregation_func='random')\n", + "data_labeler.predict(['123 FAKE St.'], predict_options=dict(show_confidences=True))" + ] + }, + { + "cell_type": "markdown", + "id": "c32b74fc-5051-4d53-b02a-4d1e4a35958f", + "metadata": {}, + "source": [ + "## Integrating the new Regex labeler into Structured Profiling\n", + "\n", + "While the labeler can be used alone, it is also possible to integrate the labeler into the StructuredProfiler with a slight change to its postprocessor. The StructuredProfiler requires a labeler which outputs othe confidence of each label for a given cell being processed. To convert the output of the `RegexPostProcessor` into said format, we will use the `StructRegexPostProcessor`. We can create the postprocessor and set the `data_labeler`'s postprocessor to this value." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a2663f2d-29a2-41ed-88dd-8a213d303365", + "metadata": {}, + "outputs": [], + "source": [ + "from dataprofiler.labelers.data_processing import StructRegexPostProcessor\n", + "\n", + "postprocesor = StructRegexPostProcessor()\n", + "data_labeler.set_postprocessor(postprocesor)" + ] + }, + { + "cell_type": "markdown", + "id": "f7352769-d636-42c6-9706-7d9cff520a72", + "metadata": {}, + "source": [ + "Below we will see the output is now one vote per sample." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18814634-0fd0-4ce8-b0c3-9b9454701a43", + "metadata": {}, + "outputs": [], + "source": [ + "data_labeler.predict(['123 FAKE St.', '123', 'FAKE'], predict_options=dict(show_confidences=True))" + ] + }, + { + "cell_type": "markdown", + "id": "b4aa4e36-7362-4966-b827-3f5a6f2dfa7c", + "metadata": {}, + "source": [ + "### Setting the Structuredprofiler's DataLabeler\n", + "\n", + "We can create a `ProfilerOption` and set the structured options to have the new data_labeler as its value. We then run the StructuredProfiler with the specified options." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f18cf7f-283e-4e54-b3f9-1312828c3029", + "metadata": {}, + "outputs": [], + "source": [ + "# create and set the option for the regex data labeler to be used at profile time\n", + "profile_options = dp.ProfilerOptions()\n", + "profile_options.set({'structured_options.data_labeler.data_labeler_object': data_labeler})\n", + "\n", + "# profile the dataset using the suggested regex data labeler\n", + "data = pd.DataFrame(\n", + " [['123 FAKE St.', 123, 'this'], \n", + " [123 , -9, 'IS'], \n", + " ['...' , +80, 'A'], \n", + " ['123' , 202, 'raNDom'], \n", + " ['test' , -1, 'TEST']], \n", + " dtype=object)\n", + "profiler = dp.Profiler(data, options=profile_options)" + ] + }, + { + "cell_type": "markdown", + "id": "663e49f7-358b-4b0f-99a4-1823908ef990", + "metadata": {}, + "source": [ + "Below we see the first column is given 3 labels as it received multiple votes for said column. However, it was confident on the second and third column which is why it only specified `digits` and `chars` respectively." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f796d7f5-7e8a-447b-9cbb-d5b8180660a3", + "metadata": {}, + "outputs": [], + "source": [ + "pprint(profiler.report(\n", + " dict(output_format='compact', \n", + " omit_keys=['data_stats.*.statistics', \n", + " 'data_stats.*.categorical', \n", + " 'data_stats.*.order', \n", + " 'global_stats'])))" + ] + }, + { + "cell_type": "markdown", + "id": "261b903f-8f4c-403f-839b-ab8813f850e9", + "metadata": {}, + "source": [ + "## Saving the Data Labeler for future use" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6ffbaf2-9400-486a-ba83-5fc9ba9334d7", + "metadata": {}, + "outputs": [], + "source": [ + "if not os.path.isdir('my_new_regex_labeler'):\n", + " os.mkdir('my_new_regex_labeler')\n", + "data_labeler.save_to_disk('my_new_regex_labeler')" + ] + }, + { + "cell_type": "markdown", + "id": "09e40cb6-9d89-41c4-ae28-3dca498f8c68", + "metadata": {}, + "source": [ + "## Loading the saved Data Labeler" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52615b25-70a6-4ebb-8a32-14aaf1e747d9", + "metadata": {}, + "outputs": [], + "source": [ + "saved_labeler = dp.DataLabeler.load_from_disk('my_new_regex_labeler')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d1ccc0b3-1dc2-4847-95c2-d6b8769b1590", + "metadata": {}, + "outputs": [], + "source": [ + "# ensuring the parametesr are what we saved.\n", + "print(\"label_mapping:\")\n", + "pprint(saved_labeler.label_mapping)\n", + "print(\"\\nmodel parameters:\")\n", + "pprint(saved_labeler.model._parameters)\n", + "print()\n", + "print(\"postprocessor: \" + saved_labeler.postprocessor.__class__.__name__)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c827f2ae-4af6-4f3f-9651-9ee9ebea9fa0", + "metadata": {}, + "outputs": [], + "source": [ + "# predicting with the loaded labeler.\n", + "saved_labeler.predict(['test', '123'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "606f9bbf-5955-4b7b-b0d1-390de5600f73", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/doctrees/nbsphinx/unstructured_profiler_example.ipynb b/docs/0.10.5/doctrees/nbsphinx/unstructured_profiler_example.ipynb new file mode 100644 index 000000000..9ab754cc7 --- /dev/null +++ b/docs/0.10.5/doctrees/nbsphinx/unstructured_profiler_example.ipynb @@ -0,0 +1,436 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f37ca393", + "metadata": {}, + "source": [ + "# Unstructured Profilers" + ] + }, + { + "cell_type": "markdown", + "id": "ff9bd095", + "metadata": {}, + "source": [ + "**Data profiling** - *is the process of examining a dataset and collecting statistical or informational summaries about said dataset.*\n", + "\n", + "The Profiler class inside the DataProfiler is designed to generate *data profiles* via the Profiler class, which ingests either a Data class or a Pandas DataFrame. \n", + "\n", + "Currently, the Data class supports loading the following file formats:\n", + "\n", + "* Any delimited (CSV, TSV, etc.)\n", + "* JSON object\n", + "* Avro\n", + "* Parquet\n", + "* Text files\n", + "* Pandas Series/Dataframe\n", + "\n", + "Once the data is loaded, the Profiler can calculate statistics and predict the entities (via the Labeler) of every column (csv) or key-value (JSON) store as well as dataset wide information, such as the number of nulls, duplicates, etc.\n", + "\n", + "This example will look at specifically the unstructured data types for unstructured profiling. This means that only text files, lists of strings, single column pandas dataframes/series, or DataProfile Data objects in string format will work with the unstructured profiler. " + ] + }, + { + "cell_type": "markdown", + "id": "de58b9c4", + "metadata": {}, + "source": [ + "## Reporting" + ] + }, + { + "cell_type": "markdown", + "id": "8001185a", + "metadata": {}, + "source": [ + "One of the primary purposes of the Profiler are to quickly identify what is in the dataset. This can be useful for analyzing a dataset prior to use or determining which columns could be useful for a given purpose.\n", + "\n", + "In terms of reporting, there are multiple reporting options:\n", + "\n", + "* **Pretty**: Floats are rounded to four decimal places, and lists are shortened.\n", + "* **Compact**: Similar to pretty, but removes detailed statistics\n", + "* **Serializable**: Output is json serializable and not prettified\n", + "* **Flat**: Nested Output is returned as a flattened dictionary\n", + "\n", + "The **Pretty** and **Compact** reports are the two most commonly used reports and includes `global_stats` and `data_stats` for the given dataset. `global_stats` contains overall properties of the data such as samples used and file encoding. `data_stats` contains specific properties and statistics for each text sample.\n", + "\n", + "For unstructured profiles, the report looks like this:\n", + "\n", + "```\n", + "\"global_stats\": {\n", + " \"samples_used\": int,\n", + " \"empty_line_count\": int,\n", + " \"file_type\": string,\n", + " \"encoding\": string\n", + "},\n", + "\"data_stats\": {\n", + " \"data_label\": {\n", + " \"entity_counts\": {\n", + " \"word_level\": dict(int),\n", + " \"true_char_level\": dict(int),\n", + " \"postprocess_char_level\": dict(int)\n", + " },\n", + " \"times\": dict(float)\n", + " },\n", + " \"statistics\": {\n", + " \"vocab\": list(char),\n", + " \"words\": list(string),\n", + " \"word_count\": dict(int),\n", + " \"times\": dict(float)\n", + " }\n", + "}\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5fcb5447", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import json\n", + "\n", + "try:\n", + " sys.path.insert(0, '..')\n", + " import dataprofiler as dp\n", + "except ImportError:\n", + " import dataprofiler as dp\n", + "\n", + "data_path = \"../dataprofiler/tests/data\"\n", + "\n", + "# remove extra tf loggin\n", + "import tensorflow as tf\n", + "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7fc2df6", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "data = dp.Data(os.path.join(data_path, \"txt/discussion_reddit.txt\"))\n", + "profile = dp.Profiler(data)\n", + "\n", + "report = profile.report(report_options={\"output_format\": \"pretty\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "4d183992", + "metadata": {}, + "source": [ + "## Profiler Type" + ] + }, + { + "cell_type": "markdown", + "id": "d7ec39d2", + "metadata": {}, + "source": [ + "It should be noted, in addition to reading the input data from text files, DataProfiler allows the input data as a pandas dataframe, a pandas series, a list, and Data objects (when an unstructured format is selected) if the Profiler is explicitly chosen as unstructured." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29737f25", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "# run data profiler and get the report\n", + "import pandas as pd\n", + "data = dp.Data(os.path.join(data_path, \"csv/SchoolDataSmall.csv\"), options={\"data_format\": \"records\"})\n", + "profile = dp.Profiler(data, profiler_type='unstructured')\n", + "\n", + "report = profile.report(report_options={\"output_format\":\"pretty\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "fe02ad64", + "metadata": {}, + "source": [ + "## Profiler options" + ] + }, + { + "cell_type": "markdown", + "id": "40804cc9", + "metadata": {}, + "source": [ + "The DataProfiler has the ability to turn on and off components as needed. This is accomplished via the `ProfilerOptions` class.\n", + "\n", + "For example, if a user doesn't require vocab count information they may desire to turn off the word count functionality.\n", + "\n", + "Below, let's remove the vocab count and set the stop words. \n", + "\n", + "Full list of options in the Profiler section of the [DataProfiler documentation](https://capitalone.github.io/DataProfiler/profile_options.html)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d25d899", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "data = dp.Data(os.path.join(data_path, \"txt/discussion_reddit.txt\"))\n", + "\n", + "profile_options = dp.ProfilerOptions()\n", + "\n", + "# Setting multiple options via set\n", + "profile_options.set({ \"*.vocab.is_enabled\": False, \"*.is_case_sensitive\": True })\n", + "\n", + "# Set options via directly setting them\n", + "profile_options.unstructured_options.text.stop_words = [\"These\", \"are\", \"stop\", \"words\"]\n", + "\n", + "profile = dp.Profiler(data, options=profile_options)\n", + "report = profile.report(report_options={\"output_format\": \"compact\"})\n", + "\n", + "# Print the report\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "2052415a", + "metadata": {}, + "source": [ + "## Updating Profiles" + ] + }, + { + "cell_type": "markdown", + "id": "7e02f746", + "metadata": {}, + "source": [ + "Beyond just profiling, one of the unique aspects of the DataProfiler is the ability to update the profiles. To update appropriately, the schema (columns / keys) must match appropriately." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ab8022f", + "metadata": {}, + "outputs": [], + "source": [ + "# Load and profile a CSV file\n", + "data = dp.Data(os.path.join(data_path, \"txt/sentence-3x.txt\"))\n", + "profile = dp.Profiler(data)\n", + "\n", + "# Update the profile with new data:\n", + "new_data = dp.Data(os.path.join(data_path, \"txt/sentence-3x.txt\"))\n", + "profile.update_profile(new_data)\n", + "\n", + "# Take a peek at the data\n", + "print(data.data)\n", + "print(new_data.data)\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile.report(report_options={\"output_format\": \"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "66ec6dc5", + "metadata": {}, + "source": [ + "## Merging Profiles" + ] + }, + { + "cell_type": "markdown", + "id": "e2265fe9", + "metadata": {}, + "source": [ + "Merging profiles are an alternative method for updating profiles. Particularly, multiple profiles can be generated seperately, then added together with a simple `+` command: `profile3 = profile1 + profile2`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc68ca07", + "metadata": {}, + "outputs": [], + "source": [ + "# Load a CSV file with a schema\n", + "data1 = dp.Data(os.path.join(data_path, \"txt/sentence-3x.txt\"))\n", + "profile1 = dp.Profiler(data1)\n", + "\n", + "# Load another CSV file with the same schema\n", + "data2 = dp.Data(os.path.join(data_path, \"txt/sentence-3x.txt\"))\n", + "profile2 = dp.Profiler(data2)\n", + "\n", + "# Merge the profiles\n", + "profile3 = profile1 + profile2\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile3.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "7ea07dc6", + "metadata": {}, + "source": [ + "As you can see, the `update_profile` function and the `+` operator function similarly. The reason the `+` operator is important is that it's possible to *save and load profiles*, which we cover next." + ] + }, + { + "cell_type": "markdown", + "id": "4704961a", + "metadata": {}, + "source": [ + "## Differences in Data\n", + "Can be applied to both structured and unstructured datasets. \n", + "\n", + "Such reports can provide details on the differences between training and validation data like in this pseudo example:\n", + "```python\n", + "profiler_training = dp.Profiler(training_data)\n", + "profiler_testing = dp.Profiler(testing_data)\n", + "\n", + "validation_report = profiler_training.diff(profiler_testing)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "58f92c1b", + "metadata": {}, + "outputs": [], + "source": [ + "from pprint import pprint\n", + "\n", + "# unstructured differences example\n", + "data_split_differences = profile1.diff(profile2)\n", + "pprint(data_split_differences)" + ] + }, + { + "cell_type": "markdown", + "id": "30868000", + "metadata": {}, + "source": [ + "## Saving and Loading a Profile" + ] + }, + { + "cell_type": "markdown", + "id": "f2858072", + "metadata": {}, + "source": [ + "Not only can the Profiler create and update profiles, it's also possible to save, load then manipulate profiles." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ad9ca57", + "metadata": {}, + "outputs": [], + "source": [ + "# Load data\n", + "data = dp.Data(os.path.join(data_path, \"txt/sentence-3x.txt\"))\n", + "\n", + "# Generate a profile\n", + "profile = dp.Profiler(data)\n", + "\n", + "# Save a profile to disk for later (saves as pickle file)\n", + "profile.save(filepath=\"my_profile.pkl\")\n", + "\n", + "# Load a profile from disk\n", + "loaded_profile = dp.Profiler.load(\"my_profile.pkl\")\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "8f9859c2", + "metadata": {}, + "source": [ + "With the ability to save and load profiles, profiles can be generated via multiple machines then merged. Further, profiles can be stored and later used in applications such as change point detection, synthetic data generation, and more. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3571f2d0", + "metadata": {}, + "outputs": [], + "source": [ + "# Load a multiple files via the Data class\n", + "filenames = [\"txt/sentence-3x.txt\",\n", + " \"txt/sentence.txt\"]\n", + "data_objects = []\n", + "for filename in filenames:\n", + " data_objects.append(dp.Data(os.path.join(data_path, filename)))\n", + "\n", + "print(data_objects)\n", + "# Generate and save profiles\n", + "for i in range(len(data_objects)):\n", + " profile = dp.Profiler(data_objects[i])\n", + " report = profile.report(report_options={\"output_format\":\"compact\"})\n", + " print(json.dumps(report, indent=4))\n", + " profile.save(filepath=\"data-\"+str(i)+\".pkl\")\n", + "\n", + "\n", + "# Load profiles and add them together\n", + "profile = None\n", + "for i in range(len(data_objects)):\n", + " if profile is None:\n", + " profile = dp.Profiler.load(\"data-\"+str(i)+\".pkl\")\n", + " else:\n", + " profile += dp.Profiler.load(\"data-\"+str(i)+\".pkl\")\n", + "\n", + "\n", + "# Report the compact version of the profile\n", + "report = profile.report(report_options={\"output_format\":\"compact\"})\n", + "print(json.dumps(report, indent=4))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/0.10.5/doctrees/overview.doctree b/docs/0.10.5/doctrees/overview.doctree new file mode 100644 index 0000000000000000000000000000000000000000..c76512ac1e9beaa7d6b433869f7f60c0746ad86e GIT binary patch literal 39414 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/popmon_dp_loader_example.doctree b/docs/0.10.5/doctrees/popmon_dp_loader_example.doctree new file mode 100644 index 0000000000000000000000000000000000000000..7c309af4da7fc00e05cd746754402aedc297f3e0 GIT binary patch literal 27518 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/profiler.doctree b/docs/0.10.5/doctrees/profiler.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4582bde1d90f41891344861b2720c9150a292af1 GIT binary patch literal 215481 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%0AP{z>zyBFYq|P4oaitR# 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 F{Tq>_W1j#3 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/profiler_example.doctree b/docs/0.10.5/doctrees/profiler_example.doctree new file mode 100644 index 0000000000000000000000000000000000000000..21850f2c28ff545b736f45d8da642c8abfd6dbdf GIT binary patch literal 47446 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 t!Kv`7@PI|QG+uP51#s^10sWZS>~v literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/regex_labeler_from_scratch.doctree b/docs/0.10.5/doctrees/regex_labeler_from_scratch.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4c1fcbdfccf79b3145e8791d05bfb40339822fea GIT binary patch literal 42399 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 Id~u`t|5m)9+W-In literal 0 HcmV?d00001 diff --git a/docs/0.10.5/doctrees/unstructured_profiler_example.doctree b/docs/0.10.5/doctrees/unstructured_profiler_example.doctree new file mode 100644 index 0000000000000000000000000000000000000000..7ab32b29969662537d3a6e669beebfbca0267490 GIT binary patch literal 36875 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 literal 0 HcmV?d00001 diff --git a/docs/0.10.5/html/.buildinfo b/docs/0.10.5/html/.buildinfo new file mode 100644 index 000000000..ba0d7425d --- /dev/null +++ b/docs/0.10.5/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: d0a7fd88361ea4747fc925205e98dd9f +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/0.10.5/html/API.html b/docs/0.10.5/html/API.html new file mode 100644 index 000000000..a2e2e586c --- /dev/null +++ b/docs/0.10.5/html/API.html @@ -0,0 +1,294 @@ + + + + + + + + + API - Data Profiler v0.10.5 + + + + + + + + + + + + + Contents + + + + + + + + + Menu + + + + + + + + Expand + + + + + + + + + + + + + +

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 @Sxxo-%dcD1WPe0ed=- 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