SHELLAPANDIANGANHUNGING commited on
Commit
bba645a
·
verified ·
1 Parent(s): be1c257

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -64
app.py CHANGED
@@ -1064,85 +1064,139 @@ with col_3d:
1064
  insight_text = "<div class='ai-insight'>Insufficient data for insight.</div>"
1065
  st.markdown(insight_text, unsafe_allow_html=True)
1066
 
1067
-
1068
-
1069
- # =================== OBJECTIVE 4 - What Unsafe Issues Appear Most Often? ===================
1070
- st.markdown("<h3 class='section-title'>OBJECTIVE 4 — What Unsafe Issues Appear Most Often?</h3>", unsafe_allow_html=True)
1071
-
1072
- # Function for consistent title
1073
- def create_consistent_title(title_text):
1074
- return f"<div style='font-family: Arial; font-size: 16px; font-weight: bold; color: #2c3e50; text-align: center; margin-bottom: 8px;'>{title_text}</div>"
1075
-
1076
- # Try to import wordcloud
1077
  try:
1078
  from wordcloud import WordCloud
1079
  import matplotlib.pyplot as plt
1080
  import plotly.express as px
1081
- import plotly.graph_objects as go
1082
  WORDCLOUD_AVAILABLE = True
1083
  except ImportError:
1084
  WORDCLOUD_AVAILABLE = False
1085
 
 
 
 
 
 
 
 
1086
  if WORDCLOUD_AVAILABLE:
1087
- # Prepare data
1088
- df_all = df_local.copy()
1089
-
1090
- # 2-column layout
1091
- col_chart, col_cloud = st.columns([1.2, 1])
1092
 
1093
- # === PIE CHART (with custom legend logic) ===
1094
- with col_chart:
 
 
 
 
 
 
 
 
 
 
1095
  st.markdown(create_consistent_title("Distribution of All Issue Categories"), unsafe_allow_html=True)
1096
-
1097
- if 'temuan_kategori' not in df_all.columns:
1098
- st.warning("Column 'temuan_kategori' not found.")
1099
- else:
1100
- # Count categories
1101
- cat_counts = df_all['temuan_kategori'].value_counts()
1102
- total = cat_counts.sum()
1103
- percentages = (cat_counts / total * 100).round(1)
1104
-
1105
- # Define colors (sesuai preferensi Anda)
1106
- color_map = {
1107
- 'Positive': '#2E7D32', # Hijau
1108
- 'Unsafe Condition': '#EF5350', # Merah tua (pastel red)
1109
- 'Unsafe Action': '#F48FB1', # Pink pastel
1110
- 'Near Miss': '#BDBDBD', # Abu-abu
1111
- }
1112
- # Default color for unknown
1113
- default_color = '#9E9E9E'
1114
-
1115
- # Assign colors
1116
- colors = [color_map.get(cat, default_color) for cat in cat_counts.index]
1117
-
1118
- # Create base pie chart — tanpa legend
1119
- fig = go.Figure(data=[go.Pie(
1120
- labels=cat_counts.index,
1121
- values=cat_counts.values,
1122
- marker=dict(colors=colors),
1123
- textinfo='percent+label',
1124
- textposition='inside',
1125
- hoverinfo='label+percent',
1126
- sort=False # pertahankan urutan asli
1127
- )])
1128
- fig.update_layout(
1129
- height=450,
1130
- showlegend=False, # ❌ Matikan legend default Plotly
1131
- margin=dict(t=20, b=20, l=20, r=20)
1132
- )
1133
- st.plotly_chart(fig, use_container_width=True)
1134
 
1135
- # === 🔥 CUSTOM LEGEND: hanya tampilkan "Unsafe Action" & "Near Miss" sebagai garis jika <10% ===
1136
- st.markdown("#### Legend")
1137
 
1138
- # Buat container HTML untuk legend custom
1139
- legend_items = []
 
 
 
 
 
 
 
1140
 
1141
- # Selalu tampilkan kategori lain sebagai blok biasa (opsional — bisa dihapus jika hanya ingin 2 line)
1142
- # Tapi sesuai permintaan: "hanya 2 garis untuk 2 kategori tsb"
1143
- # → Jadi kita tampilkan **hanya** UA & NM jika <10%, dalam bentuk garis
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1144
 
1145
- target
1146
  # =================== 5. Matrix (Tetap Dipertahankan) ===================
1147
  st.markdown("<h3 class='section-title'>OBJECTIVE 5 - Findings vs Lead Time: Which Divisions Move Slow?</h3>", unsafe_allow_html=True)
1148
 
 
1064
  insight_text = "<div class='ai-insight'>Insufficient data for insight.</div>"
1065
  st.markdown(insight_text, unsafe_allow_html=True)
1066
 
 
 
 
 
 
 
 
 
 
 
1067
  try:
1068
  from wordcloud import WordCloud
1069
  import matplotlib.pyplot as plt
1070
  import plotly.express as px
 
1071
  WORDCLOUD_AVAILABLE = True
1072
  except ImportError:
1073
  WORDCLOUD_AVAILABLE = False
1074
 
1075
+ st.markdown("<h3 class='section-title'>OBJECTIVE 4 - What Unsafe Issues Appear Most Often?</h3>",
1076
+ unsafe_allow_html=True)
1077
+
1078
+ # 🔹 Fungsi untuk membuat judul seragam
1079
+ def create_consistent_title(title_text):
1080
+ return f"<div style='font-family: Arial; font-size: 16px; font-weight: bold; color: #2c3e50; text-align: center; margin-bottom: 8px;'>{title_text}</div>"
1081
+
1082
  if WORDCLOUD_AVAILABLE:
 
 
 
 
 
1083
 
