ChatWithData / src /ui /charts.py
niddijoris's picture
Upload Streamlit app
790e0e9
"""
Chart generation for business insights visualization
"""
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
from typing import Dict, Any
def create_price_distribution_chart(data: pd.DataFrame) -> go.Figure:
"""
Create a histogram showing price distribution
Args:
data: DataFrame with sellingprice column
Returns:
Plotly figure
"""
fig = px.histogram(
data,
x='sellingprice',
nbins=50,
title='Car Price Distribution',
labels={'sellingprice': 'Selling Price ($)', 'count': 'Number of Cars'},
color_discrete_sequence=['#1f77b4']
)
fig.update_layout(
showlegend=False,
height=300,
margin=dict(l=20, r=20, t=40, b=20)
)
return fig
def create_top_makes_chart(stats: Dict[str, Any]) -> go.Figure:
"""
Create a bar chart showing top car makes
Args:
stats: Statistics dictionary with top_makes data
Returns:
Plotly figure
"""
top_makes = stats.get('top_makes', [])
if not top_makes:
return go.Figure()
makes = [item['make'] for item in top_makes]
counts = [item['count'] for item in top_makes]
fig = go.Figure(data=[
go.Bar(
x=makes,
y=counts,
marker_color='#2ca02c',
text=counts,
textposition='auto'
)
])
fig.update_layout(
title='Top 5 Car Makes',
xaxis_title='Make',
yaxis_title='Number of Cars',
height=300,
margin=dict(l=20, r=20, t=40, b=20)
)
return fig
def create_condition_pie_chart(stats: Dict[str, Any]) -> go.Figure:
"""
Create a pie chart showing condition distribution
Args:
stats: Statistics dictionary with condition_distribution data
Returns:
Plotly figure
"""
condition_dist = stats.get('condition_distribution', [])
if not condition_dist:
return go.Figure()
# Take top 10 conditions
condition_dist = condition_dist[:10]
conditions = [str(item['condition']) for item in condition_dist]
counts = [item['count'] for item in condition_dist]
fig = go.Figure(data=[
go.Pie(
labels=conditions,
values=counts,
hole=0.3
)
])
fig.update_layout(
title='Car Condition Distribution',
height=300,
margin=dict(l=20, r=20, t=40, b=20)
)
return fig
def create_price_by_make_chart(db_manager) -> go.Figure:
"""Create a bar chart of average price by make (top 10)"""
query = """
SELECT make, AVG(sellingprice) as avg_price
FROM cars
GROUP BY make
ORDER BY avg_price DESC
LIMIT 10
"""
result = db_manager.execute_query(query)
if result['success'] and result['data']:
df = pd.DataFrame(result['data'])
fig = px.bar(
df,
x='make',
y='avg_price',
title='Top 10 Average Prices by Make',
labels={'make': 'Make', 'avg_price': 'Average Price ($)'},
template='plotly_white',
color='avg_price',
color_continuous_scale='Blues'
)
return fig
else:
# Return empty figure if data fails
return go.Figure()
def create_dynamic_chart(data: list, chart_type: str, title: str, x_label: str, y_label: str) -> go.Figure:
"""
Create a dynamic chart based on data and configuration provided by the AI agent.
Args:
data: List of dictionaries containing the data
chart_type: Type of chart ('bar', 'column', 'line', 'pie', 'scatter')
title: Chart title
x_label: Name of the column for X axis
y_label: Name of the column for Y axis (or value for pie)
Returns:
Plotly Figure object
"""
if not data:
return go.Figure()
df = pd.DataFrame(data)
# Ensure labels exist in dataframe, if not, use first columns
if x_label not in df.columns:
x_label = df.columns[0]
if y_label not in df.columns and len(df.columns) > 1:
y_label = df.columns[1]
elif y_label not in df.columns:
y_label = x_label
if chart_type.lower() in ['bar', 'column']:
fig = px.bar(
df,
x=x_label,
y=y_label,
title=title,
template='plotly_white',
color=y_label if y_label != x_label else None
)
elif chart_type.lower() == 'line':
fig = px.line(
df,
x=x_label,
y=y_label,
title=title,
template='plotly_white',
markers=True
)
elif chart_type.lower() == 'pie':
fig = px.pie(
df,
names=x_label,
values=y_label,
title=title,
template='plotly_white'
)
elif chart_type.lower() == 'scatter':
fig = px.scatter(
df,
x=x_label,
y=y_label,
title=title,
template='plotly_white',
color=y_label if y_label != x_label else None
)
else:
# Fallback to bar chart
fig = px.bar(df, x=x_label, y=y_label, title=title, template='plotly_white')
fig.update_layout(
margin=dict(l=20, r=20, t=40, b=20),
xaxis_title=x_label,
yaxis_title=y_label if chart_type.lower() != 'pie' else ""
)
return fig