Introducción

Adidas es una empresa global reconocida por su participación en la industria de artículos deportivos y de estilo de vida, fundada en el año 1949 en Alemania, con un portafolio que incluye principalmente calzado, ropa y accesorios dirigidos tanto al rendimiento deportivo como al consumo cotidiano. La marca tiene un valor de 6.800 millones de dólares, lo que la convierte en una de las marcas más valiosas entre las corporaciones deportivas.

Como equipo de analistas de datos de Adidas tenemos como objetivo evaluar el desempeño comercial y financiero de distintas líneas de productos en el mercado de Estados Unidos, con el fin de comprender cómo se están desempeñando los diferentes productos, regiones y canales comerciales, y de qué manera esto afecta la rentabilidad de la compañía.

Aplicaremos técnicas de estadística descriptiva, diagnóstica y visualización de datos para detectar patrones, valores atípicos y relaciones entre variables, con el fin de facilitar la interpretación del desempeño comercial y financiero de la compañía y de proponer recomendaciones basadas en evidencia.

La base de datos utilizada contiene 9.651 registros con las siguientes variables: distribuidor, región, estado, ciudad, producto, precio por unidad, unidades vendidas, ventas totales, utilidad operativa, margen operativo y método de venta.

# Cargar librerías necesarias
library(readxl)
library(dplyr)
library(ggplot2)
library(plotly)
library(knitr)
library(kableExtra)
library(tidyr)
library(tidyverse)
library(scales)

Preparación de los datos

Cargar la base de datos

Nota importante: para que el documento compile en cualquier computador (incluido el de la profesora), el archivo DatosCaso1.xlsx debe estar guardado en la misma carpeta que este archivo .Rmd, y se carga con una ruta relativa en lugar de una ruta absoluta del computador personal.

# Cargar datos desde el archivo Excel (ruta relativa: mismo folder que el .Rmd)
datos_col <- read_excel("DatosCaso1.xlsx",
    col_types = c("text", "text", "text",
        "text", "text", "numeric", "numeric",
        "numeric", "numeric", "numeric",
        "text"))

# Ver las primeras filas de los datos
class(datos_col)
## [1] "tbl_df"     "tbl"        "data.frame"
colnames(datos_col)
##  [1] "distribuidor"       "region"             "estado"            
##  [4] "ciudad"             "producto"           "precio_unidad"     
##  [7] "unidades_vendidas"  "ventas_total"       "utilidad_operativa"
## [10] "margen_operativo"   "metodo_venta"
head(datos_col)
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

Limpieza de datos

Se revisan valores faltantes por columna:

colSums(is.na(datos_col)) %>%
  kable(col.names = "Valores faltantes", caption = "Valores faltantes por columna") %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover"))
Valores faltantes por columna
Valores faltantes
distribuidor 0
region 0
estado 0
ciudad 0
producto 0
precio_unidad 0
unidades_vendidas 0
ventas_total 0
utilidad_operativa 0
margen_operativo 0
metodo_venta 0
filas_antes <- nrow(datos_col)

datos_col <- datos_col %>%
  filter(if_all(everything(), ~ !is.na(.)))

filas_despues <- nrow(datos_col)

cat("Filas antes de la limpieza:", filas_antes,
    "\nFilas después de la limpieza:", filas_despues,
    "\nFilas eliminadas (registros incompletos):", filas_antes - filas_despues)
## Filas antes de la limpieza: 9648 
## Filas después de la limpieza: 9648 
## Filas eliminadas (registros incompletos): 0

Se eliminan los registros con datos incompletos, ya que corresponden a filas sin información aprovechable y no representan una categoría de negocio real. De aquí en adelante todo el análisis se realiza sobre el conjunto de datos ya depurado (datos_col).

Indicadores de centralidad y dispersión

# Resumen estadístico de las variables financieras
resumen <- datos_col %>%
  select(ventas_total, utilidad_operativa, margen_operativo) %>%
  summary()

resumen
##   ventas_total   utilidad_operativa margen_operativo
##  Min.   :    0   Min.   :    0      Min.   :0.100   
##  1st Qu.: 4065   1st Qu.: 1753      1st Qu.:0.350   
##  Median : 7804   Median : 3263      Median :0.410   
##  Mean   :12455   Mean   : 4895      Mean   :0.423   
##  3rd Qu.:15864   3rd Qu.: 6192      3rd Qu.:0.490   
##  Max.   :82500   Max.   :39000      Max.   :0.800

Para complementar el resumen anterior, se calculan de forma explícita las medidas de tendencia central y de variabilidad (incluyendo el coeficiente de variación, que permite comparar la dispersión relativa entre variables con escalas distintas):

resumen_variabilidad <- datos_col %>%
  summarise(across(
    c(precio_unidad, unidades_vendidas, ventas_total, utilidad_operativa, margen_operativo),
    list(
      Media = ~mean(., na.rm = TRUE),
      Mediana = ~median(., na.rm = TRUE),
      Desv_estandar = ~sd(., na.rm = TRUE),
      Coef_variacion = ~sd(., na.rm = TRUE) / mean(., na.rm = TRUE)
    ),
    .names = "{.col}__{.fn}"
  )) %>%
  pivot_longer(everything(), names_to = c("Variable", "Medida"), names_sep = "__") %>%
  pivot_wider(names_from = Medida, values_from = value) %>%
  mutate(across(where(is.numeric), ~round(., 2)))

