Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1031,6 +1031,7 @@ try:
|
|
| 1031 |
from wordcloud import WordCloud
|
| 1032 |
import matplotlib.pyplot as plt
|
| 1033 |
import plotly.express as px
|
|
|
|
| 1034 |
WORDCLOUD_AVAILABLE = True
|
| 1035 |
except ImportError:
|
| 1036 |
WORDCLOUD_AVAILABLE = False
|
|
@@ -1082,36 +1083,33 @@ if WORDCLOUD_AVAILABLE:
|
|
| 1082 |
pull_values = []
|
| 1083 |
for cat in category_counts.index:
|
| 1084 |
if cat in ['Unsafe Action', 'Near Miss']:
|
| 1085 |
-
pull_values.append(0.1)
|
| 1086 |
else:
|
| 1087 |
pull_values.append(0.0)
|
| 1088 |
|
| 1089 |
fig_pie.update_traces(
|
| 1090 |
-
textposition='outside',
|
| 1091 |
-
textinfo='percent+label',
|
| 1092 |
-
pull=pull_values,
|
| 1093 |
marker=dict(line=dict(color='#FFFFFF', width=1))
|
| 1094 |
)
|
| 1095 |
fig_pie.update_layout(
|
| 1096 |
-
showlegend=False,
|
| 1097 |
height=450,
|
| 1098 |
margin=dict(t=20, b=20, l=40, r=40)
|
| 1099 |
)
|
| 1100 |
st.plotly_chart(fig_pie, use_container_width=True)
|
| 1101 |
|
| 1102 |
-
# ✅ CUSTOM LEGEND
|
| 1103 |
st.markdown("<div style='text-align: center; font-size: 14px; margin-top: -10px;'>", unsafe_allow_html=True)
|
| 1104 |
legend_items = []
|
| 1105 |
-
|
| 1106 |
for cat in category_counts.index:
|
| 1107 |
color = color_map.get(cat, '#9E9E9E')
|
| 1108 |
item = (
|
| 1109 |
f"<span style='display: inline-block; width: 16px; height: 4px; background-color: {color}; "
|
| 1110 |
-
f"margin: 0 8px; border-radius: 1px;'></span>"
|
| 1111 |
-
f"{cat}"
|
| 1112 |
)
|
| 1113 |
legend_items.append(item)
|
| 1114 |
-
|
| 1115 |
legend_html = " | ".join(legend_items)
|
| 1116 |
st.markdown(f"<div>{legend_html}</div>", unsafe_allow_html=True)
|
| 1117 |
st.markdown("</div>", unsafe_allow_html=True)
|
|
@@ -1137,15 +1135,16 @@ if WORDCLOUD_AVAILABLE:
|
|
| 1137 |
st.warning("No data available after filtering out 'Positive' category.")
|
| 1138 |
else:
|
| 1139 |
if 'keyword_kategori' in df_filtered_kategori.columns:
|
| 1140 |
-
# Gabungkan
|
| 1141 |
import re
|
| 1142 |
-
|
| 1143 |
-
text =
|
|
|
|
| 1144 |
|
| 1145 |
-
if text
|
| 1146 |
-
#
|
| 1147 |
wordcloud = WordCloud(
|
| 1148 |
-
width=1600,
|
| 1149 |
height=800,
|
| 1150 |
background_color='white',
|
| 1151 |
colormap='viridis',
|
|
@@ -1153,13 +1152,30 @@ if WORDCLOUD_AVAILABLE:
|
|
| 1153 |
random_state=42
|
| 1154 |
).generate(text)
|
| 1155 |
|
| 1156 |
-
#
|
| 1157 |
fig, ax = plt.subplots(figsize=(3, 2), dpi=200)
|
| 1158 |
ax.imshow(wordcloud, interpolation='bilinear')
|
| 1159 |
ax.axis('off')
|
| 1160 |
plt.tight_layout()
|
| 1161 |
-
|
| 1162 |
st.pyplot(fig, use_container_width=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1163 |
else:
|
| 1164 |
st.warning("No valid text remaining after cleaning.")
|
| 1165 |
else:
|
|
|
|
| 1031 |
from wordcloud import WordCloud
|
| 1032 |
import matplotlib.pyplot as plt
|
| 1033 |
import plotly.express as px
|
| 1034 |
+
from collections import Counter
|
| 1035 |
WORDCLOUD_AVAILABLE = True
|
| 1036 |
except ImportError:
|
| 1037 |
WORDCLOUD_AVAILABLE = False
|
|
|
|
| 1083 |
pull_values = []
|
| 1084 |
for cat in category_counts.index:
|
| 1085 |
if cat in ['Unsafe Action', 'Near Miss']:
|
| 1086 |
+
pull_values.append(0.1)
|
| 1087 |
else:
|
| 1088 |
pull_values.append(0.0)
|
| 1089 |
|
| 1090 |
fig_pie.update_traces(
|
| 1091 |
+
textposition='outside',
|
| 1092 |
+
textinfo='percent+label',
|
| 1093 |
+
pull=pull_values,
|
| 1094 |
marker=dict(line=dict(color='#FFFFFF', width=1))
|
| 1095 |
)
|
| 1096 |
fig_pie.update_layout(
|
| 1097 |
+
showlegend=False,
|
| 1098 |
height=450,
|
| 1099 |
margin=dict(t=20, b=20, l=40, r=40)
|
| 1100 |
)
|
| 1101 |
st.plotly_chart(fig_pie, use_container_width=True)
|
| 1102 |
|
| 1103 |
+
# ✅ CUSTOM LEGEND
|
| 1104 |
st.markdown("<div style='text-align: center; font-size: 14px; margin-top: -10px;'>", unsafe_allow_html=True)
|
| 1105 |
legend_items = []
|
|
|
|
| 1106 |
for cat in category_counts.index:
|
| 1107 |
color = color_map.get(cat, '#9E9E9E')
|
| 1108 |
item = (
|
| 1109 |
f"<span style='display: inline-block; width: 16px; height: 4px; background-color: {color}; "
|
| 1110 |
+
f"margin: 0 8px; border-radius: 1px;'></span>{cat}"
|
|
|
|
| 1111 |
)
|
| 1112 |
legend_items.append(item)
|
|
|
|
| 1113 |
legend_html = " | ".join(legend_items)
|
| 1114 |
st.markdown(f"<div>{legend_html}</div>", unsafe_allow_html=True)
|
| 1115 |
st.markdown("</div>", unsafe_allow_html=True)
|
|
|
|
| 1135 |
st.warning("No data available after filtering out 'Positive' category.")
|
| 1136 |
else:
|
| 1137 |
if 'keyword_kategori' in df_filtered_kategori.columns:
|
| 1138 |
+
# Gabungkan & bersihkan teks
|
| 1139 |
import re
|
| 1140 |
+
text_series = df_filtered_kategori['keyword_kategori'].dropna().astype(str)
|
| 1141 |
+
text = ' '.join(text_series)
|
| 1142 |
+
text = re.sub(r'[^a-zA-Z\s]', ' ', text).strip()
|
| 1143 |
|
| 1144 |
+
if text:
|
| 1145 |
+
# Generate wordcloud
|
| 1146 |
wordcloud = WordCloud(
|
| 1147 |
+
width=1600,
|
| 1148 |
height=800,
|
| 1149 |
background_color='white',
|
| 1150 |
colormap='viridis',
|
|
|
|
| 1152 |
random_state=42
|
| 1153 |
).generate(text)
|
| 1154 |
|
| 1155 |
+
# Tampilkan
|
| 1156 |
fig, ax = plt.subplots(figsize=(3, 2), dpi=200)
|
| 1157 |
ax.imshow(wordcloud, interpolation='bilinear')
|
| 1158 |
ax.axis('off')
|
| 1159 |
plt.tight_layout()
|
|
|
|
| 1160 |
st.pyplot(fig, use_container_width=True)
|
| 1161 |
+
|
| 1162 |
+
# 🔍 🔹 Insight dinamis: top 3 keywords
|
| 1163 |
+
words_clean = [w.lower() for w in text.split() if len(w) > 2]
|
| 1164 |
+
top3 = [word.capitalize() for word, _ in Counter(words_clean).most_common(3)]
|
| 1165 |
+
if top3:
|
| 1166 |
+
insight = f"The most frequent unsafe issue themes are: <strong>{', '.join(top3)}</strong>."
|
| 1167 |
+
else:
|
| 1168 |
+
insight = "Recurring unsafe issue patterns are detectable in textual findings."
|
| 1169 |
+
|
| 1170 |
+
st.markdown(
|
| 1171 |
+
f"""
|
| 1172 |
+
<div style='text-align: center; font-size: 14px; color: #2c3e50; margin-top: 12px; line-height: 1.5;'>
|
| 1173 |
+
<strong>Insight:</strong> {insight}
|
| 1174 |
+
</div>
|
| 1175 |
+
""",
|
| 1176 |
+
unsafe_allow_html=True
|
| 1177 |
+
)
|
| 1178 |
+
|
| 1179 |
else:
|
| 1180 |
st.warning("No valid text remaining after cleaning.")
|
| 1181 |
else:
|