Introducción

El presente trabajo práctico tiene como objetivo principal consolidar las habilidades de crítica, rediseño y visualización efectiva de datos utilizando el entorno de programación R, con especial énfasis en el paquete ggplot2. El análisis se articula en dos estudios de caso:

  1. Crítica y Rediseño Gráfico: Se inicia con la evaluación crítica de una visualización ineficaz. Esta fase subraya la necesidad de elegir estructuras gráficas que eliminen la distorsión y faciliten la comparación precisa de los datos.

  2. Análisis Descriptivo y Estratégico de Ventas: Posteriormente, la actividad se centra en un conjunto de datos real de una tienda en línea. El propósito es aplicar la teoría de visualización en un contexto de negocio, realizando un análisis descriptivo exhaustivo mediante la creación de métricas financieras clave (Ventas, Ganancia) y la generación de visualizaciones gráficas esenciales.

La meta de este documento es demostrar la capacidad de transformar datos crudos en insights accionables, utilizando R para identificar patrones de estacionalidad (tendencias temporales) y motores de rentabilidad (ganancia por tipo de artículo), lo cual es fundamental para la toma de decisiones gerenciales.

Caso 1: ¿Qué especies de tiburones son realmente peligrosas?

Solo unas pocas de las más de 500 especies de tiburones pueden llegar a ser peligrosas para los humanos. Los tiburones deben tener aproximadamente el tamaño de un humano para ser peligrosos para nosotros.

Solo unas pocas de las más de 500 especies de tiburones pueden llegar a ser peligrosas para los humanos. Los tiburones deben tener aproximadamente el tamaño de un humano para ser peligrosos para nosotros.

Los Diez Tiburones Principales
Los Diez Tiburones Principales

Descripción de la tarea a realizar

  1. Analiza el gráfico proporcionado en la fuente y señala brevemente (uno o dos párrafos) cuáles son los principales problemas o deficiencias que presenta. Realiza un rediseño del gráfico utilizando los mismos datos.
  2. Incluye una breve justificación (uno o dos párrafos) explicando por qué la propuesta que haces es una mejora con respecto a la original.

Solución

El gráfico anterior presenta la información como un gráfico de pastel 3D (o semi-esfera). Entre las deficiencias importantes que dificultan la comprensión y el análisis de los datos se encuentran:

  1. Distorsión y una lectura imprescisa: no se sigue el principio de que la longitud o área debe ser proporcional al valor que representa.
  2. Etiquedado confuso: Los nombres de las especies y los valores están dispersos alrededor del gráfico y se puede ver como una lineas finas y punteadas las señala lo que obliga al lector a seguir las lineas hasta la porción correspondiente, lo cual no permite una lectura rápida.
  3. Exceso de categorías menores: algunas categorias tienen valores muy pequeños y están tan agrupadas que sus porciones apenas son visibles y sus etiquetas se superponen, saturando el espacio y haciendo imposible percibir sus diferencias relativas.

Rediseño propuesto del gráfico

Se propone usar un Gráfico de Barras Combinado con Línea, pues es común usarlo para comparar una métrica principal en este caso los ataques con una métrica secundario relacionada es decir, los ataques fatales.

Este gráfico usa la longitud de las barras para representar los Ataques lo cual es una de las formas más precisas para comparar magnitudes. Tambien esta ordenado de mayor a menor, lo que nos brinda una jeraquía visual inmediata y se visualizan las dos metricas distintas de manera clara. Sumando a lo anterior, las etiquetas de las especies están distribuidas claramente en el eje X, y los valores númericos están colocados directamente sobre las barras y los puntos, mejorando la legibilidad.

scale_factor <- max(datos_tiburones$Ataques) / max(datos_tiburones$Fatales)

ggplot(datos_tiburones, aes(x = Especie)) +
  
  # 1. Barras para Ataques 
  geom_col(aes(y = Ataques), fill = "#2C5D7D") + 
  
  # 2. Línea y puntos para Ataques Fatales 
  geom_line(aes(y = Fatales * scale_factor, group = 1), color = "#D52C2C", size = 1.2) + 
  geom_point(aes(y = Fatales * scale_factor), color = "#D52C2C", size = 3) + 
  
  # 3. Etiquetas de valor para las barras (Ataques)
  geom_text(aes(y = Ataques, label = Ataques), vjust = -0.5, color = "black", size = 3.5) +
  
  # 4. Etiquetas de valor para los puntos (Fatales)
  geom_text(aes(y = Fatales * scale_factor, label = Fatales), vjust = 1.5, color = "#D52C2C", size = 3.5) +
  
  # 5. Definición del Eje Y Secundario
  scale_y_continuous(
    name = "ATAQUES",
    limits = c(0, max(datos_tiburones$Ataques) * 1.1), 
    sec.axis = sec_axis(~ . / scale_factor, name = "ATAQUES FATALES") 
  ) +
  labs(
    title = "Ataques no provocados a humanos por especie de tiburón",
    x = "" 
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    axis.title.y.right = element_text(color = "#D52C2C", face = "bold"),
    axis.title.y.left = element_text(face = "bold"),
    axis.text.x = element_text(angle = 30, hjust = 1, size = 10), 
    panel.grid.major.x = element_blank() 
  )
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Caso 2: Análisis de ventas de una tienda en línea

