Adidas es una de las empresas más reconocidas en la industria del deporte y el estilo de vida deportivo a nivel mundial. Fundada en 1949 en Alemania, ha consolidado su presencia en más de 160 países, ofreciendo una amplia gama de productos que incluyen calzado deportivo, ropa y equipamiento, distribuidos a través de canales propios, minoristas asociados y comercio electrónico.
El análisis comercial y financiero de Adidas es clave para evaluar su desempeño en el mercado, identificar tendencias y comprender los factores que impulsan su rentabilidad y estabilidad. En este documento, realizaremos un análisis exploratorio y diagnóstico de las variables clave de ventas y rentabilidad de Adidas —precio por unidad, unidades vendidas, ventas totales, utilidad operativa y margen operativo— desagregadas por región, ciudad, distribuidor y método de venta, utilizando R. Aplicaremos técnicas de estadística descriptiva, medidas de variabilidad y visualización de datos para detectar patrones, valores atípicos y relaciones entre variables, facilitando una mejor interpretación de su desempeño comercial.
A través de este análisis, se busca proporcionar una visión más clara del comportamiento de las ventas y la rentabilidad de Adidas por segmento, lo cual puede ser útil para tomadores de decisiones comerciales, analistas de negocio y académicos interesados en la industria del retail deportivo.
El análisis exploratorio de datos (EDA) es un paso clave para comprender la información de venta de adidas, para identificar patrones y evaluar la distribución de las variables.
PASO 1. Instalar y cargar librerias
# Cargar librerías necesarias
library(readxl)
library(dplyr)
library(ggplot2)
library(plotly)
library(knitr)
library(kableExtra)
library(tidyr)
library(RecordLinkage)
library(leaflet)
library(htmltools)
library(corrplot)
library(reshape2)
library(patchwork)
library(scales)
library(tidygeocoder)
PASO 2: Limpieza y validación de datos
El código siguiente carga un archivo de Excel con datos de ventas de Adidas y filtra las unidades diferentes a 0, permitiendo contar con información mas aterrizada .
library(readxl)
library(dplyr)
datos<- read_excel("DatosCaso1.xlsx",
col_types = c("text", "text", "text",
"text", "text", "numeric", "numeric",
"numeric", "numeric", "numeric",
"text"))
#Filtro: quitar filas sin datos o con unidades_vendidas <= 0
datos <- datos %>%
filter(!is.na(unidades_vendidas), unidades_vendidas > 0)
dim(datos) # verificar cuántas filas quedaron
## [1] 9644 11
A continuación, procederemos a validar que los cálculos correspondientes a las variables ventas totales, margen operativo y utilidad operativa hayan sido elaborados correctamente en la base de datos de Excel, con el propósito de garantizar la confiabilidad de la información presentada en el informe.
library(dplyr)
library(kableExtra)
# Tolerancia para diferencias de redondeo
tolerancia <- 0.01
validacion <- datos %>%
mutate(
# 1. ventas_total debería ser precio_unidad * unidades_vendidas
ventas_calculada = precio_unidad * unidades_vendidas,
diff_ventas = abs(ventas_total - ventas_calculada),
ventas_ok = diff_ventas <= tolerancia,
# 2. margen_operativo debería ser utilidad_operativa / ventas_total
margen_calculado = utilidad_operativa / ventas_total,
diff_margen = abs(margen_operativo - margen_calculado),
margen_ok = diff_margen <= tolerancia,
# 3. utilidad_operativa debería ser ventas_total * margen_operativo
utilidad_calculada = ventas_total * margen_operativo,
diff_utilidad = abs(utilidad_operativa - utilidad_calculada),
utilidad_ok = diff_utilidad <= tolerancia
)
# Resumen en formato "bonito"
resumen_validacion <- data.frame(
Variable = c("ventas_total", "margen_operativo", "utilidad_operativa"),
Formula_esperada = c("precio_unidad × unidades_vendidas",
"utilidad_operativa / ventas_total",
"ventas_total × margen_operativo"),
Correctas = c(sum(validacion$ventas_ok, na.rm = TRUE),
sum(validacion$margen_ok, na.rm = TRUE),
sum(validacion$utilidad_ok, na.rm = TRUE)),
Incorrectas = c(sum(!validacion$ventas_ok, na.rm = TRUE),
sum(!validacion$margen_ok, na.rm = TRUE),
sum(!validacion$utilidad_ok, na.rm = TRUE))
) %>%
mutate(Porcentaje_correcto = percent(Correctas / (Correctas + Incorrectas), accuracy = 0.1))
resumen_validacion %>%
kable(col.names = c("Variable", "Fórmula esperada", "Filas correctas",
"Filas incorrectas", "% Correcto"),
caption = "Figura 1. Validación de consistencia de variables Adidas") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE, position = "center") %>%
row_spec(0, background = "#ADD8E6", bold = TRUE, color = "black") %>%
column_spec(1, bold = TRUE)
| Variable | Fórmula esperada | Filas correctas | Filas incorrectas | % Correcto |
|---|---|---|---|---|
| ventas_total | precio_unidad × unidades_vendidas | 9644 | 0 | 100.0% |
| margen_operativo | utilidad_operativa / ventas_total | 9644 | 0 | 100.0% |
| utilidad_operativa | ventas_total × margen_operativo | 9644 | 0 | 100.0% |
De las 9644 transacciones, las 3 relaciones se cumplen al 100%
Indicadores de centralidad
library(dplyr)
library(kableExtra)
# Vector con las 5 variables numéricas
variables_num <- c("precio_unidad", "unidades_vendidas", "ventas_total",
"utilidad_operativa", "margen_operativo")
# Calcular los indicadores para cada variable
tabla_indicadores <- data.frame(
Variable = variables_num,
Media = sapply(datos[variables_num], mean, na.rm = TRUE),
Mediana = sapply(datos[variables_num], median, na.rm = TRUE),
Minimo = sapply(datos[variables_num], min, na.rm = TRUE),
Maximo = sapply(datos[variables_num], max, na.rm = TRUE),
row.names = NULL
)
# Tabla visual con encabezado azul claro
tabla_indicadores %>%
kable(digits = 2, caption = "Figura 2. Indicadores de centralidad y variabilidad Adidas") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE, position = "center") %>%
row_spec(0, background = "#ADD8E6", bold = TRUE, color = "black") %>%
column_spec(1, bold = TRUE)
| Variable | Media | Mediana | Minimo | Maximo |
|---|---|---|---|---|
| precio_unidad | 45.22 | 45.00 | 7.0 | 110.0 |
| unidades_vendidas | 257.04 | 176.00 | 6.0 | 1275.0 |
| ventas_total | 12460.25 | 7812.00 | 160.0 | 82500.0 |
| utilidad_operativa | 4896.82 | 3264.00 | 75.2 | 39000.0 |
| margen_operativo | 0.42 | 0.41 | 0.1 | 0.8 |
- Precio unidad: Media y mediana casi igual, lo que indica que tienen una distribución simetrica entre ambas variables estadisticas,por lo tanto, podemos decir que el precio por unidad presenta un comportamiento bastante estable dentro de los datos analizados.
- Unidades vendidas: Tiene una distribución asimetrica a la derecha, ya que hay transacciones con volumenenes cercanos al valor maximo, lo genera que el promedio tenga una tendencia hacia arriba
- Ventas totales: Al igual que las unidades vendidas, presenta una distribución asimetrica a la derecha, existen ventas particularmente elevada lo que hala el promedio hacia arriba muy por encima de la mediana.
- Utilidad operativa: En lo analizado de la utilidad operativa se puede identificar que teniendo en cuenta la mediana, el 50% de los datos se encuentran por encima de los 3264 dolares, en comparación con la media, se identifica que esta variable tiene valores extremos y en relación con la variables anteriores, el comportamiento es coherente ya que la utilidad depende directamente de las ventas.
- Margen operativo: A diferencia de las variables anteriores, la media y la mediana son practicamente iguales, lo que indica que el porcentaje de rentabilidad se matiene estable entre transacciones.
library(dplyr)
library(kableExtra)
library(scales)
# ---- Tabla 1: Ventas totales por Distribuidor ----
tabla_distribuidor <- datos %>%
group_by(distribuidor) %>%
summarise(
Ventas_totales = sum(ventas_total, na.rm = TRUE),
N_transacciones = n(),
.groups = "drop"
) %>%
mutate(Participacion = Ventas_totales / sum(Ventas_totales)) %>%
arrange(desc(Ventas_totales))
tabla_distribuidor %>%
kable(digits = 2,
col.names = c("Distribuidor", "Ventas totales", "N° Transacciones", "Participación (%)"),
format.args = list(big.mark = ","),
caption = "Figura 3. Ventas totales por distribuidor Adidas") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE, position = "center") %>%
row_spec(0, background = "#ADD8E6", bold = TRUE, color = "black") %>%
column_spec(1, bold = TRUE)
| Distribuidor | Ventas totales | N° Transacciones | Participación (%) |
|---|---|---|---|
| West Gear | 32,409,558 | 2,374 | 0.27 |
| Foot Locker | 29,024,945 | 2,633 | 0.24 |
| Sports Direct | 24,616,622 | 2,032 | 0.20 |
| Kohl’s | 13,512,453 | 1,030 | 0.11 |
| Walmart | 10,506,085 | 626 | 0.09 |
| Amazon | 10,096,987 | 949 | 0.08 |
Validando la Figura 3. podemos observar que existe una concentración en la paticipación de ventas de la siguiente manera: West Gear (27%), Foot Locker (24%) y Sports Direct (20%) , los 3 distribuidores representan el 71% de las ventas totales, mientras que Kohl’s, Walmart y Amazon representan al 29%. Esto quiere decir que Adidas depende principalmente de estos tres primeros distribuidores.
Se identifica que Foot Locker tiene un mayor numero de transacciones que West Gear (2,633 vs. 2,374), pero menos ventas totales. Esto se traduce en que no es solo la cantidad de ventas lo que determina el liderazgo, sino también el tamaño promedio de cada transacción que se realiza por lo anterior validaremos el ticket promedio de cada distribuidor para confirmarlo.
library(dplyr)
library(kableExtra)
library(scales)
# ---- Tabla: Ventas totales por Distribuidor (con ticket promedio) ----
tabla_distribuidor <- datos %>%
group_by(distribuidor) %>%
summarise(
Ventas_totales = sum(ventas_total, na.rm = TRUE),
N_transacciones = n(),
.groups = "drop"
) %>%
mutate(
Ticket_promedio = Ventas_totales / N_transacciones,
Participacion = Ventas_totales / sum(Ventas_totales)
) %>%
arrange(desc(Ventas_totales))
# Identificar dinámicamente las filas de los hallazgos clave
fila_mayor_venta <- which.max(tabla_distribuidor$Ventas_totales)
fila_mayor_ticket <- which.max(tabla_distribuidor$Ticket_promedio)
# Resaltar la celda de "Ventas totales" del distribuidor líder
tabla_distribuidor$Ventas_totales <- cell_spec(
comma(tabla_distribuidor$Ventas_totales),
format = "html",
bold = seq_len(nrow(tabla_distribuidor)) == fila_mayor_venta,
color = ifelse(seq_len(nrow(tabla_distribuidor)) == fila_mayor_venta, "white", "black"),
background = ifelse(seq_len(nrow(tabla_distribuidor)) == fila_mayor_venta, "#2A9D8F", "white")
)
# Resaltar la celda de "Ticket promedio" del distribuidor con ticket más alto
tabla_distribuidor$Ticket_promedio <- cell_spec(
dollar(round(tabla_distribuidor$Ticket_promedio, 2)),
format = "html",
bold = seq_len(nrow(tabla_distribuidor)) == fila_mayor_ticket,
color = ifelse(seq_len(nrow(tabla_distribuidor)) == fila_mayor_ticket, "white", "black"),
background = ifelse(seq_len(nrow(tabla_distribuidor)) == fila_mayor_ticket, "#E76F51", "white")
)
tabla_distribuidor %>%
kable(digits = 2,
format = "html",
col.names = c("Distribuidor", "Ventas totales", "N° Transacciones",
"Ticket promedio", "Participación (%)"),
format.args = list(big.mark = ","),
caption = "Figura 4. Ventas totales por Distribuidor (con ticket promedio)",
escape = FALSE) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE, position = "center") %>%
row_spec(0, background = "#ADD8E6", bold = TRUE, color = "black") %>%
column_spec(1, bold = TRUE)
| Distribuidor | Ventas totales | N° Transacciones | Ticket promedio | Participación (%) |
|---|---|---|---|---|
| West Gear | 32,409,558 | 2,374 | $13,651.88 | 0.27 |
| Foot Locker | 29,024,945 | 2,633 | $11,023.53 | 0.24 |
| Sports Direct | 24,616,622 | 2,032 | $12,114.48 | 0.20 |
| Kohl’s | 13,512,453 | 1,030 | $13,118.89 | 0.11 |
| Walmart | 10,506,085 | 626 | $16,782.88 | 0.09 |
| Amazon | 10,096,987 | 949 | $10,639.61 | 0.08 |
Haciendo un analisis de la información anterior, donde calculamos el ticket promedio por distribuidos, se destacan las siguientes observaciones:
Walmart tiene el ticket promedio más alto de todos ($16,783), a pesar de ser el distribuidor con menor participación en ventas totales. Lo que quiere decir que aunque vende poco frecuentemente, cada venta es de mayor valor.
Foot Locker, aunque tiene el segundo lugar en ventas totales, tiene el ticket promedio más bajo entre los líderes ($11,007) sin embargo garantiza su posición debido a un volumen alto en sus transacciones
West Gear lidera en ventas totales combinando un buen número de transacciones y un ticket promedio alto ($13,652) ,debido a esto es el número 1.
Por lo anterior enfoqueremos nuestro analisis en el lider numero uno en ventas.
library(dplyr)
library(ggplot2)
library(reshape2)
# Filtrar solo West Gear
datos_westgear <- datos %>%
filter(distribuidor == "West Gear")
# Seleccionar las 5 variables numéricas
num_vars_wg <- datos_westgear %>%
select(precio_unidad, unidades_vendidas, ventas_total,
utilidad_operativa, margen_operativo)
# Calcular matriz de correlación
corr_westgear <- cor(num_vars_wg, use = "complete.obs")
# Convertir a formato largo para ggplot
corr_melt <- melt(corr_westgear)
# Renombrar las variables para que se vean más claras en el gráfico
etiquetas <- c(precio_unidad = "Precio", unidades_vendidas = "Unidades",
ventas_total = "Ventas", utilidad_operativa = "Utilidad",
margen_operativo = "Margen")
corr_melt$Var1 <- factor(etiquetas[as.character(corr_melt$Var1)], levels = etiquetas)
corr_melt$Var2 <- factor(etiquetas[as.character(corr_melt$Var2)], levels = etiquetas)
ggplot(corr_melt, aes(x = Var2, y = Var1, fill = value)) +
geom_tile(color = "white", linewidth = 1) +
geom_text(aes(label = round(value, 2)), size = 4, fontface = "bold") +
scale_fill_gradient2(
low = "#E24B4A", mid = "white", high = "#378ADD",
midpoint = 0, limits = c(-1, 1), name = "Correlación"
) +
labs(title = "Figura 5. Matriz de correlación - West Gair",
x = NULL, y = NULL) +
theme_minimal() +
theme(
axis.text.x = element_text(size = 11),
axis.text.y = element_text(size = 11),
panel.grid = element_blank(),
plot.title = element_text(face = "bold")
)
De la matriz de correlación real para las transacciones de West Gear, lo más destacable a tener en cuenta es:
Ventas totales y utilidad operativa están fuertemente correlacionadas (0.92), ya que la utilidad depende directamente de las ventas.
Unidades vendidas y ventas totales también muestran alta correlación (0.92), confirmando que el volumen es el principal motor de las ventas en valor.
Margen operativo se comporta distinto: tiene correlación negativa con unidades vendidas (-0.44) y ventas totales (-0.40). Esto se puede dar por que en West Gear específicamente, las transacciones de mayor volumen tienden a tener menor margen porcentual, por posibles descuentos en compras grandes volumenes.
-Precio por unidad tiene correlación moderada con ventas (0.62) y utilidad (0.60), pero es casi irrelevante para el margen (-0.15).
Histograma
Ahora creamos el histograma de los precios de West gear para ver la distribución de los datos:
library(dplyr)
library(ggplot2)
library(plotly)
# Filtrar solo West Gear
datos_westgear <- datos %>%
filter(distribuidor == "West Gear")
# Histograma de precio por unidad - West Gear
hist_precio <- ggplot(datos_westgear, aes(x = precio_unidad)) +
geom_histogram(binwidth = 5, fill = "steelblue", color = "black", alpha = 0.6) +
labs(title = "Figura 6. Histograma del Precio - West Gear",
x = "Precio",
y = "Frecuencia") +
theme_minimal()
# Mostrar como interactivo
ggplotly(hist_precio)
Interpretación Figura 6
La figura nos muestra la distribución de los precios por unidad de los productos vendidos por West Gear. Permite identificar patrones, concentración de precios y posibles sesgos en la distribución.
Distribución de precios: - La mayoría de las transacciones tienen precios entre $30 y $65. - Se observa una mayor concentración entre $35 y $55, con los valores más frecuentes en ese rango. - Hay productos más costosos, superando los $90, pero son mucho menos frecuentes.
Modo y agrupación: Se identifica un solo pico principal, alrededor de los $40, con una distribución razonablemente simétrica alrededor de ese valor central (la media, $46.7, y la mediana, $46, son casi iguales). A diferencia de otras distribuciones vistas en este informe (como ventas o unidades), aquí no hay una cola larga marcada ni múltiples modos — es una distribución más equilibrada o acampanada.
Dispersión y rango de precios: - Los precios van desde $5 hasta $110. - La dispersión es moderada, sin una diferencia tan extrema como la observada en variables como ventas totales; la mayoría de los productos se agrupan en un rango relativamente estrecho ($30-$65).
⚠️ Los productos con precios superiores a $90 son poco frecuentes (menos de 30 transacciones en total) y podrían considerarse casos atípicos o de gama alta dentro del catálogo de West Gear, posiblemente correspondientes a líneas premium o de alto desempeño.
library(dplyr)
library(ggplot2)
library(scales)
library(plotly)
# Filtrar solo West Gear
datos_westgear <- datos %>%
filter(distribuidor == "West Gear")
# Agregación: ventas totales por región y producto (solo West Gear)
ventas_region_producto <- datos_westgear %>%
group_by(region, producto) %>%
summarise(Ventas_totales = sum(ventas_total, na.rm = TRUE), .groups = "drop")
# Paleta de colores personalizada (una para cada producto)
colores_productos <- c(
"Men's Street Footwear" = "#1D3557",
"Men's Athletic Footwear" = "#457B9D",
"Men's Apparel" = "#A8DADC",
"Women's Street Footwear" = "#E63946",
"Women's Athletic Footwear" = "#F4A261",
"Women's Apparel" = "#E9C46A"
)
p <- ggplot(ventas_region_producto, aes(
x = reorder(region, -Ventas_totales),
y = Ventas_totales, fill = producto,
text = paste0("Región: ", region,
"<br>Producto: ", producto,
"<br>Ventas: ", dollar(Ventas_totales)))) +
geom_col(position = position_dodge(width = 0.8), width = 0.75,
color = "white", linewidth = 0.3) +
scale_fill_manual(values = colores_productos, name = "Producto") +
scale_y_continuous(labels = dollar_format(scale = 1e-6, suffix = "M")) +
labs(
title = "Figura 7. Ventas totales por región y producto - West Gear",
subtitle = "Comparación del desempeño comercial de West Gear por segmento",
x = NULL,
y = "Ventas totales (millones USD)"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 15, color = "#1D3557"),
plot.subtitle = element_text(color = "gray40", margin = margin(b = 15)),
axis.text.x = element_text(size = 11, face = "bold"),
axis.text.y = element_text(size = 10),
legend.position = "bottom",
legend.title = element_text(face = "bold"),
panel.grid.major.x = element_blank(),
panel.grid.minor = element_blank(),
panel.grid.major.y = element_line(color = "gray90")
)
# Convertir a gráfico interactivo, mostrando solo el "text" personalizado en el tooltip
ggplotly(p, tooltip = "text")
library(dplyr)
library(plotly)
library(scales)
# Filtrar solo West Gear y calcular ventas + participación por región
ventas_region_wg <- datos %>%
filter(distribuidor == "West Gear") %>%
group_by(region) %>%
summarise(Ventas_totales = sum(ventas_total, na.rm = TRUE), .groups = "drop") %>%
mutate(Participacion = Ventas_totales / sum(Ventas_totales))
# Paleta de colores personalizada (una por región)
colores_regiones <- c(
"Northeast" = "#1D3557",
"South" = "#457B9D",
"West" = "#A8DADC",
"Midwest" = "#E63946",
"Southeast" = "#F4A261"
)
# Gráfico de torta interactivo
plot_ly(
ventas_region_wg,
labels = ~region,
values = ~Ventas_totales,
type = "pie",
textinfo = "label+percent",
hovertemplate = paste0(
"<b>%{label}</b><br>",
"Ventas: $%{value:,.0f}<br>",
"Participación: %{percent}<extra></extra>"
),
marker = list(colors = colores_regiones[ventas_region_wg$region],
line = list(color = "white", width = 2))
) %>%
layout(
title = list(text = "Figura 8. Participación por región - West Gear",
font = list(size = 18, color = "#1D3557")),
showlegend = TRUE,
legend = list(orientation = "h", x = 0.2, y = -0.1)
)
Interpretación Figura 7 y 8
Las Figuras 7 y 8 muestran la distribución geográfica de las ventas de West Gear, complementándose entre sí: la Figura 7 detalla las ventas por región y producto, mientras que la Figura 8 resume la participación total de cada región.
Hallazgos importantes
1) Concentración geografica: La región West concentra el 57.7% de las ventas totales de West Gear; más de la mitad del negocio del distribuidor está en una sola región. Esto tiene sentido de negocio: “West Gear” como nombre de distribuidor probablemente tiene su operación y fuerza comercial centrada en esa zona.
En cuanto a la brecha con la segunda región, es enorme: South solo representa el 14.5%, seguida de cerca por Northeast (12.3%). Las dos regiones más débiles, Midwest (8.5%) y Southeast (6.9%), juntas no alcanzan ni la mitad de lo que representa South.
2) Comportamiento por producto El producto más fuerte es Men’s Street Footwear y el más débil es Women’s Athletic Footwear.
Se identifica que el orden de los productos vendidos en cada región es muy similar, lo que indica que la preferencia de los productos vendidos por West Gear no depende de la región, sino que es un patrón de negocio consistente.
⚠️ Hay un riesgo de concentraciónm el mayor porcentaje de ventas de West Gear depende de una sola región. Cualquier afectación que se presente en esa región (aumento de competencia, cambios económicos o desastres naturales), impactaría significativamente los resultados del distribuidor.
library(dplyr)
library(ggplot2)
library(plotly)
library(scales)
library(tidyr)
# Participación por producto - Todos los distribuidores
part_general <- datos %>%
group_by(producto) %>%
summarise(Ventas = sum(ventas_total, na.rm = TRUE), .groups = "drop") %>%
mutate(Participacion = Ventas / sum(Ventas), Grupo = "Todos los distribuidores")
# Participación por producto - Solo West Gear
part_westgear <- datos %>%
filter(distribuidor == "West Gear") %>%
group_by(producto) %>%
summarise(Ventas = sum(ventas_total, na.rm = TRUE), .groups = "drop") %>%
mutate(Participacion = Ventas / sum(Ventas), Grupo = "West Gear")
# Combinar ambos grupos
comparacion_producto <- bind_rows(part_general, part_westgear)
# Paleta de colores: azul y amarillo
colores_grupo <- c("Todos los distribuidores" = "#1D3557", "West Gear" = "#E9C46A")
p <- ggplot(comparacion_producto, aes(
x = reorder(producto, Participacion), y = Participacion, fill = Grupo,
text = paste0("Producto: ", producto,
"<br>Grupo: ", Grupo,
"<br>Participación: ", percent(Participacion, accuracy = 0.1)))) +
geom_col(position = position_dodge(width = 0.75), width = 0.65,
color = "white", linewidth = 0.3) +
coord_flip() +
scale_fill_manual(values = colores_grupo, name = NULL) +
scale_y_continuous(labels = percent_format(), expand = expansion(mult = c(0, 0.08))) +
labs(
title = "Participación por producto: General vs. West Gear",
subtitle = "Comparación del peso de cada producto en las ventas totales",
x = NULL,
y = "Participación (%)"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 12, color = "#1D3557"),
plot.subtitle = element_text(size = 9, color = "gray40", margin = margin(b = 12)),
axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10, face = "bold"),
legend.position = "bottom",
legend.title = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor = element_blank(),
panel.grid.major.x = element_line(color = "gray90"),
plot.margin = margin(t = 10, r = 15, b = 5, l = 5)
)
ggplotly(p, tooltip = "text") %>%
layout(
title = list(text = "Figura 9. Participación por producto: General vs. West Gear",
font = list(size = 14, color = "#1D3557"),
x = 0.02, xanchor = "left"),
margin = list(t = 60)
)
Interpretación Figura 9
El hallazgo más importante es que el orden de los productos es prácticamente idéntico entre “Todos los distribuidores” y “West Gear”: ambos lideran con Men’s Street Footwear, seguido de Women’s Apparel, Men’s Athletic Footwear, Women’s Street Footwear, Men’s Apparel, y cierran con Women’s Athletic Footwear como el más débil en ambos casos.
Esto confirma lo que ya habíamos identificado en los gráficos anteriores de West Gear: no tiene una estrategia de producto diferenciada frente al resto del mercado, simplemente refleja (a menor escala) la misma composición de ventas que existe en toda la base de distribuidores de Adidas.
Este gráfico refuerza la idea de que el comportamiento de compra por producto es un patrón de negocio estructural de Adidas, no algo que varíe significativamente por distribuidor.
library(dplyr)
library(ggplot2)
library(plotly)
library(scales)
# Filtrar solo West Gear
datos_westgear <- datos %>%
filter(distribuidor == "West Gear")
# Paleta de colores personalizada por método de venta
colores_metodo <- c(
"In-store" = "#E9C46A",
"Outlet" = "#457B9D",
"Online" = "#F4A261"
)
p <- ggplot(datos_westgear, aes(x = metodo_venta, y = margen_operativo, fill = metodo_venta,
text = paste0("Método: ", metodo_venta,
"<br>Margen: ", percent(margen_operativo, accuracy = 0.1)))) +
geom_boxplot(color = "gray20", outlier.color = "gray40",
outlier.alpha = 0.4, outlier.size = 1.2, linewidth = 0.5) +
scale_fill_manual(values = colores_metodo, name = "Método de venta") +
scale_y_continuous(labels = percent_format()) +
labs(
title = "Margen operativo por método de venta - West Gear",
subtitle = "Distribución y variabilidad de la rentabilidad por canal",
x = NULL,
y = "Margen operativo"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(size = 12, face = "bold", color = "#1D3557"),
plot.subtitle = element_text(size = 9, color = "gray40", margin = margin(b = 12)),
axis.text.x = element_text(size = 11, face = "bold"),
axis.text.y = element_text(size = 10),
legend.position = "none",
panel.grid.major.x = element_blank(),
panel.grid.minor = element_blank(),
panel.grid.major.y = element_line(color = "gray90")
)
ggplotly(p, tooltip = "text") %>%
layout(
title = list(text = "Figura 10. Margen operativo por método de venta - West Gear",
font = list(size = 14, color = "#1D3557"),
x = 0.02, xanchor = "left"),
margin = list(t = 60)
)
library(dplyr)
library(ggplot2)
library(plotly)
library(scales)
# Filtrar solo West Gear y calcular ventas totales + participación por método de venta
ventas_metodo_wg <- datos %>%
filter(distribuidor == "West Gear") %>%
group_by(metodo_venta) %>%
summarise(Ventas_totales = sum(ventas_total, na.rm = TRUE),
N_transacciones = n(), .groups = "drop") %>%
mutate(Participacion = Ventas_totales / sum(Ventas_totales))
# Misma paleta de colores usada en el boxplot de margen
colores_metodo <- c(
"In-store" = "#E9C46A",
"Outlet" = "#457B9D",
"Online" = "#F4A261"
)
p <- ggplot(ventas_metodo_wg, aes(x = reorder(metodo_venta, Ventas_totales),
y = Ventas_totales, fill = metodo_venta,
text = paste0("Método: ", metodo_venta,
"<br>Ventas: ", dollar(Ventas_totales),
"<br>Participación: ", percent(Participacion, accuracy = 0.1),
"<br>N° Transacciones: ", comma(N_transacciones)))) +
geom_col(width = 0.65, color = "white", linewidth = 0.3) +
coord_flip() +
scale_fill_manual(values = colores_metodo, name = "Método de venta") +
scale_y_continuous(labels = dollar_format(scale = 1e-6, suffix = "M"),
expand = expansion(mult = c(0, 0.1))) +
labs(
title = "Ventas totales por método de venta - West Gear",
subtitle = "Distribución del volumen de ventas por canal",
x = NULL,
y = "Ventas totales (millones USD)"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(size = 12, face = "bold", color = "#1D3557"),
plot.subtitle = element_text(size = 9, color = "gray40", margin = margin(b = 12)),
axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 11, face = "bold"),
legend.position = "none",
panel.grid.major.y = element_blank(),
panel.grid.minor = element_blank(),
panel.grid.major.x = element_line(color = "gray90")
)
ggplotly(p, tooltip = "text") %>%
layout(
title = list(text = "Figura 11. Ventas totales por método de venta - West Gear",
font = list(size = 14, color = "#1D3557"),
x = 0.02, xanchor = "left"),
margin = list(t = 60)
)
Interpretación Figura 10 y 11 Al combinar ambos gráficos, se confirma con claridad el patrón de volumen vs. rentabilidad
- In-store líder en ventas, pero el menos rentable: Es el canal con mayores ventas totales ($15.6M) y, por lo tanto, el más importante en términos de volumen para West Gear. Sin embargo, es simultáneamente el canal con el margen operativo más bajo (mediana 35%) y menor variabilidad, lo que indica que esta baja rentabilidad es un comportamiento constante, no ocasional.Lo que quiere decir que siendo el canal que más factura es el que menos eficiente en convertir ventas en utilidad.
- Online: segundo en ventas, pero el más rentable El canal cuenta con ventas de aproximadamente $9.5M (muy por debajo de In-store), Online se posiciona como el segundo canal en volumen. Sin embargo, es el que mejor margen genera (mediana 47%) y el que concentra las transacciones más rentables de todo el distribuidor. Esto significa que, aunque venda menos, cada venta en Online es más rentable que uno vendido en In-store.
-Outlet: menor participación en ventas y rentabilidad intermedia Es el canal con menor participación en ventas ($7.2M) y ocupa un margen intermedio (41%), sin destacar especialmente en ninguna de las dos variables.
Estos dos gráficos, revelan una oportunidad estratégica clara para West Gear: el canal Online, a pesar de tener menor volumen, es financieramente más eficiente que su canal líder (In-store). Esto sugiere que el crecimiento futuro de West Gear no debería enfocarse únicamente en mantener el volumen de In-store, sino en impulsar la migración o el crecimiento de las ventas hacia Online.
library(dplyr)
library(ggplot2)
library(plotly)
library(scales)
# Crear la variable de comparación: West Gear vs. Todos los distribuidores
datos_comparacion <- datos %>%
mutate(Grupo = ifelse(distribuidor == "West Gear", "West Gear", "Todos los distribuidores"))
# Margen operativo promedio por Grupo y método de venta
margen_grupo_metodo <- datos_comparacion %>%
group_by(Grupo, metodo_venta) %>%
summarise(Margen_promedio = mean(margen_operativo, na.rm = TRUE), .groups = "drop")
# Paleta de colores para los dos grupos
colores_grupo <- c("West Gear" = "#E9C46A", "Todos los distribuidores" = "#1D3557")
p <- ggplot(margen_grupo_metodo, aes(
x = reorder(metodo_venta, Margen_promedio), y = Margen_promedio, fill = Grupo,
text = paste0("Método: ", metodo_venta,
"<br>Grupo: ", Grupo,
"<br>Margen promedio: ", percent(Margen_promedio, accuracy = 0.1)))) +
geom_col(position = position_dodge(width = 0.75), width = 0.65,
color = "white", linewidth = 0.3) +
coord_flip() +
scale_fill_manual(values = colores_grupo, name = NULL) +
scale_y_continuous(labels = percent_format(), expand = expansion(mult = c(0, 0.08))) +
labs(
title = "Margen operativo por método de venta: West Gear vs. Resto",
subtitle = "Comparación de rentabilidad por canal",
x = NULL,
y = "Margen operativo promedio"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(size = 12, face = "bold", color = "#1D3557"),
plot.subtitle = element_text(size = 9, color = "gray40", margin = margin(b = 12)),
axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 11, face = "bold"),
legend.position = "bottom",
legend.title = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor = element_blank(),
panel.grid.major.x = element_line(color = "gray90")
)
ggplotly(p, tooltip = "text") %>%
layout(
title = list(text = "Figura 12. Margen operativo por método de venta: West Gear vs. Otros",
font = list(size = 14, color = "#1D3557"),
x = 0.02, xanchor = "left"),
margin = list(t = 60)
)
Interpretación Figura 12
Con este gráfico se puede confirmar algo muy relevante y es que el patrón de rentabilidad por canal es muy idéntico entre West Gear y el resto de distribuidores.
Esto confirma que el comportamiento que identificamos para West Gear (Online más rentable, In-store menos rentable) no es una particularidad de este distribuidor, sino un patrón estructural de todo el negocio de Adidas, sin importar a través de qué distribuidor se venda. West Gear simplemente refleja la dinámica general del mercado.
library(dplyr)
library(ggplot2)
library(plotly)
library(scales)
# Agregación: margen promedio y ventas totales por distribuidor y región
heatmap_dist_region <- datos %>%
group_by(distribuidor, region) %>%
summarise(
Margen_promedio = mean(margen_operativo, na.rm = TRUE),
Ventas_totales = sum(ventas_total, na.rm = TRUE),
.groups = "drop"
)
p <- ggplot(heatmap_dist_region, aes(
x = region, y = distribuidor, fill = Margen_promedio,
text = paste0("Distribuidor: ", distribuidor,
"<br>Región: ", region,
"<br>Margen promedio: ", percent(Margen_promedio, accuracy = 0.1),
"<br>Ventas totales: ", dollar(Ventas_totales)))) +
geom_tile(color = "white", linewidth = 1.2) +
geom_text(aes(label = dollar(Ventas_totales, scale = 1e-6, suffix = "M")),
color = "black", size = 3, fontface = "bold") +
scale_fill_gradient2(
low = "#E63946", mid = "#F4E8C1", high = "#2A9D8F",
midpoint = mean(heatmap_dist_region$Margen_promedio),
labels = percent_format(), name = "Margen\npromedio"
) +
labs(
title = "Rentabilidad vs. ventas por distribuidor y región",
subtitle = "El color indica margen operativo promedio; la etiqueta muestra ventas totales en millones",
x = "Región",
y = NULL
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(size = 12, face = "bold", color = "#1D3557"),
plot.subtitle = element_text(size = 9, color = "gray40", margin = margin(b = 12)),
axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 11, face = "bold"),
panel.grid = element_blank()
)
ggplotly(p, tooltip = "text") %>%
layout(
title = list(text = "Figura 13. Rentabilidad vs. ventas por distribuidor y región",
font = list(size = 14, color = "#1D3557"),
x = 0.02, xanchor = "left"),
margin = list(t = 60)
)
Interpretación Figura 13
West Gear confirma que es fuerte en volumen, pero no en margen, la celda de West Gear en la región West es la venta más alta de toda la matriz ($18.70M), pero su color es naranja/rojo claro, indicando un margen por debajo del promedio. Esto reafirma, con evidencia a nivel de todos los distribuidores, que West Gear no es más rentable por vender mucho en su región líder, al contrario, es donde tiene uno de sus márgenes más débiles.
library(dplyr)
library(plotly)
library(scales)
# Filtrar solo West Gear y agregar por estado
mapa_wg <- datos %>%
filter(distribuidor == "West Gear") %>%
group_by(estado) %>%
summarise(
Margen_promedio = mean(margen_operativo, na.rm = TRUE),
Ventas_totales = sum(ventas_total, na.rm = TRUE),
.groups = "drop"
)
# Diccionario de nombres de estado -> código de 2 letras (requerido por plotly para mapas de EE. UU.)
codigos_estado <- c(
"Alabama"="AL","Alaska"="AK","Arizona"="AZ","Arkansas"="AR","California"="CA",
"Colorado"="CO","Connecticut"="CT","Delaware"="DE","Florida"="FL","Georgia"="GA",
"Hawaii"="HI","Idaho"="ID","Illinois"="IL","Indiana"="IN","Iowa"="IA",
"Kansas"="KS","Kentucky"="KY","Louisiana"="LA","Maine"="ME","Maryland"="MD",
"Massachusetts"="MA","Michigan"="MI","Minnesota"="MN","Mississippi"="MS","Missouri"="MO",
"Montana"="MT","Nebraska"="NE","Nevada"="NV","New Hampshire"="NH","New Jersey"="NJ",
"New Mexico"="NM","New York"="NY","North Carolina"="NC","North Dakota"="ND","Ohio"="OH",
"Oklahoma"="OK","Oregon"="OR","Pennsylvania"="PA","Rhode Island"="RI","South Carolina"="SC",
"South Dakota"="SD","Tennessee"="TN","Texas"="TX","Utah"="UT","Vermont"="VT",
"Virginia"="VA","Washington"="WA","West Virginia"="WV","Wisconsin"="WI","Wyoming"="WY"
)
mapa_wg <- mapa_wg %>%
mutate(codigo = codigos_estado[estado])
# Mapa coroplético de Estados Unidos
plot_geo(mapa_wg, locationmode = "USA-states") %>%
add_trace(
z = ~Margen_promedio,
locations = ~codigo,
color = ~Margen_promedio,
colors = c("#E63946", "#F4E8C1", "#2A9D8F"),
text = ~paste0(estado, "<br>Margen promedio: ", percent(Margen_promedio, accuracy = 0.1),
"<br>Ventas totales: ", dollar(Ventas_totales)),
hoverinfo = "text",
marker = list(line = list(color = "white", width = 1))
) %>%
colorbar(title = "Margen\npromedio", tickformat = ".0%") %>%
layout(
title = list(text = "Figura 14. Margen operativo promedio por estado - West Gear",
font = list(size = 14, color = "#1D3557"), x = 0.02),
geo = list(
scope = "usa",
projection = list(type = "albers usa"),
showlakes = TRUE,
lakecolor = "white"
)
)
Interpretación Figura 14
West Gear no tiene presencia en todos los estados de EE. UU., varios aparecen en blanco (sin ventas registradas), especialmente en el sureste y parte del centro-sur del país. Esto significa que el liderazgo en ventas totales que tiene West Gear se construye sobre una cobertura geográfica limitada, no sobre presencia nacional completa, lo que podría representar una oportunidad de expansión hacia estados aún no atendidos.
Aunque en el análisis anterior identificamos que la región West tenía, en conjunto, uno de los márgenes más bajos, el mapa muestra que ese promedio regional no es homogéneo, estados como Washington presentan tonos rojos (margen bajo), mientras que Idaho, dentro de la misma región, se ve en verde (margen más alto). Lo mismo ocurre en otras zonas del país — Ohio y Vermont destacan con los mejores márgenes del mapa, mientras Maine y Texas muestran de los más bajos.
En conclusión West Gear es el distribuidor líder en ventas gracias a su alto volumen de transacciones y un ticket promedio competitivo. Sin embargo, su fortaleza comercial no se refleja plenamente en la rentabilidad, debido a la alta concentración de ventas que tiene en la región West, donde los márgenes son relativamente bajos. Adicionalmente, su cobertura geográfica es muy limitada y cuenta con una mezcla de productos similar a la del resto de distribuidores evidencian oportunidades de expansión y diferenciación.
Desde una perspectiva financiera, el principal desafío de West Gear no es incrementar sus ventas, sino mejorar la eficiencia con la que transforma sus ingresos en utilidad. El análisis demuestra que el canal Online genera márgenes superiores al canal In-store, lo que representa una oportunidad clara para impulsar un crecimiento más rentable y sostenible.
Recomendaciones
- Reducir la dependencia de la región West: Diversificar las ventas hacia estados y regiones con mejores márgenes operativos, así como desarrollar planes de expansión en mercados donde actualmente no existe presencia comercial.
- Priorizar el crecimiento del canal Online:Incrementar la inversión en estrategias digitales y comercio electrónico, diseñando campañas que incentiven la migración de clientes desde las tiendas físicas hacia canales con mayor rentabilidad.
- Optimizar la rentabilidad del canal In-store: Revisar costos operativos, promociones y descuentos aplicados en tiendas físicas. Implementar indicadores de rentabilidad por punto de venta para identificar oportunidades de mejora.
-Diferenciar el portafolio comercial: Impulsar categorías con baja participación pero mayor potencial de margen. Desarrollar estrategias de ventas y marketing que permitan diferenciarse del comportamiento promedio de los distribuidores Adidas.
-Incorporar métricas de rentabilidad en la toma de decisiones:Priorizar indicadores como margen operativo, utilidad por canal y rentabilidad por estado, además de las ventas,enfocando los objetivos comerciales en crecimiento rentable y no únicamente en volumen.