Skip to content

Commit 15442fe

Browse files
Merge pull request #35 from Intugle/features/property-dfs
Features/property dfs
2 parents e56c4d6 + dc266a6 commit 15442fe

8 files changed

Lines changed: 101 additions & 17 deletions

File tree

docsite/docs/core-concepts/dataset.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@ The library organizes metadata using Pydantic models, but you can access it thro
4040
- `[column_name].tags: Optional[List[str]]`
4141
- `[column_name].profiling_metrics: Optional[ColumnProfilingMetrics]`
4242
- **`ColumnProfilingMetrics`**: Detailed statistics for a column.
43-
- `count: Optional[int]`
44-
- `null_count: Optional[int]`
45-
- `distinct_count: Optional[int]`
46-
- `sample_data: Optional[List[Any]]`
43+
- `.count: Optional[int]`
44+
- `.null_count: Optional[int]`
45+
- `.distinct_count: Optional[int]`
46+
- `.sample_data: Optional[List[Any]]`
47+
- `.uniqueness: Optional[float]` (Read-only property)
48+
- `.completeness: Optional[float]` (Read-only property)
4749

4850
#### Example of accessing metadata
4951

@@ -64,6 +66,8 @@ print(f"Column Description: {email_column.description}")
6466
metrics = email_column.profiling_metrics
6567
if metrics:
6668
print(f"Distinct Count: {metrics.distinct_count}")
69+
print(f"Uniqueness: {metrics.uniqueness}")
70+
print(f"Completeness: {metrics.completeness}")
6771
```
6872

6973
### Automatic caching
@@ -75,7 +79,7 @@ The `DataSet` object avoids redundant work. When you initialize a `DataSet`, it
7579
You can run the analysis pipeline step-by-step for more granular control. Each of these methods includes a `save=True` option to persist the results of that specific stage.
7680

7781
```python
78-
from intugle import DataSet
82+
from intugle.analysis.models import DataSet
7983

8084
# Initialize the dataset
8185
data_source = {"path": "path/to/my_data.csv", "type": "csv"}
@@ -124,4 +128,4 @@ profiles = dataset.profiling_df
124128

125129
# Display the first 5 rows
126130
print(profiles.head())
127-
```
131+
```

docsite/docs/core-concepts/knowledge-builder.md

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ You can initialize the `KnowledgeBuilder` in two ways:
3535
2. **With a List of `DataSet` Objects**: If you have already created `DataSet` objects, you can pass a list of them directly.
3636

3737
```python
38-
from intugle import KnowledgeBuilder, DataSet
38+
from intugle.analysis.models import DataSet
39+
from intugle import KnowledgeBuilder
3940

4041
# Create DataSet objects from file-based sources
4142
customers_data = {"path": "path/to/customers.csv", "type": "csv"}
@@ -129,7 +130,40 @@ link_predictor = kb.link_predictor
129130
print(f"Primary Key for customers: {customers_dataset.source_table_model.description}")
130131
print("Discovered Links:")
131132
print(link_predictor.get_links_df())
132-
133133
```
134+
134135
Learn more about what you can do with these objects. See the [DataSet](./dataset.md) and [Link Prediction](./link-prediction.md) documentation.
135136

137+
## Utility DataFrames
138+
139+
The `KnowledgeBuilder` provides three convenient properties that consolidate the results from all processed datasets into single Pandas DataFrames.
140+
141+
### `profiling_df`
142+
143+
Returns a DataFrame containing the full profiling metrics for every column across all datasets.
144+
145+
```python
146+
# Get a single DataFrame of all column profiles
147+
all_profiles = kb.profiling_df
148+
print(all_profiles.head())
149+
```
150+
151+
### `links_df`
152+
153+
A shortcut to the `get_links_df()` method on the `LinkPredictor`, this property returns a DataFrame of all discovered relationships.
154+
155+
```python
156+
# Get a DataFrame of all predicted links
157+
all_links = kb.links_df
158+
print(all_links)
159+
```
160+
161+
### `glossary_df`
162+
163+
Returns a DataFrame that serves as a consolidated business glossary, listing the table name, column name, description, and tags for every column across all datasets.
164+
165+
```python
166+
# Get a single, unified business glossary
167+
full_glossary = kb.glossary_df
168+
print(full_glossary.head())
169+
```

docsite/docs/core-concepts/link-prediction.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ links_list = predictor_instance.links
2828
To use the `LinkPredictor` manually, you must give it a list of fully profiled `DataSet` objects.
2929

