This tutorial is an executable Jupyter notebook. Click the Open in Colab button at the top of this page to execute the code.
Jupyter Notebooks: This notebook is made of cells. Each cell can contain code written in Python or explanations in plain English. You can execute code cells and view the results instantly within the notebook. Jupyter is a powerful platform for experimentation and analysis. Don't be afraid to mess around with the code & break things - you'll learn a lot by encountering and fixing errors. You can use the "Kernel > Restart & Clear Output" menu option to clear all outputs and start again from the top.
Introduction
Data visualization is the graphic representation of data. It involves producing images that communicate relationships among the represented data to viewers. Visualizing data is an essential part of data analysis and machine learning. In this tutorial, we'll use Python libraries Matplotlib and Seaborn to learn and apply some popular data visualization techniques.
To begin let's import the libraries. We'll use the matplotlib.pyplot for basic plots like line & bar charts. It is often imported with the alias plt. The seaborn module will be used for more advanced plots, and it is imported with the alias sns.
# Uncomment the next line to install the required libraries
# !pip install matplotlib seaborn --upgrade --quietimport matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inlineNotice this we also include the special command %matplotlib inline to ensure that plots are shown and embedded within the Jupyter notebook itself. Without this command, sometimes plots may show up in pop-up windows.
Line Chart
Line charts are one of the simplest and most widely used data visualization techniques. A line chart displays information as a series of data points or markers, connected by straight lines. You can customize the shape, size, color and other aesthetic elements of the markers and lines for better visual clarity.
Here's a Python list showing the yield of apples (tons per hectare) over 6 years in an imaginary country called Kanto.
yield_apples = [0.895, 0.91, 0.919, 0.926, 0.929, 0.931]We can visualize how the yield of apples changes over time using a line chart. To draw a line chart, we can use the plt.plot function.
plt.plot(yield_apples)[<matplotlib.lines.Line2D at 0x7f2b9da87110>]Calling the plt.plot function draws the line chart as expected, and also returns a list of plots drawn [<matplotlib.lines.Line2D at 0x7ff70aa20760>] shown within the output. We can include a semicolon (;) at the end of the last statement in the cell to avoiding showing the output and just display the graph.
plt.plot(yield_apples);Let's enhance this plot step-by-step to make it more informative and beautiful.
Customizing the X-axis
The X-axis of the plot currently shows list element indexes 0 to 5. The plot would be more informative if we could show the year for which the data is being plotted. We can do this by two arguments plt.plot.
years = [2010, 2011, 2012, 2013, 2014, 2015]
yield_apples = [0.895, 0.91, 0.919, 0.926, 0.929, 0.931]plt.plot(years, yield_apples)[<matplotlib.lines.Line2D at 0x7f2b9b76f890>]Axis Labels
We can add labels to the axes to show what each axis represents using the plt.xlabel and plt.ylabel methods.
plt.plot(years, yield_apples)
plt.xlabel('Year')
plt.ylabel('Yield (tons per hectare)');Plotting Multiple Lines
It's really easy to plot multiple lines in the same graph. Just invoke the plt.plot function multiple times. Let's compare the yields of apples vs. oranges in Kanto.
years = range(2000, 2012)
apples = [0.895, 0.91, 0.919, 0.926, 0.929, 0.931, 0.934, 0.936, 0.937, 0.9375, 0.9372, 0.939]
oranges = [0.962, 0.941, 0.930, 0.923, 0.918, 0.908, 0.907, 0.904, 0.901, 0.898, 0.9, 0.896, ]plt.plot(years, apples)
plt.plot(years, oranges)
plt.xlabel('Year')
plt.ylabel('Yield (tons per hectare)');Chart Title and Legend
To differentiate between multiple lines, we can include a legend within the graph using the plt.legend function. We also give the entire chart a title using the plt.title function.
plt.plot(years, apples)
plt.plot(years, oranges)
plt.xlabel('Year')
plt.ylabel('Yield (tons per hectare)')
plt.title("Crop Yields in Kanto")
plt.legend(['Apples', 'Oranges']);Line Markers
We can also show markers for the data points on each line using the marker argument of plt.plot. Matplotlib supports many different types of markers like circle, cross, square, diamond etc. You can find the full list of marker types here: https://matplotlib.org/3.1.1/api/markers_api.html
plt.plot(years, apples, marker='o')
plt.plot(years, oranges, marker='x')
plt.xlabel('Year')
plt.ylabel('Yield (tons per hectare)')
plt.title("Crop Yields in Kanto")
plt.legend(['Apples', 'Oranges']);Styling lines and markers
The plt.plot function supports many arguments for styling lines and markers:
colororc: set the color of the line (supported colors)linestyleorls: choose between a solid or dashed linelinewidthorlw: set the width of a linemarkersizeorms: set the size of markersmarkeredgecolorormec: set the edge color for markersmarkeredgewidthormew: set the edge width for markersmarkerfacecolorormfc: set the fill color for markersalpha: opacity of the plot
Check out the documentation for plt.plot to learn more: https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html#matplotlib.pyplot.plot
plt.plot(years, apples, marker='s', c='b', ls='-', lw=2, ms=8, mew=2, mec='navy')
plt.plot(years, oranges, marker='o', c='r', ls='--', lw=3, ms=10, alpha=.5)
plt.xlabel('Year')
plt.ylabel('Yield (tons per hectare)')
plt.title("Crop Yields in Kanto")
plt.legend(['Apples', 'Oranges']);The fmt argument provides a shorthand for specifying the line style, marker and line color. It can be provided as the third argument to plt.plot.
fmt = '[marker][line][color]'
plt.plot(years, apples, 's-b')
plt.plot(years, oranges, 'o--r')
plt.xlabel('Year')
plt.ylabel('Yield (tons per hectare)')
plt.title("Crop Yields in Kanto")
plt.legend(['Apples', 'Oranges']);If no line style is specified in fmt, only markers are drawn.
plt.plot(years, oranges, 'or')
plt.title("Yield of Oranges (tons per hectare)");Changing the Figure Size
You can use the plt.figure function to change the size of the figure.
plt.figure(figsize=(12, 6))
plt.plot(years, oranges, 'or')
plt.title("Yield of Oranges (tons per hectare)");Improving Default Styles using Seaborn
An easy way to make your charts look beautiful is to use some default styles provided in the Seaborn library. These can be applied globally using the sns.set_style function. You can see a full list of predefined styles here: https://seaborn.pydata.org/generated/seaborn.set_style.html
sns.set_style("whitegrid")plt.plot(years, apples, 's-b')
plt.plot(years, oranges, 'o--r')
plt.xlabel('Year')
plt.ylabel('Yield (tons per hectare)')
plt.title("Crop Yields in Kanto")
plt.legend(['Apples', 'Oranges']);sns.set_style("darkgrid")plt.plot(years, apples, 's-b')
plt.plot(years, oranges, 'o--r')
plt.xlabel('Year')
plt.ylabel('Yield (tons per hectare)')
plt.title("Crop Yields in Kanto")
plt.legend(['Apples', 'Oranges']);plt.plot(years, oranges, 'or')
plt.title("Yield of Oranges (tons per hectare)");You can also edit default styles directly by modifying the matplotlib.rcParams dictionary. Learn more: https://matplotlib.org/3.2.1/tutorials/introductory/customizing.html#matplotlib-rcparams
import matplotlibmatplotlib.rcParams['font.size'] = 14
matplotlib.rcParams['figure.figsize'] = (9, 5)
matplotlib.rcParams['figure.facecolor'] = '#00000000' Scatter Plot
In a scatter plot, the values of 2 variables are plotted as points on a 2-dimensional grid. Additionally, you can also use a third variable to determine the size or color of the points. Let's try out an example.
The Iris flower dataset provides samples measurements of sepals and petals for 3 species of flowers. The Iris dataset is included with the Seaborn library, and can be loaded as a Pandas data frame.
# Load data into a Pandas dataframe
flowers_df = sns.load_dataset("iris")flowers_dfflowers_df.species.unique()array(['setosa', 'versicolor', 'virginica'], dtype=object)data = flowers_dfLet's try to visualize the relationship between sepal length and sepal width. Our first instinct might be to create a line chart using plt.plot. However, the output is not very informative as there are too many combinations of the two properties within the dataset, and there doesn't seem to be simple relationship between them.
plt.plot(data.sepal_length, data.sepal_width);We can use a scatter plot to visualize how sepal length & sepal width vary using the scatterplot function from seaborn (imported as sns).
sns.scatterplot(data=data, x="sepal_length", y="sepal_width");Adding Hues
Notice how the points in the above plot seem to form distinct clusters with some outliers. We can color the dots using the flower species as a hue. We can also make the points larger using the s argument.
sns.scatterplot(
data=data,
x="sepal_length",
y="sepal_width",
hue="species",
s=100,
);Adding hues makes the plot more informative. We can immediately tell that flowers of the Setosa species have a smaller sepal length but higher sepal widths, while the opposite holds true for the Virginica species.
Customizing Seaborn Figures
Since Seaborn uses Matplotlib's plotting functions internally, we can use functions like plt.figure and plt.title to modify the figure.
plt.figure(figsize=(12, 6))
plt.title('Sepal Dimensions')
sns.scatterplot(
data=data,
x="sepal_length",
y="sepal_width",
hue="species",
s=100,
);Plotting using Pandas Data Frames
Seaborn has in-built support for Pandas data frames. Instead of passing each column as a series, you can also pass column names and use the data argument to pass the data frame.
plt.title('Sepal Dimensions')
sns.scatterplot(
data=flowers_df,
x="sepal_length",
y="sepal_width",
hue="species",
s=100,
);Histogram
A histogram represents the distribution of data by forming bins along the range of the data and then drawing bars to show the number of observations that fall in each bin.
As an example, let's visualize the how the values of sepal width in the flowers dataset are distributed. We can use the plt.hist function to create a histogram.
# Load data into a Pandas dataframe
flowers_df = sns.load_dataset("iris")flowers_df.sepal_width0 3.5
1 3.0
2 3.2
3 3.1
4 3.6
...
145 3.0
146 2.5
147 3.0
148 3.4
149 3.0
Name: sepal_width, Length: 150, dtype: float64plt.title("Distribution of Sepal Width")
plt.hist(flowers_df.sepal_width);We can immediately see that values of sepal width fall in the range 2.0 - 4.5, and around 35 values are in the range 2.9 - 3.1, which seems to be the largest bin.
Controlling the size and number of bins
We can control the number of bins, or the size of each bin using the bins argument.
# Specifying the number of bins
plt.hist(flowers_df.sepal_width, bins=5);import numpy as np
# Specifying the boundaries of each bin
plt.hist(flowers_df.sepal_width, bins=np.arange(2, 5, 0.25));# Bins of unequal sizes
plt.hist(flowers_df.sepal_width, bins=[1, 3, 4, 4.5]);Multiple Histograms
Similar to line charts, we can draw multiple histograms in a single chart. We can reduce the opacity of each histogram, so the the bars of one histogram don't hide the bars for others.
Let's draw separate histograms for each species of flowers.
setosa_df = flowers_df[flowers_df.species == 'setosa']
versicolor_df = flowers_df[flowers_df.species == 'versicolor']
virginica_df = flowers_df[flowers_df.species == 'virginica']plt.hist(setosa_df.sepal_width, alpha=0.4, bins=np.arange(2, 5, 0.25));
plt.hist(versicolor_df.sepal_width, alpha=0.4, bins=np.arange(2, 5, 0.25));We can also stack multiple histograms on top of one another.
plt.title('Distribution of Sepal Width')
plt.hist([setosa_df.sepal_width, versicolor_df.sepal_width, virginica_df.sepal_width],
bins=np.arange(2, 5, 0.25),
stacked=True);
plt.legend(['Setosa', 'Versicolor', 'Virginica']);Bar Chart
Bar charts are quite similar to line charts i.e. they show a sequence of values, however a bar is shown for each value, rather than points connected by lines. We can use the plt.bar function to draw a bar chart.
years = range(2000, 2006)
apples = [0.35, 0.6, 0.9, 0.8, 0.65, 0.8]
oranges = [0.4, 0.8, 0.9, 0.7, 0.6, 0.8]plt.bar(years, oranges);Like histograms, bars can also be stacked on top of one another. We use the bottom argument to plt.bar to achieve this.
plt.bar(years, apples)
plt.bar(years, oranges, bottom=apples);Bar Plots with Averages
Let's look at another sample dataset included with Seaborn, called "tips". The dataset contains information about the sex, time of day, total bill and tip amount for customers visiting a restaurant over a week.
tips_df = sns.load_dataset("tips");tips_dfWe might want to draw a bar chart to visualize how the average bill amount varies across different days of the week. One way to do this would be to compute the day-wise averages and then use plt.bar (try it as an exercise).
However, since this is a very common use case, the Seaborn library provides a barplot function which can automatically compute averages.
sns.barplot(data=tips_df, x="day", y="total_bill");The lines cutting each bar represent the amount of variation in the values. For instance, it seems like the variation in the total bill was quite high on Fridays, and lower on Saturday.
We can also specify a hue argument to compare bar plots side-by-side based on a third feature e.g. sex.
sns.barplot(data=tips_df, x="day", y="total_bill", hue="sex"); 
Data Visualization
Data visualization is the graphic representation of data. It involves producing images that communicate relationships among the represented data to viewers. Visualizing data is an esstential part of data analysis and machine learning, but choosing the right type of visualization is often challenging. This guide provides an introduction to popluar data visualization techniques, by presenting sample use cases and providing code examples using Python.
Types of graphs covered:
- Line graph
- Scatter plot
- Histogram and Frequency Distribution
- Heatmap
- Contour Plot
- Box Plot
- Bar Chart
Import libraries
- Matplotlib: Plotting and visualization library for Python. We'll use the
pyplotmodule frommatplotlib. As convention, it is often imported asplt. - Seaborn: An easy-to-use visualizetion library that builds on top of Matplotlib and lets you create beautiful charts with just a few lines of code.
# Uncomment the next line to install the required libraries
# !pip install matplotlib seaborn --upgrade --quiet# Import libraries
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns# Configuring styles
sns.set_style("darkgrid")
matplotlib.rcParams['font.size'] = 14
matplotlib.rcParams['figure.figsize'] = (9, 5)
matplotlib.rcParams['figure.facecolor'] = '#00000000'A line chart displays information as a series of data points or markers, connected by a straight lines. You can customize the shape, size, color and other aesthetic elements of the markers and lines for better visual clarity.
Example
We'll create a line chart to compare the yields of apples and oranges over 12 years in the imaginary region of Hoenn.
# Sample data
years = range(2000, 2012)
apples = [0.895, 0.91, 0.919, 0.926, 0.929, 0.931, 0.934, 0.936, 0.937, 0.9375, 0.9372, 0.939]
oranges = [0.962, 0.941, 0.930, 0.923, 0.918, 0.908, 0.907, 0.904, 0.901, 0.898, 0.9, 0.896, ]
# First line
plt.plot(years, apples, 'b-x', linewidth=4, markersize=12, markeredgewidth=4, markeredgecolor='navy')
# Second line
plt.plot(years, oranges, 'r--o', linewidth=4, markersize=12,);
# Title
plt.title('Crop Yields in Hoenn Region')
# Line labels
plt.legend(['Apples', 'Oranges'])
# Axis labels
plt.xlabel('Year'); plt.ylabel('Yield (tons)');Scatter Plot
In a scatter plot, the values of 2 variables are plotted as points on a 2-dimensional grid. Additonally, you can also use a third variable to determine the size or color of the points.
Example
The Iris flower dataset provides samples measurements of sepals and petals for 3 species of flowers. The Iris dataset is included with the seaborn library, and can be loaded as a pandas dataframe.
# Load data into a Pandas dataframe
data = sns.load_dataset("iris")
# View the data
data.sample(5)We can use a scatter plot to visualize sepal length & sepal witdh vary across different species of flowers. The points for each species form a separate cluster, with some overlap between the Versicolor and Virginica species.
# Create a scatter plot
sns.scatterplot(
data=data,
x="sepal_length",
y="sepal_width",
hue="species",
s=100
)
plt.title("Flowers")Text(0.5, 1.0, 'Flowers')Histogram and Frequency Distribution
A histogram represents the distribution of data by forming bins along the range of the data and then drawing bars to show the number of observations that fall in each bin.
Example
We can use a histogram to visualize how the values of sepal width are distributed.
plt.title("Distribution of Sepal Width")
sns.histplot(data.sepal_width, kde=False);We can immediately see that values of sepal width fall in the range 2.0 - 4.5, and around 35 values are in the range 2.9 - 3.1. We can also look at this data as a frequency distribution, where the values on Y-axis are percentagess instead of counts.
plt.title("Distribution of Sepal Width")
sns.histplot(data.sepal_width, kde=True);# Load the example flights dataset as a matrix
flights = sns.load_dataset("flights").pivot(
index="month",
columns="year",
values="passengers"
)
# Chart Title
plt.title("No. of Passengers (1000s)")
# Draw a heatmap with the numeric values in each cell
sns.heatmap(flights,
fmt="d",
annot=True,
linewidths=.5,
cmap='Blues',
annot_kws={"fontsize":13});Contour Plot
Contour plot uses contours or color-coded regions helps us to visualize 3 numerical variables in two dimensions. One variable is represented on the horizontal axis and a second variable is represented on the vertical axis. The third variable is represented by a color gradient and isolines (lines of constant value).
Example
We can visulize the values of sepal width & sepal length from the flowers dataset using a contour plot. The shade of blue represent the density of values in a region of the graph.
plt.title("Flowers")
sns.kdeplot(
data=data,
x="sepal_length",
y="sepal_width",
fill=True,
thresh=0,
cmap="Blues"
)<Axes: title={'center': 'Flowers'}, xlabel='sepal_length', ylabel='sepal_width'>We can segment speicies of flowers by creating multiple contour plots with different colors.
fig, ax = plt.subplots()
setosa = data[data.species == 'setosa']
virginica = data[data.species == 'virginica']
sns.kdeplot(
data=setosa,
x="sepal_length",
y="sepal_width",
fill=True,
cmap="Reds",
thresh=0,
alpha=0.5,
ax=ax
)
sns.kdeplot(
data=virginica,
x="sepal_length",
y="sepal_width",
fill=True,
cmap="Blues",
thresh=0,
alpha=0.5,
ax=ax
)
ax.set_title("Flowers (Setosa & Virginica)")
plt.show()
Box Plot
A box plot shows the distribution of data along a single axis, using a "box" and "whiskers". The lower end of the box represents the 1st quartile (i.e. 25% of values are below it), and the upper end of the box represents the 3rd quartile (i.e. 25% of values are above it). The median value is represented via a line inside the box. The "whiskers" represent the minimum & maximum values (sometimes excluding outliers, which are represented as dots).
Example
We'll use another sample dataset included with Seaborn, called "tips". The dataset contains information about the sex, time of day, total bill and tip amount for customers visiting a restraurant over a week.
# Load the example tips dataset
tips = sns.load_dataset("tips");
tipsWe can use a box plot to visualize the distribution of total bill for each day of the week, segmented by whether the customer was a smoker.
# Chart title
plt.title("Daily Total Bill")
# Draw a nested boxplot to show bills by day and time
sns.boxplot(data=tips,x="day",y="total_bill",hue="smoker")<Axes: title={'center': 'Daily Total Bill'}, xlabel='day', ylabel='total_bill'>Bar Chart
A bar chart presents categorical data with rectangular bars with heights proportional to the values that they represent. If there are multiple values for each category, then a bar plot can also represent the average value, with confidence intervals.
Example
We can use a bar chart visulize the average value of total bill for different days of the week, segmented by sex, for the "tips" dataset
sns.barplot(x="day", y="total_bill", hue="sex", data=tips);Further Reading
This guide intends to serve as introduction to the most commonly used data visualization techniques. With minor modifications to the examples shown above, you can visualize a wide variety of datasets. Visit the official documentation websites for more examples & tutorials:
- Seaborn: https://seaborn.pydata.org/tutorial.html
- Matplotlib: https://matplotlib.org/tutorials/index.html