entropy25 commited on
Commit
8f25013
·
verified ·
1 Parent(s): 7ad2215

Create analytics.py

Browse files
Files changed (1) hide show
  1. analytics.py +160 -0
analytics.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import plotly.express as px
3
+ import plotly.graph_objects as go
4
+ from typing import Dict, Optional, List
5
+
6
+ from config import get_chart_theme, DESIGN_SYSTEM
7
+
8
+ def get_material_stats(df: pd.DataFrame) -> Dict:
9
+ stats = {}
10
+ total = df['weight_kg'].sum()
11
+ total_work_days = df['date'].nunique()
12
+
13
+ for material in df['material_type'].unique():
14
+ data = df[df['material_type'] == material]
15
+ work_days = data['date'].nunique()
16
+ daily_avg = data.groupby('date')['weight_kg'].sum().mean()
17
+
18
+ stats[material] = {
19
+ 'total': data['weight_kg'].sum(),
20
+ 'percentage': (data['weight_kg'].sum() / total) * 100,
21
+ 'daily_avg': daily_avg,
22
+ 'work_days': work_days,
23
+ 'records': len(data)
24
+ }
25
+
26
+ stats['_total_'] = {
27
+ 'total': total,
28
+ 'percentage': 100.0,
29
+ 'daily_avg': df.groupby('date')['weight_kg'].sum().mean(),
30
+ 'work_days': total_work_days,
31
+ 'records': len(df)
32
+ }
33
+
34
+ return stats
35
+
36
+ def detect_outliers(df: pd.DataFrame) -> Dict:
37
+ outliers = {}
38
+
39
+ for material in df['material_type'].unique():
40
+ material_data = df[df['material_type'] == material]
41
+ data = material_data['weight_kg']
42
+
43
+ Q1, Q3 = data.quantile(0.25), data.quantile(0.75)
44
+ IQR = Q3 - Q1
45
+ lower, upper = Q1 - 1.5 * IQR, Q3 + 1.5 * IQR
46
+
47
+ outlier_mask = (data < lower) | (data > upper)
48
+ outlier_dates = material_data[outlier_mask]['date'].dt.strftime('%Y-%m-%d').tolist()
49
+
50
+ outliers[material] = {
51
+ 'count': len(outlier_dates),
52
+ 'range': f"{lower:.0f} - {upper:.0f} kg",
53
+ 'dates': outlier_dates
54
+ }
55
+
56
+ return outliers
57
+
58
+ def create_total_production_chart(df: pd.DataFrame, time_period: str = 'daily'):
59
+ if time_period == 'daily':
60
+ grouped = df.groupby('date')['weight_kg'].sum().reset_index()
61
+ fig = px.line(grouped, x='date', y='weight_kg',
62
+ title='Total Production Trend',
63
+ labels={'weight_kg': 'Weight (kg)', 'date': 'Date'})
64
+ elif time_period == 'weekly':
65
+ df_copy = df.copy()
66
+ df_copy['week'] = df_copy['date'].dt.isocalendar().week
67
+ df_copy['year'] = df_copy['date'].dt.year
68
+ grouped = df_copy.groupby(['year', 'week'])['weight_kg'].sum().reset_index()
69
+ grouped['week_label'] = grouped['year'].astype(str) + '-W' + grouped['week'].astype(str)
70
+ fig = px.bar(grouped, x='week_label', y='weight_kg',
71
+ title='Total Production Trend (Weekly)',
72
+ labels={'weight_kg': 'Weight (kg)', 'week_label': 'Week'})
73
+ else:
74
+ df_copy = df.copy()
75
+ df_copy['month'] = df_copy['date'].dt.to_period('M')
76
+ grouped = df_copy.groupby('month')['weight_kg'].sum().reset_index()
77
+ grouped['month'] = grouped['month'].astype(str)
78
+ fig = px.bar(grouped, x='month', y='weight_kg',
79
+ title='Total Production Trend (Monthly)',
80
+ labels={'weight_kg': 'Weight (kg)', 'month': 'Month'})
81
+
82
+ fig.update_layout(**get_chart_theme()['layout'], height=400, showlegend=False)
83
+ return fig
84
+
85
+ def create_materials_trend_chart(df: pd.DataFrame, time_period: str = 'daily',
86
+ selected_materials: Optional[List[str]] = None):
87
+ df_copy = df.copy()
88
+
89
+ if selected_materials:
90
+ df_copy = df_copy[df_copy['material_type'].isin(selected_materials)]
91
+
92
+ if time_period == 'daily':
93
+ grouped = df_copy.groupby(['date', 'material_type'])['weight_kg'].sum().reset_index()
94
+ fig = px.line(grouped, x='date', y='weight_kg', color='material_type',
95
+ title='Materials Production Trends',
96
+ labels={'weight_kg': 'Weight (kg)', 'date': 'Date', 'material_type': 'Material'})
97
+ elif time_period == 'weekly':
98
+ df_copy['week'] = df_copy['date'].dt.isocalendar().week
99
+ df_copy['year'] = df_copy['date'].dt.year
100
+ grouped = df_copy.groupby(['year', 'week', 'material_type'])['weight_kg'].sum().reset_index()
101
+ grouped['week_label'] = grouped['year'].astype(str) + '-W' + grouped['week'].astype(str)
102
+ fig = px.bar(grouped, x='week_label', y='weight_kg', color='material_type',
103
+ title='Materials Production Trends (Weekly)',
104
+ labels={'weight_kg': 'Weight (kg)', 'week_label': 'Week', 'material_type': 'Material'})
105
+ else:
106
+ df_copy['month'] = df_copy['date'].dt.to_period('M')
107
+ grouped = df_copy.groupby(['month', 'material_type'])['weight_kg'].sum().reset_index()
108
+ grouped['month'] = grouped['month'].astype(str)
109
+ fig = px.bar(grouped, x='month', y='weight_kg', color='material_type',
110
+ title='Materials Production Trends (Monthly)',
111
+ labels={'weight_kg': 'Weight (kg)', 'month': 'Month', 'material_type': 'Material'})
112
+
113
+ fig.update_layout(**get_chart_theme()['layout'], height=400)
114
+ return fig
115
+
116
+ def create_shift_trend_chart(df: pd.DataFrame, time_period: str = 'daily'):
117
+ if time_period == 'daily':
118
+ grouped = df.groupby(['date', 'shift'])['weight_kg'].sum().reset_index()
119
+ pivot_data = grouped.pivot(index='date', columns='shift', values='weight_kg').fillna(0)
120
+
121
+ fig = go.Figure()
122
+
123
+ if 'day' in pivot_data.columns:
124
+ fig.add_trace(go.Bar(
125
+ x=pivot_data.index,
126
+ y=pivot_data['day'],
127
+ name='Day Shift',
128
+ marker_color=DESIGN_SYSTEM['colors']['warning'],
129
+ text=pivot_data['day'].round(0),
130
+ textposition='inside'
131
+ ))
132
+
133
+ if 'night' in pivot_data.columns:
134
+ fig.add_trace(go.Bar(
135
+ x=pivot_data.index,
136
+ y=pivot_data['night'],
137
+ name='Night Shift',
138
+ marker_color=DESIGN_SYSTEM['colors']['primary'],
139
+ base=pivot_data['day'] if 'day' in pivot_data.columns else 0,
140
+ text=pivot_data['night'].round(0),
141
+ textposition='inside'
142
+ ))
143
+
144
+ fig.update_layout(
145
+ **get_chart_theme()['layout'],
146
+ title='Daily Shift Production Trends (Stacked)',
147
+ xaxis_title='Date',
148
+ yaxis_title='Weight (kg)',
149
+ barmode='stack',
150
+ height=400,
151
+ showlegend=True
152
+ )
153
+ else:
154
+ grouped = df.groupby(['date', 'shift'])['weight_kg'].sum().reset_index()
155
+ fig = px.bar(grouped, x='date', y='weight_kg', color='shift',
156
+ title=f'{time_period.title()} Shift Production Trends',
157
+ barmode='stack')
158
+ fig.update_layout(**get_chart_theme()['layout'], height=400)
159
+
160
+ return fig