---
title: "Medidas de concentración"
pagetitle: "Medidas de concentración"
open-graph:
description: "Presenta razón de concentración, índice HHI, curva de Lorenz y coeficiente de Gini para medir si pocas unidades acaparan una masa total."
twitter-card:
description: "Presenta razón de concentración, índice HHI, curva de Lorenz y coeficiente de Gini para medir si pocas unidades acaparan una masa total."
description: "Presenta razón de concentración, índice HHI, curva de Lorenz y coeficiente de Gini para medir si pocas unidades acaparan una masa total."
author: "Diego Villalba"
date: today
lang: es
format:
html:
toc: true
toc-depth: 3
number-sections: true
code-fold: true
code-tools: true
code-summary: "Mostrar código"
fig-align: center
theme: cosmo
pdf:
toc: true
toc-depth: 3
number-sections: true
execute:
echo: true
warning: false
message: false
cache: false
jupyter: python3
bibliography: [referencias_eda.bib, ../../references.bib]
crossref:
fig-title: "Figura"
tbl-title: "Tabla"
eq-prefix: "Ec."
---
## El problema: ¿quién acumula el total?
Una cadena de cafeterías vendió 100 bebidas durante una hora. El total parece
sencillo, pero para operar el negocio falta responder otra pregunta:
> ¿Las ventas están repartidas entre las sucursales o dependen de unas pocas?
Supongamos que las cinco sucursales registraron:
| Sucursal | Ventas $x_i$ | Participación $s_i=x_i/T$ |
|:---:|---:|---:|
| Norte | 5 | 0.05 |
| Sur | 10 | 0.10 |
| Centro | 15 | 0.15 |
| Oriente | 20 | 0.20 |
| Poniente | 50 | 0.50 |
| **Total** | **100** | **1.00** |
La media es de 20 ventas por sucursal, pero solo Oriente vendió exactamente
20 y Poniente produjo la mitad del total. La media describe un centro; no
describe **cómo se reparte la masa** entre las unidades.
En este capítulo llamaremos **masa** a una cantidad no negativa y aditiva:
ventas, ingreso, consumo, población, participación de mercado o tráfico. Las
**unidades** son quienes reciben esa masa: sucursales, hogares, productos,
empresas o regiones.
Si
$$
T=\sum_{i=1}^{K}x_i>0,
\qquad
s_i=\frac{x_i}{T},
$$
entonces $s_i$ es la participación de la unidad $i$ y
$\sum_i s_i=1$. La concentración depende de este vector de participaciones,
no de la escala original. Multiplicar todas las ventas por 10 no cambia su
reparto.
::: {.callout-note appearance="minimal"}
### Dos casos que servirán como brújula
- Si cada sucursal vende 20, el reparto es uniforme y la concentración debe ser
**mínima**.
- Si una sucursal vende las 100 bebidas y las demás cero, la concentración debe
ser **máxima**.
Entre ambos extremos, una transferencia desde una sucursal pequeña hacia una
grande, sin cambiar el total, debe aumentar la concentración.
:::
Esta idea parece simple, pero no existe una única medida universal. Algunas
preguntan cuánto reúne el grupo líder; otras usan todas las participaciones o
comparan toda la distribución acumulada.
## Primera mirada: razones de concentración
Ordenemos las participaciones de mayor a menor:
$$
s_{[1]}\ge s_{[2]}\ge\cdots\ge s_{[K]}.
$$
La **razón de concentración de las $k$ unidades principales** es
$$
CR_k=\sum_{i=1}^{k}s_{[i]},
\qquad 1\le k\le K. \tag{1}
$$
Para las cafeterías,
$$
(s_{[1]},s_{[2]},s_{[3]},s_{[4]},s_{[5]})
=(0.50,0.20,0.15,0.10,0.05).
$$
Por tanto,
$$
CR_1=0.50,
\qquad
CR_2=0.50+0.20=0.70.
$$
La sucursal líder genera 50% de las ventas y las dos primeras generan 70%.
Estas frases son inmediatamente comprensibles; esa es la principal virtud de
$CR_k$.
### Lo que el top $k$ no ve
Compare dos repartos:
$$
A=(0.50,0.20,0.15,0.10,0.05),
$$
$$
B=(0.50,0.125,0.125,0.125,0.125).
$$
Ambos tienen $CR_1=0.50$, pero no son igual de concentrados: en $A$, el
50% restante también está escalonado; en $B$, está repartido por igual.
$CR_1$ descarta toda esa información. En general, $CR_k$:
- usa solo la frontera elegida $k$;
- no describe cómo se reparte la masa dentro del top $k$;
- tampoco describe cómo se reparte fuera de él;
- cambia de significado si se compara un $k$ distinto.
Por eso conviene acompañarlo con una medida que use **todas** las
participaciones.
## HHI: ¿de qué sucursal vienen dos ventas?
Imagine que cada una de las 100 ventas se escribe en un boleto y se colocan los
boletos en una urna. Se extrae un boleto, se devuelve, se mezcla y se extrae
otro. ¿Cuál es la probabilidad de que ambos pertenezcan a la misma sucursal?
Para Poniente,
$$
P(\text{Poniente dos veces})=0.50^2=0.25.
$$
Para Norte,
$$
P(\text{Norte dos veces})=0.05^2=0.0025.
$$
Los eventos “ambos boletos vienen de Norte”, “ambos vienen de Sur”, etcétera,
son mutuamente excluyentes. Por ello, la probabilidad total de coincidencia es
$$
\begin{aligned}
P(\text{misma sucursal})
&=0.05^2+0.10^2+0.15^2+0.20^2+0.50^2\\
&=0.0025+0.0100+0.0225+0.0400+0.2500\\
&=0.3250.
\end{aligned}
$$
Esta probabilidad es el **índice Herfindahl--Hirschman**:
$$
HHI(s)=\sum_{i=1}^{K}s_i^2. \tag{2}
$$
Su uso como índice de concentración se asocia históricamente con los trabajos
de Hirschman [@hirschman1945national]. La interpretación probabilística explica
por qué aparecen cuadrados: una coincidencia de la unidad $i$ requiere dos
selecciones independientes, cada una con probabilidad $s_i$.
::: {.callout-important appearance="minimal"}
### El puente con el capítulo anterior
El HHI es la probabilidad de **coincidencia**:
$$
HHI=P(X_1=X_2).
$$
El índice de Gini--Simpson es la probabilidad complementaria de **diferencia**:
$$
D=1-HHI=P(X_1\ne X_2).
$$
La misma suma de cuadrados mide concentración o heterogeneidad según se observe
la coincidencia o su complemento.
:::
### Cotas del HHI
Como las participaciones son no negativas y suman uno,
$$
\frac{1}{K}\le HHI\le 1. \tag{3}
$$
El máximo $HHI=1$ ocurre cuando una unidad posee toda la masa. Para justificar
el mínimo, la desigualdad de Cauchy--Schwarz da
$$
\left(\sum_{i=1}^{K}s_i\right)^2
\le K\sum_{i=1}^{K}s_i^2.
$$
Como $\sum_i s_i=1$,
$$
HHI=\sum_i s_i^2\ge\frac1K,
$$
con igualdad solo cuando $s_1=\cdots=s_K=1/K$.
En el ejemplo, $K=5$, así que el intervalo posible es
$[0.20,1]$. El valor 0.325 no significa “32.5% del máximo recorrido”, porque
la escala no comienza en cero. La versión normalizada es
$$
HHI^*=\frac{HHI-1/K}{1-1/K}\in[0,1]. \tag{4}
$$
Para las cafeterías,
$$
HHI^*=\frac{0.325-0.20}{1-0.20}
=\frac{0.125}{0.80}
=0.15625.
$$
Otra escala útil es el **número efectivo de unidades**:
$$
N_{\mathrm{efectivo}}=\frac{1}{HHI}. \tag{5}
$$
Aquí,
$$
N_{\mathrm{efectivo}}=\frac{1}{0.325}\approx3.077.
$$
La estructura observada tiene la misma probabilidad de coincidencia que un
reparto ideal entre aproximadamente 3.08 unidades de igual tamaño. Esta escala
no afirma que existan fracciones de sucursal; traduce la concentración a una
cantidad equivalente fácil de comparar.
### Por qué una transferencia hacia la unidad grande aumenta el HHI
Sean $a\ge b$ dos participaciones. Transfiera una cantidad
$\delta>0$ desde $b$ hacia $a$, con $\delta\le b$. El total no cambia,
pero la diferencia entre ambas unidades aumenta:
$$
(a,b)\longrightarrow(a+\delta,b-\delta).
$$
El cambio en el HHI es
$$
\begin{aligned}
\Delta HHI
&=(a+\delta)^2+(b-\delta)^2-a^2-b^2\\
&=2\delta(a-b)+2\delta^2>0.
\end{aligned} \tag{6}
$$
No es una intuición accidental: el cuadrado penaliza participaciones grandes
de forma creciente. Una transferencia en sentido contrario, desde la unidad
grande hacia la pequeña sin invertir su orden, reduce el HHI.
::: {.callout-warning appearance="minimal"}
### La escala 0--10,000
En análisis de mercados es común reportar $10\,000\times HHI$. Nuestro valor
sería 3250. Es exactamente el mismo índice expresado con participaciones en
porcentaje en vez de proporciones. No mezcle 0.325 con 3250 ni aplique umbrales
institucionales sin indicar jurisdicción, fecha y definición del mercado.
:::
## Curva de Lorenz: acumular desde la unidad menor
El HHI resume todo en una cifra. Para observar **cómo** se forma la
concentración, ordenamos ahora las cantidades de menor a mayor:
$$
x_{(1)}\le x_{(2)}\le\cdots\le x_{(K)}.
$$
La curva de Lorenz [@lorenz1905concentration] une los puntos
$$
\left(
\frac{i}{K},
L_i
\right),
\qquad
L_i=\frac{\sum_{j=1}^{i}x_{(j)}}{\sum_{j=1}^{K}x_{(j)}},
\qquad i=0,\ldots,K, \tag{7}
$$
con $L_0=0$. El eje horizontal acumula unidades; el vertical acumula masa.
### Construcción manual
En nuestro ejemplo los valores ya están ordenados:
$$
(5,10,15,20,50).
$$
| $i$ | Ventas $x_{(i)}$ | Fracción acumulada de unidades $i/5$ | Ventas acumuladas | Masa acumulada $L_i$ |
|---:|---:|---:|---:|---:|
| 0 | -- | 0.00 | 0 | 0.00 |
| 1 | 5 | 0.20 | 5 | 0.05 |
| 2 | 10 | 0.40 | 15 | 0.15 |
| 3 | 15 | 0.60 | 30 | 0.30 |
| 4 | 20 | 0.80 | 50 | 0.50 |
| 5 | 50 | 1.00 | 100 | 1.00 |
Los puntos son
$$
(0,0),\ (0.2,0.05),\ (0.4,0.15),\ (0.6,0.30),\
(0.8,0.50),\ (1,1).
$$
Si todas las sucursales tuvieran la misma participación, el 20% de las
sucursales acumularía 20% de las ventas, el 40% acumularía 40%, etcétera. Esa
es la diagonal $L(u)=u$, llamada **línea de igualdad**.
Nuestra curva queda debajo de la diagonal: el 80% de las sucursales con menores
ventas reúne apenas 50% del total; la última sucursal aporta el otro 50%.
Cuanto más se arquea la curva, más desigual es el reparto.
::: {.callout-note appearance="minimal"}
### Orden de Lorenz
Si la curva de una distribución queda en todo punto por debajo de la curva de
otra, la primera es inequívocamente más desigual en el sentido de Lorenz. Si
las curvas se cruzan, Lorenz no establece un orden total: dos índices pueden
ponderar partes distintas del reparto y producir rankings diferentes.
:::
## Coeficiente de Gini: convertir el arco en una cifra
El coeficiente de Gini resume la separación entre la curva de Lorenz y la
diagonal [@gini1912variabilita]. Si $B$ es el área bajo la curva de Lorenz,
el triángulo bajo la diagonal tiene área $1/2$, de modo que
$$
G=\frac{1/2-B}{1/2}=1-2B. \tag{8}
$$
### Cálculo por trapecios
Entre dos puntos consecutivos, la curva muestral es lineal. Cada tramo tiene
ancho $1/5=0.2$, así que
$$
\begin{aligned}
B
&=0.2\left[
\frac{0+0.05}{2}
+\frac{0.05+0.15}{2}
+\frac{0.15+0.30}{2}\right.\\
&\qquad\left.
+\frac{0.30+0.50}{2}
+\frac{0.50+1}{2}
\right]\\
&=0.2(0.025+0.100+0.225+0.400+0.750)\\
&=0.300.
\end{aligned}
$$
Por tanto,
$$
G=1-2(0.300)=0.400.
$$
### La misma respuesta con la fórmula de rangos
Para $K$ observaciones no negativas, ordenadas de menor a mayor y con total
positivo,
$$
G=
\frac{2\sum_{i=1}^{K}i\,x_{(i)}}{K\sum_{i=1}^{K}x_{(i)}}
-\frac{K+1}{K}. \tag{9}
$$
En nuestro ejemplo,
$$
\sum_{i=1}^{5}i\,x_{(i)}
=1(5)+2(10)+3(15)+4(20)+5(50)
=400.
$$
Entonces,
$$
G=\frac{2(400)}{5(100)}-\frac65
=1.6-1.2
=0.4.
$$
La igualdad entre ambos resultados no es coincidencia: la fórmula de rangos es
una forma algebraica de calcular el área trapezoidal.
### Una tercera interpretación: diferencias por pares
El Gini también puede escribirse como
$$
G=
\frac{\sum_{i=1}^{K}\sum_{j=1}^{K}|x_i-x_j|}
{2K^2\bar{x}}. \tag{10}
$$
El numerador suma todas las diferencias absolutas entre pares **ordenados** de
unidades. Para las cinco sucursales, la suma es 400, $\bar{x}=20$, y
$$
G=\frac{400}{2(5^2)(20)}=0.4.
$$
De manera equivalente, si se eligen dos sucursales al azar con reemplazo, la
diferencia absoluta esperada de ventas es $400/25=16$. Al dividirla entre
dos veces la media, $2\bar{x}=40$, se obtiene $16/40=0.4$.
::: {.callout-warning appearance="minimal"}
### El máximo muestral no siempre es 1
Con $K$ unidades y masa no negativa, el máximo ocurre cuando una sola unidad
posee todo:
$$
G_{\max}=\frac{K-1}{K}.
$$
Con cinco sucursales, $G_{\max}=0.8$, no 1. El valor 1 es el límite al crecer
$K$. Si se desea una escala con máximo exactamente 1 para un $K$ fijo,
puede usarse
$$
G^*=\frac{K}{K-1}G.
$$
Nuestro ejemplo tiene $G^*=5(0.4)/4=0.5$.
:::
## Laboratorio interactivo: mover la masa
El siguiente laboratorio mantiene la historia de las cinco sucursales. Los
controles permiten cambiar sus ventas; los botones realizan transferencias de
cinco ventas sin alterar el total. Observe qué aspectos detecta cada índice.
::: {.content-visible when-format="html"}
```{=html}
<div id="concentration-lab" class="concentration-lab" aria-labelledby="concentration-lab-title">
<style>
#concentration-lab {
--ink:#172033; --muted:#5b6577; --line:#cbd5e1; --soft:#f6f8fb;
--blue:#2563eb; --gold:#d97706; color:var(--ink); margin:1.25rem 0 1.75rem;
}
#concentration-lab .lab-shell { border:1px solid var(--line); border-radius:12px; padding:1rem; background:#fff; }
#concentration-lab .lab-title { font-weight:700; margin:0 0 .25rem; }
#concentration-lab .lab-intro { color:var(--muted); margin:0 0 1rem; }
#concentration-lab .lab-layout { display:grid; grid-template-columns:minmax(250px,.85fr) minmax(360px,1.15fr); gap:1.2rem; align-items:start; }
#concentration-lab .control-row { display:grid; grid-template-columns:5.5rem 1fr 3.2rem; gap:.55rem; align-items:center; margin:.55rem 0; }
#concentration-lab input { width:100%; }
#concentration-lab output, #concentration-lab strong { font-variant-numeric:tabular-nums; }
#concentration-lab .buttons { display:flex; flex-wrap:wrap; gap:.45rem; margin:.8rem 0; }
#concentration-lab button { border:1px solid #94a3b8; background:#fff; color:var(--ink); border-radius:6px; padding:.38rem .62rem; cursor:pointer; }
#concentration-lab button:hover { background:#f1f5f9; }
#concentration-lab .metrics { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:.55rem; margin-top:.8rem; }
#concentration-lab .metric { background:var(--soft); border-radius:8px; padding:.6rem .7rem; }
#concentration-lab .metric span { display:block; color:#64748b; font-size:.8rem; }
#concentration-lab .metric strong { font-size:1.08rem; }
#concentration-lab .status { min-height:1.5rem; color:var(--muted); font-size:.88rem; margin-top:.6rem; }
#concentration-lab svg { display:block; width:100%; height:auto; }
#concentration-lab .chart-title { font-size:14px; font-weight:700; fill:var(--ink); }
@media (max-width:760px) { #concentration-lab .lab-layout { grid-template-columns:1fr; } }
</style>
<div class="lab-shell">
<p id="concentration-lab-title" class="lab-title">Explorador de concentración</p>
<p class="lab-intro">Cambie las ventas o use una transferencia. Las barras se ordenan de menor a mayor para construir la curva de Lorenz.</p>
<div class="lab-layout">
<div>
<label class="control-row"><span>Norte</span><input data-unit="Norte" type="range" min="0" max="100" step="1" value="5"><output data-out="Norte">5</output></label>
<label class="control-row"><span>Sur</span><input data-unit="Sur" type="range" min="0" max="100" step="1" value="10"><output data-out="Sur">10</output></label>
<label class="control-row"><span>Centro</span><input data-unit="Centro" type="range" min="0" max="100" step="1" value="15"><output data-out="Centro">15</output></label>
<label class="control-row"><span>Oriente</span><input data-unit="Oriente" type="range" min="0" max="100" step="1" value="20"><output data-out="Oriente">20</output></label>
<label class="control-row"><span>Poniente</span><input data-unit="Poniente" type="range" min="0" max="100" step="1" value="50"><output data-out="Poniente">50</output></label>
<div class="buttons">
<button type="button" data-preset="base">Ejemplo 5, 10, 15, 20, 50</button>
<button type="button" data-preset="equal">Igualdad 20, 20, 20, 20, 20</button>
<button type="button" data-transfer="concentrate">Norte → Poniente: 5</button>
<button type="button" data-transfer="redistribute">Poniente → Norte: 5</button>
</div>
<div class="metrics" aria-live="polite">
<div class="metric"><span>Total</span><strong data-total></strong></div>
<div class="metric"><span>CR₁ / CR₂</span><strong data-cr></strong></div>
<div class="metric"><span>HHI / HHI*</span><strong data-hhi></strong></div>
<div class="metric"><span>Unidades efectivas</span><strong data-effective></strong></div>
<div class="metric"><span>Gini / Gini*</span><strong data-gini></strong></div>
<div class="metric"><span>Área bajo Lorenz</span><strong data-area></strong></div>
</div>
<p class="status" data-status></p>
</div>
<div>
<svg data-chart viewBox="0 0 620 650" role="img" aria-label="Participaciones ordenadas y curva de Lorenz"></svg>
</div>
</div>
</div>
</div>
<script>
(() => {
const root=document.getElementById('concentration-lab'); if(!root)return;
const names=['Norte','Sur','Centro','Oriente','Poniente'];
const inputs=names.map(n=>root.querySelector('[data-unit="'+n+'"]'));
const svg=root.querySelector('[data-chart]'),NS='http://www.w3.org/2000/svg';
const add=(tag,attrs,text='')=>{const e=document.createElementNS(NS,tag);Object.entries(attrs).forEach(([k,v])=>e.setAttribute(k,v));e.textContent=text;svg.appendChild(e);return e;};
const setValues=values=>{values.forEach((v,i)=>inputs[i].value=v);update();};
function update(message=''){
const raw=inputs.map(x=>+x.value),total=raw.reduce((a,b)=>a+b,0);
names.forEach((n,i)=>root.querySelector('[data-out="'+n+'"]').value=raw[i]);
if(total<=0){inputs[0].value=1;return update('El total debe ser positivo; Norte se ajustó a 1.');}
const ordered=raw.map((x,i)=>({name:names[i],x})).sort((a,b)=>a.x-b.x);
const shares=ordered.map(d=>d.x/total),desc=[...shares].sort((a,b)=>b-a),k=raw.length;
const hhi=shares.reduce((s,x)=>s+x*x,0),hhiN=(hhi-1/k)/(1-1/k),effective=1/hhi;
const weighted=ordered.reduce((s,d,i)=>s+(i+1)*d.x,0);
const gini=2*weighted/(k*total)-(k+1)/k,giniN=k*gini/(k-1);
root.querySelector('[data-total]').textContent=total.toFixed(0);
root.querySelector('[data-cr]').textContent=(100*desc[0]).toFixed(1)+'% / '+(100*(desc[0]+desc[1])).toFixed(1)+'%';
root.querySelector('[data-hhi]').textContent=hhi.toFixed(4)+' / '+hhiN.toFixed(4);
root.querySelector('[data-effective]').textContent=effective.toFixed(2);
root.querySelector('[data-gini]').textContent=gini.toFixed(4)+' / '+giniN.toFixed(4);
root.querySelector('[data-area]').textContent=((1-gini)/2).toFixed(4);
root.querySelector('[data-status]').textContent=message || 'Orden ascendente: '+ordered.map(d=>d.name).join(' → ');
svg.replaceChildren();
add('text',{x:310,y:22,'text-anchor':'middle',class:'chart-title'},'Participaciones ordenadas');
const bx=70,by=245,bw=500,bh=185,barW=68,gap=28;
add('line',{x1:bx,y1:by,x2:bx,y2:by-bh,stroke:'#64748b','stroke-width':'1.5'});
add('line',{x1:bx,y1:by,x2:bx+bw,y2:by,stroke:'#64748b','stroke-width':'1.5'});
ordered.forEach((d,i)=>{const h=(d.x/total)*bh,x=bx+22+i*(barW+gap),y=by-h;add('rect',{x,y,width:barW,height:h,rx:'3',fill:i===k-1?'#d97706':'#2563eb',opacity:'.86'});add('text',{x:x+barW/2,y:y-7,'text-anchor':'middle',fill:'#172033','font-size':'12'},(100*d.x/total).toFixed(1)+'%');add('text',{x:x+barW/2,y:by+17,'text-anchor':'middle',fill:'#475569','font-size':'11'},d.name);});
add('text',{x:310,y:295,'text-anchor':'middle',class:'chart-title'},'Curva de Lorenz');
const lx=70,ly=600,size=270;
add('rect',{x:lx,y:ly-size,width:size,height:size,fill:'#f8fafc',stroke:'#94a3b8'});
add('line',{x1:lx,y1:ly,x2:lx+size,y2:ly-size,stroke:'#94a3b8','stroke-width':'2','stroke-dasharray':'7 6'});
let cumulative=0,points=[[lx,ly]];
shares.forEach((s,i)=>{cumulative+=s;points.push([lx+(i+1)*size/k,ly-cumulative*size]);});
const areaPoints=points.concat([[lx+size,ly],[lx,ly]]);
add('polygon',{points:areaPoints.map(p=>p.join(',')).join(' '),fill:'#dbeafe',opacity:'.65'});
add('polyline',{points:points.map(p=>p.join(',')).join(' '),fill:'none',stroke:'#2563eb','stroke-width':'4'});
points.forEach(p=>add('circle',{cx:p[0],cy:p[1],r:'4',fill:'#2563eb'}));
add('text',{x:lx+size/2,y:635,'text-anchor':'middle',fill:'#475569','font-size':'12'},'Fracción acumulada de sucursales');
const yl=add('text',{x:20,y:ly-size/2,'text-anchor':'middle',fill:'#475569','font-size':'12'},'Fracción acumulada de ventas');yl.setAttribute('transform','rotate(-90 20 '+(ly-size/2)+')');
add('text',{x:455,y:410,fill:'#64748b','font-size':'12'},'Diagonal: igualdad');
add('line',{x1:430,y1:420,x2:475,y2:375,stroke:'#94a3b8','stroke-width':'2','stroke-dasharray':'7 6'});
}
inputs.forEach(x=>x.addEventListener('input',()=>update()));
root.querySelectorAll('[data-preset]').forEach(b=>b.addEventListener('click',()=>setValues(b.dataset.preset==='equal'?[20,20,20,20,20]:[5,10,15,20,50])));
root.querySelectorAll('[data-transfer]').forEach(b=>b.addEventListener('click',()=>{
const v=inputs.map(x=>+x.value),from=b.dataset.transfer==='concentrate'?0:4,to=b.dataset.transfer==='concentrate'?4:0,amount=Math.min(5,v[from],100-v[to]);
if(amount===0)return update('No hay masa disponible o capacidad en el control para completar la transferencia.');
v[from]-=amount;v[to]+=amount;setValues(v);
root.querySelector('[data-status]').textContent='Transferencia de '+amount+' ventas: '+names[from]+' → '+names[to]+'. El total se conserva.';
}));
update();
})();
</script>
```
:::
::: {.content-visible unless-format="html"}
La versión HTML contiene un laboratorio con cinco controles. El escenario base
$(5,10,15,20,50)$ produce $CR_2=0.70$, $HHI=0.325$ y $G=0.40$.
Una transferencia de cinco ventas de Norte a Poniente conserva el total, pero
arquea más la curva de Lorenz y aumenta HHI y Gini. La transferencia inversa
los reduce.
:::
## Qué ve cada indicador
Los índices no son intercambiables. Compare cuatro escenarios con cinco
unidades y total 100:
| Escenario ordenado de mayor a menor | $CR_1$ | $CR_2$ | HHI | $HHI^*$ | Gini |
|---|---:|---:|---:|---:|---:|
| Uniforme: $(20,20,20,20,20)$ | 0.20 | 0.40 | 0.2000 | 0.0000 | 0.0000 |
| Base: $(50,20,15,10,5)$ | 0.50 | 0.70 | 0.3250 | 0.1563 | 0.4000 |
| Mismo líder: $(50,12.5,12.5,12.5,12.5)$ | 0.50 | 0.625 | 0.3125 | 0.1406 | 0.3000 |
| Mismo $CR_2$: $(40,30,20,5,5)$ | 0.40 | 0.70 | 0.2950 | 0.1188 | 0.3800 |
El escenario base y “Mismo líder” comparten $CR_1$, pero HHI y Gini detectan
que el resto está más escalonado en el primero. El escenario base y “Mismo
$CR_2$” comparten 70% en las dos unidades principales, pero distribuyen ese
70% y la cola de forma distinta.
El HHI da peso cuadrático a las participaciones grandes. El Gini promedia
brechas relativas entre todas las parejas y está conectado con toda la curva
de Lorenz. No existe contradicción si dos medidas reaccionan con intensidades
distintas: están resumiendo aspectos distintos.
## Propiedades que debe cumplir una comparación
Antes de interpretar una cifra, conviene comprobar qué propiedades necesita el
problema:
1. **Anonimato.** Permutar los nombres de las unidades no cambia el índice.
2. **Invariancia de escala.** Multiplicar toda la masa por una constante
positiva no cambia la concentración.
3. **Principio de transferencia.** Mover masa de una unidad menor hacia una
mayor, conservando el total, aumenta la concentración.
4. **Sensibilidad al número de unidades.** HHI mínimo y Gini máximo dependen de
$K$; las versiones normalizadas hacen explícita esa dependencia.
$CR_k$, HHI y Gini cumplen las dos primeras. HHI y Gini también responden al
principio de transferencia. $CR_k$ puede no cambiar si la transferencia
ocurre completamente fuera de la frontera del top $k$.
### La unidad de análisis cambia la respuesta
Suponga que Poniente se divide administrativamente en dos sucursales idénticas
de 25 ventas. El fenómeno económico podría ser el mismo, pero ahora hay seis
unidades y
$$
HHI_{\text{nuevo}}
=0.05^2+0.10^2+0.15^2+0.20^2+0.25^2+0.25^2
=0.20,
$$
frente a 0.325 antes de la división. Ninguna fórmula puede decidir por sí sola
si ambas nuevas sucursales son competidores independientes o partes de una
misma entidad. La definición de “unidad” es una decisión sustantiva previa al
cálculo.
::: {.callout-warning appearance="minimal"}
### Concentración no significa automáticamente problema
Una cifra alta puede representar riesgo operativo, poder de mercado,
especialización eficiente o simplemente una agregación mal definida. Los
índices son descriptivos: no prueban causalidad, competencia insuficiente ni
una recomendación normativa.
:::
## Implementación reproducible
Las siguientes funciones validan los supuestos, conservan una sola convención
de orden y reproducen los cálculos manuales.
```{python}
import numpy as np
import pandas as pd
def indices_concentracion(x, k=2):
x = np.asarray(x, dtype=float)
if x.ndim != 1 or x.size < 2:
raise ValueError("x debe contener al menos dos unidades.")
if not np.all(np.isfinite(x)):
raise ValueError("x solo puede contener valores finitos.")
if np.any(x < 0) or x.sum() <= 0:
raise ValueError("Se requieren valores no negativos y suma positiva.")
if not 1 <= k <= x.size:
raise ValueError("k debe estar entre 1 y el número de unidades.")
n = x.size
total = x.sum()
shares = x / total
shares_desc = np.sort(shares)[::-1]
x_asc = np.sort(x)
hhi = np.square(shares).sum()
hhi_normalizado = (hhi - 1 / n) / (1 - 1 / n)
gini = (
2 * np.sum(np.arange(1, n + 1) * x_asc) / (n * total)
- (n + 1) / n
)
gini_normalizado = n * gini / (n - 1)
return pd.Series({
f"CR_{k}": shares_desc[:k].sum(),
"HHI": hhi,
"HHI normalizado": hhi_normalizado,
"Unidades efectivas": 1 / hhi,
"Gini": gini,
"Gini normalizado": gini_normalizado,
})
indices_concentracion([5, 10, 15, 20, 50], k=2).round(4)
```
La curva de Lorenz reutiliza el mismo orden ascendente:
```{python}
def curva_lorenz(x):
x = np.asarray(x, dtype=float)
if x.ndim != 1 or x.size < 2:
raise ValueError("x debe contener al menos dos unidades.")
if not np.all(np.isfinite(x)):
raise ValueError("x solo puede contener valores finitos.")
if np.any(x < 0) or x.sum() <= 0:
raise ValueError("Se requieren valores no negativos y suma positiva.")
x_asc = np.sort(x)
unidades = np.arange(x.size + 1) / x.size
masa = np.r_[0, np.cumsum(x_asc) / x_asc.sum()]
return unidades, masa
u, L = curva_lorenz([5, 10, 15, 20, 50])
pd.DataFrame({
"Fracción acumulada de unidades": u,
"Fracción acumulada de ventas": L,
}).round(2)
```
### La curva de Lorenz sobre los datos observados
La versión interactiva conserva los seis puntos calculados a mano y los
contrasta con la línea de igualdad.
```{python}
import plotly.graph_objects as go
from IPython.display import HTML, display
def mostrar_plotly(figura):
"""Incrusta Plotly sin cargar una segunda versión de MathJax."""
display(HTML(figura.to_html(
full_html=False,
include_plotlyjs="cdn",
include_mathjax=False,
)))
fig = go.Figure()
fig.add_trace(go.Scatter(
x=u,
y=L,
mode="lines+markers",
name="Cafeterías observadas",
hovertemplate="Unidades: %{x:.0%}<br>Ventas: %{y:.0%}<extra></extra>",
))
fig.add_trace(go.Scatter(
x=[0, 1],
y=[0, 1],
mode="lines",
name="Igualdad",
line={"dash": "dash", "color": "#64748b"},
hoverinfo="skip",
))
fig.update_layout(
title="El 80% de las sucursales acumula solo el 50% de las ventas",
xaxis={"title": "Fracción acumulada de sucursales", "tickformat": ".0%"},
yaxis={"title": "Fracción acumulada de ventas", "tickformat": ".0%"},
)
mostrar_plotly(fig)
```
La igualdad entre las tres fórmulas del Gini puede verificarse numéricamente:
```{python}
x = np.array([5, 10, 15, 20, 50], dtype=float)
u, L = curva_lorenz(x)
gini_trapecios = 1 - 2 * np.trapezoid(L, u)
gini_rangos = indices_concentracion(x)["Gini"]
gini_pares = np.abs(x[:, None] - x[None, :]).sum() / (2 * x.size**2 * x.mean())
pd.Series({
"Área de Lorenz": gini_trapecios,
"Fórmula de rangos": gini_rangos,
"Diferencias por pares": gini_pares,
}).round(10)
```
## Guía de decisión
| Pregunta | Herramienta principal | Qué debe acompañarla |
|---|---|---|
| ¿Cuánto aporta el grupo líder? | $CR_k$ | Declarar $k$, número total de unidades y participaciones ordenadas. |
| ¿Qué tan probable es que dos unidades de masa provengan del mismo origen? | HHI | Reportar $K$, escala usada y, al comparar cardinalidades, $HHI^*$ o $1/HHI$. |
| ¿Cómo se acumula la masa desde las unidades menores? | Curva de Lorenz | Mostrar la diagonal y puntos acumulados; revisar cruces entre curvas. |
| ¿Cuál es la brecha relativa promedio entre unidades? | Gini | Reportar $K$, tratamiento de ceros y si se normalizó el máximo finito. |
| ¿La concentración es problemática o causal? | Ningún índice descriptivo basta | Definición sustantiva del mercado o sistema, contexto y diseño causal. |
## Errores frecuentes
- **Usar valores negativos.** Participaciones, Lorenz, HHI y las fórmulas
presentadas del Gini requieren masa no negativa y total positivo. Una
utilidad neta con pérdidas necesita otra formulación.
- **Omitir unidades con cero.** Los ceros no cambian el total ni el HHI, pero sí
cambian $K$, la curva de Lorenz, el Gini y las normalizaciones.
- **Comparar distintos niveles de agregación.** Productos, marcas y empresas
producen vectores de participaciones distintos.
- **Interpretar HHI como porcentaje.** HHI es una probabilidad de coincidencia;
$HHI^*$ es la fracción del recorrido entre igualdad y concentración total.
- **Interpretar Gini como “porcentaje en manos del top”.** Esa lectura
corresponde a $CR_k$ o a un punto de la curva de Lorenz, no al Gini.
- **Aplicar mecánicamente la regla 80/20.** Pareto es una referencia descriptiva,
no una ley que toda distribución deba cumplir.
## Puentes con minería de datos
| Contexto | Papel de la concentración |
|---|---|
| Selección de variables categóricas | Una categoría dominante puede indicar baja información efectiva aunque existan muchas etiquetas nominales. |
| Riesgo de dependencia | Un $CR_k$ alto revela dependencia de pocos clientes, proveedores, productos o nodos. |
| Muestreo y particiones | Una masa muy concentrada puede producir validaciones inestables si las unidades dominantes se reparten de forma inadecuada. |
| Recomendadores | La concentración de exposición permite detectar si el sistema muestra repetidamente pocos artículos. |
| Clustering | El tamaño de los grupos puede evaluarse con HHI; $1/HHI$ expresa el número efectivo de clusters por tamaño. |
La concentración de una variable objetivo tampoco sustituye el análisis de
heterogeneidad condicional. Por ejemplo, que pocas sucursales acumulen ventas
no explica qué atributos causan esa diferencia ni si el patrón persiste dentro
de cada tipo de establecimiento.
## Puente al caso BigMart
El capítulo [Medidas de concentración en Big Mart Sales](2-7-concentracion_bigmart.qmd)
traslada estas ideas a productos y establecimientos:
- identifica qué categorías o outlets reúnen mayor parte de las ventas;
- compara $CR_k$, HHI y número efectivo de unidades;
- construye curvas de Lorenz y coeficientes de Gini;
- obliga a definir la unidad de análisis antes de interpretar el resultado.
La secuencia recomendada es: **definir unidad y masa, inspeccionar las
participaciones, calcular a mano un caso pequeño, visualizar la acumulación y
solo entonces resumir con índices**.
## Ejercicios formativos
1. **Cálculo completo.** Para $x=(10,10,20,20,40)$, calcule
participaciones, $CR_1$, $CR_2$, HHI, $HHI^*$, número efectivo,
puntos de Lorenz, Gini y $G^*$.
2. **Mismo líder, distinta cola.** Compare
$A=(50,20,15,10,5)$ y $B=(50,12.5,12.5,12.5,12.5)$. Explique por qué
$CR_1$ empata mientras HHI y Gini no.
3. **Transferencia.** Parta de $(20,20,20,20,20)$ y transfiera cinco
unidades de la primera sucursal a la quinta. Verifique con la ecuación de
transferencia que el HHI aumenta y calcule el cambio del Gini.
4. **Tres fórmulas, una cifra.** Para $x=(5,10,15,20,50)$, obtenga el Gini
mediante trapecios, rangos y diferencias por pares.
5. **Máximo finito.** Demuestre que el vector $(0,\ldots,0,T)$ produce
$G=(K-1)/K$ usando la fórmula de rangos.
6. **Unidad de análisis.** Calcule HHI y Gini antes y después de dividir la
unidad de 50 en dos unidades de 25. Discuta cuándo esa división representa
un cambio real y cuándo es solo administrativo.
7. **Curvas cruzadas.** Construya dos vectores de cinco valores cuyas curvas de
Lorenz se crucen. Compare HHI y Gini y explique por qué Lorenz no impone un
orden único en ese caso.
## Referencias {.unnumbered}
::: {#refs}
:::