Trabajas en el departamento de análisis de datos de una tienda que comercializa una amplia variedad de productos. Tu equipo ha recopilado información sobre ventas durante los últimos ocho años, y se te ha asignado la tarea de analizar estos datos con el fin de identificar patrones relevantes y generar recomendaciones para la gerencia.

Descripción de la tarea a realizar

Realiza un análisis descriptivo del conjunto de datos proporcionado. Para ello, utiliza medidas de tendencia central y dispersión, y complementa el análisis con al menos dos visualizaciones gráficas que ayuden a ilustrar los patrones observados en las ventas y las ganancias.

Solución

Primer paso, cargar los datos a R

datos_ventas <- read_excel("registro_transacciones_comerciales.xlsx")

# Ver las primeras filas
head(datos_ventas)
## # A tibble: 6 × 11
##   Region                    Country `Item Type` `Sales Channel` `Order Priority`
##   <chr>                     <chr>   <chr>       <chr>           <chr>           
## 1 Sub-Saharan Africa        South … Fruits      Offline         M               
## 2 Middle East and North Af… Morocco Clothes     Online          M               
## 3 Australia and Oceania     Papua … Meat        Offline         M               
## 4 Sub-Saharan Africa        Djibou… Clothes     Offline         H               
## 5 Europe                    Slovak… Beverages   Offline         L               
## 6 Asia                      Sri La… Fruits      Online          L               
## # ℹ 6 more variables: `Order Date` <dttm>, `Order ID` <dbl>,
## #   `Ship Date` <dttm>, `Units Sold` <dbl>, `Unit Price` <dbl>,
## #   `Unit Cost` <dbl>
# Ver la estructura y tipos de datos
str(datos_ventas)
## tibble [1,000,000 × 11] (S3: tbl_df/tbl/data.frame)
##  $ Region        : chr [1:1000000] "Sub-Saharan Africa" "Middle East and North Africa" "Australia and Oceania" "Sub-Saharan Africa" ...
##  $ Country       : chr [1:1000000] "South Africa" "Morocco" "Papua New Guinea" "Djibouti" ...
##  $ Item Type     : chr [1:1000000] "Fruits" "Clothes" "Meat" "Clothes" ...
##  $ Sales Channel : chr [1:1000000] "Offline" "Online" "Offline" "Offline" ...
##  $ Order Priority: chr [1:1000000] "M" "M" "M" "H" ...
##  $ Order Date    : POSIXct[1:1000000], format: "2012-07-27" "2013-09-14" ...
##  $ Order ID      : num [1:1000000] 4.43e+08 6.68e+08 9.41e+08 8.81e+08 1.75e+08 ...
##  $ Ship Date     : POSIXct[1:1000000], format: "2012-07-28" "2013-10-19" ...
##  $ Units Sold    : num [1:1000000] 1593 4611 360 562 3973 ...
##  $ Unit Price    : num [1:1000000] 9.33 109.28 421.89 109.28 47.45 ...
##  $ Unit Cost     : num [1:1000000] 6.92 35.84 364.69 35.84 31.79 ...
# Ver un resumen estadístico básico
summary(datos_ventas)
##     Region            Country           Item Type         Sales Channel     
##  Length:1000000     Length:1000000     Length:1000000     Length:1000000    
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  Order Priority       Order Date                        Order ID        
##  Length:1000000     Min.   :2010-01-01 00:00:00.00   Min.   :100001180  
##  Class :character   1st Qu.:2011-11-22 00:00:00.00   1st Qu.:323962950  
##  Mode  :character   Median :2013-10-15 00:00:00.00   Median :548652350  
##                     Mean   :2013-10-14 22:41:24.98   Mean   :549352019  
##                     3rd Qu.:2015-09-08 00:00:00.00   3rd Qu.:774598097  
##                     Max.   :2017-07-29 00:00:00.00   Max.   :999999892  
##    Ship Date                     Units Sold      Unit Price    
##  Min.   :2010-01-01 00:00:00   Min.   :    1   Min.   :  9.33  
##  1st Qu.:2011-12-17 00:00:00   1st Qu.: 2502   1st Qu.: 81.73  
##  Median :2013-11-09 00:00:00   Median : 4998   Median :154.06  
##  Mean   :2013-11-08 23:03:51   Mean   : 4999   Mean   :266.03  
##  3rd Qu.:2015-10-02 00:00:00   3rd Qu.: 7496   3rd Qu.:421.89  
##  Max.   :2017-09-17 00:00:00   Max.   :10000   Max.   :668.27  
##    Unit Cost     
##  Min.   :  6.92  
##  1st Qu.: 35.84  
##  Median : 97.44  
##  Mean   :187.52  
##  3rd Qu.:263.33  
##  Max.   :524.96
colnames(datos_ventas)
##  [1] "Region"         "Country"        "Item Type"      "Sales Channel" 
##  [5] "Order Priority" "Order Date"     "Order ID"       "Ship Date"     
##  [9] "Units Sold"     "Unit Price"     "Unit Cost"

