-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCMS.py
More file actions
1736 lines (1435 loc) · 77.9 KB
/
CMS.py
File metadata and controls
1736 lines (1435 loc) · 77.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import streamlit as st
import pandas as pd
import plotly.express as px
import numpy as np
import plotly.graph_objects as go
from datetime import datetime
# Function to load default data
@st.cache_data
def load_default_data():
return pd.read_excel(
'Modified_PPE_compliance_dataset.xlsx',
sheet_name='Sheet1',
engine='openpyxl'
)
# Function to load uploaded files (supports Excel and CSV)
def load_uploaded_file(uploaded_file):
try:
if uploaded_file.name.endswith('.xlsx'):
return pd.read_excel(uploaded_file, engine='openpyxl')
elif uploaded_file.name.endswith('.csv'):
return pd.read_csv(uploaded_file)
else:
st.sidebar.error("Unsupported file type! Please upload an Excel or CSV file.")
st.stop()
except Exception as e:
st.sidebar.error(f"Error loading file: {e}")
st.stop()
# Sidebar for file upload or default dataset
st.sidebar.title("Upload or Load Dataset")
data_source = st.sidebar.radio(
"Choose Data Source:",
("Default Dataset", "Upload Your Own Dataset")
)
# Load dataset based on user input
if data_source == "Default Dataset":
data = load_default_data()
st.sidebar.success("Default dataset loaded successfully!")
else:
uploaded_file = st.sidebar.file_uploader("Upload an Excel or CSV file", type=['xlsx', 'csv'])
if uploaded_file is not None:
data = load_uploaded_file(uploaded_file)
st.sidebar.success("Dataset uploaded successfully!")
else:
st.sidebar.warning("Please upload a dataset to proceed.")
st.stop()
# Ensure 'Date' column is in datetime format
data['Date'] = pd.to_datetime(data['Date']).dt.date
# Define color palettes
default_colors = px.colors.qualitative.Plotly
time_series_colors = px.colors.qualitative.Set2
selected_analysis = st.sidebar.radio(
"Select Analysis Level:",
[
"Variable Analytics",
"Strategic Insights"
]
)
# Sidebar Filters
# Refresh Button
if st.button("Refresh Dashboard"):
st.experimental_set_query_params()
# Tooltip Message
tooltip_message = (
"The dataset is a working process. You cannot open the Excel file directly, "
"and no modifications can be made. You can only add data to existing columns, "
"and you cannot change the column names."
)
st.markdown(
f'<span style="color: grey; font-size: 12px; text-decoration: underline;">{tooltip_message}</span>',
unsafe_allow_html=True
)
analysis_variable=""
selected_insight=""
# Logic for Variable Analytics
if selected_analysis == "Variable Analytics":
# Radio Button for Variable-Based Analytics
analysis_variable = st.sidebar.radio(
"Select Variable for Analysis:",
[
"Over All",
"Analytics of Employee and Employees",
"Analytics of Unit and Units",
"Analytics of Shift and Shifts",
"Analytics of Time Series",
"Analytics of Camera Units"
]
)
# Logic for Strategic Insights
elif selected_analysis == "Strategic Insights":
# Radio Buttons for Selecting Insights
selected_insight = st.sidebar.radio(
"Select an Insight:",
[
"Combined Insights",
"Critical Zone Insights",
"Targets Monitoring Insights",
"Time Tracking Insights",
"Shift Productivity Insights",
"Growth Tracker Insights",
"Risk Radar Insights",
]
)
# Data Filtering
st.sidebar.header("Filters")
analysis_type = st.sidebar.selectbox("Select Analysis Type", ["Compliance", "Violation"])
min_date, max_date = min(data['Date']), max(data['Date'])
start_date = st.sidebar.date_input("Start Date", min_date, min_value=min_date, max_value=max_date)
end_date = st.sidebar.date_input("End Date", max_date, min_value=min_date, max_value=max_date)
if start_date > end_date:
st.sidebar.error("Start Date cannot be after End Date")
# Sidebar Filters
employee = st.sidebar.multiselect('Select Employee', options=data['Employee_Name'].unique())
shift = st.sidebar.multiselect('Select Shift', options=data['Shift'].unique())
factory = st.sidebar.multiselect('Select Factory', options=data['Factory'].unique())
department = st.sidebar.multiselect('Select Department', options=data['Department'].unique())
camera = st.sidebar.multiselect('Select Camera', options=data['Camera'].unique())
violation_type = st.sidebar.multiselect('Select Violation Type', options=data['Violation_Type'].unique()) # New filter for violation types
# Render charts based on the selected variable
filtered_data = data[
(data['Date'] >= start_date) & (data['Date'] <= end_date) &
(data['Employee_Name'].isin(employee) if employee else True) &
(data['Shift'].isin(shift) if shift else True) &
(data['Factory'].isin(factory) if factory else True) &
(data['Department'].isin(department) if department else True) &
(data['Camera'].isin(camera) if camera else True) &
(data['Violation_Type'].isin(violation_type) if violation_type else True) # Apply filter for violation types
]
# Determine the relevant data based on the analysis type
if analysis_type == "Violation":
relevant_data = filtered_data[filtered_data['Violation_Type'] != 'Compliant']
current_rate = (relevant_data.shape[0] / filtered_data.shape[0] * 100) if filtered_data.shape[0] > 0 else 0
rate_label = "Current Violation Rate"
relevant_checks = relevant_data.shape[0]
else:
relevant_data = filtered_data[filtered_data['Violation_Type'] == 'Compliant']
compliant_checks = relevant_data.shape[0]
current_rate = (compliant_checks / filtered_data.shape[0] * 100) if filtered_data.shape[0] > 0 else 0
rate_label = "Current Compliance Rate"
relevant_checks = compliant_checks
print(f"{rate_label}: {current_rate:.2f}%")
# Function to create pie charts
def create_pie_chart(data, group_by, title):
pie_data = data[group_by].value_counts().reset_index()
pie_data.columns = [group_by, 'Count']
fig = px.pie(pie_data, names=group_by, values='Count', title=title)
st.plotly_chart(fig, use_container_width=True)
# Function to create bar charts
def create_bar_chart(data, group_by, title, color_palette):
grouped_data = data.groupby(group_by).size().reset_index(name='Count')
grouped_data['Color'] = grouped_data.index.map(lambda x: color_palette[x % len(color_palette)])
fig = px.bar(
grouped_data, x=group_by, y='Count',
title=title, color='Color',
labels={'Count': 'Total Count'},
color_discrete_sequence=color_palette
)
st.plotly_chart(fig, use_container_width=True)
# Display the breakdown chart
st.plotly_chart(fig_camera_breakdown, use_container_width=True)
if selected_analysis == "Variable Analytics":
if analysis_variable == "Over All":
# Select relevant data based on the analysis type
total_checks = filtered_data.shape[0]
# Display Header and Metrics
st.header(f"Overall {analysis_type} Dashboard")
# Create columns for metrics
col1, col2, col3= st.columns(3)
# Display Current Rate, Next Month Prediction, Total Checks, and Relevant Checks
col1.metric(rate_label, f"{current_rate:.2f}%")
col2.metric("Total Checks", total_checks)
col3.metric("Relevant Checks", relevant_checks)
# Group data for visualizations
if analysis_type == "Violation":
grouped_data = relevant_data.groupby(['Factory', 'Shift']).agg(
Total_Violations=('Violation_Type', 'count')
).reset_index()
else:
grouped_data = relevant_data.groupby(['Factory', 'Shift']).agg(
Total_Compliance=('Violation_Type', 'count')
).reset_index()
# Factory-wise Violations/Compliance Gauge
st.subheader(f"{analysis_type} by Factory")
factory_colors = ['#00FF00', '#FF4500', '#1E90FF', '#FFFF00',
'#FF1493'] # Green, OrangeRed, DodgerBlue, Yellow, DeepPink (avoiding pink now)
# Factory-wise Violations/Compliance Gauge
col1, col2, col3 = st.columns(3)
for i, (factory, count) in enumerate(grouped_data.groupby('Factory')[
f'Total_Violations' if analysis_type == "Violation" else 'Total_Compliance'].sum().items(),
1):
with [col1, col2, col3][i % 3]:
color_index = i % len(factory_colors) # Cycle through the color palette
fig = go.Figure(go.Indicator(
mode="gauge+number",
value=count,
title={"text": f"Factory {factory} {analysis_type}"},
gauge={
'axis': {'range': [0, max(grouped_data.groupby('Factory')[
f'Total_Violations' if analysis_type == 'Violation' else 'Total_Compliance'].sum())]},
'bar': {'color': factory_colors[color_index]}
}
))
st.plotly_chart(fig, use_container_width=True)
# Shift-wise Violations/Compliance Gauge
st.subheader(f"{analysis_type} by Shift")
col4, col5 = st.columns(2)
with col4:
shift_value = grouped_data[grouped_data['Shift'] == 'Morning'][
f'Total_Violations' if analysis_type == "Violation" else 'Total_Compliance'].sum()
fig_morning = go.Figure(go.Indicator(
mode="gauge+number",
value=shift_value,
title={"text": "Morning Shift"},
gauge={
'axis': {'range': [0, max(grouped_data.groupby('Shift')[
f'Total_Violations' if analysis_type == 'Violation' else 'Total_Compliance'].sum())]},
'bar': {'color': '#32CD32'} # LimeGreen color for Morning Shift
}
))
st.plotly_chart(fig_morning, use_container_width=True)
with col5:
shift_value = grouped_data[grouped_data['Shift'] == 'Evening'][
f'Total_Violations' if analysis_type == "Violation" else 'Total_Compliance'].sum()
fig_evening = go.Figure(go.Indicator(
mode="gauge+number",
value=shift_value,
title={"text": "Evening Shift"},
gauge={
'axis': {'range': [0, max(grouped_data.groupby('Shift')[
f'Total_Violations' if analysis_type == 'Violation' else 'Total_Compliance'].sum())]},
'bar': {'color': '#FF8C00'} # DarkOrange for Evening Shift
}
))
st.plotly_chart(fig_evening, use_container_width=True)
row_selection = st.radio("Choose Rows to Display:", ("First Five Rows", "Last Five Rows"))
# Display data based on radio selection
if row_selection == "First Five Rows":
st.write("### First Five Rows of the Dataset")
st.write(data.head())
else:
st.write("### Last Five Rows of the Dataset")
st.write(data.tail())
elif analysis_variable == "Analytics of Employee and Employees":
st.header("Employee Analytics")
if analysis_type == "Violation":
relevant_data = filtered_data[filtered_data['Violation_Type'] != 'Compliant']
title = "Employee Violations"
else:
relevant_data = filtered_data[filtered_data['Violation_Type'] == 'Compliant']
title = "Employee Compliance"
# Group data by Employee to count occurrences (first chart)
employee_counts = relevant_data['Employee_Name'].value_counts().reset_index()
employee_counts.columns = ['Employee_Name', 'Count']
# Create a bar chart: Total Compliance/Violations by Employee
fig_employee_compliance = px.bar(
employee_counts,
x='Employee_Name',
y='Count',
title=title,
labels={'Count': 'Total Count'},
color='Employee_Name', # Assign distinct colors to each employee
color_discrete_sequence=px.colors.qualitative.Plotly # Use a qualitative palette
)
# Update layout of the first chart for better appearance
fig_employee_compliance.update_layout(
xaxis_title="Employee Name",
yaxis_title="Count",
plot_bgcolor='rgba(0, 0, 0, 0)', # Transparent background
font=dict(color="white") # White font for contrast
)
# Second Chart: Breakdown by Violation/Compliance Type for Each Employee
breakdown_data = relevant_data.groupby(['Employee_Name', 'Violation_Type']).size().reset_index(name='Count')
fig_violation_breakdown = px.bar(
breakdown_data,
x='Employee_Name',
y='Count',
color='Violation_Type', # Distinguish by Violation/Compliance Type
title=f"{title} by Type",
labels={'Count': 'Total Count', 'Violation_Type': 'Type'},
barmode='group', # Group bars for better comparison
color_discrete_sequence=px.colors.qualitative.Set2 # Use a distinct color palette for types
)
# Update layout of the second chart for better appearance
fig_violation_breakdown.update_layout(
xaxis_title="Employee Name",
yaxis_title="Count",
plot_bgcolor='rgba(0, 0, 0, 0)', # Transparent background
font=dict(color="white") # White font for good contrast
)
# Display both charts
st.plotly_chart(fig_employee_compliance, use_container_width=True)
st.plotly_chart(fig_violation_breakdown, use_container_width=True)
elif analysis_variable == "Analytics of Unit and Units":
st.header("Unit Analytics")
st.header(f"{analysis_type} by Unit")
# Define distinct colors for factories
factory_colors = [
'#1f77b4', # Blue
'#ff7f0e', # Orange
'#2ca02c', # Green
'#d62728', # Red
'#9467bd', # Purple
'#8c564b', # Brown
'#e377c2', # Pink
'#7f7f7f', # Gray
'#bcbd22', # Olive
'#17becf' # Cyan
]
# Factory-wise Violations/Compliance Chart
st.subheader(f"{analysis_type} by Factory")
factory_data = relevant_data.groupby(['Factory']).agg(
Total_Count=('Violation_Type', 'count') if analysis_type == "Violation" else ('Employee_Name', 'count')
).reset_index()
# Create a color map for factories
factory_data['Color'] = factory_data.index.map(lambda x: factory_colors[x % len(factory_colors)])
fig_factory = px.bar(factory_data, x='Factory', y='Total_Count',
title=f"{analysis_type} by Factory",
labels={
'Total_Count': 'Total Violations' if analysis_type == "Violation" else 'Total Compliance'},
color='Color') # Use the assigned color
# Update layout for integer x-axis ticks
fig_factory.update_layout(
xaxis=dict(
dtick=1, # Set the tick interval to 1 for integer values
tickmode='linear' # Ensure ticks are linear
)
)
st.plotly_chart(fig_factory, use_container_width=True)
# Department-wise Violations/Compliance Chart
st.subheader(f"{analysis_type} by Department")
department_data = relevant_data.groupby(['Department']).agg(
Total_Count=('Violation_Type', 'count') if analysis_type == "Violation" else ('Employee_Name', 'count')
).reset_index()
# Define distinct colors for departments
department_colors = [
'#ffbb78', # Light Orange
'#98df8a', # Light Green
'#ff9896', # Light Red
'#c5b0d5', # Light Purple
'#f7b6d2', # Light Pink
'#c49c94', # Light Brown
'#f7f7f7', # Light Gray
'#dbdb8d', # Light Olive
'#9edae5', # Light Cyan
'#f3d9a4' # Light Yellow
]
# Create a color map for departments
department_data['Color'] = department_data.index.map(lambda x: department_colors[x % len(department_colors)])
fig_department = px.bar(department_data, x='Department', y='Total_Count',
title=f"{analysis_type} by Department",
labels={
'Total_Count': 'Total Violations' if analysis_type == "Violation" else 'Total Compliance'},
color='Color') # Use the assigned color
# Update layout for integer x-axis ticks
fig_department.update_layout(
xaxis=dict(
dtick=1, # Set the tick interval to 1 for integer values
tickmode='linear' # Ensure ticks are linear
)
)
st.plotly_chart(fig_department, use_container_width=True)
# Visualization Logic for Violations
if analysis_type == "Violation":
# Filter for Violations
violation_data = filtered_data[filtered_data['Violation_Type'] != 'Compliant']
# Create a Bar Chart for Violations
if not violation_data.empty:
violation_count = violation_data['Violation_Type'].value_counts().reset_index()
violation_count.columns = ['Violation Type', 'Count']
# Define distinct colors for violation types using qualitative colors
fig_violation = px.bar(violation_count, x='Violation Type', y='Count',
title="Violation Counts",
labels={'Count': 'Number of Violations'},
color='Violation Type', # Color by Violation Type for distinct colors
color_discrete_sequence=px.colors.qualitative.Dark2) # Darker color palette
st.plotly_chart(fig_violation, use_container_width=True)
else:
st.write("No violation data available for the selected filters.")
elif analysis_variable == "Analytics of Shift and Shifts":
st.header("Shift Analytics")
# Shift-wise Violations/Compliance Chart
st.subheader(f"{analysis_type} by Shift")
# Group data by shift to calculate total counts
shift_data = relevant_data.groupby(['Shift']).agg(
Total_Count=('Violation_Type', 'count') if analysis_type == "Violation" else ('Employee_Name', 'count')
).reset_index()
# Bar chart: Overall Violations/Compliance by Shift
fig_shift = px.bar(
shift_data,
x='Shift',
y='Total_Count',
title=f"{analysis_type} by Shift",
labels={
'Total_Count': 'Total Violations' if analysis_type == "Violation" else 'Total Compliance'
},
color='Shift', # Assign distinct colors for each shift
color_discrete_sequence=px.colors.qualitative.Plotly # Use a vibrant color palette
)
# Update layout for better appearance
fig_shift.update_layout(
xaxis_title="Shift",
yaxis_title="Total Count",
plot_bgcolor='rgba(0, 0, 0, 0)', # Transparent background
font=dict(color="white") # White font for contrast
)
# Display the shift-wise chart
st.plotly_chart(fig_shift, use_container_width=True)
# Shift-wise Breakdown by Type (Second Chart)
st.subheader(f"{analysis_type} Breakdown by Shift and Type")
# Group data by Shift and Violation/Compliance Type
shift_breakdown = relevant_data.groupby(['Shift', 'Violation_Type']).size().reset_index(name='Count')
# Bar chart: Breakdown of Types by Shift
fig_shift_breakdown = px.bar(
shift_breakdown,
x='Shift',
y='Count',
color='Violation_Type', # Color by type for distinction
title=f"{analysis_type} Breakdown by Shift and Type",
labels={'Count': 'Total Count', 'Violation_Type': 'Type'},
barmode='group', # Group bars for better comparison
color_discrete_sequence=px.colors.qualitative.Set2 # Use another qualitative palette for better distinction
)
# Update layout for better appearance
fig_shift_breakdown.update_layout(
xaxis_title="Shift",
yaxis_title="Count",
plot_bgcolor='rgba(0, 0, 0, 0)', # Transparent background
font=dict(color="white") # White font for good contrast
)
# Display the shift-wise breakdown chart
st.plotly_chart(fig_shift_breakdown, use_container_width=True)
elif analysis_variable == "Analytics of Time Series" :
# Date-wise Violations/Compliance Chart (Line Chart)
st.subheader(f"{analysis_type} by Date")
# Group data by Date to calculate total counts
date_data = relevant_data.groupby(['Date']).agg(
Total_Count=('Violation_Type', 'count') if analysis_type == "Violation" else ('Employee_Name', 'count')
).reset_index()
# Line chart: Overall Violations/Compliance Over Time
fig_date = px.line(
date_data,
x='Date',
y='Total_Count',
title=f"{analysis_type} Over Time",
labels={
'Total_Count': 'Total Violations' if analysis_type == "Violation" else 'Total Compliance'
},
markers=True, # Add markers for better visibility
color_discrete_sequence=px.colors.qualitative.Set1 # Use Set1 color scheme
)
# Update layout for better appearance
fig_date.update_layout(
xaxis_title="Date",
yaxis_title="Count",
plot_bgcolor='rgba(0, 0, 0, 0)', # Transparent background
font=dict(color="white"), # White font for contrast
)
# Display the line chart
st.plotly_chart(fig_date, use_container_width=True)
# Breakdown by Type Over Time (Area Chart)
st.subheader(f"{analysis_type} Breakdown by Date and Type")
# Group data by Date and Violation/Compliance Type
date_breakdown = relevant_data.groupby(['Date', 'Violation_Type']).size().reset_index(name='Count')
# Area chart: Breakdown by Violation/Compliance Type Over Time
fig_date_breakdown = px.area(
date_breakdown,
x='Date',
y='Count',
color='Violation_Type', # Distinguish by type
title=f"{analysis_type} Breakdown Over Time",
labels={'Count': 'Total Count', 'Violation_Type': 'Type'},
color_discrete_sequence=px.colors.qualitative.Set2 # Use another qualitative palette
)
# Update layout for better appearance
fig_date_breakdown.update_layout(
xaxis_title="Date",
yaxis_title="Count",
plot_bgcolor='rgba(0, 0, 0, 0)', # Transparent background
font=dict(color="white") # White font for contrast
)
# Display the area chart
st.plotly_chart(fig_date_breakdown, use_container_width=True)
elif analysis_variable == "Analytics of Camera Units":
st.header("Camera Unit Analytics")
# Camera-wise Violations/Compliance Chart
st.subheader(f"{analysis_type} by Camera")
# Grouping data by Camera to count occurrences of violations
camera_data = relevant_data.groupby(['Camera']).agg(
Total_Violations=(
'Violation_Type', lambda x: (x != 'Compliant').sum() if analysis_type == "Violation" else len(x)
)
).reset_index()
# Create a bar chart for total violations by camera
fig_camera = px.bar(
camera_data,
x='Camera',
y='Total_Violations',
title=f"Total {analysis_type} by Camera",
labels={'Total_Violations': 'Number of Violations'},
color='Total_Violations', # Color by Total_Violations for distinct colors
color_continuous_scale='YlOrRd' # Yellow-Orange-Red color scale
)
# Update layout for better appearance
fig_camera.update_layout(
xaxis_title="Camera",
yaxis_title="Number of Violations",
plot_bgcolor='rgba(0, 0, 0, 0)', # Transparent background for better appearance
font=dict(color="black"), # Black font color for good contrast
xaxis=dict(
tickmode='array',
tickvals=camera_data['Camera'], # Set x-axis ticks to the camera names
ticktext=camera_data['Camera'] # Display camera names as tick labels
)
)
# Display the chart
st.plotly_chart(fig_camera, use_container_width=True)
# Breakdown by Type Over Camera (Second Chart)
st.subheader(f"{analysis_type} Breakdown by Camera and Type")
# Grouping data by Camera and Violation Type to count occurrences
camera_breakdown = relevant_data.groupby(['Camera', 'Violation_Type']).size().reset_index(name='Count')
# Create a grouped bar chart for breakdown by type for each camera
fig_camera_breakdown = px.bar(
camera_breakdown,
x='Camera',
y='Count',
color='Violation_Type', # Distinguish by type
title=f"{analysis_type} Breakdown by Camera and Type",
labels={'Count': 'Total Count', 'Violation_Type': 'Type'},
barmode='group', # Group bars for better comparison
color_discrete_sequence=px.colors.qualitative.Set2 # Use another qualitative color palette
)
# Update layout for better appearance
fig_camera_breakdown.update_layout(
xaxis_title="Camera",
yaxis_title="Count",
plot_bgcolor='rgba(0, 0, 0, 0)', # Transparent background for better appearance
font=dict(color="black"), # Black font for good contrast
xaxis=dict(
tickmode='array',
tickvals=camera_breakdown['Camera'].unique(), # Set x-axis ticks to unique camera names
ticktext=camera_breakdown['Camera'].unique() # Display camera names as tick labels
)
)
# Display the breakdown chart
st.plotly_chart(fig_camera_breakdown, use_container_width=True)
elif selected_analysis == "Strategic Insights":
# Combined Insights
if selected_insight == "Combined Insights":
st.subheader(f"{analysis_type} by Factory, Department")
# Group data for Unit-wise Violations/Compliance
grouped_unit_data = relevant_data.groupby(['Factory', 'Department']).agg(
Total_Count=('Violation_Type', 'count') if analysis_type == "Violation" else ('Employee_Name', 'count')
).reset_index()
# Add a numeric index for factories (1, 2, 3...)
grouped_unit_data['Factory_Index'] = grouped_unit_data.groupby('Factory').ngroup() + 1
# Color palette for the bar chart
color_palette = px.colors.qualitative.Set3 # Vibrant color palette
# Create a bar chart for Unit-wise Violations/Compliance
fig_unit = px.bar(
grouped_unit_data,
x='Factory_Index',
y='Total_Count',
color='Department',
title=f"{analysis_type} by Unit",
labels={
'Factory_Index': 'Factory ',
'Total_Count': 'Total Violations' if analysis_type == "Violation" else 'Total Compliance'
},
color_discrete_sequence=color_palette # Assign color palette
)
# Update layout for better appearance
fig_unit.update_layout(
xaxis_title="Factory ",
yaxis_title="Count",
plot_bgcolor='rgba(0, 0, 0, 0)', # Transparent background
font=dict(color="white"), # White font color for dark background
xaxis=dict(
tickmode='linear', # Ensure all numeric ticks are displayed
tick0=1, # Start at 1
dtick=1 # Step size of 1
)
)
# Display the bar chart
st.plotly_chart(fig_unit, use_container_width=True)
# Filter data based on user input
if analysis_type == "Violation":
relevant_data = data[data['Violation_Type'] != 'Compliant']
else:
relevant_data = data[data['Violation_Type'] == 'Compliant']
# Function to create combined charts
def combined_charts():
fig = go.Figure()
# Group data by Department and Shift
department_shift_data = relevant_data.groupby(['Department', 'Shift']).agg(
Total_Count=('Violation_Type', 'count')
).reset_index()
# Add Department by Shift Bar Chart
# Using distinct colors for each department
department_colors = px.colors.qualitative.Pastel # Color palette for department-wise chart
for i, department in enumerate(department_shift_data['Department'].unique()):
department_data = department_shift_data[department_shift_data['Department'] == department]
color = department_colors[i % len(department_colors)] # Cycle through the color palette
fig.add_trace(go.Bar(
x=department_data['Shift'],
y=department_data['Total_Count'],
name=str(department), # Ensure department name is used as legend entry
hoverinfo='text',
text=department_data['Total_Count'],
marker_color=color # Set the color for each department
))
# Update the layout with title and axis labels
fig.update_layout(
title=f"{analysis_type} by Department and Shift",
barmode='stack', # Stacked bar chart
xaxis_title='Shift',
yaxis_title='Total Count',
legend_title='Department',
template='plotly_white', # White background for better visibility
font=dict(color="white") # White font for contrast
)
# Render the chart in Streamlit
st.plotly_chart(fig, use_container_width=True)
# Call the function to display combined charts
combined_charts()
# Factory by Trend Over Time
trend_data = relevant_data.groupby(['Date', 'Factory']).agg(
Total_Count=('Violation_Type', 'count')
).reset_index()
# Create a new figure for the trend chart
fig_trend = go.Figure()
# Use a color palette for the Factory trends
factory_colors = px.colors.qualitative.Vivid # Vivid colors for factory trends
for i, factory in enumerate(trend_data['Factory'].unique()):
factory_data = trend_data[trend_data['Factory'] == factory]
color = factory_colors[i % len(factory_colors)] # Assign color to each factory
fig_trend.add_trace(go.Scatter(
x=factory_data['Date'],
y=factory_data['Total_Count'],
mode='lines+markers',
name=str(factory), # Ensure name is a string
hoverinfo='text',
text=factory_data['Total_Count'],
line=dict(color=color, width=2), # Set line color
marker=dict(size=6, symbol='circle', color=color) # Set marker color
))
fig_trend.update_layout(
title=f"{analysis_type} Trend Over Time by Factory",
xaxis_title='Date',
yaxis_title='Total Count',
legend_title='Factory',
template='plotly_white', # Keep background white
plot_bgcolor='rgba(0, 0, 0, 0)' # Ensure the plot area background is transparent
)
st.plotly_chart(fig_trend, use_container_width=True)
# Employee by Over Time
employee_data = relevant_data.groupby(['Date', 'Employee_Name']).agg(
Total_Count=('Violation_Type', 'count')
).reset_index()
# Create a new figure for the employee trend chart
fig_employee = go.Figure()
# Use a color palette for Employee trends
employee_colors = px.colors.qualitative.Set2 # Soft colors for employee trends
for i, employee in enumerate(employee_data['Employee_Name'].unique()):
emp_data = employee_data[employee_data['Employee_Name'] == employee]
color = employee_colors[i % len(employee_colors)] # Assign color to each employee
fig_employee.add_trace(go.Scatter(
x=emp_data['Date'],
y=emp_data['Total_Count'],
mode='lines+markers',
name=str(employee), # Ensure name is a string
hoverinfo='text',
text=emp_data['Total_Count'],
line=dict(color=color, width=2), # Set line color
marker=dict(size=6, symbol='circle', color=color) # Set marker color
))
fig_employee.update_layout(
title=f"{analysis_type} Over Time by Employee",
xaxis_title='Date',
yaxis_title='Total Count',
legend_title='Employee',
template='plotly_white', # Keep background white
plot_bgcolor='rgba(0, 0, 0, 0)' # Ensure the plot area background is transparent
)
st.plotly_chart(fig_employee, use_container_width=True)
# Critical Zone Insights
elif selected_insight == "Critical Zone Insights":
zone_colors = {'Green Zone': 'green', 'Yellow Zone': 'yellow', 'Red Zone': 'red'}
if analysis_type == "Violation":
st.subheader("Critical Zone Insights (Red: > 50% Violation Rate, Yellow: 30-50%, Green: < 30%)")
# Calculate violation rates
violation_rates = data.groupby(['Factory', 'Department'])['Violation_Type'].apply(
lambda x: (x != 'Compliant').sum() / len(x) * 100
).reset_index(name='Violation Rate')
# Assign zones
violation_rates['Zone'] = pd.cut(
violation_rates['Violation Rate'], bins=[0, 30, 50, 100],
labels=['Green Zone', 'Yellow Zone', 'Red Zone']
)
# Display the table
st.dataframe(violation_rates)
# Factory-wise Violation Chart
fig_factory_violations = px.bar(
violation_rates,
x=violation_rates.groupby('Factory').ngroup() + 1, # Numeric x-axis
y='Violation Rate',
color='Zone',
title="Critical Zone Violation Rates by Factory",
labels={'x': 'Factory', 'Violation Rate': 'Violation Rate (%)'},
color_discrete_map=zone_colors
)
fig_factory_violations.update_layout(
xaxis=dict(tickmode='linear', tick0=1, dtick=1),
yaxis=dict(range=[0, 100]),
plot_bgcolor='rgba(0, 0, 0, 0)',
font=dict(color="white")
)
st.plotly_chart(fig_factory_violations, use_container_width=True)
# Department-wise Violation Chart
fig_department_violations = px.bar(
violation_rates,
x=violation_rates.groupby('Department').ngroup() + 1, # Numeric x-axis
y='Violation Rate',
color='Zone',
title="Critical Zone Violation Rates by Department",
labels={'x': 'Department', 'Violation Rate': 'Violation Rate (%)'},
color_discrete_map=zone_colors
)
fig_department_violations.update_layout(
xaxis=dict(tickmode='linear', tick0=1, dtick=1),
yaxis=dict(range=[0, 100]),
plot_bgcolor='rgba(0, 0, 0, 0)',
font=dict(color="white")
)
st.plotly_chart(fig_department_violations, use_container_width=True)
# Employees in the Red Zone
red_zone_employees = data[
(data['Violation_Type'] != 'Compliant') &
(data.groupby(['Factory', 'Department'])['Violation_Type'].transform(
lambda x: (x != 'Compliant').sum() / len(x) * 100 > 50
))
]['Employee_Name'].unique()
st.write(f"Employees in Red Zone: {', '.join(red_zone_employees)}")
else:
st.subheader("Critical Zone Insights (Red: < 50% Compliance, Yellow: 50-80%, Green: > 80%)")
# Calculate compliance rates
compliance_rates = data.groupby(['Factory', 'Department'])['Violation_Type'].apply(
lambda x: (x == 'Compliant').sum() / len(x) * 100
).reset_index(name='Compliance Rate')
# Assign zones
compliance_rates['Zone'] = pd.cut(
compliance_rates['Compliance Rate'], bins=[0, 50, 80, 100],
labels=['Red Zone', 'Yellow Zone', 'Green Zone']
)
# Display the table
st.dataframe(compliance_rates)
# Factory-wise Compliance Chart
fig_factory_compliance = px.bar(
compliance_rates,
x=compliance_rates.groupby('Factory').ngroup() + 1, # Numeric x-axis
y='Compliance Rate',
color='Zone',
title="Critical Zone Compliance Rates by Factory",
labels={'x': 'Factory', 'Compliance Rate': 'Compliance Rate (%)'},
color_discrete_map=zone_colors
)
fig_factory_compliance.update_layout(
xaxis=dict(tickmode='linear', tick0=1, dtick=1),
yaxis=dict(range=[0, 100]),
plot_bgcolor='rgba(0, 0, 0, 0)',
font=dict(color="white")
)
st.plotly_chart(fig_factory_compliance, use_container_width=True)
# Department-wise Compliance Chart
fig_department_compliance = px.bar(
compliance_rates,
x=compliance_rates.groupby('Department').ngroup() + 1, # Numeric x-axis
y='Compliance Rate',
color='Zone',
title="Critical Zone Compliance Rates by Department",
labels={'x': 'Department ', 'Compliance Rate': 'Compliance Rate (%)'},
color_discrete_map=zone_colors
)
fig_department_compliance.update_layout(
xaxis=dict(tickmode='linear', tick0=1, dtick=1),
yaxis=dict(range=[0, 100]),
plot_bgcolor='rgba(0, 0, 0, 0)',
font=dict(color="white")
)
st.plotly_chart(fig_department_compliance, use_container_width=True)
# Employees in the Red Zone (Compliance < 50%)
red_zone_employees = data[
(data['Violation_Type'] == 'Compliant') &
(data.groupby(['Factory', 'Department'])['Violation_Type'].transform(
lambda x: (x == 'Compliant').sum() / len(x) * 100 < 50
))
]['Employee_Name'].unique()
st.write(f"Employees in Red Zone: {', '.join(red_zone_employees)}")
# Targets Monitoring Insights
elif selected_insight == "Targets Monitoring Insights":
# For Violations
if analysis_type == "Violation":
st.subheader("Targets Monitoring - Violation Rate vs Targets")
# Group and calculate violation rates
violation_data = filtered_data.groupby(['Factory', 'Department']).agg(
violation_count=('Violation_Type', lambda x: (x != 'Compliant').sum()),
total=('Violation_Type', 'count')
).reset_index()
violation_data['Target Violation Rate'] = 30 # Assuming target of 30%
violation_data['Actual Violation Rate'] = (violation_data['violation_count'] / violation_data[
'total']) * 100
# Display the data
st.dataframe(violation_data)
# ---- Department-wise Chart ----
st.subheader("Department-wise Actual vs Target Violation Rates")
fig_dept_violation = px.bar(
violation_data.melt(id_vars=['Department'],
value_vars=['Actual Violation Rate', 'Target Violation Rate'],
var_name='Rate Type', value_name='Rate (%)'),
x='Department', y='Rate (%)', color='Rate Type', barmode='group',
title="Actual vs Target Violation Rates by Department",
color_discrete_map={'Actual Violation Rate': '#E63946', 'Target Violation Rate': '#F1FAEE'}
)
fig_dept_violation.update_traces(texttemplate='%{y:.2f}%', textposition='outside')
fig_dept_violation.update_layout(xaxis=dict(tickmode='linear', tick0=1, dtick=1),
plot_bgcolor='rgba(0,0,0,0)',
font=dict(color='white'))
st.plotly_chart(fig_dept_violation, use_container_width=True)
# ---- Factory-wise Chart ----
st.subheader("Factory-wise Actual vs Target Violation Rates")
fig_fact_violation = px.bar(
violation_data.melt(id_vars=['Factory'],
value_vars=['Actual Violation Rate', 'Target Violation Rate'],
var_name='Rate Type', value_name='Rate (%)'),
x='Factory', y='Rate (%)', color='Rate Type', barmode='group',
title="Actual vs Target Violation Rates by Factory",