
Distribution plots are statistical visualizations that reveal how values in a dataset are spread across their range, helping identify patterns, outliers, and underlying data structures. In this article, we will explore different types of distribution plots using Altair. Using movie industry data from the vega_datasets package, we will demonstrate how various visualization techniques can uncover insights about movie ratings, runtimes, and financial performance.
Setting Up Our Environment
Before we begin, ensure you have the required packages installed. If you need assistance with importing all the necessary libraries and creating a separate environment for Altair, please take a look at this post or the official documentation.
import altair as alt from vega_datasets import data import pandas as pd # Load the movies dataset movies = data.movies()
Basic Histogram: Understanding IMDB Ratings
Let’s start with a fundamental distribution plot – a histogram showing how IMDB ratings are distributed across movies:
# Basic Histogram of IMDB Ratings
basic_histogram = alt.Chart(movies).mark_bar().encode(
x=alt.X('IMDB_Rating:Q',
bin=alt.Bin(maxbins=30),
title='IMDB Rating'),
y=alt.Y('count()',
title='Number of Movies'),
tooltip=[
alt.Tooltip('count()', title='Number of Movies'),
alt.Tooltip('IMDB_Rating:Q', title='Rating', bin=True)
]
).properties(
width=700,
height=300,
title={
"text": "Distribution of IMDB Ratings",
"subtitle": "Histogram showing the spread of movie ratings"
}
)
basic_histogram

Histogram showing distribution of IMDB movie ratings from 1.0 to 9.5. Peak frequency occurs around 6.5-7.0 rating, with a roughly normal distribution | Image by Author
Key features of the visualization:
- mark_bar(): Creates the histogram bars
- bin=alt.Bin(maxbins=30): Controls the granularity of the rating groups
- Interactive tooltips showing the count and rating range for each bar
- Clear title and axis labels for easy interpretation
Box Plots: Comparing Ratings Across Genres
To understand how movie ratings vary across different genres, we’ll create box plots that show the distribution of IMDB ratings for each genre:
# Box Plot of IMDB Ratings by Genre
genre_boxplot = alt.Chart(movies[movies['Major_Genre'].notna()]).mark_boxplot(
extent='min-max',
size=50
).encode(
x=alt.X('Major_Genre:N',
title='Genre',
axis=alt.Axis(
labelAngle=-45,
labelFontSize=12
)),
y=alt.Y('IMDB_Rating:Q',
title='IMDB Rating',
scale=alt.Scale(zero=False)),
color=alt.Color('Major_Genre:N',
legend=None),
tooltip=[
alt.Tooltip('Major_Genre:N', title='Genre'),
alt.Tooltip('IMDB_Rating:Q', title='Rating', aggregate='median'),
alt.Tooltip('count()', title='Number of Movies')
]
).properties(
width=700,
height=400,
title={
"text": "IMDB Ratings Distribution by Genre",
"subtitle": "Box plots showing rating patterns across different genres"
}
)
genre_boxplot

Box plot showing IMDB ratings distribution across movie genres. Documentaries and Black Comedy genres have highest median ratings while Horror shows lowest median | Image by Author
Key features of the visualization:
- mark_boxplot(): Creates the standard box plot elements
- Angled labels for better readability
- Color coding to distinguish genres
- Interactive tooltips showing summary statistics
Violin Plots: Runtime Patterns by MPAA Rating
To explore how movie lengths vary across different MPAA ratings, we’ll use violin plots. These combine aspects of box plots with density distributions, showing both the central tendency and the shape of the runtime distribution:
# Violin Plot of Runtime by MPAA Rating (excluding NC-17)
violin_plot = alt.Chart(
movies[
(movies['MPAA_Rating'].notna()) &
(movies['Running_Time_min'].notna()) &
(movies['MPAA_Rating'] != 'NC-17') # Exclude NC-17
]
).transform_density(
'Running_Time_min',
as_=['Running_Time_min', 'density'],
groupby=['MPAA_Rating']
).mark_area(
orient='horizontal',
opacity=0.7
).encode(
y=alt.Y('Running_Time_min:Q',
title='Runtime (minutes)',
scale=alt.Scale(zero=False)),
x=alt.X('density:Q',
stack='center',
title=None,
axis=None),
color=alt.Color('MPAA_Rating:N',
title='MPAA Rating'),
column=alt.Column('MPAA_Rating:N',
header=alt.Header(
titleOrient='bottom',
labelFontSize=12,
titleFontSize=14
)),
tooltip=[
alt.Tooltip('MPAA_Rating:N', title='Rating'),
alt.Tooltip('Running_Time_min:Q', title='Runtime')
]
).properties(
width=100,
height=300,
title={
"text": "Movie Runtime Distribution by MPAA Rating",
"subtitle": "Violin plots showing runtime patterns for different ratings"
}
)
violin_plot