Segundo paso, limpieza y calculo de ventas y ganancia

datos_analisis <- datos_ventas %>%
  mutate(Ventas = `Units Sold` * `Unit Price`) %>%
  mutate(Ganancia = `Units Sold` * (`Unit Price` - `Unit Cost`)) %>%
  mutate(
    Año = year(`Order Date`),
    Mes_Año = floor_date(`Order Date`, unit = "month")
  )
head(datos_analisis %>% select(Ventas, Ganancia, Año, Mes_Año))
## # A tibble: 6 × 4
##    Ventas Ganancia   Año Mes_Año            
##     <dbl>    <dbl> <dbl> <dttm>             
## 1  14863.    3839.  2012 2012-07-01 00:00:00
## 2 503890.  338632.  2013 2013-09-01 00:00:00
## 3 151880.   20592   2015 2015-05-01 00:00:00
## 4  61415.   41273.  2017 2017-05-01 00:00:00
## 5 188519.   62217.  2016 2016-10-01 00:00:00
## 6  12866.    3323.  2011 2011-11-01 00:00:00

Tercer paso, un analisis descriptivo

Calcular las medidas de tendencia central (media y mediana) y dispersipon (desviación estandar) para las métricas creadas en el paso anterior para despues resumirlo por categoría.

resumen_general <- datos_analisis %>%
  summarise(
    # Métricas de Ventas
    Media_Ventas = mean(Ventas, na.rm = TRUE),
    Mediana_Ventas = median(Ventas, na.rm = TRUE),
    SD_Ventas = sd(Ventas, na.rm = TRUE),
    Total_Ventas = sum(Ventas, na.rm = TRUE),
    
    # Métricas de Ganancia
    Media_Ganancia = mean(Ganancia, na.rm = TRUE),
    Mediana_Ganancia = median(Ganancia, na.rm = TRUE),
    SD_Ganancia = sd(Ganancia, na.rm = TRUE),
    Total_Ganancia = sum(Ganancia, na.rm = TRUE)
  )
# Mostrar el resultado
print("Resumen General de Ventas y Ganancias:")
## [1] "Resumen General de Ventas y Ganancias:"
print(resumen_general)
## # A tibble: 1 × 8
##   Media_Ventas Mediana_Ventas SD_Ventas Total_Ventas Media_Ganancia
##          <dbl>          <dbl>     <dbl>        <dbl>          <dbl>
## 1     1329563.        784445.  1468527.      1.33e12        392296.
## # ℹ 3 more variables: Mediana_Ganancia <dbl>, SD_Ganancia <dbl>,
## #   Total_Ganancia <dbl>
resumen_por_articulo <- datos_analisis %>%
  group_by(`Item Type`) %>%
  summarise(
    Total_Ventas = sum(Ventas, na.rm = TRUE),
    Total_Ganancia = sum(Ganancia, na.rm = TRUE),
    Media_Ganancia_Transaccion = mean(Ganancia, na.rm = TRUE),
    Mediana_Ganancia_Transaccion = median(Ganancia, na.rm = TRUE),
    Transacciones = n()
  ) %>%
  arrange(desc(Total_Ganancia)) 

print("Top 5 Tipos de Artículo por Ganancia Total:")
## [1] "Top 5 Tipos de Artículo por Ganancia Total:"
print(head(resumen_por_articulo))
## # A tibble: 6 × 6
##   `Item Type`      Total_Ventas Total_Ganancia Media_Ganancia_Transaccion
##   <chr>                   <dbl>          <dbl>                      <dbl>
## 1 Cosmetics       182160446331.   72443359569.                    868303.
## 2 Household       278452465468.   69055811426.                    829330.
## 3 Office Supplies 270688503680.   52478345832.                    630583.
## 4 Baby Food       106351988407.   39936154844.                    478868.
## 5 Cereal           85420976262.   36788742280.                    442114.
## 6 Clothes          45523270758.   30593237596.                    367530.
## # ℹ 2 more variables: Mediana_Ganancia_Transaccion <dbl>, Transacciones <int>

