File size: 11,108 Bytes
d35f894 f45cfdc d35f894 a4e3f31 d35f894 a4e3f31 d35f894 |
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 |
import streamlit as st
import pandas as pd
import numpy as np
import re
import json
import joblib
from sklearn.feature_extraction.text import TfidfVectorizer
# Impor library tambahan
import matplotlib.pyplot as plt
import seaborn as sns
from wordcloud import WordCloud
# Set judul situs web
st.set_page_config(page_title="naufalnashif-ML")
# Fungsi untuk membersihkan teks dengan ekspresi reguler
def clean_text(text):
# Tahap-1: Menghapus karakter non-ASCII
text = re.sub(r'[^\x00-\x7F]+', '', text)
# Tahap-2: Menghapus URL
text = re.sub(r'http[s]?://.[a-zA-Z0-9./_?=%&#+!]+', '', text)
text = re.sub(r'pic.twitter.com?.[a-zA-Z0-9./_?=%&#+!]+', '', text)
# Tahap-3: Menghapus mentions
text = re.sub(r'@[\w]+', '', text)
# Tahap-4: Menghapus hashtag
text = re.sub(r'#([\w]+)', '', text)
# Tahap-5: Menghapus karakter khusus (simbol)
text = re.sub(r'[!$%^&*@#()_+|~=`{}\[\]%\-:";\'<>?,./]', '', text)
# Tahap-6: Menghapus angka
text = re.sub(r'[0-9]+', '', text)
# Tahap-7: Menggabungkan spasi ganda menjadi satu spasi
text = re.sub(' +', ' ', text)
# Tahap-8: Menghapus spasi di awal dan akhir kalimat
text = text.strip()
# Tahap-9: Konversi teks ke huruf kecil
text = text.lower()
return text
# Membaca kamus kata gaul Salsabila
kamus_path = '_json_colloquial-indonesian-lexicon (1).txt' # Ganti dengan path yang benar
with open(kamus_path) as f:
data = f.read()
lookp_dict = json.loads(data)
# Dict kata gaul saya sendiri yang tidak masuk di dict Salsabila
kamus_gaul_baru = {
'kurangg': 'kurang',
'udaa': 'udah',
'mnurut': 'menurut',
'anyinh': 'anjing',
'seputat': 'seputar',
'ijo' : 'hijau',
'dmma' : 'dimana',
'anjrot' : 'anjing',
'ajgg' : 'anjing',
'keboen' : 'kebun',
'aseekk' : 'asik',
'bliau' : 'beliau',
'aseek' : 'asik',
'berpaa' : 'berapa',
'berpa' : 'berapa',
'bggtt' : 'banget',
'cntoh' : 'contoh',
'anzink' : 'anjing',
'jrg' : 'jarang',
'msi' : 'masih',
'anjirt' : 'anjing',
'kesampeian' : 'kesampaian',
'dtgnya' : 'datangnya',
'dtg' : 'datang',
'dngin' : 'dingin',
'ktub' : 'kutub',
'brngkt' : 'berangkat',
'antra' : 'antara',
'pinuh': 'penuh',
'anjink': 'anjing',
'anjir' : 'anjing',
'ajg': 'anjing',
'smpet': 'sempat',
'sempet': 'sempat',
'makai': 'memakai',
'bgst': 'bangsat',
'anjg': 'anjing',
'cpk': 'lelah',
'capek': 'lelah',
'capk': 'lelah',
'cpek': 'lelah',
'anjrit': 'anjing',
'anjig': 'anjing',
'anjigg': 'anjing',
'anjingg': 'anjing',
'bukann': 'bukan',
'skrgg': 'sekarang',
'makasihh': 'terimakasih',
'asu': 'anjing',
'moga': 'semoga',
'cok': 'jancok',
'cokk': 'jancok',
'cook': 'jancok',
'cookk': 'jancok',
'amgkot': 'angkot',
'gua' : 'aku',
'gweh': 'aku',
'guah': 'aku',
'gw': 'aku',
'gwah': 'aku',
'gue' : 'aku',
'wkwkwk' : 'wkwk',
'dah' : 'udah',
'tkt' : 'takut',
'gabisa' : 'gabisa',
'umumm' : 'umum',
'umuum' : 'umum',
'yah' : 'yah',
'drtd' : 'daritadi',
'drtdi' : 'daritadi',
'ges':'gais',
'gays': 'gais',
'geys':'gais',
'trans pakuan': 'transpakuan',
'anjr' : 'anjir',
'anjer' : 'anjing',
'njir' : 'anjing',
'anjr' : 'anjing',
'trans pakuan' : 'transpakuan',
'gblk' : 'goblok',
}
# Menambahkan dict kata gaul baru ke kamus yang sudah ada
lookp_dict.update(kamus_gaul_baru)
# Fungsi untuk normalisasi kata gaul
def normalize_slang(text, slang_dict):
words = text.split()
normalized_words = [slang_dict.get(word, word) for word in words]
return ' '.join(normalized_words)
# Fungsi untuk ekstraksi fitur TF-IDF
def extract_tfidf_features(texts, tfidf_vectorizer):
tfidf_matrix = tfidf_vectorizer.transform(texts)
return tfidf_matrix
# Memuat model TF-IDF dengan joblib (pastikan path-nya benar)
tfidf_model_path = 'X_tfidf_model.joblib'
tfidf_vectorizer = joblib.load(tfidf_model_path)
# Fungsi untuk prediksi sentimen
def predict_sentiment(text, model, tfidf_vectorizer, slang_dict):
# Tahap-1: Membersihkan dan normalisasi teks
cleaned_text = clean_text(text)
norm_slang_text = normalize_slang(cleaned_text, slang_dict)
# Tahap-2: Ekstraksi fitur TF-IDF
tfidf_matrix = tfidf_vectorizer.transform([norm_slang_text])
# Tahap-3: Lakukan prediksi sentimen
sentiment = model.predict(tfidf_matrix)
# Tahap-4: Menggantikan indeks dengan label sentimen
labels = {0: "Negatif", 1: "Netral", 2: "Positif"}
sentiment_label = labels[int(sentiment)]
return sentiment_label
# Memuat model sentimen dengan joblib (pastikan path-nya benar)
sentiment_model_path = 'ensemble_clf_soft_smote.joblib'
sentiment_model = joblib.load(sentiment_model_path)
def get_emoticon(sentiment):
if sentiment == "Positif":
emoticon = "π" # Emotikon untuk sentimen positif
elif sentiment == "Negatif":
emoticon = "π" # Emotikon untuk sentimen negatif
else:
emoticon = "π" # Emotikon untuk sentimen netral
return emoticon
# Fungsi untuk membuat tautan unduhan
def get_table_download_link(df, download_format):
if download_format == "XLSX":
df.to_excel("hasil_sentimen.xlsx", index=False)
return f'<a href="hasil_sentimen.xlsx" download="hasil_sentimen.xlsx">Unduh File XLSX</a>'
else:
csv = df.to_csv(index=False)
return f'<a href="data:file/csv;base64,{b64encode(csv.encode()).decode()}" download="hasil_sentimen.csv">Unduh File CSV</a>'
# Judul
st.title("Aplikasi ML Analisis Sentimen based on data Biskita Transpakuan")
# Pilihan input teks manual atau berkas XLSX
input_option = st.radio("Pilih metode input:", ("Teks Manual", "Unggah Berkas XLSX"))
if input_option == "Teks Manual":
# Input teks dari pengguna
user_input = st.text_area("Masukkan teks:", "")
else:
# Input berkas XLSX
uploaded_file = st.file_uploader("Unggah berkas XLSX", type=["xlsx"])
st.write("**Pastikan berkas XLSX Anda memiliki kolom yang bernama 'Text'.**")
if uploaded_file is not None:
df = pd.read_excel(uploaded_file)
if 'Text' not in df.columns:
st.warning("Berkas XLSX harus memiliki kolom bernama 'Text' untuk analisis sentimen.")
else:
texts = df['Text'] # Sesuaikan dengan nama kolom di berkas XLSX Anda
# Analisis sentimen
results = []
if input_option == "Teks Manual" and user_input:
# Pisahkan teks yang dimasukkan pengguna menjadi baris-baris terpisah
user_texts = user_input.split('\n')
for text in user_texts:
sentiment_label = predict_sentiment(text, sentiment_model, tfidf_vectorizer, lookp_dict)
emoticon = get_emoticon(sentiment_label)
cleaned_text = clean_text(text)
norm_slang_text = normalize_slang(cleaned_text, lookp_dict)
results.append((text, cleaned_text, norm_slang_text, sentiment_label, emoticon))
elif input_option == "Unggah Berkas XLSX" and uploaded_file is not None:
if 'Text' in df.columns:
for text in texts:
sentiment_label = predict_sentiment(text, sentiment_model, tfidf_vectorizer, lookp_dict)
emoticon = get_emoticon(sentiment_label)
cleaned_text = clean_text(text)
norm_slang_text = normalize_slang(cleaned_text, lookp_dict)
results.append((text, cleaned_text, norm_slang_text, sentiment_label, emoticon))
else:
st.warning("Berkas XLSX harus memiliki kolom bernama 'Text' untuk analisis sentimen.")
# Membagi tampilan menjadi dua kolom
columns = st.columns(2)
# Kolom pertama untuk Word Cloud
with columns[0]:
if results:
all_texts = [result[2] for result in results if result[2] is not None and not pd.isna(result[2])]
all_texts = " ".join(all_texts)
st.subheader("Word Cloud")
if all_texts:
wordcloud = WordCloud(width=800, height=660, background_color='white',
colormap='Purples', # Warna huruf
contour_color='black', # Warna kontur
contour_width=2, # Lebar kontur
mask=None, # Gunakan mask untuk bentuk kustom
).generate(all_texts)
st.image(wordcloud.to_array())
else:
st.write("Tidak ada data untuk ditampilkan dalam Word Cloud.")
# Kolom kedua untuk Bar Chart
with columns[1]:
st.subheader("Chart")
if results:
df_results = pd.DataFrame(results, columns=["Teks", "Cleaned Text", "Norm Text", "Hasil Analisis Sentimen", "Emotikon"])
sns.set_style("whitegrid")
# Menyiapkan label kelas
class_labels = ["Negatif", "Netral", "Positif"]
# Menghitung nilai hitungan per label
value_counts = df_results["Hasil Analisis Sentimen"].value_counts()
# Mengurutkan nilai hitungan berdasarkan label
value_counts = value_counts.reindex(class_labels)
fig, ax = plt.subplots() # Buat objek Figure
sns.barplot(x=value_counts.index, y=value_counts.values, ax=ax) # Gunakan ax= untuk plot
plt.xticks(rotation=45)
st.pyplot(fig) # Tampilkan plot menggunakan st.pyplot(fig)
# Menampilkan hasil analisis sentimen dalam kotak yang dapat diperluas
with st.expander("Hasil Analisis Sentimen"):
# Tampilkan tabel hasil analisis sentimen
st.table(pd.DataFrame(results, columns=["Teks", "Cleaned Text", "Norm Text", "Hasil Analisis Sentimen", "Emotikon"]))
# Tautan untuk mengunduh hasil dalam format XLSX atau CSV
st.subheader("Unduh Hasil")
download_format = st.selectbox("Pilih format unduhan:", ["XLSX", "CSV"])
if results:
if download_format == "XLSX":
# Simpan DataFrame ke dalam file XLSX
df = pd.DataFrame(results, columns=["Teks", "Cleaned Text", "Norm Text", "Hasil Analisis Sentimen", "Emotikon"])
df.to_excel("hasil_sentimen.xlsx", index=False)
# Tampilkan tombol unduh XLSX
st.download_button(label="Unduh XLSX", data=open("hasil_sentimen.xlsx", "rb").read(), key="xlsx_download", file_name="hasil_sentimen.xlsx")
else: # Jika CSV
# Simpan DataFrame ke dalam file CSV
df = pd.DataFrame(results, columns=["Teks", "Cleaned Text", "Norm Text", "Hasil Analisis Sentimen", "Emotikon"])
csv = df.to_csv(index=False)
# Tampilkan tombol unduh CSV
st.download_button(label="Unduh CSV", data=csv, key="csv_download", file_name="hasil_sentimen.csv")
else:
st.write("Tidak ada data untuk diunduh.")
# Garis pemisah
st.divider()
# Tautan ke GitHub
github_link = "https://github.com/naufalnashif/"
st.markdown(f"GitHub: [{github_link}]({github_link})")
# Tautan ke Instagram
instagram_link = "https://www.instagram.com/naufal.nashif/"
st.markdown(f"Instagram: [{instagram_link}]({instagram_link})")
# Pesan penutup
st.write('Thank you for trying the demo!')
st.write('Best regards, Naufal Nashif')
|