Violin plot displaying movie runtime distributions across MPAA ratings (G, Not Rated, PG, PG-13, R). R-rated movies show widest runtime variation | Image by Author
Key features of the visualization:
- transform_density(): Creates the violin plot shape
- mark_area(): Fills the density curves
- Horizontal orientation for better readability
- Faceted layout using column
- Interactive tooltips for exploring specific values
Combining Distributions and Financial Performance
For our final visualization, let’s explore the relationship between movie budgets and box office success across different genres. This layered visualization combines box plots showing budget distributions with individual movie performance:
# Advanced Layered Plot - Budget and Box Office Success
# Prepare data by removing missing values
layered_data = movies[
movies['Major_Genre'].notna() &
movies['Production_Budget'].notna() &
movies['Worldwide_Gross'].notna() &
movies['Rotten_Tomatoes_Rating'].notna()
]
# Layered Plot focusing on budget and success
layered_plot = alt.Chart(layered_data).mark_boxplot(
size=40,
opacity=0.3
).encode(
x=alt.X('Major_Genre:N',
title='Genre',
axis=alt.Axis(
labelAngle=-45,
labelFontSize=12
)),
y=alt.Y('Production_Budget:Q',
title='Production Budget ($)',
scale=alt.Scale(type='log')),
color=alt.Color('Major_Genre:N',
legend=None)
) + alt.Chart(layered_data).mark_circle(
opacity=0.6
).encode(
x=alt.X('Major_Genre:N'),
y=alt.Y('Production_Budget:Q'),
size=alt.Size('Worldwide_Gross:Q',
title='Worldwide Gross',
scale=alt.Scale(range=[100, 1000])),
tooltip=[
alt.Tooltip('Title:N', title='Movie'),
alt.Tooltip('Production_Budget:Q', title='Budget', format='$,.0f'),
alt.Tooltip('Worldwide_Gross:Q', title='Gross', format='$,.0f')
]
).properties(
width=700,
height=400,
title={
"text": "Movie Budgets and Box Office Success by Genre",
"subtitle": "Box plots showing budget distributions with point size indicating worldwide gross",
"fontSize": 16
}
)
layered_plot

Box plot visualization showing movie production budgets vs genres, with point sizes indicating worldwide gross earnings. Action and Adventure genres show highest budgets and earnings spread | Image by Author
Key features of the visualization:
- Budget Distributions:
- Box plots show the typical budget ranges for each genre
- Action and Adventure films consistently have higher budgets
- Documentary films operate with lower budgets
- Financial Success:
- Circle size represents worldwide gross, showing blockbusters and smaller successes
- Some genres (like Action) show consistent high returns
- Other genres show occasional breakout successes despite lower budgets
- Technical Features:
- Logarithmic scale for handling wide budget ranges
- Combined box plots and scatter plots for rich insight
- Interactive tooltips showing detailed movie information
- Angled labels for better readability
Conclusion
Distribution plots are great for understanding patterns in your data. Through our analysis of the movie industry, we’ve seen how different types of distributions can reveal various insights:
- Histograms showed us the overall spread of IMDB ratings
- Box plots revealed how ratings vary across genres
- Violin plots demonstrated runtime patterns for different MPAA ratings
- Layered plots combined distributions with individual data points to show complex relationships
When choosing a distribution plot type, consider:
- The story you want to tell with your data
- The number of variables you’re analyzing
- The importance of showing outliers versus central tendencies
- The need to compare across categories
Each type of visualization serves different analytical purposes, and combining them can provide rich insights into your data.

What caught my attention was how you managed to make such a complex topic so accessible. Your writing style is engaging and the flow of information is perfect. Great job!
Dear Wava McKenzie:
Thank you very much for your kind comments. I am extremely happy to hear that you found this post to be helpful. We have few more posts on Altair lined up and I hope you enjoy them as well.
Best regards,
Vinod