Este informe presenta un análisis exploratorio y descriptivo de las ventas de Adidas en Estados Unidos, con el objetivo de identificar patrones comerciales, evaluar el desempeño financiero por región, retailer, producto y método de venta, y generar recomendaciones estratégicas basadas en datos.
El dataset contiene 9.651 registros con información de distribuidores (retailers), regiones, ciudades, líneas de producto, precios, unidades vendidas, ventas totales, utilidad operativa, margen operativo y método de venta.
El análisis exploratorio (EDA) es el primer paso para comprender la información comercial de Adidas: detectar distribuciones, identificar valores atípicos, medir relaciones entre variables y extraer patrones accionables.
PASO 1. Instalar y cargar librerías
# Librerías necesarias para el análisis
library(readxl) # Lectura de archivos Excel
library(dplyr) # Manipulación de datos
library(ggplot2) # Visualizaciones estáticas
library(plotly) # Visualizaciones interactivas
library(knitr) # Tablas en RMarkdown
library(kableExtra) # Formato avanzado de tablas
library(tidyr) # Transformación de datos (pivot)
library(scales) # Formato de ejes (miles, porcentajes)
PASO 2. Cargar y preparar los datos
Se carga el archivo Excel con los datos de ventas de Adidas. La
columna ventas_total contiene fórmulas Excel que R no
evalúa automáticamente, por lo que se recalcula directamente como
precio_unidad × unidades_vendidas.
# Cargar datos desde Excel
datos <- read_excel("DatosCaso1.xlsx", sheet = "Data Sales Adidas")
# Renombrar columnas para mayor claridad en el análisis
# (los nombres originales ya están en español — se conservan y se verifica)
names(datos)
## [1] "distribuidor" "region" "estado"
## [4] "ciudad" "producto" "precio_unidad"
## [7] "unidades_vendidas" "ventas_total" "utilidad_operativa"
## [10] "margen_operativo" "metodo_venta"
# Recalcular ventas_total ya que la columna original contiene fórmulas Excel
# que R lee como texto. Se sobreescribe con el cálculo numérico correcto.
datos$ventas_total <- as.numeric(datos$precio_unidad) * as.numeric(datos$unidades_vendidas)
# Asegurar que las columnas numéricas estén en el formato correcto
datos$precio_unidad <- as.numeric(datos$precio_unidad)
datos$unidades_vendidas <- as.numeric(datos$unidades_vendidas)
datos$utilidad_operativa <- as.numeric(datos$utilidad_operativa)
datos$margen_operativo <- as.numeric(datos$margen_operativo)
# Convertir variables categóricas a factor
datos$distribuidor <- as.factor(datos$distribuidor)
datos$region <- as.factor(datos$region)
datos$producto <- as.factor(datos$producto)
datos$metodo_venta <- as.factor(datos$metodo_venta)
# Vista previa de los datos
head(datos, 6)
| distribuidor | region | estado | ciudad | producto | precio_unidad | unidades_vendidas | ventas_total | utilidad_operativa | margen_operativo | metodo_venta |
|---|---|---|---|---|---|---|---|---|---|---|
| Foot Locker | Northeast | New York | New York | Men’s Street Footwear | 50 | 1200 | 60000 | 30000.0 | 0.50 | In-store |
| Foot Locker | Northeast | New York | New York | Men’s Athletic Footwear | 50 | 1000 | 50000 | 15000.0 | 0.30 | In-store |
| Foot Locker | Northeast | New York | New York | Women’s Street Footwear | 40 | 1000 | 40000 | 14000.0 | 0.35 | In-store |
| Foot Locker | Northeast | New York | New York | Women’s Athletic Footwear | 45 | 850 | 38250 | 13387.5 | 0.35 | In-store |
| Foot Locker | Northeast | New York | New York | Men’s Apparel | 60 | 900 | 54000 | 16200.0 | 0.30 | In-store |
| Foot Locker | Northeast | New York | New York | Women’s Apparel | 50 | 1000 | 50000 | 12500.0 | 0.25 | In-store |
PASO 3. Inspeccionar la estructura del dataset
# Nombres exactos de las variables
names(datos)
## [1] "distribuidor" "region" "estado"
## [4] "ciudad" "producto" "precio_unidad"
## [7] "unidades_vendidas" "ventas_total" "utilidad_operativa"
## [10] "margen_operativo" "metodo_venta"
# Estructura del dataframe: tipo de dato por columna
str(datos)
## tibble [9,648 × 11] (S3: tbl_df/tbl/data.frame)
## $ distribuidor : Factor w/ 6 levels "Amazon","Foot Locker",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ region : Factor w/ 5 levels "Midwest","Northeast",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ estado : chr [1:9648] "New York" "New York" "New York" "New York" ...
## $ ciudad : chr [1:9648] "New York" "New York" "New York" "New York" ...
## $ producto : Factor w/ 6 levels "Men's Apparel",..: 3 2 6 5 1 4 3 2 6 5 ...
## $ precio_unidad : num [1:9648] 50 50 40 45 60 50 50 50 40 45 ...
## $ unidades_vendidas : num [1:9648] 1200 1000 1000 850 900 1000 1250 900 950 825 ...
## $ ventas_total : num [1:9648] 60000 50000 40000 38250 54000 ...
## $ utilidad_operativa: num [1:9648] 30000 15000 14000 13388 16200 ...
## $ margen_operativo : num [1:9648] 0.5 0.3 0.35 0.35 0.3 0.25 0.5 0.3 0.35 0.35 ...
## $ metodo_venta : Factor w/ 3 levels "In-store","Online",..: 1 1 1 1 1 1 1 3 3 3 ...
# Total de registros en el dataset
cat("Total de registros:", nrow(datos), "\n")
## Total de registros: 9648
cat("Total de variables:", ncol(datos), "\n")
## Total de variables: 11
PASO 4. Verificar valores faltantes
# Conteo de NA por columna — importante antes de calcular estadísticas
na_por_columna <- colSums(is.na(datos))
na_por_columna
## distribuidor region estado ciudad
## 0 0 0 0
## producto precio_unidad unidades_vendidas ventas_total
## 0 0 0 0
## utilidad_operativa margen_operativo metodo_venta
## 0 0 0
Si todas las celdas muestran 0, el dataset está completo y no requiere imputación.
# ── Tendencia central para VENTAS TOTALES ──────────────────────────────────
# na.rm = TRUE garantiza que los NA no rompan el cálculo (buena práctica)
cantidad_transacciones <- nrow(datos)
promedio_ventas <- mean(datos$ventas_total, na.rm = TRUE)
mediana_ventas <- median(datos$ventas_total, na.rm = TRUE) # ← median(), no mean()
promedio_precio <- mean(datos$precio_unidad, na.rm = TRUE)
mediana_precio <- median(datos$precio_unidad, na.rm = TRUE)
promedio_unidades <- mean(datos$unidades_vendidas, na.rm = TRUE)
mediana_unidades <- median(datos$unidades_vendidas, na.rm = TRUE)
resultado_centralidad <- data.frame(
Métrica = c("Transacciones", "Promedio Ventas $", "Mediana Ventas $",
"Promedio Precio $", "Mediana Precio $",
"Promedio Unidades", "Mediana Unidades"),
Valor = c(cantidad_transacciones,
round(promedio_ventas, 2),
round(mediana_ventas, 2),
round(promedio_precio, 2),
round(mediana_precio, 2),
round(promedio_unidades, 2),
round(mediana_unidades, 2))
)
resultado_centralidad
| Métrica | Valor |
|---|---|
| Transacciones | 9648.00 |
| Promedio Ventas $ | 12455.08 |
| Mediana Ventas $ | 7803.50 |
| Promedio Precio $ | 45.22 |
| Mediana Precio $ | 45.00 |
| Promedio Unidades | 256.93 |
| Mediana Unidades | 176.00 |
Interpretación — Centralidad: La comparación entre promedio y mediana es clave: si el promedio de ventas es significativamente mayor que la mediana, existe asimetría positiva, lo que indica que algunas transacciones de alto valor elevan la media. La mediana representa mejor el “desempeño típico” del negocio en ese caso.
# ── Variabilidad para VENTAS TOTALES ───────────────────────────────────────
minimo_ventas <- min(datos$ventas_total, na.rm = TRUE)
maximo_ventas <- max(datos$ventas_total, na.rm = TRUE)
desvest_ventas <- sd(datos$ventas_total, na.rm = TRUE)
cv_ventas <- (desvest_ventas / promedio_ventas) * 100 # Coeficiente de variación
indic_ventas <- data.frame(
Promedio = round(promedio_ventas, 2),
Mediana = round(mediana_ventas, 2),
Mínimo = round(minimo_ventas, 2),
Máximo = round(maximo_ventas, 2),
Desv_Est = round(desvest_ventas, 2),
CV_Pct = round(cv_ventas, 2)
)
indic_ventas
| Promedio | Mediana | Mínimo | Máximo | Desv_Est | CV_Pct |
|---|---|---|---|---|---|
| 12455.08 | 7803.5 | 0 | 82500 | 12716.39 | 102.1 |
# ── Variabilidad para PRECIO POR UNIDAD ────────────────────────────────────
minimo_precio <- min(datos$precio_unidad, na.rm = TRUE)
maximo_precio <- max(datos$precio_unidad, na.rm = TRUE)
desvest_precio <- sd(datos$precio_unidad, na.rm = TRUE)
cv_precio <- (desvest_precio / promedio_precio) * 100
indic_precio <- data.frame(
Promedio = round(promedio_precio, 2),
Mediana = round(mediana_precio, 2),
Mínimo = round(minimo_precio, 2),
Máximo = round(maximo_precio, 2),
Desv_Est = round(desvest_precio, 2),
CV_Pct = round(cv_precio, 2)
)
indic_precio
| Promedio | Mediana | Mínimo | Máximo | Desv_Est | CV_Pct |
|---|---|---|---|---|---|
| 45.22 | 45 | 7 | 110 | 14.71 | 32.52 |
# ── Variabilidad para UTILIDAD OPERATIVA ───────────────────────────────────
promedio_utilidad <- mean(datos$utilidad_operativa, na.rm = TRUE)
mediana_utilidad <- median(datos$utilidad_operativa, na.rm = TRUE)
minimo_utilidad <- min(datos$utilidad_operativa, na.rm = TRUE)
maximo_utilidad <- max(datos$utilidad_operativa, na.rm = TRUE)
desvest_utilidad <- sd(datos$utilidad_operativa, na.rm = TRUE)
cv_utilidad <- (desvest_utilidad / promedio_utilidad) * 100
indic_utilidad <- data.frame(
Promedio = round(promedio_utilidad, 2),
Mediana = round(mediana_utilidad, 2),
Mínimo = round(minimo_utilidad, 2),
Máximo = round(maximo_utilidad, 2),
Desv_Est = round(desvest_utilidad, 2),
CV_Pct = round(cv_utilidad, 2)
)
indic_utilidad
| Promedio | Mediana | Mínimo | Máximo | Desv_Est | CV_Pct |
|---|---|---|---|---|---|
| 4894.79 | 3262.98 | 0 | 39000 | 4866.46 | 99.42 |
Interpretación — Variabilidad: El Coeficiente de Variación (CV%) normaliza la dispersión respecto al promedio, permitiendo comparar variables con distintas escalas. Un CV alto en ventas indica heterogeneidad entre transacciones; un CV alto en margen operativo señala inconsistencia en la rentabilidad del negocio.
Figura 1. Distribución de Ventas Totales
ggplotly(
ggplot(datos, aes(x = ventas_total)) +
geom_histogram(bins = 50, fill = "steelblue", color = "white", alpha = 0.8) +
scale_x_continuous(labels = dollar_format(prefix = "$", big.mark = ",")) +
labs(
title = "Figura 1. Distribución de Ventas Totales por Transacción",
x = "Ventas Totales (USD)",
y = "Frecuencia",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal()
)
Interpretación Figura 1: Este histograma revela la distribución de las ventas por transacción. Si la distribución es sesgada a la derecha (cola larga hacia valores altos), la mayoría de las transacciones son de tamaño moderado, pero un grupo pequeño genera ventas muy elevadas — patrón común en retail. La diferencia entre promedio y mediana confirma este comportamiento.
Figura 2. Distribución del Precio por Unidad
ggplotly(
ggplot(datos, aes(x = precio_unidad)) +
geom_histogram(bins = 30, fill = "darkorange", color = "white", alpha = 0.8) +
scale_x_continuous(labels = dollar_format(prefix = "$")) +
labs(
title = "Figura 2. Distribución del Precio por Unidad",
x = "Precio por Unidad (USD)",
y = "Frecuencia",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal()
)
Interpretación Figura 2: La distribución de precios muestra los rangos de precio más frecuentes en el portafolio de Adidas. Una distribución multimodal (varios picos) sugiere segmentos de precio diferenciados: líneas económicas, intermedias y premium. Los picos identifican los precios “âncora” del catálogo.
Figura 3. Distribución del Margen Operativo
ggplotly(
ggplot(datos, aes(x = margen_operativo * 100)) +
geom_histogram(bins = 30, fill = "seagreen", color = "white", alpha = 0.8) +
labs(
title = "Figura 3. Distribución del Margen Operativo (%)",
x = "Margen Operativo (%)",
y = "Frecuencia",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal()
)
Interpretación Figura 3: El margen operativo es el indicador de rentabilidad más importante del análisis. Una distribución concentrada indica uniformidad en la política de precios y costos; una distribución dispersa o bimodal señala que algunos canales, productos o regiones son significativamente más rentables que otros.
Figura 4. Boxplot de Ventas Totales
ggplotly(
ggplot(datos, aes(y = ventas_total)) +
geom_boxplot(fill = "steelblue", color = "black",
outlier.colour = "red", outlier.shape = 16, outlier.size = 2) +
scale_y_continuous(labels = dollar_format(prefix = "$", big.mark = ",")) +
labs(
title = "Figura 4. Boxplot de Ventas Totales",
y = "Ventas Totales (USD)"
) +
theme_minimal()
)
Interpretación Figura 4: El boxplot muestra la mediana (línea central), el rango intercuartílico (Q1–Q3, caja) y los bigotes hasta 1.5×IQR. Los puntos rojos son outliers: transacciones de ventas excepcionalmente altas. Estos outliers no son “errores” — representan pedidos mayoristas grandes o temporadas pico que deben analizarse por separado.
Figura 5. Boxplot de Precio por Unidad según Producto
ggplotly(
ggplot(datos, aes(x = reorder(producto, precio_unidad, median), y = precio_unidad, fill = producto)) +
geom_boxplot(color = "black", outlier.colour = "red", outlier.shape = 16, outlier.size = 1.5,
alpha = 0.8) +
coord_flip() +
scale_y_continuous(labels = dollar_format(prefix = "$")) +
labs(
title = "Figura 5. Precio por Unidad según Línea de Producto",
x = "Línea de Producto",
y = "Precio por Unidad (USD)",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal() +
theme(legend.position = "none")
)
Interpretación Figura 5: Ordenar los boxplots por mediana de precio permite identificar qué líneas de producto son premium y cuáles son de entrada. La superposición o separación entre cajas indica si existe diferenciación real de precio entre categorías o si los rangos son similares.
Figura 6. Boxplot de Margen Operativo según Método de Venta
ggplotly(
ggplot(datos, aes(x = metodo_venta, y = margen_operativo * 100, fill = metodo_venta)) +
geom_boxplot(color = "black", outlier.colour = "red", outlier.shape = 16, outlier.size = 2,
alpha = 0.8) +
labs(
title = "Figura 6. Margen Operativo (%) por Método de Venta",
x = "Método de Venta",
y = "Margen Operativo (%)",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal() +
theme(legend.position = "none")
)
Interpretación Figura 6: Este gráfico es uno de los más estratégicos del análisis: compara la rentabilidad según el canal de distribución (In-store, Online, Outlet). Si el canal online tiene un margen significativamente mayor, justifica invertir más en e-commerce. Si el canal físico tiene mayor variabilidad, puede indicar diferencias de eficiencia entre tiendas.
# Tabla resumen de métricas financieras por región
resumen_region <- datos %>%
group_by(region) %>%
summarise(
Transacciones = n(),
Ventas_Total_USD = round(sum(ventas_total, na.rm = TRUE), 0),
Promedio_Ventas = round(mean(ventas_total, na.rm = TRUE), 0),
Utilidad_Total = round(sum(utilidad_operativa, na.rm = TRUE), 0),
Margen_Prom_Pct = round(mean(margen_operativo, na.rm = TRUE) * 100, 1)
) %>%
arrange(desc(Ventas_Total_USD))
resumen_region
| region | Transacciones | Ventas_Total_USD | Promedio_Ventas | Utilidad_Total | Margen_Prom_Pct |
|---|---|---|---|---|---|
| West | 2448 | 36436157 | 14884 | 13017584 | 39.7 |
| Northeast | 2376 | 25078267 | 10555 | 9732774 | 41.0 |
| Southeast | 1224 | 21374436 | 17463 | 8393059 | 41.9 |
| South | 1728 | 20603356 | 11923 | 9221605 | 46.7 |
| Midwest | 1872 | 16674434 | 8907 | 6859945 | 43.5 |
Figura 7. Ventas Totales por Región
ggplotly(
ggplot(resumen_region, aes(x = reorder(region, Ventas_Total_USD), y = Ventas_Total_USD, fill = region)) +
geom_col(alpha = 0.85) +
coord_flip() +
scale_y_continuous(labels = dollar_format(prefix = "$", big.mark = ",")) +
labs(
title = "Figura 7. Ventas Totales por Región",
x = "Región",
y = "Ventas Totales (USD)",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal() +
theme(legend.position = "none")
)
Figura 8. Margen Operativo Promedio por Región
ggplotly(
ggplot(resumen_region, aes(x = reorder(region, Margen_Prom_Pct), y = Margen_Prom_Pct, fill = region)) +
geom_col(alpha = 0.85) +
coord_flip() +
labs(
title = "Figura 8. Margen Operativo Promedio por Región (%)",
x = "Región",
y = "Margen Operativo Promedio (%)",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal() +
theme(legend.position = "none")
)
Interpretación Figuras 7-8: La comparación entre volumen de ventas y margen operativo por región revela si las regiones de mayor ingreso también son las más rentables. Una región puede generar muchas ventas pero con márgenes bajos (posiblemente por descuentos o altos costos operativos), mientras otra puede tener menos ventas pero mayor rentabilidad.
# Tabla resumen por distribuidor/retailer
resumen_retailer <- datos %>%
group_by(distribuidor) %>%
summarise(
Transacciones = n(),
Ventas_Total_USD = round(sum(ventas_total, na.rm = TRUE), 0),
Utilidad_Total = round(sum(utilidad_operativa, na.rm = TRUE), 0),
Margen_Prom_Pct = round(mean(margen_operativo, na.rm = TRUE) * 100, 1),
Precio_Prom = round(mean(precio_unidad, na.rm = TRUE), 2)
) %>%
arrange(desc(Ventas_Total_USD))
resumen_retailer
| distribuidor | Transacciones | Ventas_Total_USD | Utilidad_Total | Margen_Prom_Pct | Precio_Prom |
|---|---|---|---|---|---|
| West Gear | 2374 | 32409558 | 12196891 | 41.8 | 46.74 |
| Foot Locker | 2637 | 29024945 | 11317027 | 41.8 | 44.78 |
| Sports Direct | 2032 | 24616622 | 10641609 | 44.5 | 42.05 |
| Kohl’s | 1030 | 13512453 | 5182260 | 41.9 | 44.61 |
| Walmart | 626 | 10506085 | 3902749 | 40.7 | 47.18 |
| Amazon | 949 | 10096987 | 3984432 | 41.8 | 48.76 |
Figura 9. Ventas y Utilidad Operativa por Retailer
# Transformar a formato largo para graficar las dos métricas lado a lado
resumen_retailer_largo <- resumen_retailer %>%
select(distribuidor, Ventas_Total_USD, Utilidad_Total) %>%
pivot_longer(cols = c(Ventas_Total_USD, Utilidad_Total),
names_to = "Métrica",
values_to = "Valor")
ggplotly(
ggplot(resumen_retailer_largo, aes(x = reorder(distribuidor, Valor), y = Valor, fill = Métrica)) +
geom_col(position = "dodge", alpha = 0.85) +
coord_flip() +
scale_y_continuous(labels = dollar_format(prefix = "$", big.mark = ",")) +
labs(
title = "Figura 9. Ventas Totales vs Utilidad Operativa por Retailer",
x = "Distribuidor",
y = "USD",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal()
)
Interpretación Figura 9: La brecha entre ventas totales y utilidad operativa por retailer mide la eficiencia de cada canal. Un retailer con ventas altas pero utilidad baja puede estar absorbiendo márgenes a través de descuentos o acuerdos comerciales desfavorables para Adidas. Este análisis orienta las negociaciones contractuales.
# Tabla resumen por línea de producto
resumen_producto <- datos %>%
group_by(producto) %>%
summarise(
Transacciones = n(),
Ventas_Total_USD = round(sum(ventas_total, na.rm = TRUE), 0),
Unidades_Totales = sum(unidades_vendidas, na.rm = TRUE),
Utilidad_Total = round(sum(utilidad_operativa, na.rm = TRUE), 0),
Margen_Prom_Pct = round(mean(margen_operativo, na.rm = TRUE) * 100, 1),
Precio_Prom = round(mean(precio_unidad, na.rm = TRUE), 2)
) %>%
arrange(desc(Ventas_Total_USD))
resumen_producto
| producto | Transacciones | Ventas_Total_USD | Unidades_Totales | Utilidad_Total | Margen_Prom_Pct | Precio_Prom |
|---|---|---|---|---|---|---|
| Men’s Street Footwear | 1610 | 27680769 | 593320 | 11629046 | 44.6 | 44.24 |
| Women’s Apparel | 1608 | 23870985 | 433827 | 9685221 | 44.1 | 51.60 |
| Men’s Athletic Footwear | 1610 | 20577180 | 435526 | 7437457 | 40.3 | 43.78 |
| Women’s Street Footwear | 1608 | 17201563 | 392269 | 6494017 | 41.0 | 40.25 |
| Men’s Apparel | 1606 | 16520632 | 306683 | 6381405 | 41.3 | 50.32 |
| Women’s Athletic Footwear | 1606 | 14315521 | 317236 | 5597822 | 42.4 | 41.11 |
Figura 10. Ventas Totales por Línea de Producto
ggplotly(
ggplot(resumen_producto, aes(x = reorder(producto, Ventas_Total_USD), y = Ventas_Total_USD, fill = producto)) +
geom_col(alpha = 0.85) +
coord_flip() +
scale_y_continuous(labels = dollar_format(prefix = "$", big.mark = ",")) +
labs(
title = "Figura 10. Ventas Totales por Línea de Producto",
x = "Producto",
y = "Ventas Totales (USD)",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal() +
theme(legend.position = "none")
)
Figura 11. Margen Operativo vs Precio Promedio por Producto
ggplotly(
ggplot(resumen_producto, aes(x = Precio_Prom, y = Margen_Prom_Pct,
size = Ventas_Total_USD, color = producto, label = producto)) +
geom_point(alpha = 0.8) +
labs(
title = "Figura 11. Precio Promedio vs Margen Operativo por Producto",
x = "Precio Promedio por Unidad (USD)",
y = "Margen Operativo Promedio (%)",
size = "Ventas Totales",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal() +
theme(legend.position = "right")
)
Interpretación Figuras 10-11: La Figura 11 es un gráfico de burbujas que combina tres dimensiones: precio, margen y volumen de ventas. Los productos ideales son los que aparecen en la esquina superior derecha (alto precio, alto margen) con burbujas grandes (alto volumen). Los productos en la esquina inferior izquierda son candidatos a revisión de estrategia.
# Tabla resumen por método de venta
resumen_metodo <- datos %>%
group_by(metodo_venta) %>%
summarise(
Transacciones = n(),
Ventas_Total_USD = round(sum(ventas_total, na.rm = TRUE), 0),
Unidades_Totales = sum(unidades_vendidas, na.rm = TRUE),
Utilidad_Total = round(sum(utilidad_operativa, na.rm = TRUE), 0),
Margen_Prom_Pct = round(mean(margen_operativo, na.rm = TRUE) * 100, 1)
) %>%
arrange(desc(Margen_Prom_Pct))
resumen_metodo
| metodo_venta | Transacciones | Ventas_Total_USD | Unidades_Totales | Utilidad_Total | Margen_Prom_Pct |
|---|---|---|---|---|---|
| Online | 4889 | 44965657 | 939093 | 19552538 | 46.4 |
| Outlet | 3019 | 39536618 | 849778 | 14913301 | 39.5 |
| In-store | 1740 | 35664375 | 689990 | 12759129 | 35.6 |
Figura 12. Participación de Ventas por Método de Venta
# Nota: ggplotly no es compatible con coord_polar (tortas).
# Se usa un gráfico de barras horizontal con porcentaje calculado manualmente,
# que transmite la misma información con mayor precisión y sin errores.
resumen_metodo <- resumen_metodo %>%
mutate(Participacion_Pct = round(Ventas_Total_USD / sum(Ventas_Total_USD) * 100, 1))
ggplotly(
ggplot(resumen_metodo, aes(x = reorder(metodo_venta, Participacion_Pct),
y = Participacion_Pct, fill = metodo_venta,
text = paste0(metodo_venta, ": ", Participacion_Pct, "%"))) +
geom_col(alpha = 0.85) +
geom_text(aes(label = paste0(Participacion_Pct, "%")), hjust = -0.2, fontface = "bold") +
coord_flip() +
ylim(0, max(resumen_metodo$Participacion_Pct) * 1.15) +
labs(
title = "Figura 12. Participación en Ventas Totales por Método de Venta (%)",
x = "Método de Venta",
y = "Participación (%)",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal() +
theme(legend.position = "none"),
tooltip = "text"
)
Figura 13. Margen Operativo vs Ventas Totales por Método de Venta
ggplotly(
ggplot(resumen_metodo, aes(x = metodo_venta, y = Margen_Prom_Pct, fill = metodo_venta)) +
geom_col(alpha = 0.85) +
geom_text(aes(label = paste0(Margen_Prom_Pct, "%")), vjust = -0.5, fontface = "bold") +
ylim(0, max(resumen_metodo$Margen_Prom_Pct) * 1.2) +
labs(
title = "Figura 13. Margen Operativo Promedio por Método de Venta",
x = "Método de Venta",
y = "Margen Operativo (%)",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal() +
theme(legend.position = "none")
)
Interpretación Figuras 12-13: El margen operativo por método de venta es un insumo crítico para la estrategia de distribución. Si el canal online muestra márgenes superiores, la inversión en plataformas digitales tiene un retorno diferencial claro. Si el canal físico concentra más volumen pero con márgenes inferiores, se deben evaluar optimizaciones de costos operativos en tiendas.
Figura 14. Relación entre Precio por Unidad y Margen Operativo
# Calcular el coeficiente de correlación entre precio y margen
cor_precio_margen <- round(cor(datos$precio_unidad, datos$margen_operativo,
use = "complete.obs"), 3)
ggplotly(
ggplot(datos, aes(x = precio_unidad, y = margen_operativo * 100, color = metodo_venta)) +
geom_point(alpha = 0.4, size = 1.2) +
geom_smooth(method = "loess", se = TRUE, color = "black", linewidth = 0.8) +
scale_x_continuous(labels = dollar_format(prefix = "$")) +
labs(
title = paste0("Figura 14. Precio vs Margen Operativo | Correlación: ", cor_precio_margen),
x = "Precio por Unidad (USD)",
y = "Margen Operativo (%)",
color = "Método de Venta",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal()
)
Figura 15. Relación entre Unidades Vendidas y Ventas Totales
cor_unidades_ventas <- round(cor(datos$unidades_vendidas, datos$ventas_total,
use = "complete.obs"), 3)
ggplotly(
ggplot(datos, aes(x = unidades_vendidas, y = ventas_total, color = region)) +
geom_point(alpha = 0.4, size = 1.2) +
geom_smooth(method = "lm", se = FALSE, color = "black", linewidth = 0.8) +
scale_y_continuous(labels = dollar_format(prefix = "$", big.mark = ",")) +
labs(
title = paste0("Figura 15. Unidades Vendidas vs Ventas Totales | Correlación: ", cor_unidades_ventas),
x = "Unidades Vendidas",
y = "Ventas Totales (USD)",
color = "Región",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal()
)
Interpretación Figuras 14-15:
Figura 14 (Precio → Margen): Un coeficiente de correlación cercano a 1 indicaría que los productos más caros generan mayor rentabilidad relativa — validando una estrategia de premiumización. Una correlación baja o negativa sugiere que los descuentos en productos de precio alto erosionan los márgenes.
Figura 15 (Unidades → Ventas): Se espera una correlación alta y positiva, ya que más unidades vendidas implica más ingresos. La dispersión en la nube de puntos refleja la variedad de precios — transacciones con pocas unidades pero precio alto pueden generar ventas similares a transacciones de alto volumen y bajo precio.
# Tabla cruzada: Margen operativo promedio por Región y Producto
heatmap_data <- datos %>%
group_by(region, producto) %>%
summarise(Margen_Prom = round(mean(margen_operativo, na.rm = TRUE) * 100, 1),
.groups = "drop")
ggplotly(
ggplot(heatmap_data, aes(x = region, y = producto, fill = Margen_Prom)) +
geom_tile(color = "white", linewidth = 0.5) +
geom_text(aes(label = paste0(Margen_Prom, "%")), size = 3, fontface = "bold") +
scale_fill_gradient2(low = "#d73027", mid = "#ffffbf", high = "#1a9850",
midpoint = mean(heatmap_data$Margen_Prom, na.rm = TRUE),
name = "Margen (%)") +
labs(
title = "Figura 16. Heatmap: Margen Operativo (%) por Región y Producto",
x = "Región",
y = "Línea de Producto",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 30, hjust = 1))
)
Interpretación Figura 16 — Heatmap: Este mapa de calor es la visualización más densa de información del análisis. Las celdas verdes identifican las combinaciones Región × Producto con mayor rentabilidad, mientras que las celdas rojas señalan combinaciones problemáticas. Permite tomar decisiones de portafolio por mercado: qué productos empujar en cada región y cuáles descontinuar o revisar en precio.
# Top 10 ciudades por ventas totales
top_ciudades <- datos %>%
group_by(ciudad, region) %>%
summarise(
Ventas_Total = round(sum(ventas_total, na.rm = TRUE), 0),
Margen_Prom = round(mean(margen_operativo, na.rm = TRUE) * 100, 1),
.groups = "drop"
) %>%
arrange(desc(Ventas_Total)) %>%
head(10)
top_ciudades
| ciudad | region | Ventas_Total | Margen_Prom |
|---|---|---|---|
| New York | Northeast | 5676160 | 39.6 |
| San Francisco | West | 4929220 | 35.8 |
| Orlando | Southeast | 3946476 | 36.4 |
| Miami | Southeast | 3874113 | 42.9 |
| Los Angeles | West | 3651288 | 41.6 |
| Houston | South | 3629632 | 43.6 |
| Charleston | Southeast | 3593112 | 43.3 |
| New Orleans | South | 3377031 | 44.7 |
| Seattle | West | 3222093 | 32.5 |
| Richmond | Southeast | 3074415 | 41.4 |
ggplotly(
ggplot(top_ciudades, aes(x = reorder(ciudad, Ventas_Total), y = Ventas_Total, fill = region)) +
geom_col(alpha = 0.85) +
coord_flip() +
scale_y_continuous(labels = dollar_format(prefix = "$", big.mark = ",")) +
labs(
title = "Figura 17. Top 10 Ciudades por Ventas Totales",
x = "Ciudad",
y = "Ventas Totales (USD)",
fill = "Región",
caption = "Fuente: Dataset Adidas USA"
) +
theme_minimal()
)
Con base en el análisis descriptivo y exploratorio realizado sobre el dataset de ventas de Adidas en EE.UU., se pueden derivar las siguientes conclusiones y recomendaciones estratégicas:
1. Estructura de ventas: El análisis de tendencia central muestra que existe asimetría en las ventas por transacción. La presencia de outliers en el boxplot confirma que un subconjunto de transacciones de alto volumen concentra una proporción importante de los ingresos totales.
2. Rentabilidad por canal: El margen operativo varía significativamente según el método de venta. El canal con mayor margen es el que debe priorizarse en la estrategia de crecimiento de Adidas, siempre que su volumen sea escalable.
3. Desempeño regional: Las regiones no son homogéneas ni en volumen ni en rentabilidad. El heatmap (Figura 16) identifica combinaciones región-producto de alto rendimiento que justifican mayor inversión en marketing y distribución localizada.
4. Portafolio de productos: Las líneas de producto con alto margen y alto precio son las más valiosas estratégicamente. Los productos con volumen alto pero margen bajo pueden ser evaluados para optimización de precios o reducción de costos de distribución.
5. Retailer performance: Existe variabilidad en la rentabilidad generada por cada distribuidor. Algunos retailers generan mayor utilidad relativa a sus ventas, lo que los convierte en socios estratégicos prioritarios.
Análisis generado en R/RMarkdown — Listo para publicar en RPubs.