smart-analytics-copilot / app /chart_customizer.py
SamadhiDBS's picture
Upload 24 files
d18f851 verified
"""
Chart Customizer - Let users choose chart types
"""
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
class ChartCustomizer:
def __init__(self, df):
self.df = df
def get_available_charts(self):
"""Return available chart types based on data"""
charts = []
if len(self.df.select_dtypes(include=['number']).columns) > 0:
charts.append('📊 Histogram')
charts.append('📈 Line Chart')
charts.append('📉 Scatter Plot')
charts.append('📦 Box Plot')
if len(self.df.select_dtypes(include=['object']).columns) > 0:
charts.append('🥧 Bar Chart')
charts.append('🍩 Pie Chart')
if len(self.df.select_dtypes(include=['datetime64']).columns) > 0:
charts.append('📅 Time Series')
charts.append('🔥 Heatmap')
return charts
def create_chart(self, chart_type, x_col, y_col=None, color_col=None, title=None):
"""Create customized chart"""
if title is None:
title = f"{chart_type}: {x_col}"
if y_col:
title += f" vs {y_col}"
# Histogram
if 'Histogram' in chart_type:
fig = px.histogram(
self.df, x=x_col,
title=title,
color=color_col if color_col else None,
nbins=30,
color_discrete_sequence=px.colors.sequential.Plasma
)
# Bar Chart
elif 'Bar Chart' in chart_type:
if y_col and y_col in self.df.columns:
# Grouped bar chart
agg_data = self.df.groupby(x_col)[y_col].mean().reset_index()
fig = px.bar(
agg_data, x=x_col, y=y_col,
title=title,
color=color_col if color_col else None,
color_discrete_sequence=px.colors.qualitative.Set2
)
else:
# Count bar chart
counts = self.df[x_col].value_counts().head(20).reset_index()
counts.columns = [x_col, 'count']
fig = px.bar(
counts, x=x_col, y='count',
title=f"Count of {x_col}",
color_discrete_sequence=['#2E86AB']
)
# Line Chart
elif 'Line Chart' in chart_type:
if y_col and y_col in self.df.columns:
fig = px.line(
self.df, x=x_col, y=y_col,
title=title,
color=color_col if color_col else None,
markers=True
)
else:
fig = px.line(
self.df, x=x_col,
title=title,
markers=True
)
# Scatter Plot (without trendline to avoid statsmodels)
elif 'Scatter' in chart_type:
if y_col and y_col in self.df.columns:
fig = px.scatter(
self.df, x=x_col, y=y_col,
title=title,
color=color_col if color_col else None,
size=y_col if y_col else None,
hover_data=[x_col, y_col] if y_col else [x_col]
# Removed trendline to avoid statsmodels
)
else:
fig = px.scatter(
self.df, x=x_col, y=x_col,
title=title,
color=color_col if color_col else None
)
# Box Plot
elif 'Box' in chart_type:
if y_col and y_col in self.df.columns:
fig = px.box(
self.df, x=x_col, y=y_col,
title=title,
color=color_col if color_col else None,
points="all"
)
else:
fig = px.box(
self.df, y=x_col,
title=f"Box Plot of {x_col}",
points="all"
)
# Pie Chart
elif 'Pie' in chart_type:
counts = self.df[x_col].value_counts().head(10).reset_index()
counts.columns = [x_col, 'count']
fig = px.pie(
counts, values='count', names=x_col,
title=f"Distribution of {x_col}",
hole=0.3
)
# Heatmap
elif 'Heatmap' in chart_type:
numeric_cols = self.df.select_dtypes(include=['number']).columns
if len(numeric_cols) > 1:
corr = self.df[numeric_cols].corr()
fig = px.imshow(
corr,
text_auto='.2f',
aspect='auto',
color_continuous_scale='RdBu',
title="Correlation Heatmap"
)
else:
return None
# Time Series
elif 'Time Series' in chart_type:
date_cols = self.df.select_dtypes(include=['datetime64']).columns
if len(date_cols) > 0:
date_col = date_cols[0]
if y_col and y_col in self.df.columns:
time_data = self.df.groupby(date_col)[y_col].mean().reset_index()
fig = px.line(
time_data, x=date_col, y=y_col,
title=f"{y_col} Over Time",
markers=True
)
else:
fig = None
else:
fig = None
else:
fig = None
if fig:
# Apply common styling
fig.update_layout(
template='plotly_white',
height=500,
title_font_size=16,
title_x=0.5
)
return fig