Business_Intelligence_Dashboard / visualizations.py
Saumith devarsetty
Refactor: Consolidated insights, updated visualizations to Plotly, and updated README
4032138
"""
Plotly visualizations - Interactive charts with hover tooltips.
Used by Smart Dashboard for better user experience.
"""
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
from typing import Optional
def create_plotly_distribution(df: pd.DataFrame, column: str, title: Optional[str] = None):
"""Creates an interactive histogram with hover details."""
fig = px.histogram(
df,
x=column,
nbins=30,
title=title or f'Distribution of {column}',
labels={column: column, 'count': 'Frequency'},
color_discrete_sequence=['#636EFA'],
template='plotly_dark'
)
# Add mean and median lines
mean_val = df[column].mean()
median_val = df[column].median()
fig.add_vline(x=mean_val, line_dash="dash", line_color="red",
annotation_text=f"Mean: {mean_val:.2f}", annotation_position="top")
fig.add_vline(x=median_val, line_dash="dash", line_color="green",
annotation_text=f"Median: {median_val:.2f}", annotation_position="bottom")
fig.update_layout(
hovermode='x unified',
showlegend=False,
height=400
)
return fig
def create_plotly_category(df: pd.DataFrame, category_column: str,
value_column: Optional[str] = None,
agg_method: str = 'count',
top_n: int = 10,
offset: int = 0,
title: Optional[str] = None):
"""Creates an interactive bar chart with hover details."""
# Aggregate data
if value_column is None or agg_method == 'count':
data = df[category_column].value_counts()
total_items = len(data)
data = data.iloc[offset : offset + top_n].reset_index()
data.columns = [category_column, 'Count']
y_col = 'Count'
else:
if agg_method == 'sum':
data = df.groupby(category_column)[value_column].sum()
elif agg_method == 'mean':
data = df.groupby(category_column)[value_column].mean()
else:
data = df.groupby(category_column)[value_column].sum()
data = data.sort_values(ascending=False)
total_items = len(data)
data = data.iloc[offset : offset + top_n].reset_index()
y_col = value_column
# Update title to reflect pagination
if title is None:
end_idx = min(offset + top_n, total_items)
title = f'Top {category_column} (Rank {offset+1}-{end_idx})'
fig = px.bar(
data,
x=category_column,
y=y_col,
title=title or f'Top {top_n} {category_column}',
color=y_col,
color_continuous_scale='Viridis',
template='plotly_dark'
)
fig.update_layout(
xaxis_tickangle=-45,
showlegend=False,
height=400
)
return fig
def create_plotly_scatter(df: pd.DataFrame, x_col: str, y_col: str,
color_col: Optional[str] = None,
title: Optional[str] = None):
"""Creates an interactive scatter plot with hover details."""
fig = px.scatter(
df,
x=x_col,
y=y_col,
color=color_col,
title=title or f'{y_col} vs {x_col}',
opacity=0.7,
template='plotly_dark'
)
fig.update_layout(
hovermode='closest',
height=400
)
return fig
def create_plotly_heatmap(df: pd.DataFrame, title: Optional[str] = None):
"""Creates an interactive correlation heatmap with hover details."""
from utils import get_column_types
col_types = get_column_types(df)
if len(col_types['numerical']) < 2:
return None
corr_matrix = df[col_types['numerical']].corr()
fig = go.Figure(data=go.Heatmap(
z=corr_matrix.values,
x=corr_matrix.columns,
y=corr_matrix.columns,
colorscale='RdBu',
zmid=0,
text=corr_matrix.values,
texttemplate='%{text:.2f}',
textfont={"size": 10},
colorbar=dict(title="Correlation")
))
fig.update_layout(
title=title or 'Correlation Heatmap',
xaxis_tickangle=-45,
height=500,
width=600
)
return fig
def create_plotly_timeseries(df: pd.DataFrame, date_col: str, value_col: str,
agg_method: str = 'sum',
title: Optional[str] = None):
"""Creates an interactive time series with hover details."""
# Aggregate by date
if agg_method == 'sum':
data = df.groupby(date_col)[value_col].sum().reset_index()
elif agg_method == 'mean':
data = df.groupby(date_col)[value_col].mean().reset_index()
else:
data = df.groupby(date_col)[value_col].sum().reset_index()
fig = px.line(
data,
x=date_col,
y=value_col,
title=title or f'{value_col} Trend',
markers=True,
template='plotly_dark'
)
fig.update_layout(
hovermode='x unified',
height=400
)
return fig