Desde la perspectiva del análisis exploratorio de datos, las medidas de localización responden a una pregunta fundamental: ¿en qué región de valores tiende a concentrarse el fenómeno observado?. En términos prácticos, esto permite identificar valores típicos, comparar distribuciones y comenzar a interpretar el comportamiento general del sistema antes de pasar a medidas de dispersión, forma o segmentación.
El dataset incluye variables numéricas como Item_Weight, Item_Visibility, Item_MRP y Item_Outlet_Sales, junto con variables categóricas asociadas a tipo de producto, establecimiento y ubicación del outlet. Para este primer analisis nos enfocaremos en el comportamiento univariado de las variables numéricas, usando medidas como la media, la mediana, la moda y algunos cuantiles.
Preparación del entorno
Trabajaremos con el siguiente dataset BigMart, para esta sección usaremos Python y las bibliotecas pandas, numpy, plotly y matplotlib.
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltplt.rcParams["figure.figsize"] = (8, 4.5)plt.rcParams["axes.grid"] =TrueDATA_PATH ="../../data/bigmart_sales.csv"df = pd.read_csv(DATA_PATH)df.head()
Item_Identifier
Item_Weight
Item_Fat_Content
Item_Visibility
Item_Type
Item_MRP
Outlet_Identifier
Outlet_Establishment_Year
Outlet_Size
Outlet_Location_Type
Outlet_Type
Item_Outlet_Sales
0
FDA15
9.30
Low Fat
0.016047
Dairy
249.8092
OUT049
1999
Medium
Tier 1
Supermarket Type1
3735.1380
1
DRC01
5.92
Regular
0.019278
Soft Drinks
48.2692
OUT018
2009
Medium
Tier 3
Supermarket Type2
443.4228
2
FDN15
17.50
Low Fat
0.016760
Meat
141.6180
OUT049
1999
Medium
Tier 1
Supermarket Type1
2097.2700
3
FDX07
19.20
Regular
0.000000
Fruits and Vegetables
182.0950
OUT010
1998
NaN
Tier 3
Grocery Store
732.3800
4
NCD19
8.93
Low Fat
0.000000
Household
53.8614
OUT013
1987
High
Tier 3
Supermarket Type1
994.7052
Inspección inicial
Antes de calcular medidas de localización conviene identificar el tipo de variables disponibles y confirmar qué columnas numéricas serán analizadas.
En este punto es útil destacar que no todas las variables numéricas tienen el mismo significado. Por ejemplo, Item_MRP representa el precio máximo sugerido del producto, mientras que Item_Outlet_Sales corresponde a las ventas del producto en un outlet particular. La interpretación del “centro” de cada variable, por tanto, depende del contexto económico de la medición.
Selección de variables para el análisis de localización
Para esta etapa trabajaremos con un subconjunto de variables numéricas especialmente interpretables:
Item_Weight
Item_Visibility
Item_MRP
Item_Outlet_Sales
Crearemos un nuevo dataframe con estas columnas para facilitar el análisis, identificando además el número de datos faltantes en las mismas.
Datos faltantes y su impacto en el análisis de localización
La presencia de valores faltantes en la variable Item_Weight no impide comenzar el análisis descriptivo de localización, sin embargo, eliminarlos sin analizar su origen puede introducir sesgos en los resultados. Por ello, antes de calcular medidas descriptivas es necesario examinar la magnitud y el posible patrón de los datos ausentes. Extrayendo un dataframe con los casos faltantes en Item_Weight tenemos:
Si bien no es el objetivo de esta sección resolver el problema de los datos faltantes, es importante tener una noción clara de su impacto. Para esto existen tres preguntas clave que podemos hacernos en estos casos:
¿Qué porcentaje de datos faltantes hay en la variable?
Este paso permite dimensionar la magnitud del problema. Calcular la proporción de valores ausentes respecto al total de observaciones ayuda a evaluar si los faltantes representan una fracción pequeña del dataset o si son lo suficientemente numerosos como para afectar la representatividad del análisis.
print(f"Porcentaje de datos faltantes en Item_Weight: {missing_report.loc['Item_Weight', 'missing_pct']:.2f}%")
Porcentaje de datos faltantes en Item_Weight: 17.17%
En nuestro caso la variable presenta aproximadamente un 17 % de valores faltantes, lo que implica que cerca de una sexta parte de las observaciones no contiene información para este atributo. Esta proporción no es despreciable, por lo que antes de excluir estos registros conviene examinar si los datos faltantes siguen algún patrón sistemático y evaluar el posible impacto de su eliminación en el análisis exploratorio.
¿Existen patrones de ausencia relacionados con otras variables?
Aquí se busca identificar si los datos faltantes aparecen de manera aleatoria o si se concentran en ciertos grupos (por ejemplo, en determinadas categorías de producto, tipos de outlet o rangos de precio). Detectar patrones de ausencia es importante porque podría indicar un posible sesgo en los datos.
Analicemos el promedio de valores faltantes en Item_Weight por tipo de producto y tipo de outlet:
Podemos observar como la falta de datos en Item_Weight se concentra principalmete en 2 tipos de outlets : Grocery Store y Supermarket Type1. Esto sugiere que la ausencia de información no es aleatoria en estos casos, mientras que tenemos una distribución más equilibrada en Item_Type.
Este patrón de ausencia podría estar relacionado con la naturaleza de los productos comercializados en esos outlets o con prácticas de registro de datos específicas, lo que implica que eliminar estos casos sin un análisis previo podría sesgar el análisis descriptivo.
import pandas as pdimport plotly.express as px# Proporción de missing de Item_Weight por Outlet_Typemissing_outlet = ( df['Item_Weight'] .isna() .groupby(df['Outlet_Type']) .mean() .mul(100) .reset_index(name='pct_missing') .sort_values('pct_missing', ascending=False))fig = px.bar( missing_outlet, x='Outlet_Type', y='pct_missing', color='pct_missing', color_continuous_scale='Reds', text='pct_missing', labels={'Outlet_Type': 'Tipo de outlet','pct_missing': '% de faltantes en Item_Weight' }, title='Porcentaje de valores faltantes de Item_Weight por Outlet_Type')fig.update_traces( texttemplate='%{text:.1f}%', textposition='outside')fig.update_layout( yaxis_title='% de faltantes', xaxis_title='Tipo de outlet', coloraxis_colorbar_title='% faltante')fig.show()
¿Cuál es el impacto potencial de eliminar casos con datos faltantes en el análisis?
En este punto, la pregunta clave ya no es solo si existen datos faltantes, sino si su eliminación cambia nuestra lectura general de los datos. Por ello, una forma natural de continuar el EDA es comparar medidas de localización antes y después de excluir los casos incompletos. Si estas medidas permanecen estables, la omisión de dichos registros tendría un impacto limitado; si cambian de manera apreciable, entonces la ausencia de datos sí afecta la interpretación.
Con lo cual procederemos en las siguientes secciones a evaluar estas medidas de localizacion asociadas.
Medidas de localización básicas
Como vimos en el capitulo pasado las medidas más usadas en esta etapa son:
Mediana: valor que deja 50% de observaciones a cada lado.
Moda: valor más frecuente. En variables continuas muchas veces es más útil hablar de la región modal observada en un histograma.
Cuantiles: percentiles como \(Q_{0.25}\), \(Q_{0.50}\) y \(Q_{0.75}\).
Estas se pueden conocer de manera rápida en pandas mediante los métodos mean(), median(), mode() y quantile(). Para facilitar la lectura comparativa, conviene construir una tabla resumen con estas medidas para cada variable numérica clave.
def mode_series(s): m = s.mode(dropna=True)iflen(m) ==0:return np.naniflen(m) ==1:return m.iloc[0]return m.iloc[:5].tolist()summary_loc = pd.DataFrame({"media": df[vars_localizacion].mean(numeric_only=True),"mediana": df[vars_localizacion].median(numeric_only=True),"moda": [mode_series(df[c]) for c in vars_localizacion],"q25": df[vars_localizacion].quantile(0.25),"q75": df[vars_localizacion].quantile(0.75),"min": df[vars_localizacion].min(numeric_only=True),"max": df[vars_localizacion].max(numeric_only=True),})summary_loc
media
mediana
moda
q25
q75
min
max
Item_Weight
12.857645
12.600000
12.1500
8.773750
16.850000
4.555
21.350000
Item_Visibility
0.066132
0.053931
0.0000
0.026989
0.094585
0.000
0.328391
Item_MRP
140.992782
143.012800
172.0422
93.826500
185.643700
31.290
266.888400
Item_Outlet_Sales
2181.288914
1794.331000
958.7520
834.247400
3101.296400
33.290
13086.964800
Esta tabla permite una primera lectura comparativa. La relación entre media y mediana es particularmente informativa. Si ambas están muy próximas, la distribución podría ser relativamente simétrica o al menos no estar muy afectada por colas extremas. Si difieren de forma notable, conviene anticipar que más adelante aparecerán señales de asimetría.
Interpretación estadística de la media y la mediana
En datos de ventas es común encontrar distribuciones con sesgo a la derecha. Esto significa que la mayor parte de las observaciones se agrupan en niveles bajos o medios, pero existe una cola de valores altos que empuja la media hacia arriba. En ese caso, la media deja de representar un valor “típico” tan bien como la mediana.
Podemos ilustrarlo directamente con histogramas sobre los que se tracen ambas medidas.
from plotly.subplots import make_subplotsimport plotly.graph_objects as gofig = make_subplots( rows=2, cols=2, subplot_titles=vars_localizacion)for i, col inenumerate(vars_localizacion): s = df[col].dropna() row = i //2+1 col_pos = i %2+1 media = s.mean() mediana = s.median()# Histograma fig.add_trace( go.Histogram( x=s, nbinsx=30, name=col, showlegend=False ), row=row, col=col_pos )# Línea de la media fig.add_vline( x=media, line_dash="dash", line_width=2, annotation_text=f"Media = {media:.2f}", annotation_position="top right", row=row, col=col_pos )# Línea de la mediana fig.add_vline( x=mediana, line_dash="dot", line_width=2, annotation_text=f"Mediana = {mediana:.2f}", annotation_position="top left", row=row, col=col_pos ) fig.update_xaxes(title_text=col, row=row, col=col_pos) fig.update_yaxes(title_text="Frecuencia", row=row, col=col_pos)fig.update_layout(# title="Distribuciones con media y mediana", height=700, width=1000, bargap=0.05)fig.show()
La superposición de estas líneas verticales ofrece una interpretación inmediata. En particular, si en Item_Outlet_Sales la media aparece sensiblemente a la derecha de la mediana, puede concluirse que las ventas no se distribuyen de forma simétrica y que existen casos de ventas altas elevan el promedio. En cambio, si en Item_MRP ambas medidas son relativamente cercanas, la estructura de precios podría ser más estable o menos sesgada.
Cuantiles y lectura ampliada del centro
Cuando hablamos de localización, no siempre basta con resumir una variable mediante un único valor, como la media o la mediana. En muchos casos, resulta más útil describir la zona central donde se concentra la mayor parte de las observaciones. Para ello, los cuantiles son especialmente importantes.
En particular, los percentiles 25, 50 y 75 permiten identificar el tramo donde se encuentra el 50 % central de los datos. Esta información ayuda a responder preguntas más ricas que un simple “¿cuál es el promedio?”, por ejemplo:
¿entre qué valores se concentra la mitad central de los casos?
¿qué tan alejados están los valores altos respecto del centro?
¿la mediana representa bien a la distribución o existen asimetrías importantes?
La tabla de cuantiles permite ampliar la lectura del centro. Mientras la media resume la localización en un solo número, los cuantiles muestran cómo se distribuyen los datos alrededor de esa zona central. Así, el percentil 25 marca el punto por debajo del cual se encuentra el 25 % de las observaciones, la mediana divide la distribución en dos partes iguales, y el percentil 75 indica el límite superior del 50 % central.
Para complementar esta lectura, es útil recurrir a los boxplots, ya que representan visualmente la mediana, los cuartiles, la dispersión central y la posible presencia de valores atípicos.
from plotly.subplots import make_subplotsimport plotly.graph_objects as gofig = make_subplots( rows=2, cols=2, subplot_titles=vars_localizacion)for i, var inenumerate(vars_localizacion): row = i //2+1 col = i %2+1 fig.add_trace( go.Box( y=df[var].dropna(), name=var, boxpoints="outliers", showlegend=False ), row=row, col=col )fig.update_layout( title="Boxplots de variables seleccionadas", height=700, width=900)fig.show()
A partir de estos gráficos, la interpretación ya no se limita a un valor “promedio”, sino que puede centrarse en la estructura de la distribución. En particular, los boxplots permiten observar:
dónde se ubica la mediana;
qué tan amplio es el rango intercuartílico;
si la distribución parece simétrica o sesgada;
y si existen valores atípicos que puedan influir en la media.
De esta forma, los cuantiles y los boxplots enriquecen el análisis de localización, porque muestran no solo un centro numérico, sino también la región en la que efectivamente se concentra la mayor parte de los datos.
Impacto de eliminar faltantes en Item_Weight
Para evaluar si eliminar las observaciones con valores faltantes en Item_Weight introduce sesgos en el análisis, compararemos el comportamiento del dataset antes y después de excluir dichos casos. La idea es verificar si esta reducción de la muestra modifica de forma importante la localización de otras variables relevantes y la composición general de los datos.
Primero construimos dos subconjuntos:
el dataset original;
el dataset filtrado, conservando solo las observaciones con Item_Weight disponible.
Los resultados muestran que la eliminación de observaciones con Item_Weight faltante produce cambios pequeños en las medidas de localización de las variables analizadas. Si bien en algunos casos las diferencias porcentuales superan ligeramente el 2 %, especialmente en Item_Outlet_Sales e Item_Visibility, la magnitud de estas variaciones no parece suficiente para modificar de manera sustantiva la interpretación general del centro de las distribuciones. Por ello, dentro del contexto de este EDA, trabajar con los casos completos puede considerarse una decisión razonable y con bajo riesgo de sesgo en términos de localización.
Ejercicio sugerido
Construya una versión inicial de dashboard en Quarto que incluya:
una tabla resumen con media, mediana y cuantiles de las variables numéricas seleccionadas;
un histograma con líneas para media y mediana de Item_Outlet_Sales;
un gráfico de barras con la mediana de ventas por Outlet_Type;
un breve comentario interpretativo donde se compare el uso de la media frente a la mediana.