kable(resumen_variabilidad, caption = "Medidas de tendencia central y variabilidad") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = TRUE) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#1F4E78")
Medidas de tendencia central y variabilidad
Variable Media Mediana Desv_estandar Coef_variacion
precio_unidad 45.22 45.00 14.71 0.33
unidades_vendidas 256.93 176.00 214.25 0.83
ventas_total 12455.08 7803.50 12716.39 1.02
utilidad_operativa 4894.79 3262.98 4866.46 0.99
margen_operativo 0.42 0.41 0.10 0.23

Interpretación: las ventas totales muestran una media claramente superior a la mediana, lo que indica una distribución sesgada a la derecha: existen registros de ventas muy altas que elevan el promedio por encima del valor típico. El coeficiente de variación de ventas_total y utilidad_operativa es superior a 1, lo que refleja una alta dispersión relativa en el desempeño comercial entre transacciones. En contraste, el margen_operativo es la variable más estable (coeficiente de variación más bajo), moviéndose de forma más homogénea alrededor de su media.

# Crear indicadores generales
tabla_general <- datos_col %>%
  summarise(
    ventas_total = sum(ventas_total, na.rm = TRUE),
    unidades_vendidas = sum(unidades_vendidas, na.rm = TRUE),
    utilidad_operativa = sum(utilidad_operativa, na.rm = TRUE),
    margen_operativo_promedio = mean(
      utilidad_operativa / ventas_total * 100,
      na.rm = TRUE
    ),
    precio_promedio = ventas_total / unidades_vendidas
  ) %>%
  mutate(
    ventas_total = dollar(
      ventas_total,
      prefix = "$",
      big.mark = ".",
      decimal.mark = ",",
      accuracy = 1
    ),
    unidades_vendidas = format(
      unidades_vendidas,
      big.mark = ".",
      decimal.mark = ",",
      scientific = FALSE
    ),
    utilidad_operativa = dollar(
      utilidad_operativa,
      prefix = "$",
      big.mark = ".",
      decimal.mark = ",",
      accuracy = 1
    ),
    margen_operativo_promedio = paste0(
      format(
        round(margen_operativo_promedio, 2),
        decimal.mark = ",",
        nsmall = 2
      ),
      "%"
    ),
    precio_promedio = dollar(
      precio_promedio,
      prefix = "$",
      big.mark = ".",
      decimal.mark = ",",
      accuracy = 1
    )
  ) %>%
  # Convertir la tabla a formato vertical
  pivot_longer(
    cols = everything(),
    names_to = "indicador",
    values_to = "valor"
  ) %>%
  mutate(
    indicador = recode(
      indicador,
      ventas_total = "Ventas totales",
      unidades_vendidas = "Unidades vendidas",
      utilidad_operativa = "Utilidad operacional",
      margen_operativo_promedio = "Margen operativo promedio",
      precio_promedio = "Precio promedio"
    )
  )
# Mostrar tabla vertical
kable(
  tabla_general,
  format = "html",
  escape = FALSE,
  align = c("l", "r"),
  col.names = c("Indicador", "Resultado"),
  caption = "Resumen general de indicadores comerciales y operativos"
) %>%
  kable_styling(
    bootstrap_options = c(
      "striped",
      "hover",
      "condensed",
      "responsive"
    ),
    full_width = FALSE,
    position = "center",
    font_size = 14
  ) %>%
  row_spec(
    0,
    bold = TRUE,
    color = "white",
    background = "#1F4E78",
    align = "center"
  ) %>%
  column_spec(
    1,
    bold = TRUE,
    color = "#1F4E78",
    width = "7cm"
  ) %>%
  column_spec(
    2,
    bold = TRUE,
    color = "#333333",
    width = "6cm"
  )
Resumen general de indicadores comerciales y operativos
Indicador Resultado
Ventas totales $120.166.650
Unidades vendidas 2.478.861
Utilidad operacional $47.224.968
Margen operativo promedio 39,30%
Precio promedio $48

Desempeño de ventas por segmento

