fg-data-profiling 4.19.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data_profiling/__init__.py +34 -0
- data_profiling/compare_reports.py +359 -0
- data_profiling/config.py +496 -0
- data_profiling/config_default.yaml +223 -0
- data_profiling/config_minimal.yaml +222 -0
- data_profiling/controller/__init__.py +1 -0
- data_profiling/controller/console.py +125 -0
- data_profiling/controller/pandas_decorator.py +21 -0
- data_profiling/expectations_report.py +117 -0
- data_profiling/model/__init__.py +4 -0
- data_profiling/model/alerts.py +780 -0
- data_profiling/model/correlations.py +163 -0
- data_profiling/model/dataframe.py +35 -0
- data_profiling/model/describe.py +210 -0
- data_profiling/model/description.py +108 -0
- data_profiling/model/duplicates.py +14 -0
- data_profiling/model/expectation_algorithms.py +112 -0
- data_profiling/model/handler.py +81 -0
- data_profiling/model/missing.py +146 -0
- data_profiling/model/pairwise.py +33 -0
- data_profiling/model/pandas/__init__.py +55 -0
- data_profiling/model/pandas/correlations_pandas.py +207 -0
- data_profiling/model/pandas/dataframe_pandas.py +26 -0
- data_profiling/model/pandas/describe_boolean_pandas.py +43 -0
- data_profiling/model/pandas/describe_categorical_pandas.py +274 -0
- data_profiling/model/pandas/describe_counts_pandas.py +63 -0
- data_profiling/model/pandas/describe_date_pandas.py +77 -0
- data_profiling/model/pandas/describe_file_pandas.py +56 -0
- data_profiling/model/pandas/describe_generic_pandas.py +36 -0
- data_profiling/model/pandas/describe_image_pandas.py +255 -0
- data_profiling/model/pandas/describe_numeric_pandas.py +175 -0
- data_profiling/model/pandas/describe_path_pandas.py +63 -0
- data_profiling/model/pandas/describe_supported_pandas.py +41 -0
- data_profiling/model/pandas/describe_text_pandas.py +62 -0
- data_profiling/model/pandas/describe_timeseries_pandas.py +222 -0
- data_profiling/model/pandas/describe_url_pandas.py +57 -0
- data_profiling/model/pandas/discretize_pandas.py +81 -0
- data_profiling/model/pandas/duplicates_pandas.py +56 -0
- data_profiling/model/pandas/imbalance_pandas.py +35 -0
- data_profiling/model/pandas/missing_pandas.py +42 -0
- data_profiling/model/pandas/sample_pandas.py +38 -0
- data_profiling/model/pandas/summary_pandas.py +101 -0
- data_profiling/model/pandas/table_pandas.py +56 -0
- data_profiling/model/pandas/timeseries_index_pandas.py +33 -0
- data_profiling/model/pandas/utils_pandas.py +27 -0
- data_profiling/model/sample.py +37 -0
- data_profiling/model/spark/__init__.py +48 -0
- data_profiling/model/spark/correlations_spark.py +152 -0
- data_profiling/model/spark/dataframe_spark.py +34 -0
- data_profiling/model/spark/describe_boolean_spark.py +27 -0
- data_profiling/model/spark/describe_categorical_spark.py +28 -0
- data_profiling/model/spark/describe_counts_spark.py +105 -0
- data_profiling/model/spark/describe_date_spark.py +51 -0
- data_profiling/model/spark/describe_generic_spark.py +30 -0
- data_profiling/model/spark/describe_numeric_spark.py +155 -0
- data_profiling/model/spark/describe_supported_spark.py +33 -0
- data_profiling/model/spark/describe_text_spark.py +25 -0
- data_profiling/model/spark/duplicates_spark.py +54 -0
- data_profiling/model/spark/missing_spark.py +96 -0
- data_profiling/model/spark/sample_spark.py +43 -0
- data_profiling/model/spark/summary_spark.py +95 -0
- data_profiling/model/spark/table_spark.py +58 -0
- data_profiling/model/spark/timeseries_index_spark.py +12 -0
- data_profiling/model/summarizer.py +207 -0
- data_profiling/model/summary.py +66 -0
- data_profiling/model/summary_algorithms.py +276 -0
- data_profiling/model/table.py +10 -0
- data_profiling/model/timeseries_index.py +16 -0
- data_profiling/model/typeset.py +365 -0
- data_profiling/model/typeset_relations.py +143 -0
- data_profiling/profile_report.py +573 -0
- data_profiling/report/__init__.py +4 -0
- data_profiling/report/formatters.py +346 -0
- data_profiling/report/presentation/__init__.py +1 -0
- data_profiling/report/presentation/core/__init__.py +39 -0
- data_profiling/report/presentation/core/alerts.py +18 -0
- data_profiling/report/presentation/core/collapse.py +24 -0
- data_profiling/report/presentation/core/container.py +50 -0
- data_profiling/report/presentation/core/correlation_table.py +21 -0
- data_profiling/report/presentation/core/dropdown.py +44 -0
- data_profiling/report/presentation/core/duplicate.py +16 -0
- data_profiling/report/presentation/core/frequency_table.py +14 -0
- data_profiling/report/presentation/core/frequency_table_small.py +16 -0
- data_profiling/report/presentation/core/html.py +14 -0
- data_profiling/report/presentation/core/image.py +34 -0
- data_profiling/report/presentation/core/item_renderer.py +17 -0
- data_profiling/report/presentation/core/renderable.py +42 -0
- data_profiling/report/presentation/core/root.py +35 -0
- data_profiling/report/presentation/core/sample.py +20 -0
- data_profiling/report/presentation/core/scores.py +32 -0
- data_profiling/report/presentation/core/table.py +26 -0
- data_profiling/report/presentation/core/toggle_button.py +14 -0
- data_profiling/report/presentation/core/variable.py +40 -0
- data_profiling/report/presentation/core/variable_info.py +36 -0
- data_profiling/report/presentation/flavours/__init__.py +9 -0
- data_profiling/report/presentation/flavours/flavour_html.py +64 -0
- data_profiling/report/presentation/flavours/flavour_widget.py +61 -0
- data_profiling/report/presentation/flavours/flavours.py +43 -0
- data_profiling/report/presentation/flavours/html/__init__.py +47 -0
- data_profiling/report/presentation/flavours/html/alerts.py +10 -0
- data_profiling/report/presentation/flavours/html/collapse.py +7 -0
- data_profiling/report/presentation/flavours/html/container.py +58 -0
- data_profiling/report/presentation/flavours/html/correlation_table.py +13 -0
- data_profiling/report/presentation/flavours/html/dropdown.py +7 -0
- data_profiling/report/presentation/flavours/html/duplicate.py +24 -0
- data_profiling/report/presentation/flavours/html/frequency_table.py +20 -0
- data_profiling/report/presentation/flavours/html/frequency_table_small.py +15 -0
- data_profiling/report/presentation/flavours/html/html.py +6 -0
- data_profiling/report/presentation/flavours/html/image.py +7 -0
- data_profiling/report/presentation/flavours/html/root.py +14 -0
- data_profiling/report/presentation/flavours/html/sample.py +12 -0
- data_profiling/report/presentation/flavours/html/scores.py +11 -0
- data_profiling/report/presentation/flavours/html/table.py +7 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_constant.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_constant_length.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_dirty_category.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_duplicates.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_empty.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_high_cardinality.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_high_correlation.html +4 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_imbalance.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_infinite.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_missing.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_near_duplicates.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_non_stationary.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_seasonal.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_skewed.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_truncated.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_type_date.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_uniform.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_unique.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_unsupported.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts/alert_zeros.html +1 -0
- data_profiling/report/presentation/flavours/html/templates/alerts.html +47 -0
- data_profiling/report/presentation/flavours/html/templates/collapse.html +11 -0
- data_profiling/report/presentation/flavours/html/templates/correlation_table.html +5 -0
- data_profiling/report/presentation/flavours/html/templates/diagram.html +11 -0
- data_profiling/report/presentation/flavours/html/templates/dropdown.html +16 -0
- data_profiling/report/presentation/flavours/html/templates/duplicate.html +5 -0
- data_profiling/report/presentation/flavours/html/templates/frequency_table.html +45 -0
- data_profiling/report/presentation/flavours/html/templates/frequency_table_small.html +34 -0
- data_profiling/report/presentation/flavours/html/templates/report.html +26 -0
- data_profiling/report/presentation/flavours/html/templates/sample.html +10 -0
- data_profiling/report/presentation/flavours/html/templates/scores.html +78 -0
- data_profiling/report/presentation/flavours/html/templates/sequence/batch_grid.html +16 -0
- data_profiling/report/presentation/flavours/html/templates/sequence/grid.html +18 -0
- data_profiling/report/presentation/flavours/html/templates/sequence/list.html +7 -0
- data_profiling/report/presentation/flavours/html/templates/sequence/named_list.html +8 -0
- data_profiling/report/presentation/flavours/html/templates/sequence/overview_tabs.html +30 -0
- data_profiling/report/presentation/flavours/html/templates/sequence/scores.html +3 -0
- data_profiling/report/presentation/flavours/html/templates/sequence/sections.html +13 -0
- data_profiling/report/presentation/flavours/html/templates/sequence/select.html +40 -0
- data_profiling/report/presentation/flavours/html/templates/sequence/tabs.html +30 -0
- data_profiling/report/presentation/flavours/html/templates/table.html +38 -0
- data_profiling/report/presentation/flavours/html/templates/toggle_button.html +18 -0
- data_profiling/report/presentation/flavours/html/templates/variable.html +7 -0
- data_profiling/report/presentation/flavours/html/templates/variable_info.html +49 -0
- data_profiling/report/presentation/flavours/html/templates/wrapper/assets/bootstrap.bundle.min.js +7 -0
- data_profiling/report/presentation/flavours/html/templates/wrapper/assets/bootstrap.min.css +6 -0
- data_profiling/report/presentation/flavours/html/templates/wrapper/assets/cosmo.bootstrap.min.css +12 -0
- data_profiling/report/presentation/flavours/html/templates/wrapper/assets/flatly.bootstrap.min.css +12 -0
- data_profiling/report/presentation/flavours/html/templates/wrapper/assets/script.js +52 -0
- data_profiling/report/presentation/flavours/html/templates/wrapper/assets/simplex.bootstrap.min.css +12 -0
- data_profiling/report/presentation/flavours/html/templates/wrapper/assets/style.css +253 -0
- data_profiling/report/presentation/flavours/html/templates/wrapper/assets/united.bootstrap.min.css +12 -0
- data_profiling/report/presentation/flavours/html/templates/wrapper/footer.html +7 -0
- data_profiling/report/presentation/flavours/html/templates/wrapper/javascript.html +18 -0
- data_profiling/report/presentation/flavours/html/templates/wrapper/navigation.html +36 -0
- data_profiling/report/presentation/flavours/html/templates/wrapper/style.html +53 -0
- data_profiling/report/presentation/flavours/html/templates.py +76 -0
- data_profiling/report/presentation/flavours/html/toggle_button.py +7 -0
- data_profiling/report/presentation/flavours/html/variable.py +7 -0
- data_profiling/report/presentation/flavours/html/variable_info.py +7 -0
- data_profiling/report/presentation/flavours/widget/__init__.py +49 -0
- data_profiling/report/presentation/flavours/widget/alerts.py +45 -0
- data_profiling/report/presentation/flavours/widget/collapse.py +43 -0
- data_profiling/report/presentation/flavours/widget/container.py +121 -0
- data_profiling/report/presentation/flavours/widget/correlation_table.py +14 -0
- data_profiling/report/presentation/flavours/widget/dropdown.py +31 -0
- data_profiling/report/presentation/flavours/widget/duplicate.py +14 -0
- data_profiling/report/presentation/flavours/widget/frequency_table.py +57 -0
- data_profiling/report/presentation/flavours/widget/frequency_table_small.py +66 -0
- data_profiling/report/presentation/flavours/widget/html.py +11 -0
- data_profiling/report/presentation/flavours/widget/image.py +26 -0
- data_profiling/report/presentation/flavours/widget/notebook.py +81 -0
- data_profiling/report/presentation/flavours/widget/root.py +10 -0
- data_profiling/report/presentation/flavours/widget/sample.py +14 -0
- data_profiling/report/presentation/flavours/widget/table.py +30 -0
- data_profiling/report/presentation/flavours/widget/toggle_button.py +17 -0
- data_profiling/report/presentation/flavours/widget/variable.py +12 -0
- data_profiling/report/presentation/flavours/widget/variable_info.py +11 -0
- data_profiling/report/presentation/frequency_table_utils.py +141 -0
- data_profiling/report/structure/__init__.py +1 -0
- data_profiling/report/structure/correlations.py +123 -0
- data_profiling/report/structure/overview.py +376 -0
- data_profiling/report/structure/report.py +457 -0
- data_profiling/report/structure/variables/__init__.py +35 -0
- data_profiling/report/structure/variables/render_boolean.py +132 -0
- data_profiling/report/structure/variables/render_categorical.py +566 -0
- data_profiling/report/structure/variables/render_common.py +31 -0
- data_profiling/report/structure/variables/render_complex.py +102 -0
- data_profiling/report/structure/variables/render_count.py +172 -0
- data_profiling/report/structure/variables/render_date.py +143 -0
- data_profiling/report/structure/variables/render_file.py +70 -0
- data_profiling/report/structure/variables/render_generic.py +45 -0
- data_profiling/report/structure/variables/render_image.py +204 -0
- data_profiling/report/structure/variables/render_path.py +134 -0
- data_profiling/report/structure/variables/render_real.py +314 -0
- data_profiling/report/structure/variables/render_text.py +189 -0
- data_profiling/report/structure/variables/render_timeseries.py +371 -0
- data_profiling/report/structure/variables/render_url.py +132 -0
- data_profiling/report/utils.py +34 -0
- data_profiling/serialize_report.py +143 -0
- data_profiling/utils/__init__.py +1 -0
- data_profiling/utils/backend.py +9 -0
- data_profiling/utils/cache.py +59 -0
- data_profiling/utils/common.py +142 -0
- data_profiling/utils/compat.py +31 -0
- data_profiling/utils/dataframe.py +238 -0
- data_profiling/utils/logger.py +53 -0
- data_profiling/utils/notebook.py +8 -0
- data_profiling/utils/paths.py +45 -0
- data_profiling/utils/progress_bar.py +15 -0
- data_profiling/utils/styles.py +22 -0
- data_profiling/utils/versions.py +19 -0
- data_profiling/version.py +1 -0
- data_profiling/visualisation/__init__.py +1 -0
- data_profiling/visualisation/context.py +87 -0
- data_profiling/visualisation/missing.py +138 -0
- data_profiling/visualisation/plot.py +1158 -0
- data_profiling/visualisation/utils.py +113 -0
- fg_data_profiling-4.19.0.dist-info/METADATA +362 -0
- fg_data_profiling-4.19.0.dist-info/RECORD +238 -0
- fg_data_profiling-4.19.0.dist-info/WHEEL +6 -0
- fg_data_profiling-4.19.0.dist-info/entry_points.txt +3 -0
- fg_data_profiling-4.19.0.dist-info/licenses/LICENSE +21 -0
- fg_data_profiling-4.19.0.dist-info/top_level.txt +2 -0
- ydata_profiling/__init__.py +43 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import List, Sequence
|
|
3
|
+
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from tqdm.auto import tqdm
|
|
6
|
+
|
|
7
|
+
from data_profiling.config import Settings
|
|
8
|
+
from data_profiling.model import BaseDescription
|
|
9
|
+
from data_profiling.model.alerts import AlertType
|
|
10
|
+
from data_profiling.model.handler import get_render_map
|
|
11
|
+
from data_profiling.report.presentation.core import (
|
|
12
|
+
HTML,
|
|
13
|
+
Collapse,
|
|
14
|
+
Container,
|
|
15
|
+
Dropdown,
|
|
16
|
+
Duplicate,
|
|
17
|
+
)
|
|
18
|
+
from data_profiling.report.presentation.core import Image as ImageWidget
|
|
19
|
+
from data_profiling.report.presentation.core import Sample, ToggleButton, Variable
|
|
20
|
+
from data_profiling.report.presentation.core.renderable import Renderable
|
|
21
|
+
from data_profiling.report.presentation.core.root import Root
|
|
22
|
+
from data_profiling.report.structure.correlations import get_correlation_items
|
|
23
|
+
from data_profiling.report.structure.overview import get_dataset_items
|
|
24
|
+
from data_profiling.utils.dataframe import slugify
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_missing_items(config: Settings, summary: BaseDescription) -> list:
|
|
28
|
+
"""Return the missing diagrams
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
config: report Settings object
|
|
32
|
+
summary: the dataframe summary
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
A list with the missing diagrams
|
|
36
|
+
"""
|
|
37
|
+
items = [
|
|
38
|
+
ImageWidget(
|
|
39
|
+
item["matrix"],
|
|
40
|
+
image_format=config.plot.image_format,
|
|
41
|
+
alt=item["name"],
|
|
42
|
+
name=item["name"],
|
|
43
|
+
anchor_id=key,
|
|
44
|
+
caption=item["caption"],
|
|
45
|
+
)
|
|
46
|
+
if isinstance(item["name"], str)
|
|
47
|
+
else Container(
|
|
48
|
+
[
|
|
49
|
+
ImageWidget(
|
|
50
|
+
item["matrix"][i],
|
|
51
|
+
image_format=config.plot.image_format,
|
|
52
|
+
alt=item["name"][i],
|
|
53
|
+
name=config.html.style._labels[i],
|
|
54
|
+
anchor_id=key,
|
|
55
|
+
caption=item["caption"][i],
|
|
56
|
+
)
|
|
57
|
+
for i in range(len(item["name"]))
|
|
58
|
+
],
|
|
59
|
+
sequence_type="batch_grid",
|
|
60
|
+
batch_size=len(config.html.style._labels),
|
|
61
|
+
anchor_id=key,
|
|
62
|
+
name=item["name"][0],
|
|
63
|
+
)
|
|
64
|
+
for key, item in summary.missing.items()
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
return items
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def render_variables_section(
|
|
71
|
+
config: Settings, dataframe_summary: BaseDescription
|
|
72
|
+
) -> list:
|
|
73
|
+
"""Render the HTML for each of the variables in the DataFrame.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
config: report Settings object
|
|
77
|
+
dataframe_summary: The statistics for each variable.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
The rendered HTML, where each row represents a variable.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
templs = []
|
|
84
|
+
|
|
85
|
+
descriptions = config.variables.descriptions
|
|
86
|
+
show_description = config.show_variable_description
|
|
87
|
+
reject_variables = config.reject_variables
|
|
88
|
+
|
|
89
|
+
render_map = get_render_map()
|
|
90
|
+
|
|
91
|
+
for idx, summary in dataframe_summary.variables.items():
|
|
92
|
+
# Common template variables
|
|
93
|
+
if not isinstance(dataframe_summary.alerts, tuple):
|
|
94
|
+
alerts = [
|
|
95
|
+
alert.fmt()
|
|
96
|
+
for alert in dataframe_summary.alerts
|
|
97
|
+
if alert.column_name == idx
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
alert_fields = {
|
|
101
|
+
field
|
|
102
|
+
for alert in dataframe_summary.alerts
|
|
103
|
+
if alert.column_name == idx
|
|
104
|
+
for field in alert.fields
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
alert_types = {
|
|
108
|
+
alert.alert_type
|
|
109
|
+
for alert in dataframe_summary.alerts
|
|
110
|
+
if alert.column_name == idx
|
|
111
|
+
}
|
|
112
|
+
else:
|
|
113
|
+
alerts = tuple(
|
|
114
|
+
[alert.fmt() for alert in summary_alerts if alert.column_name == idx]
|
|
115
|
+
for summary_alerts in dataframe_summary.alerts
|
|
116
|
+
) # type: ignore
|
|
117
|
+
|
|
118
|
+
alert_fields = {
|
|
119
|
+
field
|
|
120
|
+
for summary_alerts in dataframe_summary.alerts
|
|
121
|
+
for alert in summary_alerts
|
|
122
|
+
if alert.column_name == idx
|
|
123
|
+
for field in alert.fields
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
alert_types = {
|
|
127
|
+
alert.alert_type
|
|
128
|
+
for summary_alerts in dataframe_summary.alerts
|
|
129
|
+
for alert in summary_alerts
|
|
130
|
+
if alert.column_name == idx
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
template_variables = {
|
|
134
|
+
"varname": idx,
|
|
135
|
+
"varid": hash(idx),
|
|
136
|
+
"alerts": alerts,
|
|
137
|
+
"description": descriptions.get(idx, "") if show_description else "",
|
|
138
|
+
"alert_fields": alert_fields,
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
template_variables.update(summary)
|
|
142
|
+
|
|
143
|
+
# Per type template variables
|
|
144
|
+
if isinstance(summary["type"], list):
|
|
145
|
+
types = set(summary["type"])
|
|
146
|
+
if len(types) == 1:
|
|
147
|
+
variable_type = list(types)[0]
|
|
148
|
+
else:
|
|
149
|
+
# This logic may be treated by the typeset
|
|
150
|
+
if (
|
|
151
|
+
types == {"Numeric", "Categorical"}
|
|
152
|
+
or types == {"Categorical", "Unsupported"}
|
|
153
|
+
or types == {"Categorical", "Text"}
|
|
154
|
+
):
|
|
155
|
+
# Treating numeric as categorical, if one is unsupported, still render as categorical
|
|
156
|
+
variable_type = "Categorical"
|
|
157
|
+
else:
|
|
158
|
+
raise ValueError(f"Types for {idx} are not compatible: {types}")
|
|
159
|
+
else:
|
|
160
|
+
variable_type = summary["type"]
|
|
161
|
+
render_map_type = render_map.get(variable_type, render_map["Unsupported"])
|
|
162
|
+
template_variables.update(render_map_type(config, template_variables))
|
|
163
|
+
|
|
164
|
+
# Ignore these
|
|
165
|
+
if reject_variables:
|
|
166
|
+
ignore = AlertType.REJECTED in alert_types
|
|
167
|
+
else:
|
|
168
|
+
ignore = False
|
|
169
|
+
|
|
170
|
+
bottom = None
|
|
171
|
+
if "bottom" in template_variables and template_variables["bottom"] is not None:
|
|
172
|
+
btn = ToggleButton("More details", anchor_id=template_variables["varid"])
|
|
173
|
+
bottom = Collapse(btn, template_variables["bottom"])
|
|
174
|
+
|
|
175
|
+
var = Variable(
|
|
176
|
+
template_variables["top"],
|
|
177
|
+
bottom=bottom,
|
|
178
|
+
anchor_id=template_variables["varid"],
|
|
179
|
+
name=idx,
|
|
180
|
+
ignore=ignore,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
templs.append(var)
|
|
184
|
+
|
|
185
|
+
return templs
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def get_duplicates_items(
|
|
189
|
+
config: Settings, duplicates: pd.DataFrame
|
|
190
|
+
) -> List[Renderable]:
|
|
191
|
+
"""Create the list of duplicates items
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
config: settings object
|
|
195
|
+
duplicates: DataFrame of duplicates
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
List of duplicates items to show in the interface.
|
|
199
|
+
"""
|
|
200
|
+
items: List[Renderable] = []
|
|
201
|
+
if duplicates is not None and len(duplicates) > 0:
|
|
202
|
+
if isinstance(duplicates, list):
|
|
203
|
+
generator = (d is None for d in duplicates)
|
|
204
|
+
if any(generator):
|
|
205
|
+
return items
|
|
206
|
+
|
|
207
|
+
for idx, df in enumerate(duplicates):
|
|
208
|
+
items.append(
|
|
209
|
+
Duplicate(
|
|
210
|
+
duplicate=df,
|
|
211
|
+
name=config.html.style._labels[idx],
|
|
212
|
+
anchor_id="duplicates",
|
|
213
|
+
)
|
|
214
|
+
)
|
|
215
|
+
else:
|
|
216
|
+
items.append(
|
|
217
|
+
Duplicate(
|
|
218
|
+
duplicate=duplicates,
|
|
219
|
+
name="Most frequently occurring",
|
|
220
|
+
anchor_id="duplicates",
|
|
221
|
+
)
|
|
222
|
+
)
|
|
223
|
+
return items
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def get_definition_items(definitions: pd.DataFrame) -> Sequence[Renderable]:
|
|
227
|
+
"""Create the list of duplicates items
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
definitions: DataFrame of column definitions
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
List of column definitions to show in the interface.
|
|
234
|
+
"""
|
|
235
|
+
items = []
|
|
236
|
+
if definitions is not None and len(definitions) > 0:
|
|
237
|
+
items.append(
|
|
238
|
+
Duplicate(
|
|
239
|
+
duplicate=definitions,
|
|
240
|
+
name="Columns",
|
|
241
|
+
anchor_id="definitions",
|
|
242
|
+
)
|
|
243
|
+
)
|
|
244
|
+
return items
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def get_sample_items(config: Settings, sample: dict) -> List[Renderable]:
|
|
248
|
+
"""Create the list of sample items
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
config: settings object
|
|
252
|
+
sample: dict of samples
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
List of sample items to show in the interface.
|
|
256
|
+
"""
|
|
257
|
+
items: List[Renderable] = []
|
|
258
|
+
if isinstance(sample, tuple):
|
|
259
|
+
for s in zip(*sample):
|
|
260
|
+
items.append(
|
|
261
|
+
Container(
|
|
262
|
+
[
|
|
263
|
+
Sample(
|
|
264
|
+
sample=obj.data,
|
|
265
|
+
name=config.html.style._labels[idx],
|
|
266
|
+
anchor_id=obj.id,
|
|
267
|
+
caption=obj.caption,
|
|
268
|
+
)
|
|
269
|
+
for idx, obj in enumerate(s)
|
|
270
|
+
],
|
|
271
|
+
sequence_type="batch_grid",
|
|
272
|
+
batch_size=len(sample),
|
|
273
|
+
anchor_id=f"sample_{slugify(s[0].name)}",
|
|
274
|
+
name=s[0].name,
|
|
275
|
+
)
|
|
276
|
+
)
|
|
277
|
+
else:
|
|
278
|
+
for obj in sample:
|
|
279
|
+
items.append(
|
|
280
|
+
Sample(
|
|
281
|
+
sample=obj.data,
|
|
282
|
+
name=obj.name,
|
|
283
|
+
anchor_id=obj.id,
|
|
284
|
+
caption=obj.caption,
|
|
285
|
+
)
|
|
286
|
+
)
|
|
287
|
+
return items
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def get_interactions(config: Settings, interactions: dict) -> list:
|
|
291
|
+
"""Returns the interaction components for the report
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
config: report Settings object
|
|
295
|
+
interactions: a nested dict containing the scatter plots
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
A list of components for the interaction section of the report
|
|
299
|
+
"""
|
|
300
|
+
titems: List[Renderable] = []
|
|
301
|
+
|
|
302
|
+
for x_col, y_cols in interactions.items():
|
|
303
|
+
items: List[Renderable] = []
|
|
304
|
+
for y_col, splot in y_cols.items():
|
|
305
|
+
if not isinstance(splot, list):
|
|
306
|
+
items.append(
|
|
307
|
+
ImageWidget(
|
|
308
|
+
splot,
|
|
309
|
+
image_format=config.plot.image_format,
|
|
310
|
+
alt=f"{x_col} x {y_col}",
|
|
311
|
+
anchor_id=f"interactions_{slugify(x_col)}_{slugify(y_col)}",
|
|
312
|
+
name=y_col,
|
|
313
|
+
)
|
|
314
|
+
)
|
|
315
|
+
else:
|
|
316
|
+
items.append(
|
|
317
|
+
Container(
|
|
318
|
+
[
|
|
319
|
+
ImageWidget(
|
|
320
|
+
zplot,
|
|
321
|
+
image_format=config.plot.image_format,
|
|
322
|
+
alt=f"{x_col} x {y_col}",
|
|
323
|
+
anchor_id=f"interactions_{slugify(x_col)}_{slugify(y_col)}",
|
|
324
|
+
name=config.html.style._labels[idx],
|
|
325
|
+
)
|
|
326
|
+
if zplot != ""
|
|
327
|
+
else HTML(
|
|
328
|
+
f"<h4 class='indent'>{config.html.style._labels[idx]}</h4><br />"
|
|
329
|
+
f"<em>Interaction plot not present for dataset</em>"
|
|
330
|
+
)
|
|
331
|
+
for idx, zplot in enumerate(splot)
|
|
332
|
+
],
|
|
333
|
+
sequence_type="batch_grid",
|
|
334
|
+
batch_size=len(config.html.style._labels),
|
|
335
|
+
anchor_id=f"interactions_{slugify(x_col)}_{slugify(y_col)}",
|
|
336
|
+
name=y_col,
|
|
337
|
+
)
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
titems.append(
|
|
341
|
+
Container(
|
|
342
|
+
items,
|
|
343
|
+
sequence_type="tabs" if len(items) <= 10 else "select",
|
|
344
|
+
name=x_col,
|
|
345
|
+
nested=len(interactions) > 10,
|
|
346
|
+
anchor_id=f"interactions_{slugify(x_col)}",
|
|
347
|
+
)
|
|
348
|
+
)
|
|
349
|
+
return titems
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def get_report_structure(config: Settings, summary: BaseDescription) -> Root:
|
|
353
|
+
"""Generate a HTML report from summary statistics and a given sample.
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
config: report Settings object
|
|
357
|
+
summary: Statistics to use for the overview, variables, correlations and missing values.
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
The profile report in HTML format
|
|
361
|
+
"""
|
|
362
|
+
disable_progress_bar = not config.progress_bar
|
|
363
|
+
with tqdm(
|
|
364
|
+
total=1, desc="Generate report structure", disable=disable_progress_bar
|
|
365
|
+
) as pbar:
|
|
366
|
+
alerts = summary.alerts
|
|
367
|
+
|
|
368
|
+
section_items: List[Renderable] = [
|
|
369
|
+
Container(
|
|
370
|
+
get_dataset_items(config, summary, alerts),
|
|
371
|
+
sequence_type="overview_tabs",
|
|
372
|
+
name="Overview",
|
|
373
|
+
anchor_id="overview",
|
|
374
|
+
oss=not bool(os.getenv("YDATA_SUPPRESS_BANNER", "")),
|
|
375
|
+
),
|
|
376
|
+
]
|
|
377
|
+
|
|
378
|
+
if len(summary.variables) > 0:
|
|
379
|
+
section_items.append(
|
|
380
|
+
Dropdown(
|
|
381
|
+
name="Variables",
|
|
382
|
+
anchor_id="variables-dropdown",
|
|
383
|
+
id="variables-dropdown",
|
|
384
|
+
is_row=False,
|
|
385
|
+
classes=["form-select"],
|
|
386
|
+
items=list(summary.variables),
|
|
387
|
+
item=Container(
|
|
388
|
+
render_variables_section(config, summary),
|
|
389
|
+
sequence_type="accordion",
|
|
390
|
+
name="Variables",
|
|
391
|
+
anchor_id="variables",
|
|
392
|
+
),
|
|
393
|
+
)
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
scatter_items = get_interactions(config, summary.scatter)
|
|
397
|
+
if len(scatter_items) > 0:
|
|
398
|
+
section_items.append(
|
|
399
|
+
Container(
|
|
400
|
+
scatter_items,
|
|
401
|
+
sequence_type="tabs" if len(scatter_items) <= 10 else "select",
|
|
402
|
+
name="Interactions",
|
|
403
|
+
anchor_id="interactions",
|
|
404
|
+
),
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
corr = get_correlation_items(config, summary)
|
|
408
|
+
if corr is not None:
|
|
409
|
+
section_items.append(corr)
|
|
410
|
+
|
|
411
|
+
missing_items = get_missing_items(config, summary)
|
|
412
|
+
if len(missing_items) > 0:
|
|
413
|
+
section_items.append(
|
|
414
|
+
Container(
|
|
415
|
+
missing_items,
|
|
416
|
+
sequence_type="tabs",
|
|
417
|
+
name="Missing values",
|
|
418
|
+
anchor_id="missing",
|
|
419
|
+
)
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
sample_items = get_sample_items(config, summary.sample)
|
|
423
|
+
if len(sample_items) > 0:
|
|
424
|
+
section_items.append(
|
|
425
|
+
Container(
|
|
426
|
+
items=sample_items,
|
|
427
|
+
sequence_type="tabs",
|
|
428
|
+
name="Sample",
|
|
429
|
+
anchor_id="sample",
|
|
430
|
+
)
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
duplicate_items = get_duplicates_items(config, summary.duplicates)
|
|
434
|
+
if len(duplicate_items) > 0:
|
|
435
|
+
section_items.append(
|
|
436
|
+
Container(
|
|
437
|
+
items=duplicate_items,
|
|
438
|
+
sequence_type="batch_grid",
|
|
439
|
+
batch_size=len(duplicate_items),
|
|
440
|
+
name="Duplicate rows",
|
|
441
|
+
anchor_id="duplicate",
|
|
442
|
+
)
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
sections = Container(
|
|
446
|
+
section_items,
|
|
447
|
+
name="Root",
|
|
448
|
+
sequence_type="sections",
|
|
449
|
+
full_width=config.html.full_width,
|
|
450
|
+
)
|
|
451
|
+
pbar.update()
|
|
452
|
+
|
|
453
|
+
footer = HTML(
|
|
454
|
+
content='Report generated by <a href="https://ydata.ai/?utm_source=opensource&utm_medium=pandasprofiling&utm_campaign=report">YData</a>.'
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
return Root("Root", sections, footer, style=config.html.style)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from data_profiling.report.structure.variables.render_boolean import render_boolean
|
|
2
|
+
from data_profiling.report.structure.variables.render_categorical import (
|
|
3
|
+
render_categorical,
|
|
4
|
+
)
|
|
5
|
+
from data_profiling.report.structure.variables.render_common import render_common
|
|
6
|
+
from data_profiling.report.structure.variables.render_complex import render_complex
|
|
7
|
+
from data_profiling.report.structure.variables.render_count import render_count
|
|
8
|
+
from data_profiling.report.structure.variables.render_date import render_date
|
|
9
|
+
from data_profiling.report.structure.variables.render_file import render_file
|
|
10
|
+
from data_profiling.report.structure.variables.render_generic import render_generic
|
|
11
|
+
from data_profiling.report.structure.variables.render_image import render_image
|
|
12
|
+
from data_profiling.report.structure.variables.render_path import render_path
|
|
13
|
+
from data_profiling.report.structure.variables.render_real import render_real
|
|
14
|
+
from data_profiling.report.structure.variables.render_text import render_text
|
|
15
|
+
from data_profiling.report.structure.variables.render_timeseries import (
|
|
16
|
+
render_timeseries,
|
|
17
|
+
)
|
|
18
|
+
from data_profiling.report.structure.variables.render_url import render_url
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"render_boolean",
|
|
22
|
+
"render_categorical",
|
|
23
|
+
"render_common",
|
|
24
|
+
"render_complex",
|
|
25
|
+
"render_count",
|
|
26
|
+
"render_date",
|
|
27
|
+
"render_file",
|
|
28
|
+
"render_generic",
|
|
29
|
+
"render_image",
|
|
30
|
+
"render_path",
|
|
31
|
+
"render_real",
|
|
32
|
+
"render_text",
|
|
33
|
+
"render_timeseries",
|
|
34
|
+
"render_url",
|
|
35
|
+
]
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from data_profiling.config import Settings
|
|
4
|
+
from data_profiling.report.formatters import fmt, fmt_bytesize, fmt_percent
|
|
5
|
+
from data_profiling.report.presentation.core import (
|
|
6
|
+
Container,
|
|
7
|
+
FrequencyTable,
|
|
8
|
+
FrequencyTableSmall,
|
|
9
|
+
Image,
|
|
10
|
+
Table,
|
|
11
|
+
VariableInfo,
|
|
12
|
+
)
|
|
13
|
+
from data_profiling.report.presentation.core.renderable import Renderable
|
|
14
|
+
from data_profiling.report.presentation.frequency_table_utils import freq_table
|
|
15
|
+
from data_profiling.report.structure.variables.render_common import render_common
|
|
16
|
+
from data_profiling.visualisation.plot import cat_frequency_plot
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def render_boolean(config: Settings, summary: dict) -> dict:
|
|
20
|
+
varid = summary["varid"]
|
|
21
|
+
n_obs_bool = config.vars.bool.n_obs
|
|
22
|
+
image_format = config.plot.image_format
|
|
23
|
+
|
|
24
|
+
# Prepare variables
|
|
25
|
+
template_variables = render_common(config, summary)
|
|
26
|
+
|
|
27
|
+
# Element composition
|
|
28
|
+
info = VariableInfo(
|
|
29
|
+
anchor_id=summary["varid"],
|
|
30
|
+
alerts=summary["alerts"],
|
|
31
|
+
var_type="Boolean",
|
|
32
|
+
var_name=summary["varname"],
|
|
33
|
+
description=summary["description"],
|
|
34
|
+
style=config.html.style,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
table = Table(
|
|
38
|
+
[
|
|
39
|
+
{
|
|
40
|
+
"name": "Distinct",
|
|
41
|
+
"value": fmt(summary["n_distinct"]),
|
|
42
|
+
"alert": "n_distinct" in summary["alert_fields"],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "Distinct (%)",
|
|
46
|
+
"value": fmt_percent(summary["p_distinct"]),
|
|
47
|
+
"alert": "p_distinct" in summary["alert_fields"],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "Missing",
|
|
51
|
+
"value": fmt(summary["n_missing"]),
|
|
52
|
+
"alert": "n_missing" in summary["alert_fields"],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "Missing (%)",
|
|
56
|
+
"value": fmt_percent(summary["p_missing"]),
|
|
57
|
+
"alert": "p_missing" in summary["alert_fields"],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "Memory size",
|
|
61
|
+
"value": fmt_bytesize(summary["memory_size"]),
|
|
62
|
+
"alert": False,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
style=config.html.style,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
fqm = FrequencyTableSmall(
|
|
69
|
+
freq_table(
|
|
70
|
+
freqtable=summary["value_counts_without_nan"],
|
|
71
|
+
n=summary["n"],
|
|
72
|
+
max_number_to_print=n_obs_bool,
|
|
73
|
+
),
|
|
74
|
+
redact=False,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
template_variables["top"] = Container([info, table, fqm], sequence_type="grid")
|
|
78
|
+
|
|
79
|
+
items: List[Renderable] = [
|
|
80
|
+
FrequencyTable(
|
|
81
|
+
template_variables["freq_table_rows"],
|
|
82
|
+
name="Common Values (Table)",
|
|
83
|
+
anchor_id=f"{varid}frequency_table",
|
|
84
|
+
redact=False,
|
|
85
|
+
)
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
show = config.plot.cat_freq.show
|
|
89
|
+
max_unique = config.plot.cat_freq.max_unique
|
|
90
|
+
|
|
91
|
+
if show and (max_unique > 0):
|
|
92
|
+
if isinstance(summary["value_counts_without_nan"], list):
|
|
93
|
+
items.append(
|
|
94
|
+
Container(
|
|
95
|
+
[
|
|
96
|
+
Image(
|
|
97
|
+
cat_frequency_plot(
|
|
98
|
+
config,
|
|
99
|
+
s,
|
|
100
|
+
),
|
|
101
|
+
image_format=image_format,
|
|
102
|
+
alt=config.html.style._labels[idx],
|
|
103
|
+
name=config.html.style._labels[idx],
|
|
104
|
+
anchor_id=f"{varid}cat_frequency_plot_{idx}",
|
|
105
|
+
)
|
|
106
|
+
for idx, s in enumerate(summary["value_counts_without_nan"])
|
|
107
|
+
],
|
|
108
|
+
anchor_id=f"{varid}cat_frequency_plot",
|
|
109
|
+
name="Common Values (Plot)",
|
|
110
|
+
sequence_type="batch_grid",
|
|
111
|
+
batch_size=len(config.html.style._labels),
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
else:
|
|
115
|
+
items.append(
|
|
116
|
+
Image(
|
|
117
|
+
cat_frequency_plot(
|
|
118
|
+
config,
|
|
119
|
+
summary["value_counts_without_nan"],
|
|
120
|
+
),
|
|
121
|
+
image_format=image_format,
|
|
122
|
+
alt="Common Values (Plot)",
|
|
123
|
+
name="Common Values (Plot)",
|
|
124
|
+
anchor_id=f"{varid}cat_frequency_plot",
|
|
125
|
+
)
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
template_variables["bottom"] = Container(
|
|
129
|
+
items, sequence_type="tabs", anchor_id=f"{varid}bottom"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
return template_variables
|