Estimating Concentration in Champagne Purchasing

Author

Abdullah Mahmood

Published

July 19, 2026

1 Import

Code
import numpy as np
import pandas as pd
from scipy.optimize import minimize
import matplotlib.pyplot as plt

%config InlineBackend.figure_formats = ['svg']

2 Concentration 101

  • Concentration in customer purchasing means that a small proportion of customers make a large proportion of the total purchases of the product (e.g., “80/20”).

\[ \text{Higher Concentration} \Leftrightarrow \text{Greater Inequality} \]

  • The Lorenz curve is used to illustrate the degree of inequality in the distribution of a quantity of interest (e.g., purchasing, income, wealth).
  • The greater the curvature of the Lorenz Curve, the greater the concentration/inequality.
  • Every point on the Lorenz curve represents the \(y%\) of the quantity of interest accounted for by the bottom \(x%\) of all relevant individuals:

\[ y = L(x) \]

  • \(80/20\) represents a spcific point on the Lorenz Curve: \(20=L(80)\)
  • The Gini coefficient is the ratio of the area between the \(45^{\circ}\) line (“line of perfect equality”) and the Lorenz curve to the area under the line of perfect equality.
Code
d = pd.DataFrame({
    'x': range(6),
    'f_x': [70, 45, 25, 15, 10, 5],
})

d['total_units'] = d.x * d.f_x
total_units = d.where(d.x > 0).total_units
total_buyers = d.where(d.x > 0).f_x

print('Total Units = ', total_units.sum())
print('Total Buyers = ', total_buyers.sum())
Total Units =  205.0
Total Buyers =  100.0

Consider those buyers that purchased \(x\) times \((x ≥ 1)\):

  • What proportion of total buyers are they?

\[ \frac{P(X=x)}{1-P(X=0)}, \]

-   where $P(X=x)$ is the percentage of customers for all levels of purchases, and 
-   $P(X=0)$ is the percentage of people who made 0 purchase.
  • What proportion of total purchasing do they account for?

\[ \frac{xP(X=x)}{E(X)} \]

-   where $xP(X=x)$ is the product of purchase levels and percentage of customers who made those purchases, and
-   $E(x)$ is the sum total of $xP(X=x)$.
Code
d['pct_buyers'] = total_buyers / total_buyers.sum()
d['pct_purchases'] = total_units / total_units.sum()
d['cum_pct_buyers'] = d.pct_buyers.cumsum()
d['cum_pct_purchases'] = d.pct_purchases.cumsum()

d = d.fillna(0)
d
x f_x total_units pct_buyers pct_purchases cum_pct_buyers cum_pct_purchases
0 0 70 0 0.00 0.000000 0.00 0.000000
1 1 45 45 0.45 0.219512 0.45 0.219512
2 2 25 50 0.25 0.243902 0.70 0.463415
3 3 15 45 0.15 0.219512 0.85 0.682927
4 4 10 40 0.10 0.195122 0.95 0.878049
5 5 5 25 0.05 0.121951 1.00 1.000000
Code
plt.clf()
plt.bar(d.x, d.f_x, color='k')
plt.xlabel('# Units')
plt.ylabel('# People')
plt.title('Hypothetical distribution of purchases (n = 170 people)');

Code
plt.clf()
plt.plot(d.cum_pct_buyers, d.cum_pct_purchases, color='k', marker='o', label='Lorenz Curve')
x = np.linspace(0, 1)
plt.plot(x,x,'k--', label='Line of Perfect Equality') 
plt.xlabel('Cumulative % Buyers')
plt.ylabel('Cumulative % Purchases')
plt.title('Lorenz Curve')
plt.legend();

3 Problem

Consider the following data on the number of bottles of champagne purchased in a year by a sample of 568 French households:

Code
d = pd.DataFrame({
    'x': range(9),
    'f_x': [400, 60, 30, 20, 8, 8, 9, 6, 27],
})
d['total_units'] = d.x * d.f_x

total_units = d.where(d.x > 0).total_units
total_buyers = d.where(d.x > 0).f_x

print('Total Units = ', total_units.sum())
print('Total Buyers = ', total_buyers.sum())
Total Units =  564.0
Total Buyers =  168.0