import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("ggplot")
def segment_analysis_dashboard(
df,
segment_col,
subgroup_col,
metric_cols,
agg_func="sum",
chart_type="grouped_bar",
top_n=None,
figsize=(14, 8),
normalize=False
):
"""
Flexible visualization dashboard generator
Parameters
----------
df : pandas.DataFrame
segment_col : str
Main grouping column
Example: "segment"
subgroup_col : str
Sub grouping column
Example: "ort_type"
metric_cols : list
Metrics to visualize
Example:
["transaction_amount", "customer_count", "p50"]
agg_func : str
Aggregation function
Options:
- sum
- mean
- median
- count
chart_type : str
Options:
- grouped_bar
- stacked_bar
- heatmap
- line
- percentage
top_n : int or None
Show only top N segments
normalize : bool
Convert to percentage
"""
for metric in metric_cols:
# Aggregation
pivot_df = (
df.groupby([segment_col, subgroup_col])[metric]
.agg(agg_func)
.reset_index()
)
# Pivot
pivot_df = pivot_df.pivot(
index=segment_col,
columns=subgroup_col,
values=metric
).fillna(0)
# Top N filtering
if top_n:
pivot_df["TOTAL"] = pivot_df.sum(axis=1)
pivot_df = (
pivot_df.sort_values("TOTAL", ascending=False)
.head(top_n)
.drop(columns="TOTAL")
)
# Normalize
if normalize:
pivot_df = pivot_df.div(
pivot_df.sum(axis=1),
axis=0
) * 100
# Plot
plt.figure(figsize=figsize)
if chart_type == "grouped_bar":
pivot_df.plot(
kind="bar",
figsize=figsize
)
elif chart_type == "stacked_bar":
pivot_df.plot(
kind="bar",
stacked=True,
figsize=figsize
)
elif chart_type == "line":
pivot_df.T.plot(
kind="line",
marker="o",
figsize=figsize
)
elif chart_type == "heatmap":
plt.imshow(
pivot_df,
aspect='auto'
)
plt.colorbar()
plt.xticks(
range(len(pivot_df.columns)),
pivot_df.columns,
rotation=45
)
plt.yticks(
range(len(pivot_df.index)),
pivot_df.index
)
elif chart_type == "percentage":
percentage_df = (
pivot_df.div(
pivot_df.sum(axis=1),
axis=0
) * 100
)
percentage_df.plot(
kind="bar",
stacked=True,
figsize=figsize
)
plt.ylabel("Percentage")
else:
raise ValueError("Unsupported chart type")
# Titles
plt.title(
f"{metric} by {segment_col} and {subgroup_col}",
fontsize=16
)
plt.xlabel(segment_col)
plt.ylabel(metric)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()