Skip to content

Commit 263ebf1

Browse files
committed
feat: exclude selected fields from json output
1 parent 628d400 commit 263ebf1

2 files changed

Lines changed: 93 additions & 1 deletion

File tree

src/data_profiling/profile_report.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ def __init__(
7373
sortby: Optional[str] = None,
7474
sensitive: bool = False,
7575
explorative: bool = False,
76+
excluded_fields: list[str] | None = None,
7677
sample: Optional[dict] = None,
7778
config_file: Optional[Union[Path, str]] = None,
7879
lazy: bool = True,
@@ -97,6 +98,7 @@ def __init__(
9798
Only available for pd.DataFrame
9899
sort_by: ignored if ts_mode=False. Order the dataset by a provided column.
99100
sensitive: hides the values for categorical and text variables for report privacy
101+
excluded_fields: excludes selected fields from JSON generation
100102
config_file: a config file (.yml), mutually exclusive with `minimal`
101103
lazy: compute when needed
102104
sample: optional dict(name="Sample title", caption="Caption", data=pd.DataFrame())
@@ -110,6 +112,8 @@ def __init__(
110112

111113
self._df_type = type(df)
112114

115+
self.excluded_fields = excluded_fields
116+
113117
if config_file or minimal:
114118
if not config_file:
115119
config_file = get_config("config_minimal.yaml")
@@ -453,7 +457,11 @@ def encode_it(o: Any) -> Any:
453457
if is_dataclass(o):
454458
o = asdict(o)
455459
if isinstance(o, dict):
456-
return {encode_it(k): encode_it(v) for k, v in o.items()}
460+
return {
461+
encode_it(k): encode_it(v)
462+
for k, v in o.items()
463+
if (self.excluded_fields is None or k not in self.excluded_fields)
464+
}
457465
else:
458466
if isinstance(o, (bool, int, float, str)):
459467
return o
@@ -502,6 +510,22 @@ def to_json(self) -> str:
502510
503511
Returns:
504512
JSON string
513+
514+
To disable fields for output, pass a list with
515+
of fields to exclude.
516+
Example:
517+
from data_profiling import ProfileReport
518+
import pandas as pd
519+
520+
df = pd.DataFrame(np.random.rand(7, 3), columns=["a", "b", "c"])
521+
fields = ["value_counts_without_nan",
522+
"value_counts_index_sorted", "n_var"]
523+
profile = ProfileReport(
524+
df, title="Data Profiling Report",
525+
excluded_fields=fields
526+
)
527+
report_json = profile.to_json()
528+
505529
"""
506530

507531
return self.json

tests/issues/test_issue1680.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""
2+
Test for issue 1680.
3+
4+
https://github.com/Data-Centric-AI-Community/fg-data-profiling/issues/1680
5+
"""
6+
import json
7+
8+
import numpy as np
9+
import pandas as pd
10+
import pytest
11+
from typeguard import TypeCheckError
12+
13+
from data_profiling import ProfileReport
14+
15+
16+
@pytest.fixture
17+
def data():
18+
"""Create a dataframe."""
19+
np.random.seed(42)
20+
21+
return pd.DataFrame(np.random.rand(7, 3), columns=["a", "b", "c"])
22+
23+
24+
def test_empty_df(data):
25+
"""Check if the data frame is empty."""
26+
if not len(data):
27+
raise ValueError("Check the dataframe it is empty")
28+
29+
30+
# Checking excluded fields
31+
def test_excluded_fields(data):
32+
"""Check if there are excluded fields in the json."""
33+
test_empty_df(data)
34+
35+
excluded_fields = [
36+
"value_counts_without_nan",
37+
"value_counts_index_sorted",
38+
"n_var",
39+
"mean",
40+
"sum",
41+
"mad",
42+
]
43+
44+
report = ProfileReport(data, excluded_fields=excluded_fields)
45+
report_json = report.to_json()
46+
data_json = json.loads(report_json)
47+
48+
def check_no_key(dict_recursion):
49+
for key, value in dict_recursion.items():
50+
if key in excluded_fields:
51+
description = f"The field: {key} " f"that was excluded is present."
52+
raise ValueError(description)
53+
if isinstance(value, dict):
54+
check_no_key(value)
55+
56+
check_no_key(data_json)
57+
58+
59+
@pytest.mark.parametrize("invalid_value", [12345, "abcde", {}, True])
60+
def test_invalid_excluded_fields(data, invalid_value):
61+
"""
62+
Validate excluded_fields types.
63+
64+
Checks that passing invalid types
65+
to excluded_fields causes a type error.
66+
"""
67+
with pytest.raises(TypeCheckError):
68+
ProfileReport(data, excluded_fields=invalid_value) # type: ignore # noqa

0 commit comments

Comments
 (0)