naufalnashif's picture
Update app.py
f45cfdc
raw
history blame
No virus
11.1 kB
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')