sales-analysis / visualizations.py
majorine's picture
Create visualizations.py
e9072d5 verified
Raw
History Blame Contribute Delete
12.6 kB
"""
Visualization functions for the sales dashboard.
"""
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
def create_profit_trend_chart(monthly_trends):
"""
Create profit trend line chart.
"""
if monthly_trends.empty:
return go.Figure()
fig = go.Figure()
fig.add_trace(go.Scatter(
x=monthly_trends['Date'],
y=monthly_trends['Profit'],
mode='lines+markers',
name='Profit',
line=dict(color='#2E86AB', width=3),
marker=dict(size=8)
))
fig.update_layout(
title='Monthly Profit Trend',
xaxis_title='Month',
yaxis_title='Profit ($)',
hovermode='x unified',
template='plotly_white'
)
return fig
def create_quantity_trend_chart(monthly_trends):
"""
Create quantity sold trend line chart.
"""
if monthly_trends.empty:
return go.Figure()
fig = go.Figure()
fig.add_trace(go.Scatter(
x=monthly_trends['Date'],
y=monthly_trends['Quantity Sold'],
mode='lines+markers',
name='Units Sold',
line=dict(color='#A23B72', width=3),
marker=dict(size=8),
fill='tozeroy',
fillcolor='rgba(162, 59, 114, 0.1)'
))
fig.update_layout(
title='Monthly Units Sold Trend',
xaxis_title='Month',
yaxis_title='Units Sold',
hovermode='x unified',
template='plotly_white'
)
return fig
def create_top_models_bar_chart(top_models, metric='Profit'):
"""
Create bar chart for top models.
"""
if top_models.empty:
return go.Figure()
metric_label = 'Profit ($)' if metric == 'Profit' else 'Units Sold'
colors = ['#2E86AB', '#A23B72', '#F18F01', '#C73E1D', '#048A81'] * (len(top_models) // 5 + 1)
fig = go.Figure(data=[
go.Bar(
x=top_models['Model'],
y=top_models[metric],
marker_color=colors[:len(top_models)],
text=top_models[metric].apply(lambda x: f'${x:,.0f}' if metric == 'Profit' else f'{x:,.0f}'),
textposition='outside'
)
])
fig.update_layout(
title=f'Top Models by {metric}',
xaxis_title='Model',
yaxis_title=metric_label,
template='plotly_white'
)
return fig
def create_top_dealers_chart(top_dealers, metric='Profit'):
"""
Create bar chart for top dealers.
"""
if top_dealers.empty:
return go.Figure()
metric_label = 'Profit ($)' if metric == 'Profit' else 'Units Sold'
fig = go.Figure(data=[
go.Bar(
x=top_dealers['Dealer ID'].astype(str),
y=top_dealers[metric],
marker_color='#2E86AB',
text=top_dealers[metric].apply(lambda x: f'${x:,.0f}' if metric == 'Profit' else f'{x:,.0f}'),
textposition='outside'
)
])
fig.update_layout(
title=f'Top Dealers by {metric}',
xaxis_title='Dealer ID',
yaxis_title=metric_label,
template='plotly_white'
)
return fig
def create_seasonal_heatmap(sales_df):
"""
Create heatmap of sales by month and year.
"""
if sales_df.empty:
return go.Figure()
pivot_data = sales_df.pivot_table(
values='Profit',
index='Year',
columns='Month_Name',
aggfunc='sum',
fill_value=0
)
# Reorder months
month_order = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December']
pivot_data = pivot_data[[m for m in month_order if m in pivot_data.columns]]
fig = px.imshow(
pivot_data,
text_auto='.0s',
aspect='auto',
color_continuous_scale='Viridis',
title='Seasonal Sales Heatmap (Profit)'
)
fig.update_layout(
xaxis_title='Month',
yaxis_title='Year',
template='plotly_white'
)
return fig
def create_model_share_pie_chart(top_models, n=6):
"""
Create pie chart for model market share.
"""
if top_models.empty:
return go.Figure()
top_n = top_models.head(n).copy()
other_sum = top_models.iloc[n:]['Profit'].sum() if len(top_models) > n else 0
if other_sum > 0:
other_row = pd.DataFrame({'Model': ['Other'], 'Profit': [other_sum]})
top_n = pd.concat([top_n, other_row], ignore_index=True)
fig = px.pie(
top_n,
values='Profit',
names='Model',
title='Profit Distribution by Model',
color_discrete_sequence=px.colors.qualitative.Set3
)
fig.update_traces(textposition='inside', textinfo='percent+label')
fig.update_layout(template='plotly_white')
return fig
def create_model_comparison_chart(model_performance):
"""
Create comparison chart for model performance metrics.
"""
if model_performance.empty:
return go.Figure()
fig = make_subplots(
rows=1, cols=2,
subplot_titles=('Profit by Model', 'Units Sold by Model'),
specs=[[{'type': 'bar'}, {'type': 'bar'}]]
)
# Profit bar chart
fig.add_trace(
go.Bar(
x=model_performance['Model'],
y=model_performance['Profit'],
name='Profit',
marker_color='#2E86AB',
text=model_performance['Profit'].apply(lambda x: f'${x:,.0f}'),
textposition='outside'
),
row=1, col=1
)
# Units bar chart
fig.add_trace(
go.Bar(
x=model_performance['Model'],
y=model_performance['Quantity Sold'],
name='Units Sold',
marker_color='#F18F01',
text=model_performance['Quantity Sold'].apply(lambda x: f'{x:,.0f}'),
textposition='outside'
),
row=1, col=2
)
fig.update_layout(
title='Model Performance Comparison',
height=500,
template='plotly_white',
showlegend=False
)
fig.update_xaxes(tickangle=45)
return fig
def create_top_models_over_time_chart(ranking_over_time):
"""
Create line chart showing top models' performance over time.
"""
if ranking_over_time.empty:
return go.Figure()
fig = go.Figure()
colors = ['#2E86AB', '#A23B72', '#F18F01', '#C73E1D', '#048A81']
for i, model in enumerate(ranking_over_time['Model'].unique()):
model_data = ranking_over_time[ranking_over_time['Model'] == model]
fig.add_trace(go.Scatter(
x=model_data['Date'],
y=model_data['Profit'],
mode='lines+markers',
name=model,
line=dict(color=colors[i % len(colors)], width=2),
marker=dict(size=6)
))
fig.update_layout(
title='Top Models Profit Over Time',
xaxis_title='Date',
yaxis_title='Profit ($)',
hovermode='x unified',
template='plotly_white'
)
return fig
def create_quarterly_breakdown_chart(quarterly_data):
"""
Create bar chart for quarterly breakdown.
"""
if quarterly_data.empty:
return go.Figure()
fig = make_subplots(
rows=2, cols=1,
subplot_titles=('Quarterly Profit', 'Quarterly Units Sold'),
vertical_spacing=0.15
)
# Profit chart
fig.add_trace(
go.Bar(
x=quarterly_data['Year_Quarter'],
y=quarterly_data['Profit'],
name='Profit',
marker_color='#2E86AB',
text=quarterly_data['Profit'].apply(lambda x: f'${x:,.0f}'),
textposition='outside'
),
row=1, col=1
)
# Units chart
fig.add_trace(
go.Bar(
x=quarterly_data['Year_Quarter'],
y=quarterly_data['Quantity Sold'],
name='Units Sold',
marker_color='#A23B72',
text=quarterly_data['Quantity Sold'].apply(lambda x: f'{x:,.0f}'),
textposition='outside'
),
row=2, col=1
)
fig.update_layout(
title='Quarterly Sales Breakdown',
height=600,
template='plotly_white',
showlegend=False
)
fig.update_xaxes(tickangle=45)
return fig
def create_dealer_map(dealer_performance):
"""
Create map visualization for dealer locations.
"""
if dealer_performance.empty or 'Latitude' not in dealer_performance.columns:
return go.Figure()
# Filter out rows with missing coordinates
map_data = dealer_performance.dropna(subset=['Latitude', 'Longitude'])
if map_data.empty:
return go.Figure()
fig = px.scatter_geo(
map_data,
lat='Latitude',
lon='Longitude',
size='Profit',
hover_name='Dealer Name',
hover_data={
'City': True,
'State': True,
'Profit': ':$,.0f',
'Quantity Sold': ':,.0f'
},
title='Dealer Locations and Performance',
projection='albers usa',
size_max=50,
color='Profit',
color_continuous_scale='Viridis'
)
fig.update_layout(
title_x=0.5,
geo=dict(
scope='usa',
showland=True,
landcolor='rgb(243, 243, 243)',
countrycolor='rgb(204, 204, 204)'
),
template='plotly_white'
)
return fig
def create_recalls_impact_chart(recalls_impact):
"""
Create chart showing recall impact on models.
"""
if recalls_impact.empty:
return go.Figure()
fig = make_subplots(
rows=1, cols=2,
subplot_titles=('Recall Ratio by Model', 'Recall Units vs Total Sales'),
specs=[[{'type': 'bar'}, {'type': 'bar'}]]
)
# Recall ratio chart
fig.add_trace(
go.Bar(
x=recalls_impact['Model'].head(10),
y=recalls_impact['Recall_Ratio'].head(10),
name='Recall Ratio',
marker_color='#C73E1D',
text=recalls_impact['Recall_Ratio'].head(10).apply(lambda x: f'{x:.1%}'),
textposition='outside'
),
row=1, col=1
)
# Recall vs Sales chart (using a subset)
comparison_data = recalls_impact.head(10).copy()
fig.add_trace(
go.Bar(
x=comparison_data['Model'],
y=comparison_data['Recall_Units'],
name='Recall Units',
marker_color='#F18F01'
),
row=1, col=2
)
fig.add_trace(
go.Bar(
x=comparison_data['Model'],
y=comparison_data['Quantity Sold'],
name='Total Sales',
marker_color='#2E86AB'
),
row=1, col=2
)
fig.update_layout(
title='Recall Impact Analysis',
height=500,
template='plotly_white',
barmode='group',
legend=dict(orientation='h', yanchor='bottom', y=1.02, xanchor='right', x=1)
)
fig.update_xaxes(tickangle=45)
return fig
def create_yearly_growth_chart(yearly_summary):
"""
Create chart showing year-over-year growth.
"""
if yearly_summary.empty:
return go.Figure()
fig = make_subplots(
rows=1, cols=2,
subplot_titles=('Year-over-Year Profit Growth', 'Year-over-Year Units Growth'),
specs=[[{'type': 'bar'}, {'type': 'bar'}]]
)
# Profit growth
fig.add_trace(
go.Bar(
x=yearly_summary['Year'].astype(str),
y=yearly_summary['Profit_Growth'].fillna(0),
name='Profit Growth %',
marker_color='#2E86AB',
text=yearly_summary['Profit_Growth'].fillna(0).apply(lambda x: f'{x:.1f}%'),
textposition='outside'
),
row=1, col=1
)
# Units growth
fig.add_trace(
go.Bar(
x=yearly_summary['Year'].astype(str),
y=yearly_summary['Units_Growth'].fillna(0),
name='Units Growth %',
marker_color='#A23B72',
text=yearly_summary['Units_Growth'].fillna(0).apply(lambda x: f'{x:.1f}%'),
textposition='outside'
),
row=1, col=2
)
fig.update_layout(
title='Year-over-Year Growth',
height=400,
template='plotly_white',
showlegend=False
)
return fig