bidviz 1.0.0__py3-none-any.whl → 1.1.0__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.
@@ -0,0 +1,120 @@
1
+ """Heatmap transformers for Polars DataFrames."""
2
+
3
+ from typing import Any, Dict, List, Optional
4
+
5
+ import polars as pl
6
+
7
+ from bidviz.exceptions import TransformationError
8
+ from bidviz_polars.core.base import BaseChartTransformer
9
+ from bidviz_polars.utils import format_label, get_numeric_columns, safe_get_value, validate_columns
10
+
11
+
12
+ class HeatmapTransformer(BaseChartTransformer):
13
+ """Transform Polars DataFrame into heatmap data."""
14
+
15
+ def transform(
16
+ self, df: pl.DataFrame, x_column: str, y_column: str, value_column: str
17
+ ) -> Dict[str, Any]:
18
+ """
19
+ Transform Polars DataFrame into heatmap data for 2D intensity visualization.
20
+
21
+ Args:
22
+ df: Polars DataFrame containing the data
23
+ x_column: Column name for x-axis
24
+ y_column: Column name for y-axis
25
+ value_column: Column name for cell values
26
+
27
+ Returns:
28
+ Dict with chart_type='heatmap', data points, and labels
29
+ """
30
+ try:
31
+ validate_columns(df, [x_column, y_column, value_column])
32
+
33
+ data = []
34
+ for row in df.iter_rows(named=True):
35
+ data.append(
36
+ {
37
+ "x": str(safe_get_value(row[x_column])),
38
+ "y": str(safe_get_value(row[y_column])),
39
+ "value": safe_get_value(row[value_column]),
40
+ }
41
+ )
42
+
43
+ return {
44
+ "chart_type": "heatmap",
45
+ "data": data,
46
+ "x_label": format_label(x_column),
47
+ "y_label": format_label(y_column),
48
+ "value_label": format_label(value_column),
49
+ }
50
+
51
+ except ValueError as e:
52
+ raise TransformationError(str(e), chart_type="heatmap", df_shape=df.shape)
53
+ except Exception as e:
54
+ raise TransformationError(
55
+ f"Failed to transform heatmap: {str(e)}",
56
+ chart_type="heatmap",
57
+ df_shape=df.shape,
58
+ )
59
+
60
+
61
+ class CorrelationHeatmapTransformer(BaseChartTransformer):
62
+ """Transform Polars DataFrame into correlation heatmap."""
63
+
64
+ def transform(self, df: pl.DataFrame, metrics: Optional[List[str]] = None) -> Dict[str, Any]:
65
+ """
66
+ Transform Polars DataFrame into correlation heatmap for statistical analysis.
67
+
68
+ Args:
69
+ df: Polars DataFrame containing numeric columns
70
+ metrics: Optional list of column names to correlate
71
+
72
+ Returns:
73
+ Dict with chart_type='heatmap' and correlation data
74
+ """
75
+ try:
76
+ if metrics is None:
77
+ metrics = get_numeric_columns(df)
78
+
79
+ if len(metrics) < 2:
80
+ raise TransformationError(
81
+ "Need at least 2 numeric columns for correlation",
82
+ chart_type="correlation_heatmap",
83
+ df_shape=df.shape,
84
+ )
85
+
86
+ validate_columns(df, metrics)
87
+
88
+ # Polars uses corr() method on DataFrame
89
+ corr_matrix = df.select(metrics).corr()
90
+
91
+ data = []
92
+ for i, x_metric in enumerate(metrics):
93
+ for j, y_metric in enumerate(metrics):
94
+ # Access correlation value from the matrix
95
+ value = corr_matrix.row(j)[i]
96
+ data.append(
97
+ {
98
+ "x": x_metric,
99
+ "y": y_metric,
100
+ "value": safe_get_value(value),
101
+ }
102
+ )
103
+
104
+ return {
105
+ "chart_type": "heatmap",
106
+ "data": data,
107
+ "metrics": metrics,
108
+ "x_label": "Metrics",
109
+ "y_label": "Metrics",
110
+ "value_label": "Correlation Coefficient",
111
+ }
112
+
113
+ except ValueError as e:
114
+ raise TransformationError(str(e), chart_type="correlation_heatmap", df_shape=df.shape)
115
+ except Exception as e:
116
+ raise TransformationError(
117
+ f"Failed to transform correlation heatmap: {str(e)}",
118
+ chart_type="correlation_heatmap",
119
+ df_shape=df.shape,
120
+ )
@@ -0,0 +1,60 @@
1
+ """KPI Cards transformer for Polars DataFrames."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ import polars as pl
6
+
7
+ from bidviz.exceptions import TransformationError
8
+ from bidviz_polars.core.base import BaseChartTransformer
9
+ from bidviz_polars.utils import format_label, safe_get_value
10
+
11
+
12
+ class KPICardsTransformer(BaseChartTransformer):
13
+ """Transform single-row Polars DataFrame into KPI cards."""
14
+
15
+ def transform(self, df: pl.DataFrame) -> Dict[str, Any]:
16
+ """
17
+ Transform a single-row Polars DataFrame into KPI cards for dashboard metrics.
18
+
19
+ Args:
20
+ df: Single-row Polars DataFrame containing metrics
21
+
22
+ Returns:
23
+ Dict with chart_type='kpi_cards' and list of card data
24
+
25
+ Raises:
26
+ TransformationError: If DataFrame has more than one row
27
+ """
28
+ try:
29
+ if len(df) == 0:
30
+ return {"chart_type": "kpi_cards", "data": []}
31
+
32
+ if len(df) > 1:
33
+ raise TransformationError(
34
+ "KPI cards expect a single-row DataFrame",
35
+ chart_type="kpi_cards",
36
+ df_shape=df.shape,
37
+ )
38
+
39
+ row = df.row(0, named=True)
40
+ cards = []
41
+
42
+ for column in df.columns:
43
+ cards.append(
44
+ {
45
+ "key": column,
46
+ "label": format_label(column),
47
+ "value": safe_get_value(row[column]),
48
+ }
49
+ )
50
+
51
+ return {"chart_type": "kpi_cards", "data": cards}
52
+
53
+ except Exception as e:
54
+ if isinstance(e, TransformationError):
55
+ raise
56
+ raise TransformationError(
57
+ f"Failed to transform KPI cards: {str(e)}",
58
+ chart_type="kpi_cards",
59
+ df_shape=df.shape,
60
+ )
@@ -0,0 +1,126 @@
1
+ """Line chart transformers for Polars DataFrames."""
2
+
3
+ from typing import Any, Dict, List, Optional
4
+
5
+ import polars as pl
6
+
7
+ from bidviz.exceptions import TransformationError
8
+ from bidviz_polars.core.base import BaseChartTransformer
9
+ from bidviz_polars.utils import format_label, safe_get_value, validate_columns
10
+
11
+
12
+ class LineChartTransformer(BaseChartTransformer):
13
+ """Transform Polars DataFrame into line chart data."""
14
+
15
+ def transform(
16
+ self,
17
+ df: pl.DataFrame,
18
+ x_column: str,
19
+ y_column: str,
20
+ series_name: Optional[str] = None,
21
+ ) -> Dict[str, Any]:
22
+ """
23
+ Transform Polars DataFrame into line chart data for time series or trends.
24
+
25
+ Args:
26
+ df: Polars DataFrame containing the data
27
+ x_column: Column name for x-axis
28
+ y_column: Column name for y-axis
29
+ series_name: Optional custom name for the data series
30
+
31
+ Returns:
32
+ Dict with chart_type='line_chart', data points, and labels
33
+ """
34
+ try:
35
+ validate_columns(df, [x_column, y_column])
36
+
37
+ data = []
38
+ for row in df.iter_rows(named=True):
39
+ data.append(
40
+ {
41
+ "x": str(safe_get_value(row[x_column])),
42
+ "y": safe_get_value(row[y_column]),
43
+ }
44
+ )
45
+
46
+ return {
47
+ "chart_type": "line_chart",
48
+ "data": data,
49
+ "series_name": series_name or format_label(y_column),
50
+ "x_label": format_label(x_column),
51
+ "y_label": format_label(y_column),
52
+ }
53
+
54
+ except ValueError as e:
55
+ raise TransformationError(str(e), chart_type="line_chart", df_shape=df.shape)
56
+ except Exception as e:
57
+ raise TransformationError(
58
+ f"Failed to transform line chart: {str(e)}",
59
+ chart_type="line_chart",
60
+ df_shape=df.shape,
61
+ )
62
+
63
+
64
+ class MultiLineChartTransformer(BaseChartTransformer):
65
+ """Transform Polars DataFrame into multi-line chart data."""
66
+
67
+ def transform(
68
+ self,
69
+ df: pl.DataFrame,
70
+ x_column: str,
71
+ y_columns: List[str],
72
+ series_names: Optional[List[str]] = None,
73
+ ) -> Dict[str, Any]:
74
+ """
75
+ Transform Polars DataFrame into multi-line chart for comparing multiple series.
76
+
77
+ Args:
78
+ df: Polars DataFrame containing the data
79
+ x_column: Column name for x-axis
80
+ y_columns: List of column names for y-axis
81
+ series_names: Optional custom names for each series
82
+
83
+ Returns:
84
+ Dict with chart_type='multi_line_chart' and series data
85
+ """
86
+ try:
87
+ validate_columns(df, [x_column] + y_columns)
88
+
89
+ if series_names and len(series_names) != len(y_columns):
90
+ raise TransformationError(
91
+ "Number of series_names must match number of y_columns",
92
+ chart_type="multi_line_chart",
93
+ )
94
+
95
+ series = []
96
+ for idx, y_col in enumerate(y_columns):
97
+ data = []
98
+ for row in df.iter_rows(named=True):
99
+ data.append(
100
+ {
101
+ "x": str(safe_get_value(row[x_column])),
102
+ "y": safe_get_value(row[y_col]),
103
+ }
104
+ )
105
+
106
+ series.append(
107
+ {
108
+ "name": series_names[idx] if series_names else format_label(y_col),
109
+ "data": data,
110
+ }
111
+ )
112
+
113
+ return {
114
+ "chart_type": "multi_line_chart",
115
+ "series": series,
116
+ "x_label": format_label(x_column),
117
+ }
118
+
119
+ except ValueError as e:
120
+ raise TransformationError(str(e), chart_type="multi_line_chart", df_shape=df.shape)
121
+ except Exception as e:
122
+ raise TransformationError(
123
+ f"Failed to transform multi-line chart: {str(e)}",
124
+ chart_type="multi_line_chart",
125
+ df_shape=df.shape,
126
+ )
@@ -0,0 +1,108 @@
1
+ """Funnel and stacked bar chart transformers for Polars DataFrames."""
2
+
3
+ from typing import Any, Dict, List, Optional
4
+
5
+ import polars as pl
6
+
7
+ from bidviz.exceptions import TransformationError
8
+ from bidviz_polars.core.base import BaseChartTransformer
9
+ from bidviz_polars.utils import format_label, safe_get_value, validate_columns
10
+
11
+
12
+ class FunnelChartTransformer(BaseChartTransformer):
13
+ """Transform Polars DataFrame into funnel chart data."""
14
+
15
+ def transform(self, df: pl.DataFrame, stage_column: str, value_column: str) -> Dict[str, Any]:
16
+ """
17
+ Transform Polars DataFrame into funnel chart data for conversion pipelines.
18
+
19
+ Args:
20
+ df: Polars DataFrame containing the data
21
+ stage_column: Column name for funnel stages
22
+ value_column: Column name for stage values
23
+
24
+ Returns:
25
+ Dict with chart_type='funnel_chart' and data points
26
+ """
27
+ try:
28
+ validate_columns(df, [stage_column, value_column])
29
+
30
+ data = []
31
+ for row in df.iter_rows(named=True):
32
+ data.append(
33
+ {
34
+ "stage": str(safe_get_value(row[stage_column])),
35
+ "value": safe_get_value(row[value_column]),
36
+ }
37
+ )
38
+
39
+ return {"chart_type": "funnel_chart", "data": data}
40
+
41
+ except ValueError as e:
42
+ raise TransformationError(str(e), chart_type="funnel_chart", df_shape=df.shape)
43
+ except Exception as e:
44
+ raise TransformationError(
45
+ f"Failed to transform funnel chart: {str(e)}",
46
+ chart_type="funnel_chart",
47
+ df_shape=df.shape,
48
+ )
49
+
50
+
51
+ class StackedBarChartTransformer(BaseChartTransformer):
52
+ """Transform Polars DataFrame into stacked bar chart data."""
53
+
54
+ def transform(
55
+ self,
56
+ df: pl.DataFrame,
57
+ x_column: str,
58
+ y_columns: List[str],
59
+ category_names: Optional[List[str]] = None,
60
+ ) -> Dict[str, Any]:
61
+ """
62
+ Transform Polars DataFrame into stacked bar chart for composed comparisons.
63
+
64
+ Args:
65
+ df: Polars DataFrame containing the data
66
+ x_column: Column name for x-axis
67
+ y_columns: List of column names for stacked values
68
+ category_names: Optional custom names for each stack
69
+
70
+ Returns:
71
+ Dict with chart_type='stacked_bar_chart' and data
72
+ """
73
+ try:
74
+ validate_columns(df, [x_column] + y_columns)
75
+
76
+ if category_names and len(category_names) != len(y_columns):
77
+ raise TransformationError(
78
+ "Number of category_names must match number of y_columns",
79
+ chart_type="stacked_bar_chart",
80
+ )
81
+
82
+ data = []
83
+ for row in df.iter_rows(named=True):
84
+ point = {"x": str(safe_get_value(row[x_column]))}
85
+ for y_col in y_columns:
86
+ point[y_col] = safe_get_value(row[y_col])
87
+ data.append(point)
88
+
89
+ categories = [
90
+ category_names[i] if category_names else format_label(y_col)
91
+ for i, y_col in enumerate(y_columns)
92
+ ]
93
+
94
+ return {
95
+ "chart_type": "stacked_bar_chart",
96
+ "data": data,
97
+ "categories": categories,
98
+ "x_label": format_label(x_column),
99
+ }
100
+
101
+ except ValueError as e:
102
+ raise TransformationError(str(e), chart_type="stacked_bar_chart", df_shape=df.shape)
103
+ except Exception as e:
104
+ raise TransformationError(
105
+ f"Failed to transform stacked bar chart: {str(e)}",
106
+ chart_type="stacked_bar_chart",
107
+ df_shape=df.shape,
108
+ )
@@ -0,0 +1,57 @@
1
+ """Pie chart transformer for Polars DataFrames."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ import polars as pl
6
+
7
+ from bidviz.exceptions import TransformationError
8
+ from bidviz_polars.core.base import BaseChartTransformer
9
+ from bidviz_polars.utils import format_label, safe_get_value, validate_columns
10
+
11
+
12
+ class PieChartTransformer(BaseChartTransformer):
13
+ """Transform Polars DataFrame into pie chart data."""
14
+
15
+ def transform(
16
+ self, df: pl.DataFrame, label_column: str, value_column: str
17
+ ) -> Dict[str, Any]:
18
+ """
19
+ Transform Polars DataFrame into pie chart data for part-to-whole relationships.
20
+
21
+ Args:
22
+ df: Polars DataFrame containing the data
23
+ label_column: Column name for slice labels
24
+ value_column: Column name for slice values
25
+
26
+ Returns:
27
+ Dict with chart_type='pie_chart' and data points
28
+
29
+ Raises:
30
+ TransformationError: If required columns are missing
31
+ """
32
+ try:
33
+ validate_columns(df, [label_column, value_column])
34
+
35
+ data = []
36
+ for row in df.iter_rows(named=True):
37
+ data.append(
38
+ {
39
+ "label": str(safe_get_value(row[label_column])),
40
+ "value": safe_get_value(row[value_column]),
41
+ }
42
+ )
43
+
44
+ return {
45
+ "chart_type": "pie_chart",
46
+ "data": data,
47
+ "label": format_label(label_column),
48
+ }
49
+
50
+ except ValueError as e:
51
+ raise TransformationError(str(e), chart_type="pie_chart", df_shape=df.shape)
52
+ except Exception as e:
53
+ raise TransformationError(
54
+ f"Failed to transform pie chart: {str(e)}",
55
+ chart_type="pie_chart",
56
+ df_shape=df.shape,
57
+ )
@@ -0,0 +1,48 @@
1
+ """Data table transformer for Polars DataFrames."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ import polars as pl
6
+
7
+ from bidviz.exceptions import TransformationError
8
+ from bidviz_polars.core.base import BaseChartTransformer
9
+ from bidviz_polars.utils import format_label, paginate_dataframe, safe_get_value
10
+
11
+
12
+ class DataTableTransformer(BaseChartTransformer):
13
+ """Transform Polars DataFrame into paginated data table."""
14
+
15
+ def transform(self, df: pl.DataFrame, page: int = 1, page_size: int = 50) -> Dict[str, Any]:
16
+ """
17
+ Transform Polars DataFrame into paginated data table structure.
18
+
19
+ Args:
20
+ df: Polars DataFrame containing the data
21
+ page: Page number (1-indexed)
22
+ page_size: Number of rows per page
23
+
24
+ Returns:
25
+ Dict with chart_type='data_table', columns, rows, and pagination
26
+ """
27
+ try:
28
+ paginated_df, metadata = paginate_dataframe(df, page, page_size)
29
+
30
+ columns = []
31
+ for col in df.columns:
32
+ columns.append({"key": col, "label": format_label(col)})
33
+
34
+ rows = []
35
+ for row in paginated_df.iter_rows(named=True):
36
+ row_data = {}
37
+ for col in df.columns:
38
+ row_data[col] = safe_get_value(row[col])
39
+ rows.append(row_data)
40
+
41
+ return {"chart_type": "data_table", "columns": columns, "rows": rows, **metadata}
42
+
43
+ except Exception as e:
44
+ raise TransformationError(
45
+ f"Failed to transform data table: {str(e)}",
46
+ chart_type="data_table",
47
+ df_shape=df.shape,
48
+ )