W3docs

Percentiles en Python con NumPy

Aprende a calcular percentiles en Python con NumPy. Cubre cuartiles, detección de valores atípicos con IQR, métodos de interpolación y casos de uso en ML.

Un percentil indica el valor por debajo del cual cae un porcentaje determinado de las observaciones de tu conjunto de datos. Si un estudiante obtiene el percentil 80 en un examen, el 80 % de las puntuaciones están por debajo de la suya. Los percentiles son un pilar del análisis exploratorio de datos y se utilizan en machine learning para la detección de valores atípicos, el recorte de características y la generación de informes sobre el rendimiento del modelo en diferentes subgrupos.

Este capítulo abarca:

  • Qué es un percentil y cómo se calcula
  • Cómo usar numpy.percentile() y numpy.quantile()
  • Cuartiles y el resumen de cinco números
  • El rango intercuartílico (IQR) para la detección de valores atípicos
  • Métodos de interpolación y cuándo importan
  • Cómo obtener el rango percentil de un valor específico con SciPy
  • Casos de uso prácticos en ML: winsorización y recorte de datos

¿Qué es un percentil?

Un percentil divide un conjunto de datos ordenado en 100 partes iguales. El percentil P es el valor en o por debajo del cual cae el P por ciento de los datos.

PercentilNombre comúnSignificado
25Q1 (primer cuartil)El 25 % de los valores están por debajo de este punto
50Q2 / MedianaLa mitad de los valores están por debajo de este punto
75Q3 (tercer cuartil)El 75 % de los valores están por debajo de este punto
90El 90 % de los valores están por debajo de este punto

Los percentiles están estrechamente relacionados con la media, la mediana y la moda: el percentil 50 es exactamente la mediana.

Percentil vs. cuantil

Ambos términos se usan a menudo de manera intercambiable. Un cuantil expresa la misma idea usando una fracción de 0 a 1 en lugar de un porcentaje de 0 a 100:

  • El percentil 25 = el cuantil 0,25
  • El percentil 75 = el cuantil 0,75

NumPy ofrece tanto np.percentile() como np.quantile(). Se comportan de forma idéntica; elige el que haga tu código más claro.

Calcular un percentil con NumPy

numpy.percentile(a, q) recibe un array-like a y un percentil q (0–100) y devuelve el valor interpolado en esa posición.

Calcular el percentil 75 de un conjunto de datos

import numpy as np

data = [10, 20, 30, 40, 50]
result = np.percentile(data, 75)
print(result)  # Output: 40.0

Pasa una lista a q para calcular varios percentiles en una sola llamada — NumPy los devuelve en un array:

Calcular los percentiles 25, 50 y 75 a la vez

import numpy as np

data = [10, 20, 30, 40, 50]
p25, p50, p75 = np.percentile(data, [25, 50, 75])
print(f'Q1 = {p25}')  # Output: Q1 = 20.0
print(f'Q2 = {p50}')  # Output: Q2 = 30.0
print(f'Q3 = {p75}')  # Output: Q3 = 40.0

Usar np.quantile()

np.quantile() acepta una fracción (0,0–1,0) en lugar de un porcentaje:

Usar np.quantile() con un argumento de fracción

import numpy as np

data = [10, 20, 30, 40, 50]
q1 = np.quantile(data, 0.25)
q3 = np.quantile(data, 0.75)
print(f'Q1 = {q1}')  # Output: Q1 = 20.0
print(f'Q3 = {q3}')  # Output: Q3 = 40.0

Cuartiles y el resumen de cinco números

Los tres cuartiles (Q1, Q2, Q3) junto con el mínimo y el máximo forman el resumen de cinco números — una instantánea compacta de la dispersión de cualquier conjunto de datos. Puedes calcular los cinco valores en una sola llamada:

Calcular el resumen de cinco números

import numpy as np

data = [10, 20, 30, 40, 50]
minimum, q1, median, q3, maximum = np.percentile(data, [0, 25, 50, 75, 100])

print(f'Min    = {minimum}')   # Output: Min    = 10.0
print(f'Q1     = {q1}')        # Output: Q1     = 20.0
print(f'Median = {median}')    # Output: Median = 30.0
print(f'Q3     = {q3}')        # Output: Q3     = 40.0
print(f'Max    = {maximum}')   # Output: Max    = 50.0

El resumen de cinco números es la base de un diagrama de caja (box plot), que puedes dibujar con Matplotlib (consulta Histogramas en Matplotlib para técnicas de visualización relacionadas).

El rango intercuartílico y la detección de valores atípicos

El rango intercuartílico (IQR) es la distancia entre Q1 y Q3:

IQR = Q3 − Q1

Describe la dispersión del 50 % central de los datos. Como ignora los cuartos superior e inferior, el IQR es robusto frente a valores extremos, lo que lo convierte en la herramienta estándar para la detección de valores atípicos basada en reglas.

La regla del cercado de Tukey marca como posible valor atípico cualquier valor que supere 1,5 × IQR más allá de cualquiera de los cuartiles:

  • Valla inferior: Q1 − 1,5 × IQR
  • Valla superior: Q3 + 1,5 × IQR

Detectar valores atípicos con el método IQR

import numpy as np

data = [5, 7, 8, 9, 10, 11, 12, 13, 14, 80]

q1 = np.percentile(data, 25)
q3 = np.percentile(data, 75)
iqr = q3 - q1

lower_fence = q1 - 1.5 * iqr
upper_fence = q3 + 1.5 * iqr

outliers = [x for x in data if x < lower_fence or x > upper_fence]

