| import streamlit as st |
| import pandas as pd |
| import joblib |
| import plotly.express as px |
|
|
| |
| |
| |
| DATA_PATH = "spotify_clustered.csv" |
| MODEL_PATH = "kmeans_music_model.pkl" |
| SCALER_PATH = "scaler_music.pkl" |
|
|
| @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_data |
| def load_model_scaler(): |
| model = joblib.load(MODEL_PATH) |
| scaler = joblib.load(SCALER_PATH) |
| return model, scaler |
|
|
| df, df_display = load_data() |
| model, scaler = load_model_scaler() |
|
|
| |
| |
| |
| st.set_page_config(page_title="Spotify Clusters", layout="wide") |
| st.title("🎵 Spotify Music Clustering / Spotify Müzik Kümeleme") |
| st.markdown("---") |
|
|
| |
| |
| |
| st.subheader("📄 Dataset Preview / Veri Önizleme") |
| st.dataframe(df_display.head(10), use_container_width=True) |
|
|
| |
| |
| |
| st.subheader("🎯 Feature Analysis / Özellik Analizi") |
| fig = px.scatter( |
| df, |
| x='danceability', |
| y='energy', |
| color='cluster', |
| labels={'danceability': 'Danceability / Dans Edilebilirlik', |
| 'energy': 'Energy / Enerji', |
| 'cluster': 'Cluster / Küme'}, |
| opacity=0.6 |
| ) |
| st.plotly_chart(fig, use_container_width=True) |
|
|
| |
| |
| |
| st.divider() |
| st.subheader("🤖 Predict New Song Cluster / Yeni Şarkı Tahmini") |
| c1, c2, c3 = st.columns(3) |
| with c1: |
| pop = st.slider("Popularity", 0, 100, 50) |
| dur = st.slider("Duration (ms)", 0, 600000, 200000) |
| dance = st.slider("Danceability", 0.0, 1.0, 0.5) |
| with c2: |
| energy = st.slider("Energy", 0.0, 1.0, 0.5) |
| loud = st.slider("Loudness", -60.0, 0.0, -10.0) |
| tempo = st.slider("Tempo", 0.0, 250.0, 120.0) |
| with c3: |
| speech = st.slider("Speechiness", 0.0, 1.0, 0.1) |
|
|
| if st.button("Predict Cluster"): |
| new_data = [[pop, dur, dance, energy, loud, tempo, speech]] |
| new_data_scaled = scaler.transform(new_data) |
| res = model.predict(new_data_scaled)[0] |
| st.success(f"Predicted Cluster: {res}") |
| st.write(df[df['cluster']==res][['track_name','artists']].head(5)) |
|
|
| |
| |
| |
| st.divider() |
| st.subheader("Cluster Characteristics / Küme Ortalamaları") |
| numeric_only = df.select_dtypes(include=['float64','int64']) |
| means = numeric_only.groupby(df['cluster']).mean() |
| st.dataframe(means, use_container_width=True) |