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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -90
app.py CHANGED
@@ -1066,111 +1066,83 @@ with col_3d:
1066
 
1067
 
1068
 
 
 
 
 
 
 
 
 
1069
  try:
1070
  from wordcloud import WordCloud
1071
  import matplotlib.pyplot as plt
1072
  import plotly.express as px
 
1073
  WORDCLOUD_AVAILABLE = True
1074
  except ImportError:
1075
  WORDCLOUD_AVAILABLE = False
1076
 
1077
- st.markdown("<h3 class='section-title'>OBJECTIVE 4 - What Unsafe Issues Appear Most Often?</h3>",
1078
- unsafe_allow_html=True)
1079
-
1080
- # 🔹 Fungsi untuk membuat judul seragam
1081
- def create_consistent_title(title_text):
1082
- return f"<div style='font-family: Arial; font-size: 16px; font-weight: bold; color: #2c3e50; text-align: center; margin-bottom: 8px;'>{title_text}</div>"
1083
-
1084
  if WORDCLOUD_AVAILABLE:
 
 
 
 
 
1085
 
1086
- # 🔥 Pie Chart: Semua data (tidak difilter)
1087
- df_all_kategori = df_local.copy()
1088
-
1089
- # 🔥 WordCloud: Hanya data Non-Positive
1090
- df_filtered_kategori = df_local[df_local['temuan_kategori'] != 'Positive'] \
1091
- if 'temuan_kategori' in df_local.columns else df_local
1092
-
1093
- # 2 Kolom
1094
- col1, col2 = st.columns(2)
1095
-
1096
- # === PIE CHART: Semua temuan_kategori (Warna Sesuai Kategori) ===
1097
- with col1:
1098
- # Tampilkan judul terpisah
1099
  st.markdown(create_consistent_title("Distribution of All Issue Categories"), unsafe_allow_html=True)
1100
-
1101
- if 'temuan_kategori' in df_all_kategori.columns:
1102
- # Hitung jumlah per kategori
1103
- category_counts = df_all_kategori['temuan_kategori'].value_counts()
1104
-
1105
- if not category_counts.empty:
1106
- # Buat warna sesuai kategori
1107
- colors = []
1108
- for cat in category_counts.index:
1109
- if cat == 'Positive':
1110
- colors.append('#2E7D32') # Hijau
1111
- elif cat == 'Unsafe Condition':
1112
- colors.append('#EF5350') # Merah Muda
1113
- elif cat == 'Unsafe Action':
1114
- colors.append('#F48FB1') # Pink
1115
- elif cat == 'Near Miss':
1116
- colors.append('#BDBDBD') # Abu-abu
1117
- else:
1118
- colors.append('#9E9E9E') # Default abu-abu
1119
-
1120
- # Buat pie chart tanpa judul
1121
- fig_pie = px.pie(
1122
- names=category_counts.index,
1123
- values=category_counts.values,
1124
- color_discrete_sequence=colors
1125
- )
1126
- fig_pie.update_traces(textposition='inside', textinfo='percent+label')
1127
- fig_pie.update_layout(height=450)
1128
- st.plotly_chart(fig_pie, use_container_width=True)
1129
- else:
1130
- st.warning("No data available for pie chart.")
1131
  else:
1132
- st.warning("Column 'temuan_kategori' not available.")
1133
-
1134
- # === WORDCLOUD: Hanya Non-Positive (dari keyword_kategori) ===
1135
- with col2:
1136
- # Tampilkan judul terpisah
1137
- st.markdown(create_consistent_title("Unsafe Issues"), unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1138
 
1139
- if df_filtered_kategori.empty:
1140
- st.warning("No data available after filtering out 'Positive' category.")
1141
- else:
1142
- if 'keyword_kategori' in df_filtered_kategori.columns:
1143
- # Gabungkan text
1144
- import re
1145
- text = ' '.join(df_filtered_kategori['keyword_kategori'].dropna().astype(str))
1146
- text = re.sub(r'[^a-zA-Z\s]', ' ', text)
1147
-
1148
- if text.strip():
1149
- # Buat WordCloud
1150
- wordcloud = WordCloud(
1151
- width=1600, # resolusi besar agar HD
1152
- height=800,
1153
- background_color='white',
1154
- colormap='viridis',
1155
- max_words=1000,
1156
- random_state=42
1157
- ).generate(text)
1158
-
1159
- # Output kecil tapi tajam
1160
- fig, ax = plt.subplots(figsize=(3, 2), dpi=200)
1161
- ax.imshow(wordcloud, interpolation='bilinear')
1162
- ax.axis('off')
1163
- plt.tight_layout()
1164
-
1165
- st.pyplot(fig, use_container_width=True)
1166
- else:
1167
- st.warning("No valid text remaining after cleaning.")
1168
- else:
1169
- st.warning("Column 'keyword_kategori' not available.")
1170
 
1171
- else:
1172
- st.info("WordCloud library not installed. Install `wordcloud` and `matplotlib` to enable this feature.")
 
1173
 
 
1174
  # =================== 5. Matrix (Tetap Dipertahankan) ===================
1175
  st.markdown("<h3 class='section-title'>OBJECTIVE 5 - Findings vs Lead Time: Which Divisions Move Slow?</h3>", unsafe_allow_html=True)
1176
 
 
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