4 formas de cuantificar colas gordas con Python |  de Shawhin Talebi |  diciembre de 2023

Comenzamos importando algunas bibliotecas útiles.

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import powerlaw
from scipy.stats import kurtosis

A continuación, cargaremos cada conjunto de datos y los almacenaremos en un diccionario.

filename_list = ['medium-followers', 'YT-earnings', 'LI-impressions']

df_dict = {}

for filename in filename_list:
df = pd.read_csv('data/'+filename+'.csv')
df = df.set_index(df.columns[0]) # set index
df_dict[filename] = df

En este punto, mirar los datos siempre es una buena idea. Podemos hacerlo trazando histogramas e imprimiendo los 5 registros principales para cada conjunto de datos.

for filename in filename_list:
df = df_dict[filename]

# plot histograms (function bleow is defined in notebook on GitHub)
plot_histograms(df.iloc[:,0][df.iloc[:,0]>0], filename, filename.split('-')[1])
plt.savefig("images/"+filename+"_histograms.png")

# print top 5 records
print("Top 5 Records by Percentage")
print((df.iloc[:,0]/df.iloc[:,0].sum()).sort_values(ascending=False)[:5])
print("")

Histogramas para seguidores medios mensuales. Imagen del autor.
Histogramas de ganancias de videos de YouTube. Nota: si notas una diferencia con el artículo anterior, es porque encontré un registro falso en los datos (por eso buscar es una buena idea 😅). Imagen del autor.
Histogramas de impresiones diarias de LinkedIn. Imagen del autor.

Según los histogramas anteriores, cada conjunto de datos parece tener cola ancha hasta cierto punto. Veamos los 5 registros principales por porcentaje para ver esto de nuevo.

Los 5 registros principales por porcentaje para cada conjunto de datos. Imagen del autor.

Desde este punto de vista, los seguidores de Medium parecen ser los que tienen más cola, con un 60% de seguidores provenientes de solo 2 meses. Las ganancias de YouTube también son muy variables, donde alrededor del 60% de los ingresos provienen de solo 4 videos. Las impresiones de LinkedIn parecen las menos confusas.

Si bien podemos tener una idea cualitativa de la cola gorda con sólo mirando los datoshagamos esto más cuantitativo a través de nuestras 4 heurísticas.

Heurística 1: Índice de cola de la ley de potencia

Para obtener un α Para cada conjunto de datos, podemos usar el ley de potencia biblioteca como lo hicimos en el Artículo anterior. Esto se hace en el bloque de código siguiente, donde realizamos el ajuste e imprimimos las estimaciones de parámetros para cada conjunto de datos en un bucle for.

for filename in filename_list:
df = df_dict[filename]

# perform Power Law fit
results = powerlaw.Fit(df.iloc[:,0])

# print results
print("")
print(filename)
print("-"*len(filename))
print("Power Law Fit")
print("a = " + str(results.power_law.alpha-1))
print("xmin = " + str(results.power_law.xmin))
print("")

Resultados del ajuste de la ley de potencia. Imagen del autor.

Los resultados anteriores coinciden con nuestra evaluación cualitativa de que los seguidores de Medium son los que tienen más cola, seguidos de las ganancias de YouTube y las impresiones de LinkedIn (recuerde, una proporción más pequeña). α significa una cola más gorda).

Heurística 2: Kurtosis

Una forma sencilla de calcular la curtosis es utilizar una implementación disponible en el mercado. Aquí yo uso picante e imprima los resultados de forma similar a como antes.

for filename in filename_list:
df = df_dict[filename]

# print results
print(filename)
print("-"*len(filename))
print("kurtosis = " + str(kurtosis(df.iloc[:,0], fisher=True)))
print("")

Valores de curtosis para cada conjunto de datos. Imagen del autor.

Kurtosis nos cuenta una historia diferente a la Heurística 1. La clasificación de la cola gruesa según esta medida es la siguiente: LinkedIn > Medio > YouTube.

Sin embargo, estos resultados deben tomarse con cautela. Como vimos con los ajustes de la ley de potencia arriba, los 3 conjuntos de datos se ajustan a una ley de potencia con α < 4, lo que significa que la Kurtosis es infinita. Entonces, si bien el cálculo arroja un valor, probablemente sea prudente desconfiar de estos números.

Heurística 3: σ de Log-normal

Podemos volver a utilizar el ley de potencia biblioteca para obtener estimaciones de σ similares a las que hicimos para Heurística 1. Esto es lo que parece.

for filename in filename_list:
df = df_dict[filename]

# perform Power Law fit
results = powerlaw.Fit(df.iloc[:,0])

# print results
print("")
print(filename)
print("-"*len(filename))
print("Log Normal Fit")
print("mu = " + str(results.lognormal.mu))
print("sigma = " + str(results.lognormal.sigma))
print("")

