IS455_FP3 / src /streamlit_app.py
litingchen's picture
Update src/streamlit_app.py
7cf54fd verified
Raw
History Blame
6.46 kB
import streamlit as st
import pandas as pd
import altair as alt
import os
# --- PAGE CONFIGURATION ---
st.set_page_config(layout="wide", page_title="IMDb Cinematic Trends")
# Enable Altair Dark Theme for visibility on black backgrounds
alt.themes.enable('dark')
# --- DATA LOADING (Cached for Speed) ---
@st.cache_data
def load_all_data():
# Using relative paths matching your Hugging Face structure
# If files are in a 'src' folder, we check there first
main_path = 'src/merged_imdb_sample.csv' if os.path.exists('src/merged_imdb_sample.csv') else 'merged_imdb_sample.csv'
ctx_path = 'src/principals_context_sample.csv' if os.path.exists('src/principals_context_sample.csv') else 'principals_context_sample.csv'
# 1. Load Primary Data
df = pd.read_csv(main_path)
df['decade'] = (df['startYear'] // 10 * 10).astype(int).astype(str) + 's'
df['genre_list'] = df['genres'].str.split(',')
df_exploded = df.explode('genre_list')
df_exploded['genre_list'] = df_exploded['genre_list'].str.strip()
# 2. Load Contextual Data
df_ctx = pd.read_csv(ctx_path)
return df_exploded, df_ctx
try:
df, df_ctx = load_all_data()
except FileNotFoundError:
st.error("⚠️ CSV files not found. Please ensure the datasets are in the 'src' folder or root directory.")
st.stop()
# --- HEADER & NAVIGATION ---
st.title("The Architects of Entertainment: Mapping Quality and Collaboration")
st.write("**Authors:** Group 6 (Le Kim Ngan Hoang)")
col_nav1, col_nav2, col_nav3 = st.columns(3)
with col_nav1:
st.link_button("📂 Primary Dataset", "https://github.com/lekimngan3010/IS455_Final_FP3_Group6/blob/main/merged_imdb_sample.csv")
with col_nav2:
st.link_button("📂 Contextual Dataset", "https://github.com/lekimngan3010/IS455_Final_FP3_Group6/blob/main/principals_context_sample.csv")
with col_nav3:
st.link_button("🐍 Python Notebook", "https://github.com/lekimngan3010/IS455_Final_FP3_Group6/blob/main/analysis.ipynb")
st.divider()
# --- NARRATIVE PARAGRAPH 1 ---
st.markdown("""
### The Evolution of Cinematic Quality
Cinema is often discussed through the lens of individual success—a high rating or a famous director.
As seen in our primary dashboard, certain decades show marked shifts in average ratings for different genres.
By exploring the trends below, we can identify 'Golden Eras' and the creators who defined them.
""")
# --- MAIN INTERACTIVE DASHBOARD (ALTAIR) ---
st.header("1. Interactive Trend Explorer")
st.info("💡 **Interaction:** Click a cell in the Heatmap to filter the Top Directors chart below.")
# 1. Define selection WITHOUT a default value (prevents the Schema Error)
# 'toggle=False' makes it so clicking outside doesn't clear the selection
selection = alt.selection_point(
fields=['genre_list', 'decade'],
name='cell',
toggle=False
)
# 2. Heatmap
heatmap = alt.Chart(df).mark_rect().encode(
x=alt.X('decade:O', title='Decade'),
y=alt.Y('genre_list:N', title='Genre'),
color=alt.Color('mean(averageRating):Q',
scale=alt.Scale(scheme='redyellowgreen'),
title='Avg Rating'),
stroke=alt.condition(selection, alt.value('white'), alt.value('transparent')),
strokeWidth=alt.condition(selection, alt.value(2), alt.value(0)),
tooltip=['genre_list', 'decade', 'mean(averageRating)']
).properties(
width=800,
height=400,
title="Average Movie Ratings by Genre and Decade"
).add_params(selection)
# 3. Bar Chart with "Fallback" Logic
bar_chart = alt.Chart(df).mark_bar().encode(
x=alt.X('total_votes:Q', title='Total Popularity (Votes)'),
y=alt.Y('directorName:N', sort='-x', title='Director'),
color=alt.value('#4682B4'),
tooltip=['directorName', 'sum(numVotes)']
).transform_filter(
# If nothing is selected, this filter now returns TRUE for everything
# OR you can keep it strict.
selection
).transform_aggregate(
total_votes='sum(numVotes)',
groupby=['directorName']
).transform_window(
rank='rank()',
sort=[alt.SortField('total_votes', order='descending')]
).transform_filter(
alt.datum.rank <= 10
).properties(
width=800,
height=300,
title="Top 10 Directors (Select a cell to view)"
)
# Render charts with standard dark-mode visibility
st.altair_chart(heatmap & bar_chart, use_container_width=True)
# --- NARRATIVE PARAGRAPH 2 ---
st.markdown("""
### Behind the Screen: Professional Infrastructure
While our dashboard focuses on ratings, the first contextual view below, **Professional Roles**, reveals
the vast workforce required to achieve these scores. For every director highlighted in our dashboard,
there is an infrastructure of writers, composers, and cinematographers. This visualization shifts the
perspective from a single 'Auteur' to a realistic view of cinema as a multifaceted professional ecosystem.
""")
# --- CONTEXTUAL CHARTS ---
st.header("2. Production Context")
ctx_col1, ctx_col2 = st.columns(2)
with ctx_col1:
role_dist = alt.Chart(df_ctx).mark_bar().encode(
x=alt.X('count():Q', title='Number of Credits'),
y=alt.Y('category:N', sort='-x', title='Role Category'),
color=alt.value('#57A44C'),
tooltip=['category', 'count()']
).properties(
title="Distribution of Professional Roles",
height=300
)
st.altair_chart(role_dist, use_container_width=True)
st.caption("Source: IMDb Principals Sample. Highlights technical vs. creative workforce balance.")
with ctx_col2:
crew_counts = df_ctx.groupby('tconst').size().reset_index(name='crew_count')
collab_density = alt.Chart(crew_counts).mark_bar().encode(
x=alt.X('crew_count:Q', bin=alt.Bin(maxbins=10), title='Key Personnel per Film'),
y=alt.Y('count():Q', title='Frequency'),
color=alt.value('#F2CF5B')
).properties(
title="Collaboration Density (Team Size)",
height=300
)
st.altair_chart(collab_density, use_container_width=True)
st.caption("Source: IMDb Principals Sample. Most successful films require 4-8 key leaders.")
# --- NARRATIVE PARAGRAPH 3 ---
st.markdown("""
### The Final Story: Complexity and Quality
Our final contextual chart, **Collaboration Density**, highlights the scale of these productions.
Most high-quality films in our sample rely on 4 to 10 'principal' personnel in leadership roles.
This suggests a strong correlation between cinematic quality and team density.
""")