3.3.8. Interactive plots: plotly
¶
I want to show you how far we can push our ongoing exploration of leverage and firm value. The code uses plotly
’s subpackage plotly-express
which is ridiculously easy to use, for how cool these plots are.
Putting the lessons to work
As an exercise, you can critique the figures on this page. What about them could be improved? (I certainly think there are aspects to improve!)
Hit the “+” sign to show the code.
First, I plot industry-level average leverage and average market to book. This animation makes it easy to see trends:
The cloud of points gets wider > increasing dispersion in firm leverage
The cloud of points moves up > valuations have been increasing
No obvious slope > the relationship between firm leverage and valuation is unclear from this graph1
#!pip install plotly
%matplotlib inline
import pandas as pd
import numpy as np
import plotly.express as px # pip install plotly.. the animation below is from plotly module
from io import BytesIO
from zipfile import ZipFile
from urllib.request import urlopen
url = 'https://github.com/LeDataSciFi/data/blob/main/Firm%20Year%20Datasets%20(Compustat)/CCM_cleaned_for_class.zip?raw=true'
#firms = pd.read_stata(url) <-- would work, but GH said "too big" and forced me to zip it,
# so here is the work around to download it:
with urlopen(url) as request:
data = BytesIO(request.read())
with ZipFile(data) as archive:
with archive.open(archive.namelist()[0]) as stata:
firms = pd.read_stata(stata)
# firms = pd.read_stata('https://github.com/LeDataSciFi/data/blob/main/Firm%20Year%20Datasets%20(Compustat)/CCM_cleaned_for_class.zip?raw=true')
firms.name = "Firms"
# https://jupyterbook.org/guide/05_faq.html#How-can-I-include-interactive-Plotly-figures?
# the lines before and after the fig help make sure this is viewable on the website
# but shouldn't be necessary just for notebook viewing... but I'm not sure about github viewing
from IPython.display import display
from IPython.core.display import HTML
from plotly.offline import init_notebook_mode, plot
init_notebook_mode(connected=True)
fig = (
firms
.query('(fyear < 2014) & (mb < 5) & (td_a >= 0) & (td_a < 1.5) ') # some sensible limits
.groupby(['state','gsector','fyear'])
.agg({'td_a':'mean','mb':'mean','at':'sum','lpermno':'count'
}) # we need the # of firms per industry-state for an extra filter
# and I wanted the total assets summed so bigger industries get bigger circles
.rename(columns={'td_a':'Avg Book Leverage', 'mb':'Avg Market to Book','lpermno':'Num_Firms'})
.query('Num_Firms > 20 ') # disgard small industry-states
.reset_index() # get fyear as a variable for plotting function
.sort_values(['fyear'])
.pipe(
(px.scatter,'data_frame'),
y='Avg Market to Book', x='Avg Book Leverage', animation_frame="fyear",
range_x=[0,.5], range_y=[0,2], hover_data=["state","gsector"],
title = "State-By-Industry Avg Leverage and Avg Firm Value"
)
)
plot(fig, filename = 'ind-state mb vs lev.html')
display(HTML('ind-state mb vs lev.html'))