Skip to main content

Explain why metrics change by unpacking them

Project description

icanexplain

tests code_quality documentation pypi license

Explain why metrics change by unpacking them

This library is here to help with the difficult task of explaining why a metric changes. It's particularly useful for analysts, data scientists, analytics engineers, and business intelligence professionals who need to understand the drivers of a metric's change.

This README provides a small introduction. For more information, please refer to the documentation.

Let's say you're an analyst at an Airbnb-like company. You're tasked with analyzing year-over-year revenue growth. You have obtained the following dataset:

>>> import locale
>>> import pandas as pd
>>> _ = locale.setlocale(locale.LC_ALL, 'en_US')
>>> fmt_currency = lambda x: '' if pd.isna(x) else locale.currency(x, grouping=True)[:-3]

>>> revenue = pd.DataFrame.from_dict([
...     {'year': 2019, 'bookings': 1_000, 'revenue_per_booking': 200},
...     {'year': 2020, 'bookings': 1_000, 'revenue_per_booking': 220},
...     {'year': 2021, 'bookings': 1_500, 'revenue_per_booking': 220},
...     {'year': 2022, 'bookings': 1_700, 'revenue_per_booking': 225},
... ])
>>> (
...     revenue
...     .assign(bookings=revenue.bookings.apply('{:,d}'.format))
...     .assign(revenue_per_booking=revenue.revenue_per_booking.apply(fmt_currency))
...     .set_index('year')
... )
     bookings revenue_per_booking
year
2019    1,000                $200
2020    1,000                $220
2021    1,500                $220
2022    1,700                $225

It's quite straightforward to calculate the revenue for each year, and then to measure the year-over-year growth:

>>> (
...     revenue
...     .assign(revenue=revenue.eval('bookings * revenue_per_booking'))
...     .assign(growth=lambda x: x.revenue.diff())
...     .assign(bookings=revenue.bookings.apply('{:,d}'.format))
...     .assign(revenue_per_booking=revenue.revenue_per_booking.apply(fmt_currency))
...     .assign(revenue=lambda x: x.revenue.apply(fmt_currency))
...     .assign(growth=lambda x: x.growth.apply(fmt_currency))
...     .set_index('year')
... )
     bookings revenue_per_booking   revenue    growth
year
2019    1,000                $200  $200,000
2020    1,000                $220  $220,000   $20,000
2021    1,500                $220  $330,000  $110,000
2022    1,700                $225  $382,500   $52,500

Growth can be due to two factors: an increase in the number of bookings, or an increase in the revenue per booking. The icanexplain library to decompose the growth into these two factors:

>>> import icanexplain as ice
>>> explainer = ice.SumExplainer(
...     fact='revenue_per_booking',
...     period='year',
...     count='bookings'
... )
>>> explanation = explainer(revenue)
>>> explanation.map(fmt_currency)
        inner       mix
year
2020  $20,000        $0
2021       $0  $110,000
2022   $7,500   $45,000

Here's how to interpret this explanation:

  • From 2019 to 2020, the revenue growth was entirely due to an increase in the revenue per booking. The number of bookings was exactly the same. Therefore, the $20,000 is entirely due to the inner effect (increase in revenue per booking).
  • From 2020 to 2021, the revenue growth was entirely due to an increase in the number of bookings. The revenue per booking was exactly the same. Therefore, the $110,000 is entirely due to the mix effect (increase in bookings).
  • From 2021 to 2022, there was a $52,500 revenue growth. However, the revenue per booking went down by $10, so the increase is due to the higher number of bookings. The inner effect is -$7,500 while the mix effect is $45,000.

Here's a visual representation of this last interpretation:

example

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

icanexplain-0.1.0.tar.gz (2.4 MB view details)

Uploaded Source

Built Distribution

icanexplain-0.1.0-py3-none-any.whl (2.4 MB view details)

Uploaded Python 3

File details

Details for the file icanexplain-0.1.0.tar.gz.

File metadata

  • Download URL: icanexplain-0.1.0.tar.gz
  • Upload date:
  • Size: 2.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.11.4 Darwin/23.5.0

File hashes

Hashes for icanexplain-0.1.0.tar.gz
Algorithm Hash digest
SHA256 83e7ecbe32fd0fbb667c5cb789cfacd421084dba678bf9d653ea7a95d771b719
MD5 96952d4ab5851ebe293e5b16cba07fdd
BLAKE2b-256 e635326ffa874a717b88770e9af32bf005aa486e21826cd922cc59e66e3e39f2

See more details on using hashes here.

File details

Details for the file icanexplain-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: icanexplain-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 2.4 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.11.4 Darwin/23.5.0

File hashes

Hashes for icanexplain-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9a795c474ce44677234ba269ff3e37d4f9d17254b80d821157c9837ac39c26c5
MD5 bcf6d0f5a1ddaec2b5579e7670b113a6
BLAKE2b-256 c21cede8605fcc6f77dc6a0aea3d5de845ad90c14dc27a53bbdbaffafefc0ec6

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page