Skip to content

Commit

Permalink
feat: add heatmap values as a table under correlations
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardodcpereira authored and aquemy committed Dec 21, 2022
1 parent 2170338 commit fc5da9e
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 30 deletions.
3 changes: 3 additions & 0 deletions src/pandas_profiling/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ class Config:
"auto": Correlation(key="auto"),
}

correlation_table: bool = True

interactions: Interactions = Interactions()

categorical_maximum_correlation_distinct: int = 100
Expand Down Expand Up @@ -394,6 +396,7 @@ class Config:
"phi_k": {"calculate": False},
"cramers": {"calculate": False},
},
"correlation_table": True,
}

@staticmethod
Expand Down
4 changes: 4 additions & 0 deletions src/pandas_profiling/report/presentation/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
from pandas_profiling.report.presentation.core.toggle_button import ToggleButton
from pandas_profiling.report.presentation.core.variable import Variable
from pandas_profiling.report.presentation.core.variable_info import VariableInfo
from pandas_profiling.report.presentation.core.correlation_table import (
CorrelationTable,
)

__all__ = [
"Collapse",
Expand All @@ -32,4 +35,5 @@
"Variable",
"VariableInfo",
"Alerts",
"CorrelationTable",
]
16 changes: 16 additions & 0 deletions src/pandas_profiling/report/presentation/core/correlation_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from typing import Any

import pandas as pd

from pandas_profiling.report.presentation.core.item_renderer import ItemRenderer


class CorrelationTable(ItemRenderer):
def __init__(self, name: str, correlation_matrix: pd.DataFrame, **kwargs):
super().__init__("correlation_table", {"correlation_matrix": correlation_matrix}, name=name, **kwargs)

def __repr__(self) -> str:
return "CorrelationTable"

def render(self) -> Any:
raise NotImplementedError()
6 changes: 6 additions & 0 deletions src/pandas_profiling/report/presentation/flavours/flavours.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def get_html_renderable_mapping() -> Dict[Type[Renderable], Type[Renderable]]:
ToggleButton,
Variable,
VariableInfo,
CorrelationTable,
)
from pandas_profiling.report.presentation.flavours.html import (
HTMLHTML,
Expand All @@ -51,6 +52,7 @@ def get_html_renderable_mapping() -> Dict[Type[Renderable], Type[Renderable]]:
HTMLToggleButton,
HTMLVariable,
HTMLVariableInfo,
HTMLCorrelationTable,
)

return {
Expand All @@ -69,6 +71,7 @@ def get_html_renderable_mapping() -> Dict[Type[Renderable], Type[Renderable]]:
Sample: HTMLSample,
ToggleButton: HTMLToggleButton,
Collapse: HTMLCollapse,
CorrelationTable: HTMLCorrelationTable,
}


Expand Down Expand Up @@ -103,6 +106,7 @@ def get_widget_renderable_mapping() -> Dict[Type[Renderable], Type[Renderable]]:
ToggleButton,
Variable,
VariableInfo,
CorrelationTable,
)
from pandas_profiling.report.presentation.flavours.widget import (
WidgetAlerts,
Expand All @@ -120,6 +124,7 @@ def get_widget_renderable_mapping() -> Dict[Type[Renderable], Type[Renderable]]:
WidgetToggleButton,
WidgetVariable,
WidgetVariableInfo,
WidgetCorrelationTable,
)

