spotify-clustering / src /streamlit_app.py
ESMATUGBA's picture
Update src/streamlit_app.py
61ba4b6 verified
Raw
History Blame
4.6 kB
import streamlit as st
import pandas as pd
import joblib
import matplotlib.pyplot as plt
import os
# --------------------------------------
# 🎨 PAGE CONFIG
# --------------------------------------
st.set_page_config(page_title="Spotify Clustering", layout="wide")
# --------------------------------------
# 🔧 AUTO PATH (LOCAL + CLOUD FIX)
# --------------------------------------
def get_path(filename):
base_dir = os.path.dirname(os.path.abspath(__file__))
local_path = os.path.join(base_dir, filename)
parent_path = os.path.join(base_dir, "..", filename)
if os.path.exists(local_path):
return local_path
elif os.path.exists(parent_path):
return parent_path
else:
st.error(f"{filename} bulunamadı!")
st.stop()
DATA_PATH = get_path("spotify_clustered.csv")
MODEL_PATH = get_path("kmeans_music_model.pkl")
SCALER_PATH = get_path("scaler_music.pkl")
# --------------------------------------
# 📂 LOAD DATA (CACHE)
# --------------------------------------
@st.cache_data
def load_data():
df = pd.read_csv(DATA_PATH)
unnecessary_cols = ['Unnamed: 0', 'track_id', 'album_name', 'explicit']
df_display = df.drop(columns=[c for c in unnecessary_cols if c in df.columns])
return df, df_display
@st.cache_resource
def load_model():
model = joblib.load(MODEL_PATH)
scaler = joblib.load(SCALER_PATH)
return model, scaler
df, df_display = load_data()
model, scaler = load_model()
# --------------------------------------
# 🧠 SESSION STATE (NO FLICKER)
# --------------------------------------
if "prediction" not in st.session_state:
st.session_state.prediction = None
st.session_state.samples = None
# --------------------------------------
# 🏷️ TITLE
# --------------------------------------
st.title("🎵 Spotify Music Clustering / Spotify Müzik Kümeleme")
st.markdown("---")
# --------------------------------------
# 📄 DATA PREVIEW
# --------------------------------------
st.subheader("📄 Dataset Preview / Veri Önizleme")
st.dataframe(df_display.head(10), use_container_width=True)
# --------------------------------------
# 📊 VISUALS
# --------------------------------------
col1, col2 = st.columns(2)
with col1:
st.subheader("📊 Cluster Distribution / Küme Dağılımı")
st.bar_chart(df['cluster'].value_counts(), use_container_width=True)
with col2:
st.subheader("🎯 Feature Analysis / Özellik Analizi")
fig, ax = plt.subplots(figsize=(6, 4))
scatter = ax.scatter(
df['danceability'],
df['energy'],
c=df['cluster'],
cmap='viridis',
alpha=0.6
)
ax.set_xlabel("Danceability / Dans Edilebilirlik")
ax.set_ylabel("Energy / Enerji")
plt.colorbar(scatter, ax=ax)
st.pyplot(fig, clear_figure=True)
plt.close(fig)
# --------------------------------------
# 🤖 PREDICTION
# --------------------------------------
st.divider()
st.subheader("🤖 Predict New Song Cluster / Yeni Şarkı Tahmini")
c1, c2, c3 = st.columns(3)
with c1:
pop = st.slider("Popularity / Popülerlik", 0, 100, 50)
dur = st.slider("Duration (ms) / Süre", 0, 600000, 200000)
dance = st.slider("Danceability / Dans Edilebilirlik", 0.0, 1.0, 0.5)
with c2:
energy = st.slider("Energy / Enerji", 0.0, 1.0, 0.5)
loud = st.slider("Loudness / Ses Yüksekliği", -60.0, 0.0, -10.0)
tempo = st.slider("Tempo / Tempo", 0.0, 250.0, 120.0)
with c3:
speech = st.slider("Speechiness / Konuşma Oranı", 0.0, 1.0, 0.1)
if st.button("Predict Cluster / Kümeyi Tahmin Et ✨"):
new_data = [[pop, dur, dance, energy, loud, tempo, speech]]
try:
new_data_scaled = scaler.transform(new_data)
res = model.predict(new_data_scaled)[0]
st.session_state.prediction = res
st.session_state.samples = df[df['cluster'] == res][['track_name', 'artists']].head(5)
except Exception as e:
st.error(f"Error / Hata: {e}")
# SONUÇ (STABLE)
if st.session_state.prediction is not None:
st.success(f"### Predicted Cluster / Tahmin Edilen Küme: {st.session_state.prediction}")
st.write("Similar Songs / Benzer Şarkılar:")
st.table(st.session_state.samples)
# --------------------------------------
# 🔍 CLUSTER ANALYSIS
# --------------------------------------
st.divider()
st.subheader("🔍 Cluster Characteristics / Küme Özellikleri")
numeric_only = df.select_dtypes(include=['float64', 'int64'])
if 'cluster' in df.columns:
means = numeric_only.groupby(df['cluster']).mean()
st.dataframe(means, use_container_width=True)