1084
+ # 🔥 Data untuk pie chart: semua kategori
1085
+ df_all_kategori = df_local.copy()
1086
+
1087
+ # 🔥 Data untuk wordcloud: hanya Non-Positive
1088
+ df_filtered_kategori = df_local[df_local['temuan_kategori'] != 'Positive'] \
1089
+ if 'temuan_kategori' in df_local.columns else df_local
1090
+
1091
+ # 2 Kolom
1092
+ col1, col2 = st.columns(2)
1093
+
1094
+ # === PIE CHART: Semua temuan_kategori (Tanpa Legend Default, Custom Legend Khusus) ===
1095
+ with col1:
1096
  st.markdown(create_consistent_title("Distribution of All Issue Categories"), unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1097
 
1098
+ if 'temuan_kategori' in df_all_kategori.columns:
1099
+ category_counts = df_all_kategori['temuan_kategori'].value_counts()
1100
 
1101
+ if not category_counts.empty:
1102
+ # Mapping warna
1103
+ color_map = {
1104
+ 'Positive': '#2E7D32', # Hijau
1105
+ 'Unsafe Condition': '#EF5350', # Merah Muda
1106
+ 'Unsafe Action': '#F48FB1', # Pink
1107
+ 'Near Miss': '#BDBDBD' # Abu-abu
1108
+ }
1109
+ colors = [color_map.get(cat, '#9E9E9E') for cat in category_counts.index]
1110
 
1111
+ # Buat pie chart tanpa legend
1112
+ fig_pie = px.pie(
1113
+ names=category_counts.index,
1114
+ values=category_counts.values,
1115
+ color_discrete_sequence=colors
1116
+ )
1117
+ fig_pie.update_traces(
1118
+ textposition='inside',
1119
+ textinfo='percent+label',
1120
+ marker=dict(line=dict(color='#FFFFFF', width=1))
1121
+ )
1122
+ fig_pie.update_layout(
1123
+ showlegend=False, # ❌ matikan legend default
1124
+ height=450,
1125
+ margin=dict(t=20, b=20, l=40, r=40)
1126
+ )
1127
+ st.plotly_chart(fig_pie, use_container_width=True)
1128
+
1129
+ # ✅ CUSTOM LEGEND: Gabungan lingkaran + garis
1130
+ st.markdown("<div style='text-align: center; font-size: 14px; margin-top: -10px;'>", unsafe_allow_html=True)
1131
+ legend_items = []
1132
+
1133
+ for cat in category_counts.index:
1134
+ color = color_map.get(cat, '#9E9E9E')
1135
+ if cat in ['Unsafe Action', 'Near Miss']:
1136
+ # Gunakan garis horizontal kecil
1137
+ item = (
1138
+ f"<span style='display: inline-block; width: 16px; height: 4px; background-color: {color}; "
1139
+ f"margin: 0 8px; border-radius: 1px;'></span>"
1140
+ f"{cat}"
1141
+ )
1142
+ else:
1143
+ # Gunakan lingkaran kecil (default)
1144
+ item = (
1145
+ f"<span style='display: inline-block; width: 12px; height: 12px; background-color: {color}; "
1146
+ f"border-radius: 50%; margin: 0 8px;'></span>"
1147
+ f"{cat}"
1148
+ )
1149
+ legend_items.append(item)
1150
+
1151
+ # Gabungkan semua item
1152
+ legend_html = " | ".join(legend_items)
1153
+ st.markdown(f"<div>{legend_html}</div>", unsafe_allow_html=True)
1154
+ st.markdown("</div>", unsafe_allow_html=True)
1155
+
1156
+ else:
1157
+ st.warning("No data available for pie chart.")
1158
+ else:
1159
+ st.warning("Column 'temuan_kategori' not available.")
1160
+
1161
+ # === WORDCLOUD: Hanya Non-Positive (dari keyword_kategori) ===
1162
+ with col2:
1163
+ st.markdown(create_consistent_title("Unsafe Issues"), unsafe_allow_html=True)
1164
+
1165
+ if df_filtered_kategori.empty:
1166
+ st.warning("No data available after filtering out 'Positive' category.")
1167
+ else:
1168
+ if 'keyword_kategori' in df_filtered_kategori.columns:
1169
+ # Gabungkan text
1170
+ import re
1171
+ text = ' '.join(df_filtered_kategori['keyword_kategori'].dropna().astype(str))
1172
+ text = re.sub(r'[^a-zA-Z\s]', ' ', text)
1173
+
1174
+ if text.strip():
1175
+ # Buat WordCloud
1176
+ wordcloud = WordCloud(
1177
+ width=1600, # resolusi besar agar HD
1178
+ height=800,
1179
+ background_color='white',
1180
+ colormap='viridis',
1181
+ max_words=1000,
1182
+ random_state=42
1183
+ ).generate(text)
1184
+
1185
+ # Output kecil tapi tajam
1186
+ fig, ax = plt.subplots(figsize=(3, 2), dpi=200)
1187
+ ax.imshow(wordcloud, interpolation='bilinear')
1188
+ ax.axis('off')
1189
+ plt.tight_layout()
1190
+
1191
+ st.pyplot(fig, use_container_width=True)
1192
+ else:
1193
+ st.warning("No valid text remaining after cleaning.")
1194
+ else:
1195
+ st.warning("Column 'keyword_kategori' not available.")
1196
+
1197
+ else:
1198
+ st.info("WordCloud library not installed. Install `wordcloud` and `matplotlib` to enable this feature.")
1199
 
 
1200
  # =================== 5. Matrix (Tetap Dipertahankan) ===================
1201
  st.markdown("<h3 class='section-title'>OBJECTIVE 5 - Findings vs Lead Time: Which Divisions Move Slow?</h3>", unsafe_allow_html=True)
1202