Chris Parmer — home

Income Statement Sankey

revenue decomposition to net income

Example from the compendium of canonical charts

Income Statement Sankey — revenue decomposition to net income

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