3030
```python
31-
from intugle import DataSet, LinkPredictor
31+
from intugle.analysis.models import DataSet,
32+
from intugle.link_predictor.predictor import LinkPredictor
33+
3234

3335
# 1. Initialize and fully profile your DataSet objects first
3436
customers_data = {"path": "path/to/customers.csv", "type": "csv"}

notebooks/quickstart_healthcare.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2916,7 +2916,7 @@
29162916
},
29172917
{
29182918
"cell_type": "code",
2919-
"execution_count": 4,
2919+
"execution_count": null,
29202920
"id": "0aa894eb",
29212921
"metadata": {},
29222922
"outputs": [
@@ -3610,8 +3610,8 @@
36103610
}
36113611
],
36123612
"source": [
3613-
"allergies_dataset = kb.datasets['patients']\n",
3614-
"allergies_dataset.profiling_df\n"
3613+
"patients_dataset = kb.datasets['patients']\n",
3614+
"patients_dataset.profiling_df"
36153615
]
36163616
},
36173617
{

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "intugle"
7-
version = "0.1.6"
7+
version = "0.1.7"
88
authors = [
99
{ name="Intugle", email="hello@intugle.ai" },
1010
]

src/intugle/knowledge_builder.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
from typing import TYPE_CHECKING, Any, Awaitable, Dict, List, TypeVar
66

7+
import pandas as pd
8+
79
from intugle.analysis.models import DataSet
810
from intugle.core.console import console, success_style
911
from intugle.link_predictor.predictor import LinkPredictor
@@ -125,6 +127,35 @@ def build(self, force_recreate: bool = False):
125127

126128
return self
127129

130+
@property
131+
def profiling_df(self) -> pd.DataFrame:
132+
"""Returns a consolidated DataFrame of profiling metrics for all datasets."""
133+
all_profiles = [dataset.profiling_df for dataset in self.datasets.values()]
134+
return pd.concat(all_profiles, ignore_index=True)
135+
136+
@property
137+
def links_df(self) -> pd.DataFrame:
138+
"""Returns the predicted links as a pandas DataFrame."""
139+
if hasattr(self, "link_predictor"):
140+
return self.link_predictor.get_links_df()
141+
return pd.DataFrame()
142+
143+
@property
144+
def glossary_df(self) -> pd.DataFrame:
145+
"""Returns a consolidated DataFrame of glossary information for all datasets."""
146+
glossary_data = []
147+
for dataset in self.datasets.values():
148+
for column in dataset.source_table_model.columns:
149+
glossary_data.append(
150+
{
151+
"table_name": dataset.name,
152+
"column_name": column.name,
153+
"column_description": column.description,
154+
"column_tags": column.tags,
155+
}
156+
)
157+
return pd.DataFrame(glossary_data)
158+
128159
def initialize_semantic_search(self):
129160
"""Initialize the semantic search engine."""
130161
try:
@@ -150,5 +181,4 @@ def search(self, query: str):
150181
return _run_async_in_sync(search_client.search(query))
151182
except Exception as e:
152183
log.error(f"Could not perform semantic search: {e}")
153-
raise e
154-
184+
raise e

src/intugle/models/resources/model.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@ class ColumnProfilingMetrics(SchemaBase):
1313
sample_data: Optional[List[Any]] = Field(default_factory=list)
1414
dtype_sample: Optional[List[Any]] = Field(default_factory=list, exclude=True)
1515

16+
@property
17+
def uniqueness(self) -> Optional[float]:
18+
"""The ratio of distinct values to total count."""
19+
if self.count is not None and self.distinct_count is not None and self.count > 0:
20+
return self.distinct_count / self.count
21+
return None
22+
23+
@property
24+
def completeness(self) -> Optional[float]:
25+
"""The ratio of non-null values to total count."""
26+
if self.count is not None and self.null_count is not None and self.count > 0:
27+
return (self.count - self.null_count) / self.count
28+
return None
29+
1630

1731
class Column(SchemaBase):
1832
name: str
@@ -37,4 +51,4 @@ class ModelProfilingMetrics(SchemaBase):
3751
class Model(BaseResource):
3852
resource_type: NodeType = NodeType.MODEL
3953
columns: List[Column] = Field(default_factory=list)
40-
profiling_metrics: Optional[ModelProfilingMetrics] = None
54+
profiling_metrics: Optional[ModelProfilingMetrics] = None

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)