return {
Expand All @@ -138,6 +143,7 @@ def get_widget_renderable_mapping() -> Dict[Type[Renderable], Type[Renderable]]:
Sample: WidgetSample,
ToggleButton: WidgetToggleButton,
Collapse: WidgetCollapse,
CorrelationTable: WidgetCorrelationTable,
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
from pandas_profiling.report.presentation.flavours.html.variable_info import (
HTMLVariableInfo,
)
from pandas_profiling.report.presentation.flavours.html.correlation_table import (
HTMLCorrelationTable,
)

__all__ = [
"HTMLCollapse",
Expand All @@ -38,4 +41,5 @@
"HTMLVariable",
"HTMLVariableInfo",
"HTMLAlerts",
"HTMLCorrelationTable",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from pandas_profiling.report.presentation.core.correlation_table import CorrelationTable
from pandas_profiling.report.presentation.flavours.html import templates


class HTMLCorrelationTable(CorrelationTable):
def render(self) -> str:
correlation_matrix_html = self.content["correlation_matrix"].to_html(
classes="correlation-table table table-striped"
)
return templates.template("correlation_table.html").render(
**self.content, correlation_matrix_html=correlation_matrix_html
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div id="correlation-table-container" class="col-sm-12">
{{ correlation_matrix_html }}
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ body {
border-top: hidden;
}

.row.spacing{
.row.spacing, [id^=correlations_tab] {
padding: 2em 1em;
}

Expand Down Expand Up @@ -72,11 +72,11 @@ table.example_values {
}

/* STATS */
table.stats, table.sample, table.duplicate{
table.stats, table.sample, table.duplicate, table.correlation-table{
border: 0;
}

.stats tr, .sample tr, .duplicate tr {
.stats tr, .sample tr, .duplicate tr, .correlation-table tr {
border: 0;
}

Expand All @@ -96,27 +96,26 @@ table.stats, table.sample, table.duplicate{


/* Sample table */
table.sample, table.duplicate{
table.sample, table.duplicate, table.correlation-table {
margin-bottom: 2em;
margin-left: 1em;
}

.sample td, .sample th, .duplicate td, .duplicate th {
.sample td, .sample th, .duplicate td, .duplicate th, .correlation-table td, .correlation-table th {
padding: 0.5em;
white-space: nowrap;
border: 0;

}

.sample thead, .duplicate thead {
.sample thead, .duplicate thead, .correlation-table thead {
border-top: 0;
border-bottom: 2px solid #ddd;
}

.sample td, .duplicate td {
width: 100%;
}

}

/* There is no good solution available to make the divs equal height and then center ... */
.histogram {
Expand Down Expand Up @@ -266,10 +265,10 @@ a.anchor-pos-variable{
/*top: -70px;*/
}

#sample-container, #duplicate-container{
#sample-container, #duplicate-container, #correlation-table-container {
overflow: auto;
width: 100%;
overflow-y: hidden;
overflow: hidden;
}

#overview-content td, #overview-content th{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
from pandas_profiling.report.presentation.flavours.widget.variable_info import (
WidgetVariableInfo,
)
from pandas_profiling.report.presentation.flavours.widget.correlation_table import (
WidgetCorrelationTable,
)

__all__ = [
"WidgetCollapse",
Expand All @@ -42,4 +45,5 @@
"WidgetVariable",
"WidgetVariableInfo",
"WidgetAlerts",
"WidgetCorrelationTable",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from IPython.core.display import display
from ipywidgets import Output, widgets

from pandas_profiling.report.presentation.core.correlation_table import CorrelationTable


class WidgetCorrelationTable(CorrelationTable):
def render(self) -> widgets.VBox:
out = Output()
with out:
display(self.content["correlation_matrix"])

name = widgets.HTML(f"<h4>{self.content['name']}</h4>")
return widgets.VBox([name, out])
79 changes: 59 additions & 20 deletions src/pandas_profiling/report/structure/correlations.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
Container,
Image,
ToggleButton,
CorrelationTable,
)
from pandas_profiling.report.presentation.core.renderable import Renderable
from pandas_profiling.visualisation import plot
Expand Down Expand Up @@ -59,7 +60,6 @@ def get_correlation_items(config: Settings, summary: dict) -> Optional[Renderabl
The auto setting is an interpretable pairwise
column metric of the following mapping:
<ul>
<li> Variable_type-Variable_type : Method, <strong> Range </strong> <br /> </li>
<li> Categorical-Categorical : Cramer's V, <strong> [0,1] </strong> <br /> </li>
<li> Numerical-Categorical : Cramer's V, <strong> [0,1] </strong> (using a discretized numerical column) <br /> </li>
<li> Numerical-Numerical : Spearman's ρ, <strong> [-1,1] </strong> <br /> </li>
Expand All @@ -83,7 +83,6 @@ def get_correlation_items(config: Settings, summary: dict) -> Optional[Renderabl
vmin, name, description = key_to_data[key]

if isinstance(item, list):
cont: List[Renderable] = []
diagrams: List[Renderable] = []
for idx, i in enumerate(item):
diagram: Renderable = Image(
Expand All @@ -103,18 +102,42 @@ def get_correlation_items(config: Settings, summary: dict) -> Optional[Renderabl
name=name,
)

tbl = Container(
diagrams_with_desc = Container(
diagrams + [desc],
anchor_id=key,
name=name,
anchor_id=f"{key}_diagram_with_desc",
name="Heatmap" if config.correlation_table else name,
sequence_type="batch_grid",
batch_size=len(config.html.style._labels) + 1,
)
cont.append(tbl)

items.append(
Container(cont, anchor_id=key, name=name, sequence_type="grid")
)
if config.correlation_table:
tables: List[Renderable] = []
for idx, i in enumerate(item):
table = CorrelationTable(
name=config.html.style._labels[idx],
correlation_matrix=i,
anchor_id=f"{key}_table"
)
tables.append(table)

tables_tab = Container(
tables,
anchor_id=f"{key}_tables",
name="Table",
sequence_type="batch_grid",
batch_size=len(config.html.style._labels),
)

diagrams_tables_tab = Container(
[diagrams_with_desc, tables_tab],
anchor_id=f"{key}_diagram_table",
name=name,
sequence_type="tabs"
)

items.append(diagrams_tables_tab)
else:
items.append(diagrams_with_desc)
else:
diagram = Image(
plot.correlation_matrix(config, item, vmin=vmin),
Expand All @@ -125,26 +148,42 @@ def get_correlation_items(config: Settings, summary: dict) -> Optional[Renderabl
classes="correlation-diagram",
)

if len(description) > 0:
desc = HTML(
f'<div style="padding:20px" class="text-muted"><h3>{name}</h3>{description}</div>',
anchor_id=f"{key}_html",
classes="correlation-description",
)
desc = HTML(
f'<div style="padding:20px" class="text-muted"><h3>{name}</h3>{description}</div>',
anchor_id=f"{key}_html",
classes="correlation-description",
)

tbl = Container(
[diagram, desc], anchor_id=key, name=name, sequence_type="grid"
diagram_with_desc = Container(
[diagram, desc],
anchor_id=f"{key}_diagram_with_desc",
name="Heatmap" if config.correlation_table else name,
sequence_type="grid"
)

if config.correlation_table:
table = CorrelationTable(
name="Table",
correlation_matrix=item,
anchor_id=f"{key}_table"
)

items.append(tbl)
diagram_table_tabs = Container(
[diagram_with_desc, table],
anchor_id=f"{key}_diagram_table",
name=name,
sequence_type="tabs"
)

items.append(diagram_table_tabs)
else:
items.append(diagram)
items.append(diagram_with_desc)

corr = Container(
items,
sequence_type="tabs",
name="Correlations Tab",
anchor_id="correlations_tab",
anchor_id="correlations_tab"
)

if len(items) > 0:
Expand Down
Loading

0 comments on commit fc5da9e

Please sign in to comment.