0ng 9 E4act Lt3qn.jpeg

Las correlaciones ocultas pueden engañar a las estrategias de optimización

Foto por Chun Kit Soo en desempaquetar

p99, o el valor por debajo del cual caen el 99% de las observaciones, se usa ampliamente para rastrear y optimizar el desempeño en el peor de los casos en todas las industrias. Por ejemplo, el tiempo que tarda una página en cargarse, completar un pedido de compra o entregar un envío se puede optimizar mediante el seguimiento de p99.

Si bien p99 es indudablemente valioso, es crucial reconocer que ignora el 1% superior de las observaciones, lo que puede tener un impacto inesperadamente grande cuando se correlacionan con otras métricas comerciales críticas. Buscar ciegamente p99 sin verificar dichas correlaciones puede potencialmente socavar otros objetivos comerciales.

En este artículo, analizaremos las limitaciones de p99 a través de un ejemplo con datos ficticios, entenderemos cuándo confiar en p99 y exploraremos métricas alternativas.

Considere una plataforma de comercio electrónico en la que un equipo tiene la tarea de optimizar la experiencia de pago del carrito de compras. El equipo ha recibido quejas de clientes de que el proceso de pago es bastante lento en comparación con otras plataformas. Entonces, el equipo toma los últimos 1000 pagos y analiza el tiempo necesario para realizar el pago. (Creé algunos datos ficticios para esto, eres libre de usarlos y modificarlos sin restricciones)

import pandas as pd
import seaborn as sns
order_time = pd.read_csv('https://gist.githubusercontent.com/kkraoj/77bd8332e3155ed42a2a031ce63d8903/raw/458a67d3ebe5b649ec030b8cd21a8300d8952b2c/order_time.csv')
fig, ax = plt.subplots(figsize=(4,2))
sns.histplot(data = order_time, x = 'fulfillment_time_seconds', bins = 40, color = 'k', ax = ax)
print(f'p99 for fulfillment_time_seconds: {order_time.fulfillment_time_seconds.quantile(0.99):0.2f} s')
Distribución de tiempos de pago de pedidos. Imagen del autor.

Como era de esperar, la mayoría de los pagos con carritos de compras parecen completarse en unos pocos segundos. Y el 99% de los pagos se realizan en 12,1 segundos. En otras palabras, el p99 es de 12,1 segundos. Hay algunos casos de cola larga que tardan hasta 30 segundos. Dado que son tan pocos, pueden ser valores atípicos y debería ser seguro ignorarlos, ¿verdad?

Ahora bien, si no nos detenemos y analizamos las implicaciones de la última frase, podría ser bastante peligroso. ¿Es realmente seguro ignorar al 1% superior? ¿Estamos seguros de que los tiempos de pago no están correlacionados con ninguna otra métrica comercial?

Digamos que nuestra empresa de comercio electrónico también se preocupa por el valor bruto de la mercancía (GMV) y tiene el objetivo general a nivel de empresa de aumentarlo. Deberíamos comprobar inmediatamente si el tiempo necesario para pagar está correlacionado con el GMV antes de ignorar el 1% superior.

import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter
order_value = pd.read_csv('https://gist.githubusercontent.com/kkraoj/df53cac7965e340356d6d8c0ce24cd2d/raw/8f4a30db82611a4a38a90098f924300fd56ec6ca/order_value.csv')
df = pd.merge(order_time, order_value, on='order_id')
fig, ax = plt.subplots(figsize=(4,4))
sns.scatterplot(data=df, x="fulfillment_time_seconds", y="order_value_usd", color = 'k')
plt.yscale('log')
ax.yaxis.set_major_formatter(ScalarFormatter())
Relación entre el valor del pedido y el tiempo de cumplimiento. Imagen del autor.

¡Oh chico! El valor del carrito no solo está correlacionado con los tiempos de pago, sino que aumenta exponencialmente cuando los tiempos de pago son más prolongados. ¿Cuál es la penalización por ignorar el 1% superior de los tiempos de pago?

pct_revenue_ignored = df2.loc[df1.fulfilment_time_seconds>df1.fulfilment_time_seconds.quantile(0.99), 'order_value_usd'].sum()/df2.order_value_usd.sum()*100
print(f'If we only focussed on p99, we would ignore {pct_revenue_ignored:0.0f}% of revenue')
## >>> If we only focussed on p99, we would ignore 27% of revenue

Si solo nos centráramos en p99, ignoraríamos el 27% de los ingresos (27 veces más que el 1% que pensábamos que estábamos ignorando). Es decir, p99 de tiempos de pago son p73 de ingresos. Centrarse en p99 en este caso perjudica inadvertidamente al negocio. Ignora las necesidades de nuestros compradores de mayor valor.

df.sort_values('fulfillment_time_seconds', inplace = True)
dfc = df.cumsum()/df.cumsum().max() # percent cumulative sum
fig, ax = plt.subplots(figsize=(4,4))
ax.plot(dfc.fulfillment_time_seconds.values, color = 'k')
ax2 = ax.twinx()
ax2.plot(dfc.order_value_usd.values, color = 'magenta')
ax.set_ylabel('cumulative fulfillment time')
ax.set_xlabel('orders sorted by fulfillment time')
ax2.set_ylabel('cumulative order value', color = 'magenta')
ax.axvline(0.99*1000, linestyle='--', color = 'k')
ax.annotate('99% of orders', xy = (970,0.05), ha = 'right')
ax.axhline(0.73, linestyle='--', color = 'magenta')
ax.annotate('73% of revenue', xy = (0,0.75), color = 'magenta')
Función de distribución acumulativa de los tiempos de cumplimiento de los pedidos y el valor del pedido. Imagen del autor.

Arriba, vemos por qué existe un gran desajuste entre los percentiles de tiempos de pago y el GMV. La curva GMV aumenta bruscamente cerca del percentil 99 de los pedidos, lo que hace que el 1% superior de los pedidos tenga un impacto enorme en el GMV.

Esto no es sólo un artefacto de nuestros datos ficticios. Desafortunadamente, estas correlaciones extremas no son infrecuentes. Por ejemplo, el 1% superior de los clientes de Slack representan 50% de los ingresos. Alrededor del 12% de los ingresos de UPS provienen de solo 1 cliente (Amazonas).

Para evitar los peligros de optimizar únicamente para p99, podemos adoptar un enfoque más holístico.

Una solución es realizar un seguimiento de p99 y p100 (el valor máximo) simultáneamente. De esta manera, no seremos propensos a ignorar a los usuarios de alto valor.

Otra solución es utilizar p99 ponderado por ingresos (o ponderado por valor bruto de la mercancía, ganancias o cualquier otra métrica comercial de interés), que asigna mayor importancia a las observaciones con mayores ingresos asociados. Esta métrica garantiza que los esfuerzos de optimización prioricen las transacciones o procesos más valiosos, en lugar de tratar todas las observaciones por igual.

Finalmente, cuando existen altas correlaciones entre el rendimiento y las métricas comerciales, un p99.5 o p99.9 más estricto puede mitigar el riesgo de ignorar a los usuarios de alto valor.

Es tentador confiar únicamente en métricas como p99 para los esfuerzos de optimización. Sin embargo, como vimos, ignorar el 1% superior de las observaciones puede afectar negativamente a un gran porcentaje de otros resultados comerciales. El seguimiento de p99 y p100 o el uso de p99 ponderado por ingresos puede proporcionar una vista más completa y mitigar los riesgos de optimizar solo para p99. Como mínimo, recordemos evitar centrarnos estrictamente en alguna métrica de rendimiento y perder de vista los resultados generales del cliente.