Income Statement Sankey
revenue decomposition to net income
Example from the compendium of canonical charts
Python Code
"""Income Statement Sankey — revenue decomposition to net income."""
import plotly.graph_objects as go
# Nodes
# 0=Revenue, 1=COGS, 2=Gross Profit, 3=R&D, 4=S&M, 5=G&A, 6=Operating Income,
# 7=Interest/Other, 8=Tax, 9=Net Income
NODES = [
"Revenue", # 0
"COGS", # 1
"Gross Profit", # 2
"R&D", # 3
"Sales & Mktg", # 4
"G&A", # 5
"Operating Income", # 6
"Interest/Other", # 7
"Tax", # 8
"Net Income", # 9
]
# ($M) — illustrative tech-company P&L
FLOWS = [
(0, 1, 380), # Revenue → COGS
(0, 2, 620), # Revenue → Gross Profit
(2, 3, 180), # Gross Profit → R&D
(2, 4, 140), # Gross Profit → Sales & Mktg
(2, 5, 60), # Gross Profit → G&A
(2, 6, 240), # Gross Profit → Operating Income
(6, 7, 20), # Operating Income → Interest/Other
(6, 8, 50), # Operating Income → Tax
(6, 9, 170), # Operating Income → Net Income
]
NODE_COLORS = [
"#845EEE", # Revenue
"#DA5597", # COGS
"#52B3D0", # Gross Profit
"#E9A23B", # R&D
"#E9A23B", # S&M
"#E9A23B", # G&A
"#55B685", # Operating Income
"#DA5597", # Interest
"#DA5597", # Tax
"#55B685", # Net Income
]
def generate():
print("building Income Statement Sankey …")
sources = [f[0] for f in FLOWS]
targets = [f[1] for f in FLOWS]
values = [f[2] for f in FLOWS]
fig = go.Figure(go.Sankey(
node=dict(
label=NODES,
color=NODE_COLORS,
pad=20, thickness=24,
line=dict(color="rgba(0,0,0,0.08)", width=0.5),
),
link=dict(
source=sources,
target=targets,
value=values,
color="rgba(150,150,150,0.2)",
),
))
fig.update_layout(
title=dict(text="Income Statement Flow ($M)", x=0.5),
margin=dict(t=60, b=40, l=20, r=20),
height=480,
font=dict(size=11),
)
return fig
if __name__ == "__main__":
generate()
Made with Plotly