Spaces:
Sleeping
Sleeping
File size: 11,277 Bytes
a43b609 ae671bf 3dd7f29 e592371 903d68d ae671bf 3dd7f29 569ef62 ae671bf 3dd7f29 ae671bf 3dd7f29 f30da53 ae671bf 3dd7f29 ae671bf 3dd7f29 ae671bf 903d68d ae671bf 96de129 ae671bf ab0baa2 ae671bf ab0baa2 e7adbbd ae671bf 903d68d ae671bf 903d68d ae671bf 903d68d ae671bf 3dd7f29 ae671bf 6ad9b22 2266e51 6ad9b22 ae671bf 3dd7f29 ae671bf 903d68d ae671bf 3dd7f29 6ad9b22 ae671bf 6ad9b22 3dd7f29 ae671bf 569ef62 ae671bf 7b42b47 f30da53 ae671bf 569ef62 ae671bf 7b42b47 ae671bf 6ad9b22 3dd7f29 2266e51 ae671bf 3dd7f29 ae671bf 903d68d ae671bf d8538c2 ae671bf 569ef62 903d68d ae671bf d8538c2 ae671bf d8538c2 ae671bf 3dd7f29 ae671bf d8538c2 ae671bf 903d68d a43b609 569ef62 903d68d ae671bf 903d68d 608d3b6 2c5feef 608d3b6 2c5feef 608d3b6 2c5feef 608d3b6 2c5feef 608d3b6 2c5feef | 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 | 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
@st.cache_data
def load_all_data():
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 = df[df['startYear'] > 1900].copy()
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")
st.write("Le Kim Ngan Hoang - lkhoang2")
st.write("Karen Xiong - karenhx2")
st.write("Liting Chen - lchen235")
st.write("Kelsey Li - yitingl7")
col_nav1, col_nav2, col_nav3 = st.columns(3)
with col_nav1:
st.link_button("📂 Primary Dataset", "https://github.com/Lekimnganhoang3010/IS_445_Final-Project/blob/main/merged_imdb_sample.csv")
with col_nav2:
st.link_button("📂 Contextual Dataset", "https://github.com/Lekimnganhoang3010/IS_445_Final-Project/blob/main/principals_context_sample.csv")
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.
Each square in the heatmap's grid corresponds to a specific genre during a specific decade, with its color correlating
to the average ratings of movies under that genre during that decade (the color scale is denoted to the right of the
heatmap). Uncolored squares indicate a lack of information from our original dataset (i.e., no movies were found to
be under that genre during that decade). Upon clicking a given colored cell, the graph displaying the top 10 directors
(in terms of total votes received) for that specific genre-decade combination is appropriately updated. Clicking the
aforementioned dark cells results in a chart displaying the overall top 10 directors across all of the studied movies.
This can be useful in providing recommendations to users, both for those who are interested in specific genres and/or
decades of movies and those who are generally looking for highly rated types of movies. Furthermore, information about
the directors is important in terms of informing users about which director's movies are most well-rated if they have a
favorite genre and/or decade of movies. This dashboard is extremely informative, providing an overview of the most well-rated
genres and decades, along with the top directors for them, and how those ratings have changed over time.
""")
# Main Interactive Dashboard with Altair
st.header("1. Interactive Trend Explorer")
st.info("💡 **Interaction:** Click a cell in the Heatmap to filter the Top Directors chart below.")
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', axis=alt.Axis(labelLimit=200)),
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
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', axis=alt.Axis(labelLimit=200)),
color=alt.value('#4682B4'),
tooltip=['directorName', alt.Tooltip('total_votes:Q', format=',')]
).transform_filter(
selection # Ensure 'selection' is defined above this block!
).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.
This contextual visualization examines how different movie credit roles are positioned in the IMDb
principal dataset. In this dataset, each row represents a person connected to a movie, such as an actor,
actress, director, writer, or producer. The ordering column shows the order in which that person appears in
the movie’s principal credits. A smaller number means that the person appears earlier in the credits, so
this chart focuses on the first few credit positions to understand which roles are usually given the most
visibility. This visualization is useful because it gives background context for the main movie dataset.
The main dataset focuses on movie-level information, such as title, genre, runtime, year, average rating,
and number of votes. However, movies are not only defined by their ratings or genres - they are also shaped
by the people involved in creating them. By looking at the credit order, readers can better understand
which types of contributors are most visible in IMDb’s movie records. For example, if actors and actresses
appear most often in the earliest credit positions, this suggests that on-screen performers are usually
emphasized more strongly than "behind the scenes" roles. While the main dataset focuses on movie ratings,
genres, and runtimes, this contextual visualization adds background about the people behind those movies.
It suggests that movie records are not only about the films themselves, but also about how different
contributors, such as actors, actresses, directors, and writers, are presented to the public.
""")
# 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', axis=alt.Axis(labelLimit=200)),
color=alt.value('#57A44C'),
tooltip=['category', 'count()']
).properties(
title="Distribution of Professional Roles",
height=400
)
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=400
)
st.altair_chart(collab_density, use_container_width=True)
st.caption("Source: IMDb Principals Sample. Most successful films require 10-25 key leaders.")
# Narrative Paragraph
st.markdown("""
### The Final Story: Complexity and Quality
Our final contextual chart, **Collaboration Density**, highlights the scale of these productions.
This chart portrays the frequency of the different numbers of key staff members working on each
film that was observed from our dataset, with higher bars corresponding to greater frequency (i.e.,
more movies with that particular number of personnel). Most high-quality films in our sample rely on
10 to 25 principal personnel in leadership roles, with the highest peak at 15 to 20 personnel.
Additionally, we do not observe more than 35 personnel working on any of the films from our original
dataset, indicating that this is a general threshold in terms of trends in film staff size.
These observations suggest a strong correlation between cinematic quality and team density, providing further
context for our primary dashboard showcasing the movies' average ratings.
""")
st.divider()
st.markdown("""
### Citation
#### Original Dataset
The name of the dataset is “merged_imdb_sample”. This aggregated dataset is created using IMDb Non-Commercial Datasets: https://datasets.imdbws.com/
Given that the original datasets are computationally expensive and exceed typical project and GitHub storage limits, a sampling and preprocessing strategy was applied:
- A subset of approximately 1021 movie records was randomly sampled from the primary table (**title.basics**) after filtering for valid (non-null) entries.
- Related tables (**title.ratings, title.crew, and name.basics**) were then filtered using matching keys (tconst, nconst) to ensure relational consistency.
- Only relevant columns (e.g., title, year, genre, rating, votes, director name) were retained to reduce dimensionality.
- Missing values were selectively handled to preserve as much usable data as possible without significantly reducing the dataset size.
#### Contextual dataset
To add further depth to the story of how certain genres and directors rose to prominence, I have identified the following contextual dataset:
- **Dataset Name**: IMDb Title Principals
- **Link**: https://datasets.imdbws.com/
- **Contextual Utility**:
While the current dashboard focuses on directors, the title.principals dataset provides data on the entire "creative team," including lead actors, writers, and cinematographers.
This would allow us to investigate if the high ratings in specific genres (like Sci-Fi or Noir) were driven by specific recurring collaborations or technical shifts in cinematography.""")
|