print(f'Q1 = {q1}, Q3 = {q3}, IQR = {iqr}')
# Output: Q1 = 8.25, Q3 = 12.75, IQR = 4.5

print(f'Lower fence = {lower_fence}, Upper fence = {upper_fence}')
# Output: Lower fence = 1.5, Upper fence = 19.5

print(f'Outliers: {outliers}')
# Output: Outliers: [80]

El valor 80 supera ampliamente la valla superior de 19,5, por lo que se marca como valor atípico. El método IQR es ampliamente utilizado porque no requiere ninguna suposición sobre la distribución de los datos subyacente.

Métodos de interpolación

Cuando el percentil solicitado cae entre dos puntos de datos, NumPy interpola. El parámetro method (añadido en NumPy 1.22, en sustitución del antiguo parámetro interpolation) controla cómo se realiza esta operación.

Comparar métodos de interpolación en el percentil 35

import numpy as np

data = [10, 20, 30, 40, 50]
# The 35th percentile falls between 20 (index 1) and 30 (index 2)

print(np.percentile(data, 35, method='linear'))    # Output: 24.0  (default)
print(np.percentile(data, 35, method='lower'))     # Output: 20
print(np.percentile(data, 35, method='higher'))    # Output: 30
print(np.percentile(data, 35, method='midpoint'))  # Output: 25.0
print(np.percentile(data, 35, method='nearest'))   # Output: 20
MétodoDescripciónCuándo usarlo
linearMedia ponderada de los dos valores adyacentesPor defecto; estadísticamente más correcto
lowerDevuelve el menor de los dos valores adyacentesCuando se requieren índices enteros
higherDevuelve el mayor de los dos valores adyacentesLímites superiores conservadores
midpointMedia de lower y higherInformes simples de punto medio
nearestPunto de datos real más cercanoCuando el resultado debe ser una observación real

Para la mayoría de los trabajos de análisis de datos y ML, el método linear predeterminado es la opción correcta.

Obtener el rango percentil de un valor

A veces tienes la pregunta inversa: dado un valor, ¿en qué percentil se encuentra? Usa scipy.stats.percentileofscore():

Encontrar el rango percentil que ocupa un valor específico

from scipy import stats

data = [10, 20, 30, 40, 50]

rank = stats.percentileofscore(data, 30)
print(rank)  # Output: 60.0

rank_of_25 = stats.percentileofscore(data, 25)
print(rank_of_25)  # Output: 40.0

Una puntuación de 30 está en el percentil 60, lo que significa que el 60 % de los valores de data son iguales o inferiores a 30.

Caso de uso práctico en ML: winsorización

La winsorización (también llamada clipping) limita los valores extremos al límite de un percentil elegido en lugar de eliminarlos. Esto conserva el número de filas mientras reduce la influencia de los valores atípicos en el entrenamiento del modelo.

Recortar valores atípicos al rango del percentil 10 al 90

import numpy as np

data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200]

lower = np.percentile(data, 10)
upper = np.percentile(data, 90)

clipped = np.clip(data, lower, upper)

print(f'Lower bound (10th): {lower}')  # Output: Lower bound (10th): 20.0
print(f'Upper bound (90th): {upper}')  # Output: Upper bound (90th): 100.0
print('Clipped:', list(clipped))
# Output: Clipped: [20.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 100.0]

Ambos valores extremos — 10 (por debajo del límite del percentil 10, que es 20) y 200 (por encima del límite del percentil 90, que es 100) — se recortan al valor de la valla. La winsorización es un paso de preprocesamiento habitual antes de entrenar modelos lineales o redes neuronales, especialmente con datos financieros o de sensores donde las lecturas extremas son frecuentes.

Para más información sobre los enfoques de escalado de características que complementan el recorte basado en percentiles, consulta el capítulo Scale.

Referencia rápida

TareaFunciónEjemplo
Percentil individualnp.percentile(data, q)np.percentile(data, 75)
Varios percentilesnp.percentile(data, [q1, q2, …])np.percentile(data, [25, 50, 75])
Cuantil (escala 0–1)np.quantile(data, q)np.quantile(data, 0.75)
Resumen de cinco númerosnp.percentile(data, [0,25,50,75,100])
IQRQ3 − Q1np.percentile(data, 75) - np.percentile(data, 25)
Rango percentil de un valorscipy.stats.percentileofscore(data, v)
Recortar a límites de percentilnp.clip(data, lower, upper)np.clip(data, p10, p90)

Temas relacionados

  • Media, mediana y moda — medidas de tendencia central; el percentil 50 es la mediana.
  • Desviación estándar — mide la dispersión alrededor de la media; complementa el IQR.
  • Distribución de datos — comprende la asimetría y los valores atípicos antes de elegir estadísticas de resumen.
  • Scale — técnicas de escalado de características para el preprocesamiento en ML.
  • Tutorial de NumPy — habilidades fundamentales de NumPy utilizadas a lo largo de este capítulo.

Conclusión

Los percentiles clasifican los valores dentro de un conjunto de datos y revelan su forma de maneras que la media y la desviación estándar no pueden. Con numpy.percentile(), calcular Q1, Q2, Q3 y el IQR requiere una sola línea de Python. En machine learning, los percentiles aparecen en cada etapa: en el análisis exploratorio de datos para detectar valores atípicos, en el preprocesamiento para winsorizar valores extremos y en la evaluación para comprender la precisión del modelo a lo largo de la distribución de tus datos. Dominarlos te proporciona una herramienta fiable y sin suposiciones que funciona con cualquier conjunto de datos independientemente de su distribución.

Was this page helpful?