Como se puede observar la media es significativamente mayor que la mediana, lo cual indica que hay pocas transacciones de muy alto valor que sesgan la media al alza. La columna “Total_Ganancia” muestra los productos más importantes en volumen.Mientras que la “Media_Ganancia_Transaccion” indica que productos tienen la mayor rentabilidad por transaccion individual.

Visualizaciones Gráficas

A continuación se presentan dos visualizaciones, la primera muestra los patrones de venta a lo largo del tiempo y la segunda ilustar los patrones de ganancias por una categoria clave.

Tendencia Mensual de Ventas Totales

Esté gráfico de línea nos ayuda a identificar estacionalidades, crecimiento y picos de venta a lo largo de los ocho años de datos.

# 1. Agrupar las ventas por mes
ventas_mensuales <- datos_analisis %>%
  group_by(Mes_Año) %>%
  summarise(Ventas_Acumuladas = sum(Ventas, na.rm = TRUE))

# 2. Crear el gráfico de línea
ggplot(ventas_mensuales, aes(x = Mes_Año, y = Ventas_Acumuladas)) +
  geom_line(color = "#0072B2", linewidth = 1) + 
  geom_point(color = "#0072B2") +
  labs(
    title = "Tendencia Mensual de Ventas Totales (8 Años)",
    x = "Fecha del Pedido",
    y = "Ventas Totales"
  ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"))

Ganancia total por tipo de articulo

Este gráfico de barras nos permite comparar rápidamente qué tipos de productos impulsan la mayor parte de la ganancia.

# 1. Crear el gráfico de barras
ggplot(resumen_por_articulo, aes(x = reorder(`Item Type`, Total_Ganancia), y = Total_Ganancia)) +
  geom_col(fill = "#D55E00") + # Barras color naranja
  coord_flip() + # Voltear las coordenadas para mejorar la lectura de las etiquetas largas
  labs(
    title = "Ganancia Total por Tipo de Artículo",
    x = "Tipo de Artículo",
    y = "Ganancia Total"
  ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold")) +
  geom_text(aes(label = round(Total_Ganancia, 0)), hjust = -0.1, size = 3) +
  scale_y_continuous(limits = c(0, max(resumen_por_articulo$Total_Ganancia) * 1.15))

Conclusiones y recomendaciones

El análisis descriptivo general de las transacciones revela una alta dispersión y dependencia de operaciones de gran magnitud.

  1. Ventas y Ganancias: La Ganancia Total durante el período analizado asciende a aproximadamente 1.33e12 unidades monetarias, mientras que la Venta Total es de 1.47e12. La Ganancia Promedio por Transacción es de 392,296 unidades, con una Desviación Estándar (SD) muy alta de 784,445. El hecho de que la desviación estándar supere la media indica que la rentabilidad del negocio está fuertemente impulsada por un pequeño número de transacciones de muy alto valor.

  2. Patrones de Estacionalidad (Gráfico de Tendencia Mensual): El gráfico no muestra un crecimiento sostenido o lineal a lo largo de los ocho años (2010-2017). En cambio, se observa una marcada y predecible estacionalidad cíclica anual. Las ventas alcanzan un pico máximo aproximadamente cada 12 meses (finales de cada año o inicios del siguiente) y luego experimentan una fuerte caída antes de recuperarse. Este patrón anual es la principal tendencia del negocio, más que el crecimiento a largo plazo.

  3. El artículo “Cosmetics” es, con diferencia, el principal motor de rentabilidad de la tienda en línea, generando una Ganancia Total de 72.44 mil millones (la cifra más alta).

  4. Los tres tipos de artículos que concentran la mayor parte de las ganancias son “Cosmetics”, “Household” (69.05 mil millones) y “Office Supplies” (52.47 mil millones).

  5. Los productos “Beverages” (6.54 mil millones) y “Fruits” (1.00 mil millones) son los que menos contribuyen a la ganancia total de la empresa, lo que sugiere una baja rentabilidad o un bajo volumen de ventas para estas categorías.

Se sugiere realizar un análisis de costos detallado para las categorías de bajo rendimiento como “Fruits” y “Beverages”. Si estos artículos son estratégicos para atraer tráfico o completar pedidos, se deben mantener. Si no son estratégicos, se debe considerar si es necesario ajustar precios, mejorar los márgenes o descontinuar su venta para reasignar recursos a productos más rentables. De igual forma se recomienda aumentar la inversión en la adquisición, publicidad y desarrollo de las categorías “Cosmetics”, “Household” y “Office Supplies”.