Line Chart Animation with Plotly on Jupyter
By: Shinichi Okada
Tags: Data Visualization, Data Science, Plotly, Programming, Python

Data preparation

You can download the dataset from Our World in Data or this repo.



import plotly.express as px

df = pd.read_csv(' import pandas as pdimport plotly.express as pxdf = pd.read_csv(' https://raw.githubusercontent.com/shinokada/covid-19-stats/master/data/daily-new-confirmed-cases-of-covid-19-tests-per-case.csv ') display(df.head())

display(df.shape)

Original dataset. It has 26123 rows x 5 columns. Image by the author

import pandas as pd

import plotly.express as px df = pd.read_csv('https://raw.githubusercontent.com/shinokada/covid-19-stats/master/data/daily-new-confirmed-cases-of-covid-19-tests-per-case.csv') excludes = ["World", "Africa", "North America", "South America", "Asia", "Europe", "European Union", "High income", "Low income", "Lower middle income", "Oceania", "Upper middle income", "World excl. China", "World excl. China and South Korea", "International", "World excl. China, South Korea, Japan and Singapore","Asia excl. China"] df=df[~df['Entity'].isin(excludes)]

df.columns = ['Country','Code','Date','Confirmed','Days since confirmed']

df['Date']= pd.to_datetime(df['Date']).dt.strftime('%Y-%m-%d')

df_all=df[(df['Date']>'2020-03-01') & (df['Date'] <'2020-06-14')]

Import necessary libraries, Pandas, and Plotly.express. Read a comma-separated values(csv) file into DataFrame.

file into DataFrame. excludes is a list of names in the Entity column that we want to exclude.

is a list of names in the column that we want to exclude. isin method finds excludes values in Entity column and we use ~ to exclude these rows.

method finds values in column and we use to exclude these rows. We rename the column names to Country, Code, Date, Confirmed, Days since confirmed.

We change the data type of Date column from object to datetime .

We also format it to Year-Month-Day.

column from to . We also format it to Year-Month-Day. We select rows from 2020-03-01 to 2020-06-14 in the Date column.

display(df.head())

display(df.shape)

Prepared dataset. It has 23414 rows x 5 columns. Image by the author

All countries line chart

Let’s create a line chart using df_all . We set Date for the x-axis, Confirmed for the y-axis and use Country for line colors.

fig = px.line(df_all, x="Date", y="Confirmed", color="Country")

fig.show()

Line chart. Image by the author

The chart has the ability to reveal more information about a data point by moving a mouse cursor over the point. We can hide or show lines by clicking country names on the right side.

Adding LOG and LINEAR buttons

We are going to add two buttons that change the y-axis scale.

fig = px.line(df_all, x="Date", y="Confirmed", color="Country")



fig.update_layout(

updatemenus=[

dict(

type = "buttons",

direction = "left",

buttons=list([

dict(

args=[{"yaxis.type": "linear"}],

label="LINEAR",

method="relayout"

),

dict(

args=[{"yaxis.type": "log"}],

label="LOG",

method="relayout"

)

]),

),

]

)

fig.show()

Using the update_layout method to update the properties of the figure’s layout. Adding two buttons, LINEAR and LOG and changing the yaxis.type to linear and log accordingly.

LINEAR and LOG buttons. Image by the author

Changing hovermode

Plotly has three different hovermode . The default setting is hovermode='closest' , as we can see in the previous image, a single hover label appears for the point directly underneath the cursor.

For this chart, we are going to use a unified hovermode='x unified' . It shows a single hover label with all the data information. For clarity, we select four countries.

import numpy as np

import pandas as pd

import plotly.graph_objects as go #plotly 4.0.0rc1 df = pd.read_csv('https://raw.githubusercontent.com/shinokada/covid-19-stats/master/data/daily-new-confirmed-cases-of-covid-19-tests-per-case.csv')

df.columns = ['Country','Code','Date','Confirmed','Days since confirmed']

df['Date']= pd.to_datetime(df['Date']).dt.strftime('%Y-%m-%d')

df=df[(df['Date']>'2020-03-15') & (df['Date'] <'2020-06-14')] includes=['United States','Russia', 'India','Brazil']df_selected=df[df['Country'].isin(includes)] fig = px.line(df_selected, x="Date", y="Confirmed", color="Country") fig.update_layout(

hovermode='x unified',

updatemenus=[

dict(

type = "buttons",

direction = "left",

buttons=list([

dict(

args=[{"yaxis.type": "linear"}],

label="LINEAR",

method="relayout"

),

dict(

args=[{"yaxis.type": "log"}],

label="LOG",

method="relayout"

)

]),

),

]

)

fig.show()

hovermode='x unified' in a line chart. Image by the author

Line chart animation

Plotly animations have some limitations and the line chart is not supported.

Line chart animation can be done but it is not as neat as other animations such as those for bar and scatter charts.

import numpy as np

import pandas as pd

import plotly.graph_objects as go

df.columns = ['Country','Code','Date','Confirmed','Days since confirmed']

df['Date']= pd.to_datetime(df['Date']).dt.strftime('%Y-%m-%d')

df=df[(df['Date']>'2020-03-15') & (df['Date'] <'2020-06-14')] df = pd.read_csv(' https://raw.githubusercontent.com/shinokada/covid-19-stats/master/data/daily-new-confirmed-cases-of-covid-19-tests-per-case.csv' df.columns = ['Country','Code','Date','Confirmed','Days since confirmed']df['Date']= pd.to_datetime(df['Date']).dt.strftime('%Y-%m-%d')df=df[(df['Date']>'2020-03-15') & (df['Date'] usa=df[df['Country'].isin(['United States'])]

brazil=df[df['Country'].isin(['Brazil'])]

india=df[df['Country'].isin(['India'])]

russia=df[df['Country'].isin(['Russia'])] trace1 = go.Scatter(x=usa['Date'][:2],

y=usa['Confirmed'][:2],

mode='lines',

line=dict(width=1.5)) trace2 = go.Scatter(x = brazil['Date'][:2],

y = brazil['Confirmed'][:2],

mode='lines',

line=dict(width=1.5)) trace3 = go.Scatter(x = india['Date'][:2],

y = india['Confirmed'][:2],

mode='lines',

line=dict(width=1.5)) trace4 = go.Scatter(x = russia['Date'][:2],

y = russia['Confirmed'][:2],

mode='lines',

line=dict(width=1.5)) frames = [dict(data= [dict(type='scatter',

x=usa['Date'][:k+1],

y=usa['Confirmed'][:k+1]),

dict(type='scatter',

x=brazil['Date'][:k+1],

y=brazil['Confirmed'][:k+1]),

dict(type='scatter',

x=india['Date'][:k+1],

y=india['Confirmed'][:k+1]),

dict(type='scatter',

x=russia['Date'][:k+1],

y=russia['Confirmed'][:k+1]),

],

traces= [0, 1, 2, 3],

)for k in range(1, len(usa)-1)] layout = go.Layout(width=700,

height=600,

showlegend=False,

hovermode='x unified',

updatemenus=[

dict(

type='buttons', showactive=False,

y=1.05,

x=1.15,

xanchor='right',

yanchor='top',

pad=dict(t=0, r=10),

buttons=[dict(label='Play',

method='animate',

args=[None,

dict(frame=dict(duration=3,

redraw=False),

transition=dict(duration=0),

fromcurrent=True,

mode='immediate')]

)]

),

dict(

type = "buttons",

direction = "left",

buttons=list([

dict(

args=[{"yaxis.type": "linear"}],

label="LINEAR",

method="relayout"

),

dict(

args=[{"yaxis.type": "log"}],

label="LOG",

method="relayout"

)

]),

),

]

) layout.update(xaxis =dict(range=['2020-03-16', '2020-06-13'], autorange=False),

yaxis =dict(range=[0, 35000], autorange=False)); fig = go.Figure(data=[trace1, trace2, trace3, trace4], frames=frames, layout=layout)

fig.show()

We can add more countries if we want.

We create four separate DataFrame. You can increase or decrease the number of countries.

We create four traces with own x , y , mode , and line values. If you change the number of countries, you need to adjust here as well.

, , , and values. If you change the number of countries, you need to adjust here as well. We create frames with data list values. traces=[0,1,2,3] is used to iterate frame[k]['data'][0] , frame[k]['data'][1] , etc. If you change the number of countries, again, you need to adjust the code here. e.g. traces=[0,1,2,3,4,5] .

list values. is used to iterate , , etc. If you change the number of countries, again, you need to adjust the code here. e.g. . We set width , height , hovermode , and updatemenus . We set two kinds of buttons, one for play and others for LINEAR and LOG .

, , , and . We set two kinds of buttons, one for play and others for and . update updates the properties of the figure with a dict with keyword arguments.

We create a new Figure instance and add all the traces we created in line 15–33. If you change the number of countries, you need to update this line.

Plotly line chart animation. Image by the author.

Scatter and bar chart animations

Plotly supports the scatter and bar chart animations.

You can find the code here.

Scatter chart animation. Image by the author.

You can drop the animation buttons by adding fig["layout"].pop("updatemenus") , and use it as a slider.

Code

pop(“updatemenus”) drop the animation button. Image by the author.

In a bar chart animation, we can hover to see more detailed information and we can hide/show items by clicking on the right menu.

Code

Bar chart animation. Image by the author.

Conclusion

It was not exactly the same as Our World in Data Website, but we learned how to create line charts, line chart animations, add unified hover mode, and add buttons.

Currently, Plotly requires more code to make a line chart animation. Also, it would be great if the scatter chart could draw trace lines and a speed control parameter for the animation.

Newsletter

Get full access to every story on Medium by becoming a member.