Resultados de ajuste log-normales. Imagen del autor.

Al observar los valores de σ anteriores, vemos que todos los ajustes implican que los datos tienen cola gruesa, donde los seguidores medios y las impresiones de LinkedIn tienen estimaciones de σ similares. Las ganancias de YouTube, por otro lado, tienen un valor σ significativamente mayor, lo que implica una cola (mucho) más gruesa.

Sin embargo, un motivo de sospecha es que el ajuste estima un μ negativo, lo que puede sugerir que un ajuste log-normal puede no explicar bien los datos.

Heurística 4: κ de Taleb

Como no pude encontrar una implementación de Python disponible para calcular κ (no busqué mucho), este cálculo requiere algunos pasos adicionales. Es decir, necesitamos definir 3 funciones auxiliares, como se muestra a continuación.

def mean_abs_deviation(S):
"""
Computation of mean absolute deviation of an input sample S
"""
M = np.mean(np.abs(S - np.mean(S)))

return M

def generate_n_sample(X,n):
"""
Function to generate n random samples of size len(X) from an array X
"""
# initialize sample
S_n=0

for i in range(n):
# ramdomly sample len(X) observations from X and add it to the sample
S_n = S_n + X[np.random.randint(len(X), size=int(np.round(len(X))))]

return S_n

def kappa(X,n):
"""
Taleb's kappa metric from n0=1 as described here: https://arxiv.org/abs/1802.05495

Note: K_1n = kappa(1,n) = 2 - ((log(n)-log(1))/log(M_n/M_1)), where M_n denotes the mean absolute deviation of the sum of n random samples
"""
S_1 = X
S_n = generate_n_sample(X,n)

M_1 = mean_abs_deviation(S_1)
M_n = mean_abs_deviation(S_n)

K_1n = 2 - (np.log(n)/np.log(M_n/M_1))

return K_1n

La primera función, media_abs_desviación(), calcula la desviación absoluta media como se definió anteriormente.

A continuación, necesitamos una forma de generar y sumar. norte muestras de nuestros datos empíricos. Aquí, adopto un enfoque ingenuo y muestro aleatoriamente una matriz de entrada (X) norte veces y sumar las muestras.

Finalmente, reúno desviación_abs_media(S) y generar_n_muestra(X,n) para implementar el cálculo de κ definido anteriormente y calcularlo para cada conjunto de datos.

n = 100 # number of samples to include in kappa calculation

for filename in filename_list:
df = df_dict[filename]

# print results
print(filename)
print("-"*len(filename))
print("kappa_1n = " + str(kappa(df.iloc[:,0].to_numpy(), n)))
print("")

Valores de κ (1100) para cada conjunto de datos. Imagen del autor.

Los resultados anteriores nos dan otra historia más. Sin embargo, dada la aleatoriedad implícita de este cálculo (recordemos generar_n_muestra() definición) y el hecho de que estamos tratando con colas gruesas, no se puede confiar en las estimaciones puntuales (es decir, simplemente ejecutar el cálculo una vez).

En consecuencia, ejecuto el mismo cálculo 1000x e imprimo la media k(1,100) para cada conjunto de datos.

num_runs = 1_000
kappa_dict = {}

for filename in filename_list:
df = df_dict[filename]

kappa_list = []
for i in range(num_runs):
kappa_list.append(kappa(df.iloc[:,0].to_numpy(), n))

kappa_dict[filename] = np.array(kappa_list)

print(filename)
print("-"*len(filename))
print("mean kappa_1n = " + str(np.mean(kappa_dict[filename])))
print("")

Valores medios de κ(1100) de 1000 ejecuciones para cada conjunto de datos. Imagen del autor.

Estos resultados más estables indican que los seguidores de Medium son los que tienen más cola, seguidos de las impresiones de LinkedIn y las ganancias de YouTube.

Nota: Se pueden comparar estos valores con la Tabla III en la referencia. [3] para comprender mejor cada valor de κ. Es decir, estos valores son comparables a una distribución de Pareto con α entre 2 y 3.

Aunque cada heurística cuenta una historia ligeramente diferente, todas las señales apuntan a que los seguidores medios obtenidos son los que tienen más cola de los 3 conjuntos de datos.

Si bien etiquetar datos binarios como de cola gruesa (o no) puede resultar tentador, la cola gruesa vive en un espectro. Aquí, desglosamos 4 heurísticas para cuantificar que cola gorda los datos son.

Aunque cada enfoque tiene sus limitaciones, proporcionan a los profesionales formas cuantitativas de comparar la complejidad de los datos empíricos.

👉 Más sobre las leyes de potencia y las colas gordas: Introducción | Ajustes de la ley de potencia