# Resumen de ventas y utilidad operativa por región
resumen_region <- datos_col %>%
  group_by(region) %>%
  summarise(
    ventas_total = sum(ventas_total, na.rm = TRUE),
    utilidad_operativa = sum(utilidad_operativa, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  pivot_longer(
    cols = c(ventas_total, utilidad_operativa),
    names_to = "indicador",
    values_to = "valor"
  ) %>%
  mutate(
    indicador = recode(
      indicador,
      ventas_total = "Ventas totales",
      utilidad_operativa = "Utilidad operativa"
    ),
    valor_millones = valor / 1000000
  )

# Gráfico vertical de barras agrupadas
ggplot(
  resumen_region,
  aes(
    x = region,
    y = valor_millones,
    fill = indicador
  )
) +
  geom_col(
    position = position_dodge(width = 0.75),
    width = 0.55
  ) +

  scale_fill_manual(
    values = c(
      "Ventas totales" = "#1F4E78",
      "Utilidad operativa" = "#5B9DB5"
    )
  ) +

  scale_y_continuous(
    labels = function(x) {
      paste0(
        "$",
        format(
          x,
          decimal.mark = ",",
          big.mark = ".",
          nsmall = 1
        ),
        " M"
      )
    },
    expand = expansion(mult = c(0, 0.10))
  ) +

  labs(
    title = "Figura 1. Ventas y utilidad operativa por región",
    subtitle = "Valores acumulados expresados en millones de USD",
    x = "Región",
    y = "Valor financiero",
    fill = "Indicador"
  ) +

  theme_minimal() +

  theme(
    panel.grid = element_blank(),

    plot.title = element_text(
      size = 16,
      face = "bold",
      color = "black"
    ),

    plot.subtitle = element_text(
      size = 11,
      color = "#4B5563"
    ),

    axis.title = element_text(
      size = 11,
      face = "bold",
      color = "#1F2937"
    ),

    axis.text = element_text(
      size = 10,
      color = "#374151"
    ),

    axis.text.x = element_text(
      angle = 30,
      hjust = 1
    ),

    legend.position = "top",
    legend.title = element_text(
      face = "bold",
      color = "#1F2937"
    ),

    legend.text = element_text(
      color = "#374151"
    )
  )
Figura 1

Figura 1

Interpretación: la región West concentra el mayor volumen de ventas y de utilidad operativa, seguida de Northeast, mientras que Midwest es sistemáticamente la región con menor desempeño comercial. Sin embargo, como se verá más adelante, un mayor volumen de ventas no siempre implica un mayor margen relativo: South, pese a no ser la región líder en ventas, presenta el margen operativo promedio más alto del país.

# Resumen de ventas y utilidad por método de venta
resumen_metodo <- datos_col %>%
  group_by(metodo_venta) %>%
  summarise(
    ventas_total = sum(ventas_total, na.rm = TRUE),
    utilidad_operativa = sum(utilidad_operativa, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  mutate(
    ventas_total = ventas_total / 1000000,
    utilidad_operativa = utilidad_operativa / 1000000
  ) %>%
  pivot_longer(
    cols = c(ventas_total, utilidad_operativa),
    names_to = "indicador",
    values_to = "valor"
  ) %>%
  mutate(
    indicador = recode(
      indicador,
      ventas_total = "Ventas totales",
      utilidad_operativa = "Utilidad operativa"
    )
  )

# Gráfico de barras agrupadas
ggplot(
  resumen_metodo,
  aes(
    x = metodo_venta,
    y = valor,
    fill = indicador
  )
) +
  geom_col(
    position = position_dodge(width = 0.75),
    width = 0.65
  ) +

  geom_text(
    aes(
      label = paste0(
        "$",
        format(
          round(valor, 2),
          decimal.mark = ",",
          big.mark = ".",
          nsmall = 2
        ),
        " M"
      )
    ),
    position = position_dodge(width = 0.75),
    vjust = -0.35,
    size = 3.8,
    color = "#263238"
  ) +

  scale_fill_manual(
    values = c(
      "Ventas totales" = "#164E70",
      "Utilidad operativa" = "#8FA9B5"
    )
  ) +

  scale_y_continuous(
    labels = function(x) {
      paste0("$", format(x, decimal.mark = ",", nsmall = 0), " M")
    },
    expand = expansion(mult = c(0, 0.15))
  ) +

  labs(
    title = "Figura 2. Ventas y utilidad operativa por método de venta",
    subtitle = "Valores acumulados expresados en millones de USD",
    x = "Método de venta",
    y = "Valor financiero",
    fill = "Indicador"
  ) +

  theme_minimal() +

  theme(
    panel.grid = element_blank(),

    plot.title = element_text(
      size = 16,
      face = "bold",
      color = "black"
    ),

    plot.subtitle = element_text(
      size = 11,
      color = "#5B6770"
    ),

    axis.title = element_text(
      size = 11,
      face = "bold",
      color = "#263238"
    ),

    axis.text = element_text(
      size = 10,
      color = "#374151"
    ),

    legend.position = "top",
    legend.title = element_text(face = "bold"),
    legend.text = element_text(size = 10)
  )
Figura 2

Figura 2

Interpretación: el canal Online genera el mayor volumen de ventas y de utilidad operativa, seguido de Outlet y de In-store. Este resultado es relevante porque, como se confirma en la sección de rentabilidad, el canal Online no solo vende más: también es el canal con mejor margen operativo promedio, es decir, combina volumen y rentabilidad.

# Resumen de ventas y utilidad operativa por distribuidor
resumen_distribuidor <- datos_col %>%
  group_by(distribuidor) %>%
  summarise(
    ventas_total = sum(ventas_total, na.rm = TRUE),
    utilidad_operativa = sum(utilidad_operativa, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  pivot_longer(
    cols = c(ventas_total, utilidad_operativa),
    names_to = "indicador",
    values_to = "valor"
  ) %>%
  mutate(
    indicador = recode(
      indicador,
      ventas_total = "Ventas totales",
      utilidad_operativa = "Utilidad operativa"
    ),
    valor_millones = valor / 1000000
  )

# Gráfico vertical de barras agrupadas
ggplot(
  resumen_distribuidor,
  aes(
    x = distribuidor,
    y = valor_millones,
    fill = indicador
  )
) +
  geom_col(
    position = position_dodge(width = 0.75),
    width = 0.55
  ) +
  scale_fill_manual(
    values = c(
      "Ventas totales" = "#1F4E78",
      "Utilidad operativa" = "#5B9DB5"
    )
  ) +
  scale_y_continuous(
    labels = function(x) {
      paste0(
        "$",
        format(
          x,
          decimal.mark = ",",
          big.mark = ".",
          nsmall = 1
        ),
        " M"
      )
    },
    expand = expansion(mult = c(0, 0.10))
  ) +
  labs(
    title = "Figura 3. Ventas y utilidad operativa por distribuidor",
    subtitle = "Valores acumulados expresados en millones de USD",
    x = "Distribuidor",
    y = "Valor financiero",
    fill = "Indicador"
  ) +
  theme_minimal() +
  theme(
    panel.grid = element_blank(),

    plot.title = element_text(
      size = 16,
      face = "bold",
      color = "black"
    ),

    plot.subtitle = element_text(
      size = 11,
      color = "#4B5563"
    ),

    axis.title = element_text(
      size = 11,
      face = "bold",
      color = "#1F2937"
    ),

    axis.text = element_text(
      size = 10,
      color = "#374151"
    ),

    axis.text.x = element_text(
      angle = 35,
      hjust = 1
    ),

    legend.position = "top",

    legend.title = element_text(
      face = "bold",
      color = "#1F2937"
    ),

    legend.text = element_text(
      color = "#374151"
    )
  )
Figura 3

Figura 3

Interpretación: West Gear y Foot Locker son los distribuidores con mayor volumen de ventas y utilidad, mientras que Amazon y Walmart presentan la menor participación dentro de este conjunto de datos. Esto sugiere que la relación comercial con distribuidores especializados de calzado/deporte (West Gear, Foot Locker, Sports Direct) es, hasta ahora, más fuerte que con los grandes marketplaces generalistas.

# Resumir unidades vendidas por producto
unidades_producto <- datos_col %>%
  group_by(producto) %>%
  summarise(
    total_unidades = sum(unidades_vendidas, na.rm = TRUE),
    ventas_totales = sum(ventas_total, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  mutate(participacion_ventas = ventas_totales / sum(ventas_totales) * 100) %>%
  arrange(desc(total_unidades))

# Paleta en escala de grises y azules
colores_grises_azules <- c(
  "#0B2D45",  # Azul marino
  "#164E70",  # Azul petróleo
  "#287A9F",  # Azul medio
  "#5B9DB5",  # Azul grisáceo
  "#8FA9B5",  # Gris azulado
  "#B8C2C8",  # Gris claro
  "#6B7280",  # Gris medio
  "#374151"   # Gris oscuro
)
# Repetir colores si hay más productos que colores definidos
colores_grises_azules <- rep(
  colores_grises_azules,
  length.out = nrow(unidades_producto)
)
# Gráfico de torta
plot_ly(
  unidades_producto,
  labels = ~producto,              # Nombres completos en la leyenda
  values = ~total_unidades,
  type = "pie",
  textinfo = "percent",            # Solo porcentajes dentro de la torta
  textposition = "inside",
  insidetextorientation = "radial",
  hovertemplate = paste(
    "<b>%{label}</b><br>",
    "Unidades vendidas: %{value:,}<br>",
    "Participación: %{percent}<extra></extra>"
  ),
  marker = list(
    colors = colores_grises_azules,
    line = list(
      color = "#FFFFFF",
      width = 2
    )
  )
) %>%
  layout(
    title = list(
      text = "Figura 4. Participación de unidades vendidas por producto",
      font = list(
        color = "#000000",
        size = 18,
        family = "Arial"
      )
    ),
    showlegend = TRUE,
    legend = list(
      title = list(
        text = "Productos"
      ),
      orientation = "v",
      x = 1,
      y = 0.5,
      font = list(
        size = 11,
        color = "#263238"
      )
    ),
    margin = list(
      l = 10,
      r = 220,
      t = 75,
      b = 10
    ),
    paper_bgcolor = "#FFFFFF",
    plot_bgcolor = "#FFFFFF"
  )

Figura 4

unidades_producto %>%
  mutate(
    total_unidades = comma(total_unidades),
    ventas_totales = dollar(ventas_totales, big.mark = ".", decimal.mark = ",", accuracy = 1),
    participacion_ventas = paste0(round(participacion_ventas, 1), "%")
  ) %>%
  kable(col.names = c("Producto", "Unidades vendidas", "Ventas totales", "Participación en ventas"),
        caption = "Participación de cada línea de producto en unidades y ventas totales") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = TRUE)
Participación de cada línea de producto en unidades y ventas totales
Producto Unidades vendidas Ventas totales Participación en ventas
Men’s Street Footwear 593,320 $27.680.769 23%
Men’s Athletic Footwear 435,526 $20.577.180 17.1%
Women’s Apparel 433,827 $23.870.985 19.9%
Women’s Street Footwear 392,269 $17.201.563 14.3%
Women’s Athletic Footwear 317,236 $14.315.521 11.9%
Men’s Apparel 306,683 $16.520.632 13.7%

Interpretación: el portafolio de Adidas está razonablemente diversificado: ninguna línea de producto concentra más del 23% de las ventas totales. Men’s Street Footwear lidera tanto en unidades vendidas como en participación de ventas (23,0%), seguido de Women’s Apparel (19,9%). Esta diversificación reduce el riesgo de depender de una sola categoría de producto.

Distribución de las ventas y detección de valores atípicos

# Crear y mostrar el boxplot interactivo
grafico <- ggplot(datos_col,
                  aes(x = metodo_venta,
                      y = ventas_total,
                      fill = metodo_venta,
                      text = paste(
                        "Método:", metodo_venta,
                        "<br>Ventas totales:", ventas_total,
                        "<br>Producto:", producto,
                        "<br>Ciudad:", ciudad,
                        "<br>Distribuidor:", distribuidor
                      ))) +

  geom_boxplot() +

  labs(
    title = "Figura 5. Distribución de ventas totales por método de venta",
    x = "Método de venta",
    y = "Ventas total (USD)"
  ) +

  theme_minimal() +

  theme(
    legend.position = "none",
    plot.title = element_text(hjust = 0.5)
  )

ggplotly(grafico, tooltip = "text")

Figura 5

q_out <- quantile(datos_col$ventas_total, c(0.25, 0.75))
iqr_out <- q_out[2] - q_out[1]
lim_sup_out <- q_out[2] + 1.5 * iqr_out
n_outliers <- sum(datos_col$ventas_total > lim_sup_out)
pct_outliers <- n_outliers / nrow(datos_col) * 100

Interpretación: en los tres métodos de venta la distribución de ventas_total está sesgada a la derecha y presenta numerosos valores atípicos (los puntos por encima de las cajas), lo cual es consistente con lo observado en la sección de indicadores generales. Usando el criterio estadístico de 1,5 veces el rango intercuartílico (IQR), se identifican 799 registros atípicos en el total de la base (8.3% de las observaciones): transacciones puntuales de muy alto valor que conviene monitorear y gestionar de forma diferenciada, ya que concentran una parte importante de los ingresos totales.

Rentabilidad: distribución del margen operativo

grafico_margen_producto <- ggplot(
  datos_col,
  aes(x = reorder(producto, margen_operativo, FUN = median), y = margen_operativo, fill = producto,
      text = paste("Producto:", producto, "<br>Margen operativo:", scales::percent(margen_operativo, accuracy = 0.1)))
) +
  geom_boxplot(show.legend = FALSE) +
  scale_fill_manual(values = colores_grises_azules) +
  scale_y_continuous(labels = percent) +
  coord_flip() +
  labs(
    title = "Figura 6. Distribución del margen operativo por línea de producto",
    x = NULL, y = "Margen operativo"
  ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5, size = 13, face = "bold"))

ggplotly(grafico_margen_producto, tooltip = "text")

Figura 6

grafico_margen_metodo <- ggplot(
  datos_col,
  aes(x = reorder(metodo_venta, margen_operativo, FUN = median), y = margen_operativo, fill = metodo_venta,
      text = paste("Método:", metodo_venta, "<br>Margen operativo:", scales::percent(margen_operativo, accuracy = 0.1)))
) +
  geom_boxplot(show.legend = FALSE) +
  scale_fill_manual(values = c("#1F4E78", "#5B9DB5", "#8FA9B5")) +
  scale_y_continuous(labels = percent) +
  coord_flip() +
  labs(
    title = "Figura 7. Distribución del margen operativo por método de venta",
    x = NULL, y = "Margen operativo"
  ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5, size = 13, face = "bold"))

ggplotly(grafico_margen_metodo, tooltip = "text")

Figura 7

margen_region <- datos_col %>%
  group_by(region) %>%
  summarise(margen_promedio = mean(margen_operativo, na.rm = TRUE), .groups = "drop") %>%
  arrange(desc(margen_promedio))

margen_region %>%
  mutate(margen_promedio = paste0(round(margen_promedio * 100, 1), "%")) %>%
  kable(col.names = c("Región", "Margen operativo promedio"),
        caption = "Margen operativo promedio por región") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Margen operativo promedio por región
Región Margen operativo promedio
South 46.7%
Midwest 43.5%
Southeast 41.9%
Northeast 41%
West 39.7%

Interpretación: Men’s Street Footwear y Women’s Apparel son las líneas de producto con mayor margen operativo promedio, mientras que Men’s Athletic Footwear es la de menor margen relativo (Figura 6). Por método de venta (Figura 7), el canal Online presenta el margen más alto y menos disperso, mientras que In-store es el menos rentable en términos relativos, probablemente por mayores costos de operación física y descuentos más frecuentes. A nivel geográfico, la región South tiene el mejor margen operativo promedio del país, aun sin ser la de mayores ventas (ver tabla anterior), lo que confirma que volumen de ventas y rentabilidad relativa no siempre van de la mano.

Relación entre variables clave

Correlación-Dispersión

# Crear gráfico interactivo con correlación
cor_precio_unidades <- round(cor(datos_col$precio_unidad, datos_col$unidades_vendidas, use = "complete.obs"), 2)

ggplotly(
  ggplot(datos_col, aes(x = precio_unidad, y = unidades_vendidas)) +
    geom_point(color = "lightblue", alpha = 0.9, size = 2) +
    geom_smooth(method = "lm", color = "grey", se = TRUE) +
    labs(
      title = paste("Figura 8. Relación entre Precio por Unidad y Unidades Vendidas \nCoef. de correlación:",
                    cor_precio_unidades),
      x = "Precio unidad (USD)",
      y = "Unidades vendidas",
      caption = "Fuente: Base de datos Caso 1 - Ventas Adidas"
    ) +
    theme_minimal() +
    theme(
      plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
      axis.title = element_text(size = 12),
      axis.text = element_text(size = 10)
    )
)

Figura 8

Interpretación: la correlación entre precio por unidad y unidades vendidas es positiva pero débil (r = 0.27). Esto no confirma la hipótesis de que precios más altos reducen el volumen de ventas; de hecho, la relación es ligeramente positiva, lo que sugiere que el precio está capturando en parte diferencias de categoría de producto (p. ej. calzado vs. ropa) más que un efecto de elasticidad-precio dentro de un mismo producto.

# Crear gráfico interactivo con correlación
cor_ventas_utilidad <- round(cor(datos_col$ventas_total, datos_col$utilidad_operativa, use = "complete.obs"), 2)

ggplotly(
  ggplot(datos_col, aes(x = ventas_total, y = utilidad_operativa)) +
    geom_point(color = "lightblue", alpha = 0.9, size = 2) +
    geom_smooth(method = "lm", color = "grey", se = TRUE) +
    labs(
      title = paste("Figura 9. Relación entre Ventas Totales y Utilidad Operativa \nCoef. de correlación:",
                    cor_ventas_utilidad),
      x = "Ventas totales (USD)",
      y = "Utilidad operativa (USD)",
      caption = "Fuente: Base de datos Caso 1 - Ventas Adidas"
    ) +
    theme_minimal() +
    theme(
      plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
      axis.title = element_text(size = 12),
      axis.text = element_text(size = 10)
    )
)

Figura 9

En la Figura 9 se observa una fuerte correlación positiva entre las ventas totales y la utilidad operativa, con un coeficiente de correlación de 0.94. Esto indica que, a medida que las ventas aumentan, la utilidad operativa también crece de forma casi proporcional. Esta relación es esperable: a mayor volumen vendido, mayor utilidad en términos absolutos. Sin embargo, esto no implica que un mayor volumen de ventas garantice también un mayor margen (rentabilidad relativa), como se explora a continuación.

cor_precio_margen <- round(cor(datos_col$precio_unidad, datos_col$margen_operativo, use = "complete.obs"), 2)

ggplotly(
  ggplot(datos_col, aes(x = precio_unidad, y = margen_operativo)) +
    geom_point(color = "#8B5CF6", alpha = 0.7, size = 2) +
    geom_smooth(method = "lm", color = "grey", se = TRUE) +
    scale_y_continuous(labels = percent) +
    labs(
      title = paste("Figura 10. Relación entre Precio por Unidad y Margen Operativo \nCoef. de correlación:",
                    cor_precio_margen),
      x = "Precio unidad (USD)",
      y = "Margen operativo",
      caption = "Fuente: Base de datos Caso 1 - Ventas Adidas"
    ) +
    theme_minimal() +
    theme(
      plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
      axis.title = element_text(size = 12),
      axis.text = element_text(size = 10)
    )
)

Figura 10

Interpretación: la correlación entre precio por unidad y margen operativo es negativa y débil (r = -0.14), por lo que el precio, de forma aislada, no explica de manera importante la rentabilidad. Esto refuerza la conclusión de que el margen depende más del canal de venta y del distribuidor (secciones anteriores) que del nivel de precio en sí mismo.

Combinaciones estratégicas: producto, región y método de venta

# Resumir las ventas por producto y región
heatmap_producto_region <- datos_col %>%
  group_by(producto, region) %>%
  summarise(
    ventas_total = sum(ventas_total, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  pivot_wider(
    names_from = region,
    values_from = ventas_total,
    values_fill = 0
  )
# Conservar los nombres de los productos
productos <- heatmap_producto_region$producto
# Convertir los valores a una matriz numérica
matriz_heatmap <- heatmap_producto_region %>%
  select(-producto) %>%
  as.matrix()
# Heatmap con escala de colores fríos a cálidos
grafico_heatmap <- plot_ly(
  x = colnames(matriz_heatmap),
  y = productos,
  z = matriz_heatmap,
  type = "heatmap",
  colorscale = list(
    list(0.00, "#2166AC"),
    list(0.25, "#67A9CF"),
    list(0.50, "#FFFFBF"),
    list(0.75, "#F4A582"),
    list(1.00, "#B2182B")
  ),
  colorbar = list(
    title = "Ventas",
    tickprefix = "$",
    tickformat = ",.0f"
  ),
  hovertemplate = paste(
    "<b>Producto:</b> %{y}<br>",
    "<b>Región:</b> %{x}<br>",
    "<b>Ventas:</b> $%{z:,.0f}<extra></extra>"
  )
) %>%
  layout(
    title = list(
      text = "Figura 11. Mapa de calor de ventas por producto y región",
      font = list(
        color = "#000000",
        size = 18,
        family = "Arial"
      ),
      x = 0.05
    ),
    xaxis = list(
      title = "Región",
      tickfont = list(color = "#374151", size = 11),
      showgrid = FALSE
    ),
    yaxis = list(
      title = "Producto",
      tickfont = list(color = "#374151", size = 11),
      showgrid = FALSE
    ),
    paper_bgcolor = "#FFFFFF",
    plot_bgcolor = "#FFFFFF",
    margin = list(l = 160, r = 100, t = 90, b = 80)
  )
# Mostrar el heatmap
grafico_heatmap

Figura 11

# Resumir el margen operativo promedio por producto y método de venta
heatmap_producto_metodo <- datos_col %>%
  group_by(producto, metodo_venta) %>%
  summarise(
    margen_promedio = mean(margen_operativo, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  pivot_wider(
    names_from = metodo_venta,
    values_from = margen_promedio,
    values_fill = 0
  )

productos_m <- heatmap_producto_metodo$producto
matriz_heatmap_m <- heatmap_producto_metodo %>%
  select(-producto) %>%
  as.matrix()

plot_ly(
  x = colnames(matriz_heatmap_m),
  y = productos_m,
  z = matriz_heatmap_m,
  type = "heatmap",
  colorscale = list(
    list(0.00, "#F7FBFF"),
    list(0.50, "#6BAED6"),
    list(1.00, "#08306B")
  ),
  colorbar = list(title = "Margen", tickformat = ".0%"),
  hovertemplate = paste(
    "<b>Producto:</b> %{y}<br>",
    "<b>Método de venta:</b> %{x}<br>",
    "<b>Margen operativo promedio:</b> %{z:.1%}<extra></extra>"
  )
) %>%
  layout(
    title = list(
      text = "Figura 12. Margen operativo promedio por producto y método de venta",
      font = list(color = "#000000", size = 18, family = "Arial"),
      x = 0.05
    ),
    xaxis = list(title = "Método de venta", tickfont = list(color = "#374151", size = 11), showgrid = FALSE),
    yaxis = list(title = "Producto", tickfont = list(color = "#374151", size = 11), showgrid = FALSE),
    paper_bgcolor = "#FFFFFF",
    plot_bgcolor = "#FFFFFF",
    margin = list(l = 160, r = 60, t = 90, b = 80)
  )

Figura 12

Interpretación: en la Figura 11, la combinación de mayor volumen de ventas es Men’s Street Footwear en la región West, lo que la convierte en la combinación producto-región más relevante en términos comerciales. En la Figura 12, el patrón es muy claro: para todas las líneas de producto, el canal Online es el que ofrece el mayor margen operativo promedio, mientras que In-store es sistemáticamente el de menor margen. Esto sugiere una oportunidad estratégica clara: reforzar la venta online de las líneas de mayor participación (Men’s Street Footwear, Women’s Apparel) para capturar simultáneamente volumen y rentabilidad.

cor_margen_utilidad <- round(cor(datos_col$margen_operativo, datos_col$utilidad_operativa, use = "complete.obs"), 2)

ggplotly(
  ggplot(datos_col, aes(x = margen_operativo, y = utilidad_operativa)) +
    geom_point(color = "purple", alpha = 0.8, size = 2) +
    geom_smooth(method = "loess", color = "grey", se = TRUE) +
    scale_x_continuous(labels = percent) +
    labs(
      title = paste("Figura 13. Relación entre Margen Operativo y Utilidad Operativa \nCoef. de correlación:",
                    cor_margen_utilidad),
      x = "Margen Operativo",
      y = "Utilidad Operativa (USD)",
      caption = "Fuente: Base de datos Caso 1 - Ventas Adidas"
    ) +
    theme_minimal() +
    theme(
      plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
      axis.title = element_text(size = 12),
      axis.text = element_text(size = 10)
    )
)

Figura 13

Interpretación: el margen operativo y la utilidad operativa en dólares están prácticamente descorrelacionados (r = -0.05). Esto ocurre porque la utilidad en dólares depende principalmente del volumen de ventas (Figura 9), mientras que el margen depende de la eficiencia relativa de cada transacción; una transacción puede generar mucha utilidad en dólares con un margen moderado (alto volumen), o poca utilidad con un margen alto (bajo volumen). Ambas métricas son complementarias y deben monitorearse por separado.

vars_numericas <- datos_col %>%
  select(precio_unidad, unidades_vendidas, ventas_total, utilidad_operativa, margen_operativo)

mat_cor <- round(cor(vars_numericas, use = "complete.obs"), 2)

mat_cor_long <- as.data.frame(mat_cor) %>%
  mutate(var1 = rownames(mat_cor)) %>%
  pivot_longer(-var1, names_to = "var2", values_to = "correlacion")

plot_ly(
  x = colnames(mat_cor),
  y = rownames(mat_cor),
  z = mat_cor,
  type = "heatmap",
  colorscale = list(
    list(0.00, "#B2182B"),
    list(0.50, "#FFFFFF"),
    list(1.00, "#2166AC")
  ),
  zmin = -1, zmax = 1,
  colorbar = list(title = "r"),
  hovertemplate = "<b>%{y} vs %{x}</b><br>r = %{z}<extra></extra>"
) %>%
  layout(
    title = list(text = "Figura 14. Matriz de correlación entre variables numéricas",
                 font = list(color = "#000000", size = 18, family = "Arial"), x = 0.05),
    xaxis = list(title = "", tickfont = list(size = 10)),
    yaxis = list(title = "", tickfont = list(size = 10)),
    paper_bgcolor = "#FFFFFF",
    plot_bgcolor = "#FFFFFF",
    margin = list(l = 140, r = 60, t = 90, b = 100)
  )

Figura 14

Interpretación: la matriz de correlación resume los hallazgos anteriores: unidades_vendidas y ventas_total están muy fuertemente correlacionadas (r = 0.92), al igual que ventas_total y utilidad_operativa (r = 0.94). En contraste, margen_operativo tiene correlaciones negativas y débiles con unidades_vendidas (r = -0.31) y con ventas_total (r = -0.3), lo que confirma que los productos o transacciones de mayor volumen tienden a operar, en promedio, con un margen ligeramente menor — un clásico trade-off entre volumen y rentabilidad relativa.

Principales hallazgos

  • El portafolio de producto está razonablemente diversificado: ninguna línea supera el 23% de participación en ventas totales, liderado por Men’s Street Footwear.
  • West y Northeast concentran la mayor parte del volumen de ventas; Midwest es consistentemente la región de menor desempeño comercial.
  • El canal Online combina el mayor volumen de ventas con el mayor margen operativo promedio, mientras que In-store es el canal menos rentable en términos relativos, en todas las líneas de producto.
  • La región South tiene el mejor margen operativo promedio del país pese a no ser la de mayores ventas, confirmando que volumen y rentabilidad relativa no siempre coinciden.
  • Existe una alta variabilidad y presencia de valores atípicos en las ventas totales (799 registros, 8.3% del total), transacciones puntuales de alto valor que conviene gestionar de forma diferenciada.
  • El precio por unidad no es el principal determinante ni del volumen de ventas ni de la rentabilidad: sus correlaciones con unidades_vendidas (r = 0.27) y con margen_operativo (r = -0.14) son débiles.
  • Ventas y utilidad operativa están fuertemente correlacionadas (r = 0.94), pero el margen se comporta de forma prácticamente independiente del volumen, evidenciando el trade-off entre vender más y vender con mejor rentabilidad relativa.
  • La combinación más estratégica identificada es producto + canal Online: en las seis líneas de producto, vender por este canal genera el margen más alto, siendo Women’s Apparel Online y Men’s Street Footwear Online las combinaciones con mejor margen promedio.

Conclusiones y recomendaciones

El análisis descriptivo y diagnóstico muestra una compañía con un portafolio de producto diversificado y un desempeño de ventas fuertemente influenciado por la región y, sobre todo, por el canal de venta. La rentabilidad (margen operativo) no está determinada principalmente por el precio, sino por cómo y dónde se vende el producto. A partir de estos hallazgos se proponen las siguientes recomendaciones de negocio (analítica prescriptiva):

  • Priorizar la expansión del canal Online, dado que combina buen volumen con el mayor margen operativo promedio en todas las líneas de producto; evaluar mayor inversión en comercio electrónico y marketing digital, especialmente para las líneas de mayor participación (Men’s Street Footwear, Women’s Apparel).
  • Revisar la estrategia comercial del canal In-store, ya que concentra volumen pero con la menor rentabilidad relativa; evaluar políticas de descuento más disciplinadas y mejoras de eficiencia operativa en tienda física.
  • Replicar en otras regiones las condiciones comerciales de South, la región con mejor margen operativo pese a no ser la de mayor volumen, para entender qué factores (mezcla de canal, de producto o de distribuidor) explican su mejor rentabilidad relativa.
  • Fortalecer el desempeño comercial de Midwest, la región más rezagada, con planes específicos que se apoyen en el aprendizaje de las combinaciones producto-canal más exitosas en otras regiones.
  • Gestionar de forma diferenciada las transacciones de muy alto valor (valores atípicos), dado que representan cerca del 8.3% de los registros y concentran una porción relevante de los ingresos; formalizar su seguimiento como cuentas o pedidos clave.
  • No basar la estrategia de precios únicamente en el volumen esperado, dado que la relación precio–unidades y precio–margen es débil; explorar otras palancas de rentabilidad (canal, distribuidor, categoría, temporada).

Estas recomendaciones deberían complementarse, en una siguiente fase, con información adicional no disponible en este dataset (por ejemplo, costos de marketing por canal o datos con marca temporal que permitan calcular tasas de crecimiento en el tiempo), pero constituyen un punto de partida sólido y basado en evidencia para la toma de decisiones comerciales de Adidas.